diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-12-10 19:35:37 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-12-10 19:35:37 +0000 |
commit | f4b2de8ebb01a1e4a906682edaa17785fff813c9 (patch) | |
tree | caae0a89736a380f7879b2181ad999725ac83f5b | |
parent | d1b6fb1ce48424b1eb608f8432a758627a3ba25d (diff) | |
download | classpath-f4b2de8ebb01a1e4a906682edaa17785fff813c9.tar.gz |
2006-12-10 Andrew John Hughes <gnu_andrew@member.fsf.org>generics-stoppoint
* Merge of HEAD-->generics-branch for
classpath-0.93-branch-point to generics-mergepoint
32 files changed, 2608 insertions, 262 deletions
@@ -1,8 +1,441 @@ +2006-12-10 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * javax/management/MBeanServerFactory.java: + (createMBeanServer(String)): Added security check. + (findMBeanServer(String)): Likewise. + (newMBeanServer(String)): Likewise. + (releaseMBeanServer(String)): Likewise. + * javax/management/MBeanServerPermission.java: + New file. + +2006-12-08 David Daney <ddaney@avtrex.com> + + * native/jni/java-nio/gnu_java_nio_VMChannel.c (is_non_blocking_fd): + Fix comment. + +2006-12-08 David Daney <ddaney@avtrex.com> + + * NEWS: Mention URLConnection.[get|set]ReadTimeout. + +2006-12-08 David Daney <ddaney@avtrex.com> + + * gnu/java/net/protocol/http/HTTPConnection.java (imports): Add + SocketException. + (HTTPConnection): Handle NumberFormatException in properties parsing. + (Pool.get): Set timeout on reused sockets. + * gnu/java/net/protocol/http/HTTPURLConnection.java (proxyPort): + Initialize. + (HTTPURLConnection): Cleanup properties handling. + (getConnection): Use both connection and read timeouts. + (setConnectTimeout): Removed. + (setReadTimeout): New method. + * java/net/URLConnection.java (timeout): Renamed to... + (connectTimeout): ... connectTimeout throughout. + (readTimeout): New field. + (getReadTimeout): New method. + (setReadTimeout): New method. + +2006-12-08 Tania Bento <tbento@redhat.com> + + * java/awt/ScrollPane.java + (doLayout): Change the location of the scrollpane's child + to (0, 0). + +2006-12-08 David Daney <ddaney@avtrex.com> + + * native/jni/java-nio/gnu_java_nio_VMChannel.c (is_non_blocking_fd): + New method. + (Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2): Throw + SocketTimeoutException if a blocking socket timesout. + (Java_gnu_java_nio_VMChannel_readScattering): Same. + (Java_gnu_java_nio_VMChannel_read__I): Same. + (Java_gnu_java_nio_VMChannel_connect): Initialize the fd set. + (Java_gnu_java_nio_VMChannel_connect6): Same. + 2006-12-08 Mark Wielaard <mark@klomp.org> * configure.ac (VERSION): Set to 0.93-generics. * NEWS: Add release date. +2006-12-08 Tania Bento <tbento@redhat.com> + + * java/awt/ScrollPane.java + (getScrollPosition): Throw NullPointerException if scrollpane + does have a child. + (setScrollPosition(int, int)): Throw NullPointerException if + scrollpane does have a child. Check that both ints are within + the allowed bounds; If they are not, scroll to the closest allowed + bound. + +2006-12-07 Roman Kennke <kennke@aicas.com> + + * javax/swing/JEditorPane.java + (EditorKitMapping): New inner helper class. + (editorKits): New static field for caching editor kit instances. + (static_initiazer): Initialize static mappings here. + (createEditorKitForContentType): Try to use cached instance. + Use correct classloader for loading. + (getEditorKitClassNameForContentType): Make use of EditorKitMapping + class. + (getEditorKitForContentType): Store the fetched editor kit. + Fallback to createDefaultEditorKit(). + (init): Don't clean the static registry here. + (registerEditorKitForContentType(String,String,ClassLoader)): + Implemented. + (registerEditorKitForContentType(String,String)): Delegate to + the other version of this method with the thread's context + classloader. + +2006-12-07 Mark Wielaard <mark@klomp.org> + + * examples/gnu/classpath/examples/swing/HtmlDemo.java + (setPage): Don't convert URL to String for setPage(). + +2006-12-07 Mark Wielaard <mark@klomp.org> + + * tools/Makefile.am (clean-local): Remove iasm and asm.lst. + +2006-12-07 Mark Wielaard <mark@klomp.org> + + * tools/Makefile.am: Explicitly define and use bootclasspath as + GLIBJ_BOOTCLASSPATH + +2006-12-07 Mark Wielaard <mark@klomp.org> + + * javax/swing/JEditorPane.java (createEditorKitForContentType): + Always load from system class loader. + +2006-12-07 Mark Wielaard <mark@klomp.org> + + * java/net/URL.java (URL(URL,String,URLStreamHandler,boolean)): New + private constructor. + (URL(URL,String,URLStreamHandler)): Call new constructor. + (URL(URL,String)): Likewise. + (URL(String)): Likewise. + +2006-12-07 Tom Tromey <tromey@redhat.com> + + * NEWS: Mention ASM. + * INSTALL: Don't mention --with-asm. + * tools/external/README: New file. + * tools/toolwrapper.c (main): Don't use ASM_JAR. + * tools/gjavah.in: Don't use PATH_TO_ASM. + * tools/grmic.in: Likewise. + * tools/Makefile.am (GLIBJ_CLASSPATH): Removed PATH_TO_ASM, added + 'asm'. + (javah, rmic): Removed variables. + (bin_PROGRAMS): Updated. + (gappletviewer_CFLAGS): Don't define ASM_JAR. + (gjarsigner_CFLAGS): Likewise. + (gkeytool_CFLAGS): Likewise. + (gjar_CFLAGS): Likewise. + (gnative2ascii_CFLAGS): Likewise. + (gserialver_CFLAGS): Likewise. + (grmiregistry_CFLAGS): Likewise. + (gtnameserv_CFLAGS): Likewise. + (gorbd_CFLAGS): Likewise. + (grmid_CFLAGS): Likewise. + (gjavah_CFLAGS): Likewise. + (grmic_CFLAGS): Likewise. + (bin_SCRIPTS): Updated. + (TOOLS_JAVA_FILES): Updated. + ($(TOOLS_ZIP)): Compile ASM sources. Copy resource files. + * configure.ac: Removed --with-asm. Always build gjavah. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * examples/gnu/classpath/examples/swing/BrowserEditorKit.java: + New class. + * examples/gnu/classpath/examples/swing/HtmlDemo.java + (LoadActionListener): Call setPage() helper method. + (createContent): Register tweaked editor kit. For FormSubmitEvents + call submitForm(), otherwise setPage(). + (postData): Helper method for posting form data. + (setPage): Helper method for navigating to a new URL. + (submitForm): Helper method for submitting a form. + * examples/gnu/classpath/examples/swing/forms.html: + Added text/password fields and select boxes. + * examples/gnu/classpath/examples/swing/welcome.html: Fixed typo. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/html/FormView.java + (SubmitThread.postData): Implemented. + (SubmitThread.run): Pass data to postData(). + (actionPerformed): Reset form when reset button is activated. + (createComponent): Add support for select lists and comboboxes. + Don't set value of text and password fields here, this is done + now in HTMLDocument for consistency. + (getElementFormData): Add support for fetching form data from + select lists and comboboxes as well as textareas. + (getSelectData): New helper method. Fetches form data from + select boxes. + (getTextAreaData): New helper method. Fetches form data from + textareas. + (resetForm): New helper method. Resets the entire form. + * javax/swing/text/html/HTMLDocument.java + (HTMLReader.FormAction.end): Handle SELECT and OPTION tags. + (HTMLReader.FormAction.start): Handle SELECT and OPTION tags. + (HTMLReader.FormAction.setModel): Initialize text and password + values here. Also, use the resetable special models. + Group radio buttons into ButtonGroup for exclusive selection. + (HTMLReader.FormTagAction): New class. Handles FORM tags. + (HTMLReader.buttonGroups): New field. + (HTMLReader.numOptions): New field. + (HTMLReader.option): New field. + (HTMLReader.selectModel): New field. + (HTMLReader.textAreaDocument): Make ResetablePlainDocument. + (HTMLReader.handleText): Handle OPTION text. + (HTMLReader.initTags): Map FORM tags to FormTagAction. + (HTMLReader.textAreaContent): Set initial content. + * javax/swing/text/html/Option.java + (Option): Make copy of attribute set. Initialize selected state. + (getValue): Fetch value from attribute set. + * javax/swing/text/html/ResetableModel.java: New interface. + * javax/swing/text/html/ResetablePlainDocument.java: New class. + Supports resetting the state. + * javax/swing/text/html/ResetableToggleButtonModel.java: Likewise. + * javax/swing/text/html/SelectComboBoxModel.java: Likewise. + * javax/swing/text/html/SelectListModel.java: Likewise. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/DefaultCaret.java + (appear): Adjust visibility here. + (setDotImpl): Don't adjust visibility here. + (moveDotImpl): Don't adjust visibility here. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/gtk/AsyncImage.java + (Loader.run): Synchronize on the AsyncImage to avoid threading + issues. + (addObservers): Check for obs==null outside and synchronize on + this inside to avoid locking issues. + (checkImage): New helper method. + (notifyObservers): Check that the correct lock is held and + remove actual locking. + * gnu/java/awt/peer/gtk/GtkToolkit.java + (checkImage): Added special handling for AsyncImages. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * examples/gnu/classpath/examples/swing/Demo.java + (getIcon): Made package private. + * examples/gnu/classpath/examples/swing/HtmlDemo.java + (hyperlinkUpdate): Convert URL to string. + +2006-12-06 Mark Wielaard <mark@klomp.org> + + * gnu/java/awt/peer/gtk/AsyncImage.java (addObserver): Never notify + null Observer. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * examples/gnu/classpath/examples/icons/back.png, + * examples/gnu/classpath/examples/icons/reload.png: + New icons for the HTML browser. + * examples/gnu/classpath/examples/swing/HtmlDemo.java + (history): New field. Manages the browsing history. + (HtmlDemo): Initialize history. + (createContent): Set location and add history. Add toolbar. + (createToolBar): New helper method. + (main): Make default size bigger. + * examples/gnu/classpath/examples/swing/frame1.html, + * examples/gnu/classpath/examples/swing/frame2.html, + * examples/gnu/classpath/examples/swing/frame3.html, + * examples/gnu/classpath/examples/swing/frame4.html, + * examples/gnu/classpath/examples/swing/frames.html, + * examples/gnu/classpath/examples/swing/tables.html: + New example pages. + * examples/gnu/classpath/examples/swing/welcome.html + Add a couple of links and new test pages. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * javax/swing/JEditorPane.java + (getStream): Buffer the stream for efficiency. + (setPage): Don't scroll the view at this point. + * javax/swing/plaf/basic/BasicTextUI.java + (RootView.paint): Call RootView's setSize to get synchronization. + (RootView.setSize): Synchronize to prevent race in layout code. + * javax/swing/text/AbstractDocument.java + (notifyListeners): New field. + (fireChangedUpdate): Track notifyListener field. + (fireRemoveUpdate): Track notifyListener field. + (fireIndertUpdate): Track notifyListener field. + (writeLock): Check notifyListener and throw IllegalStateException. + * javax/swing/text/View.java + (preferenceChanged): Create local var for better thread safety and + more efficiency. + +2006-12-06 Thomas Fitzsimmons <fitzsim@redhat.com> + + * java/awt/ScrollPane.java (addNotify): Add a parent panel for any + lightweight component, not just for non-Panel components. + (addImpl): Do not call doLayout. + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c + (setNativeBounds): Ensure widget parent is a GtkFixed before + calling gtk_fixed_move. + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c + (setNativeBounds): Likewise. + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c + (setNativeBounds): Likewise. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/html/TableView.java + (RowView.layoutMajorAxis): Check column index for invalid value. + (updateGrid): Check column index for invalid value. + +2006-12-06 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/html/BlockView.java + (getAlignment): Align blocks horizontally by the superclass. + * javax/swing/text/html/HTMLEditorKit.java + (HTMLFactory.create): Replace equals comparison by == for efficiency. + Add mapping for misplaced tr, td and th tags. Include object mapping. + * javax/swing/text/html/TableView.java + (RowView.replace): Invalidate grid early. + (gridValid): Initialize with false. + (create): Only create RowView and CellView for correctly placed + tags. Avoid unnecessary casts. + (getAlignment): Removed. + (replace): Invalidate grid early. + +2006-12-06 Francis Kung <fkung@redhat.com> + + * java/awt/geom/RectangularShape.java + (getBounds): Remove empty rectangle check. + +2006-12-06 Ben Konrath <bkonrath@redhat.com> + + Fixes PR 29853. + * gnu/xml/dom/DomAttr.java: Don't report mutation if oldValue and + newValue are the same. + * gnu/xml/dom/DomNode.java: Set parent if null during mutation. + +2006-12-06 Tania Bento <tbento@redhat.com> + + * javax/swing/border/CompoundBorder.java: + (isBorderOpaque): If inside border is null, return true if outside + border is opaque, false otherwise; if outside border is null, return + true if inside border is opaque, false otherwise; if inside or + outside border are both not null, then return true only if both the + inside and outside border are opaque, false otherwise. + +2006-12-06 Tania Bento <tbento@redhat.com> + + * javax/swing/border/CompoundBorder.java: + (isBorderOpaque): If inside and outside border both have a null + value, return true. + +2006-12-06 Chris Burdess <dog@gnu.org> + + Fixes PR 29272. + * javax/xml/parsers/DocumentBuilderFactory.java: Fix broken Javadoc. + * gnu/xml/stream/SAXParser.java: Fix file descriptor leak. + +2006-12-06 Chris Burdess <dog@gnu.org> + + Fixes PR 29264. + * gnu/xml/stream/XMLStreamWriterImpl.java: Allow arbitrary text in + writeDTD method. + +2006-12-06 Chris Burdess <dog@gnu.org> + + Fixes PR 28816. + * javax/xml/validation/SchemaFactory.java: Use correct algorithm to + discover schema factory implementation class. + +2006-12-05 Francis Kung <fkung@redhat.com> + + * java/awt/BasicStroke.java + (capEnd): Prevent division by zero. + * java/awt/geom/Arc2D.java + (ArcIterator.ArcIterator): Do not shift the arc to make the extent positive. + (ArcIterator.currentSegment): Handle a negative extent. + +2006-12-05 Francis Kung <fkung@redhat.com> + + * gnu/java/awt/peer/gtk/BufferedImageGraphics.java + (constructor): Handle translated subimages properly, ie, if the image's + 0,0 position is not the data buffer's first element. + +2006-12-05 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/gtk/AsyncImage.java + (Loader.run): Nullify observers after loading. + (observers): Made package private. + (addObserver): Check for null observers field. Create local + variable for thread safety. + (getHeight): Use addObserver() for checking state of field + and notifying observer when necessary. + (getWidth): Use addObserver() for checking state of field + and notifying observer when necessary. + (getProperty): Use addObserver() for checking state of field + and notifying observer when necessary. + (notifyObservers): Check for null observers field. Create local + variable for thread safety. + +2006-12-05 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/html/HTMLEditorKit.java + (HTMLFactory.create): Removed debug output. + * javax/swing/text/html/InlineView.java + (getBreakWeight): Likewise. + * javax/swing/text/html/StyleSheet.java + (addRule): Likewise. + (ListPainter.paint): Removed debug output. + +2006-12-05 Roman Kennke <kennke@aicas.com> + + * javax/swing/text/html/BlockView.java + (painter): Made package visible. + * javax/swing/text/html/StyleSheet.java + (translateBorder): New helper method. + (translateHTMLToCSS): Add mappings for border attributes. + * javax/swing/text/html/TableView.java + Made class subclass of BlockView to get CSS goodness. + (CellView.rowSpan): New field. + (CellView.setPropertiesFromAttributes): Fetch rowspan. + (RowView.overlap): New field. + (RowView.rowIndex): New field. + (RowView.layoutMajorAxis): Skip overlapping cells. + (RowView.layoutMinorAxis): Layout cells that span more than 1 row. + (numColumns): New field. + (tmpRect): New field. + (TableView): Initialize tmpRect. + (calculateColumnRequirements): Adjusted and fixed for multirows. + (getAlignment): Overridden to center tables. + (paint): Overridden to fix clipping. + (getStyleSheet): Made protected. + (layoutMajorAxis): Invalidate rows. + (setPropertiesFromAttributes): Made protected and call super. + (updateGrid): Update the overlapping information for multirows. + +2006-12-05 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/gtk/AsyncImage.java + (addObserver): Check for null and ignore null observers. + (getWidth): Check for null and ignore null observers. + (getHeight): Check for null and ignore null observers. + (getProperty): Check for null and ignore null observers. + +2006-12-05 Francis Kung <fkung@redhat.com> + + * java/awt/BasicStroke.java + (capEnd): Prevent division by zero. + * java/awt/geom/Arc2D.java + (ArcIterator.ArcIterator): Do not shift the arc to make the extent positive. + (ArcIterator.currentSegment): Handle a negative extent. + +2006-12-05 Francis Kung <fkung@redhat.com> + + * gnu/java/awt/peer/gtk/BufferedImageGraphics.java + (constructor): Handle translated subimages properly, ie, if the image's + 0,0 position is not the data buffer's first element. + 2006-12-05 Roman Kennke <kennke@aicas.com> * javax/swing/text/html/ImageView.java @@ -234,6 +667,20 @@ 2006-12-05 Roman Kennke <kennke@aicas.com> + * gnu/java/awt/peer/gtk/AsyncImage.java: New class. Supports + asynchronous loading of images. + * gnu/java/awt/peer/gtk/CairoGraphics2D.java + (drawImage): Fetch real image from possibly AsyncImage. + * gnu/java/awt/peer/gtk/ComponentGraphics.java + (drawImage): Fetch real image from possibly AsyncImage. + * gnu/java/awt/peer/gtk/GtkToolkit.java + (createImage(URL)): Create async image. + (imageOrError): Made method static for easy access from AsyncImage. + (prepareImage): For async images, register the observer to the + image. + +2006-12-05 Roman Kennke <kennke@aicas.com> + (paintComponent): Include paint area from event. (updateComponent): Include paint area from event. @@ -266,17 +713,36 @@ (hitTestChar): Fixed conditions for inclusion of range. Use layout information in the run for more efficiency. -2006-12-04 Andrew John Hughes <gnu_andrew@member.fsf.org> +2006-12-04 Roman Kennke <kennke@aicas.com> - * javax/management/openmbean/OpenType.java: - (OpenType(String,String,String)): Actually use - the string created to handle arrays. + * javax/swing/text/GlyphView.java + (J2DGlyphPainter): New inner class. + (checkPainter): For Java2D capable environments create + a J2DGlyphPainter. + +2006-12-04 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java + (FreeTypeGlyphVector): Don't filter control chars here. + (getGlyphs): Filter control chars and replace them by + hair space char. 2006-12-04 Roman Kennke <kennke@aicas.com> * native/jni/java-nio/gnu_java_nio_VMChannel.c (Java_gnu_java_nio_VMChannel_connect): Retry on EINTR. +2006-12-04 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * gnu/java/lang/management/BeanImpl.java: + (translate(String)): Don't assume the list uses "E", + just use the first and only type variable. + * java/lang/management/ManagementFactory.java: + (getPlatformMBeanServer()): Register logging bean. + * javax/management/openmbean/OpenType.java: + (OpenType(String,String,String)): Actually use + the string created to handle arrays. + 2006-12-04 Mark Wielaard <mark@klomp.org> * native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -293,6 +759,17 @@ Wrap all reads() and writes() in do-while blocks that check interrupted status. +2006-12-04 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * gnu/javax/management/Server.java: + Make map final and initialise it. + (unregisterMBean(ObjectName)): Match against + delegate's object name and not the instance. + * java/lang/management/ManagementFactory.java: + Added constant fields. + (getPlatformMBeanServer()): Implemented. + * javax/management/MBeanServerFactory.java: New file. + 2006-12-04 Roman Kennke <kennke@aicas.com> * javax/swing/text/BoxView.java @@ -364,6 +841,10 @@ (updateComponent): Likewise. (coalescePaintEvent): Set currentPaintArea. +2006-12-02 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * javax/management/MBeanServerBuilder.java: New file. + 2006-12-01 Mark Wielaard <mark@klomp.org> * java/text/DecimalFormat.java (parse): Always increment parsing @@ -85,13 +85,6 @@ Suggested Software http://www.xmlsoft.org/XSLT/ Minimum version of libxslt required: 1.1.11 - For building the gjavah and grmic tool, you will need the ASM library. - Current version 2.2.1 is needed (other 2.2.x versions should - be ok; 3.x is not ok). You can get ASM from - http://asm.objectweb.org/ - You will need to pass the --with-asm option to configure - and point it at your ASM jar file. - For building the documentation you will need - texinfo 4.2 or higher. @@ -137,8 +130,6 @@ gives a complete list. --enable-xmlj compile native libxml/xslt library default=no --enable-load-library enable to use JNI native methods default=yes --enable-local-sockets enable build of local Unix sockets - --with-asm=/path/to/asm.jar - the ASM jar to use for javah --with-jikes to compile the class library using jikes the default is to use gcj --with-glibj define what to install (zip|flat|both|none) @@ -1,3 +1,10 @@ +New in release 0.94 (UNRELEASED) + +* The ASM library is now included. A separate copy is no longer needed. + +* The setReadTimeout and getReadTimeout methods have been added to + java.net.URLConnection. They are now fully implemented for http URLs. + New in release 0.93 (Dec 8, 2006) * CORBA objects that exist on the same virtual machine and only are connected diff --git a/configure.ac b/configure.ac index 0cdb90197..cda0074db 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ dnl ----------------------------------------------------------- dnl define([AC_CACHE_LOAD], )dnl dnl define([AC_CACHE_SAVE], )dnl -AC_INIT([GNU Classpath],[0.93-generics],[classpath@gnu.org],[classpath]) +AC_INIT([GNU Classpath],[0.94-pre],[classpath@gnu.org],[classpath]) AC_CONFIG_SRCDIR(java/lang/System.java) AC_CANONICAL_TARGET @@ -806,31 +806,6 @@ AM_CONDITIONAL(USE_ESCHER, test x$use_escher = xtrue) AC_SUBST(PATH_TO_ESCHER) dnl ----------------------------------------------------------- -dnl Build javah using ASM library -dnl ----------------------------------------------------------- -AC_ARG_WITH([asm], - AS_HELP_STRING([--with-asm=ABS.PATH], - [specify path to ASM jar to enable gjavah and grmic build])) -case "$with_asm" in -"") - use_asm=false - ;; -"no") - use_asm=false - ;; -"yes") - AC_MSG_ERROR([Please supply an absolute path to ASM jar]) - ;; -*) - use_asm=true - PATH_TO_ASM=$with_asm - ;; -esac - -AM_CONDITIONAL(USE_ASM, test x$use_asm = xtrue) -AC_SUBST(PATH_TO_ASM) - -dnl ----------------------------------------------------------- dnl Check if local socket support should be included. dnl ----------------------------------------------------------- AC_ARG_ENABLE([local-sockets], @@ -914,7 +889,8 @@ tools/grmiregistry tools/gtnameserv tools/gorbd tools/grmid -tools/grmic]) +tools/grmic +tools/gjavah]) AC_CONFIG_COMMANDS([gappletviewer],[chmod 755 tools/gappletviewer]) AC_CONFIG_COMMANDS([gjarsigner],[chmod 755 tools/gjarsigner]) AC_CONFIG_COMMANDS([gkeytool],[chmod 755 tools/gkeytool]) @@ -926,11 +902,7 @@ AC_CONFIG_COMMANDS([gtnameserv],[chmod 755 tools/gtnameserv]) AC_CONFIG_COMMANDS([gorbd],[chmod 755 tools/gorbd]) AC_CONFIG_COMMANDS([grmid],[chmod 755 tools/grmid]) AC_CONFIG_COMMANDS([grmic],[chmod 755 tools/grmic]) - - if test "$use_asm" = true; then - AC_CONFIG_FILES([tools/gjavah]) - AC_CONFIG_COMMANDS([gjavah], [chmod 755 tools/gjavah]) - fi +AC_CONFIG_COMMANDS([gjavah], [chmod 755 tools/gjavah]) fi AC_CONFIG_COMMANDS([gen-classlist],[chmod 755 lib/gen-classlist.sh]) diff --git a/examples/gnu/classpath/examples/swing/HtmlDemo.java b/examples/gnu/classpath/examples/swing/HtmlDemo.java index 35a9df290..1a24ae276 100644 --- a/examples/gnu/classpath/examples/swing/HtmlDemo.java +++ b/examples/gnu/classpath/examples/swing/HtmlDemo.java @@ -284,7 +284,7 @@ public class HtmlDemo extends JPanel try { url.setText(u.toString()); - html.setPage(u.toString()); + html.setPage(u); history.addLast(u); } catch (IOException ex) diff --git a/gnu/java/awt/peer/gtk/AsyncImage.java b/gnu/java/awt/peer/gtk/AsyncImage.java new file mode 100644 index 000000000..5238bfe74 --- /dev/null +++ b/gnu/java/awt/peer/gtk/AsyncImage.java @@ -0,0 +1,283 @@ +/* AsyncImage.java -- Loads images asynchronously + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt.peer.gtk; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; + +/** + * Supports asynchronous loading of images. + */ +public class AsyncImage + extends Image +{ + + /** + * Returned as source as long as the image is not complete. + */ + private class NullImageSource + implements ImageProducer + { + private ArrayList consumers; + + NullImageSource() + { + consumers = new ArrayList(); + } + + public void addConsumer(ImageConsumer ic) + { + consumers.add(ic); + } + + public boolean isConsumer(ImageConsumer ic) + { + return consumers.contains(ic); + } + + public void removeConsumer(ImageConsumer ic) + { + consumers.remove(ic); + } + + public void requestTopDownLeftRightResend(ImageConsumer ic) + { + startProduction(ic); + } + + public void startProduction(ImageConsumer ic) + { + consumers.add(ic); + for (int i = consumers.size() - 1; i >= 0; i--) + { + ImageConsumer c = (ImageConsumer) consumers.get(i); + c.setDimensions(1, 1); + ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE); + } + } + + } + + /** + * Loads the image asynchronously. + */ + private class Loader + implements Runnable + { + private URL url; + Loader(URL u) + { + url = u; + } + + public void run() + { + Image image; + try + { + GtkImage gtkImage = new GtkImage(url); + image = CairoSurface.getBufferedImage(gtkImage); + } + catch (IllegalArgumentException iae) + { + image = null; + } + realImage = GtkToolkit.imageOrError(image); + synchronized (AsyncImage.this) + { + notifyObservers(ImageObserver.ALLBITS | ImageObserver.HEIGHT + | ImageObserver.WIDTH | ImageObserver.PROPERTIES); + observers = null; // Not needed anymore. + } + } + } + + /** + * The real image. This is null as long as the image is not complete. + */ + Image realImage; + + /** + * The image observers. + * + * This is package private to avoid accessor methods. + */ + HashSet observers; + + /** + * Creates a new AsyncImage that loads from the specified URL. + */ + AsyncImage(URL url) + { + observers = new HashSet(); + Loader l = new Loader(url); + Thread t = new Thread(l); + t.start(); + } + + public void flush() + { + // Nothing to do here. + } + + public Graphics getGraphics() + { + Image r = realImage; + Graphics g = null; + if (r != null) + g = r.getGraphics(); // Should we return some dummy graphics instead? + return g; + } + + public int getHeight(ImageObserver observer) + { + addObserver(observer); + int height = 0; + Image r = realImage; + if (r != null) + height = r.getHeight(observer); + return height; + } + + public Object getProperty(String name, ImageObserver observer) + { + addObserver(observer); + Image r = realImage; + Object prop = null; + if (r != null) + prop = r.getProperty(name, observer); + return prop; + } + + public ImageProducer getSource() + { + Image r = realImage; + ImageProducer source; + if (r == null) + source = new NullImageSource(); + else + source = r.getSource(); + return source; + } + + public int getWidth(ImageObserver observer) + { + addObserver(observer); + int width = 0; + Image r = realImage; + if (r != null) + width = r.getWidth(observer); + return width; + } + + void addObserver(ImageObserver obs) + { + if (obs != null) + { + synchronized (this) + { + // This field gets null when image loading is complete and we don't + // need to store any more observers. + HashSet observs = observers; + if (observs != null) + { + observs.add(obs); + } + else + { + // When the image is complete, notify the observer. Dunno if + // that's really needed, but to be sure. + obs.imageUpdate(this, ImageObserver.WIDTH + | ImageObserver.HEIGHT + |ImageObserver.ALLBITS + | ImageObserver.PROPERTIES, 0, 0, + realImage.getWidth(null), + realImage.getHeight(null)); + } + } + } + } + + static Image realImage(Image img, ImageObserver obs) + { + if (img instanceof AsyncImage) + { + ((AsyncImage) img).addObserver(obs); + Image r = ((AsyncImage) img).realImage; + if (r != null) + img = r; + } + return img; + } + + void notifyObservers(int status) + { + assert Thread.holdsLock(this); + // This field gets null when image loading is complete. + HashSet observs = observers; + if (observs != null) + { + Image r = realImage; + Iterator i = observs.iterator(); + while (i.hasNext()) + { + ImageObserver obs = (ImageObserver) i.next(); + obs.imageUpdate(this, status, 0, 0, r.getWidth(null), + r.getHeight(null)); + } + } + } + + int checkImage(ImageObserver obs) + { + addObserver(obs); + int flags = 0; + if (realImage != null) + flags = ImageObserver.ALLBITS | ImageObserver.WIDTH + | ImageObserver.HEIGHT | ImageObserver.PROPERTIES; + return flags; + } +} diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java index 37ae498ad..c792645d3 100644 --- a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java +++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java @@ -137,27 +137,45 @@ public class BufferedImageGraphics extends CairoGraphics2D cairo_t = surface.newCairoContext(); + // Get pixels out of buffered image and set in cairo surface Raster raster = bi.getRaster(); int[] pixels; - // get pixels - if(raster instanceof CairoSurface) - pixels = ((CairoSurface)raster).getPixels(imageWidth * imageHeight); + if (hasFastCM) + { + SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel(); + int minX = image.getRaster().getSampleModelTranslateX(); + int minY = image.getRaster().getSampleModelTranslateY(); + + // Pull pixels directly out of data buffer + if(raster instanceof CairoSurface) + pixels = ((CairoSurface)raster).getPixels(raster.getWidth() * raster.getHeight()); + else + pixels = ((DataBufferInt)raster.getDataBuffer()).getData(); + + // Discard pixels that fall outside of the image's bounds + // (ie, this image is actually a subimage of a different image) + if (!(sm.getScanlineStride() == imageWidth && minX == 0 && minY == 0)) + { + int[] pixels2 = new int[imageWidth * imageHeight]; + int scanline = sm.getScanlineStride(); + + for (int i = 0; i < imageHeight; i++) + System.arraycopy(pixels, (i - minY) * scanline - minX, pixels2, i * imageWidth, imageWidth); + + pixels = pixels2; + } + + // Fill the alpha channel as opaque if image does not have alpha + if( !hasAlpha ) + for(int i = 0; i < pixels.length; i++) + pixels[i] &= 0xFFFFFFFF; + } else { - if( hasFastCM ) - { - pixels = ((DataBufferInt)raster.getDataBuffer()).getData(); - if( !hasAlpha ) - for(int i = 0; i < pixels.length; i++) - pixels[i] &= 0xFFFFFFFF; - } - else - { - pixels = CairoGraphics2D.findSimpleIntegerArray - (image.getColorModel(),image.getData()); - } + pixels = CairoGraphics2D.findSimpleIntegerArray(image.getColorModel(),image.getData()); } + surface.setPixels( pixels ); setup( cairo_t ); diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java index ec9890524..348801800 100644 --- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java +++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -1463,7 +1463,7 @@ public abstract class CairoGraphics2D extends Graphics2D // Note - this can get us in trouble when the gdk lock is re-acquired. // for example by VolatileImage. See ComponentGraphics for how we work // around this. - + img = AsyncImage.realImage(img, obs); if( !(img instanceof BufferedImage) ) { ImageProducer source = img.getSource(); diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java index 612efd628..763ad7dfd 100644 --- a/gnu/java/awt/peer/gtk/ComponentGraphics.java +++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java @@ -468,6 +468,7 @@ public class ComponentGraphics extends CairoGraphics2D } BufferedImage bimg; + img = AsyncImage.realImage(img, observer); if (img instanceof BufferedImage) bimg = (BufferedImage) img; else diff --git a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java index 4ad87a84b..131a96448 100644 --- a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java +++ b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java @@ -101,13 +101,7 @@ public class FreetypeGlyphVector extends GlyphVector public FreetypeGlyphVector(Font f, char[] chars, int start, int len, FontRenderContext frc, int flags) { - // We need to filter out control characters (and possibly other - // non-renderable characters here). - StringBuilder b = new StringBuilder(chars.length); - for (int i = start; i < start + len; i++) - if (!Character.isISOControl(chars[i])) - b.append(chars[i]); - this.s = b.toString(); + this.s = new String(chars, start, len); this.font = f; this.frc = frc; @@ -187,10 +181,17 @@ public class FreetypeGlyphVector extends GlyphVector for(int i = 0; i < nGlyphs; i++) { codePoints[i] = s.codePointAt( stringIndex ); - // UTF32 surrogate handling + // UTF32 surrogate handling if( codePoints[i] != (int)s.charAt( stringIndex ) ) stringIndex ++; stringIndex ++; + + if (Character.isISOControl(codePoints[i])) + { + // Replace with 'hair space'. Should better be 'zero-width space' + // but that doesn't seem to be supported by default font. + codePoints[i] = 8202; + } } glyphCodes = getGlyphs( codePoints ); diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java index 26724206d..f746a4747 100644 --- a/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -176,6 +176,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit if (image instanceof GtkImage) return ((GtkImage) image).checkImage (observer); + if (image instanceof AsyncImage) + return ((AsyncImage) image).checkImage(observer); + if (observer != null) observer.imageUpdate (image, status, -1, -1, @@ -189,7 +192,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit * Helper to return either a Image -- the argument -- or a * GtkImage with the errorLoading flag set if the argument is null. */ - private Image imageOrError(Image b) + static Image imageOrError(Image b) { if (b == null) return GtkImage.getErrorImage(); @@ -216,16 +219,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public Image createImage (URL url) { - Image image; - try - { - image = CairoSurface.getBufferedImage( new GtkImage( url ) ); - } - catch (IllegalArgumentException iae) - { - image = null; - } - return imageOrError(image); + return new AsyncImage(url); } public Image createImage (ImageProducer producer) @@ -391,6 +385,13 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit return ((((GtkImage)image).checkImage (observer) & ImageObserver.ALLBITS) != 0); + if (image instanceof AsyncImage) + { + AsyncImage aImg = (AsyncImage) image; + aImg.addObserver(observer); + return aImg.realImage != null; + } + /* Assume anything else is too */ return true; } diff --git a/gnu/java/lang/management/BeanImpl.java b/gnu/java/lang/management/BeanImpl.java index 529ee5896..10ae420b3 100644 --- a/gnu/java/lang/management/BeanImpl.java +++ b/gnu/java/lang/management/BeanImpl.java @@ -500,11 +500,8 @@ public class BeanImpl { OpenType e = SimpleType.VOID; TypeVariable[] vars = c.getTypeParameters(); - for (int a = 0; a < vars.length; ++a) - { - if (vars[a].getName().equals("E")) - e = getTypeFromClass((Class) vars[a].getGenericDeclaration()); - } + if (vars.length > 0) + e = getTypeFromClass((Class) vars[0].getGenericDeclaration()); return new OpenMBeanParameterInfoSupport("TransParam", "Translated parameter", new ArrayType(1, e) diff --git a/gnu/java/net/protocol/http/HTTPConnection.java b/gnu/java/net/protocol/http/HTTPConnection.java index f5e831c6a..3956d2aba 100644 --- a/gnu/java/net/protocol/http/HTTPConnection.java +++ b/gnu/java/net/protocol/http/HTTPConnection.java @@ -48,6 +48,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketException; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.HashMap; @@ -227,10 +228,16 @@ public class HTTPConnection * @param secure whether to use a secure connection * @param connectionTimeout the connection timeout * @param timeout the socket read timeout + * + * @throws IllegalArgumentException if either connectionTimeout or + * timeout less than zero. */ public HTTPConnection(String hostname, int port, boolean secure, int connectionTimeout, int timeout) { + if (connectionTimeout < 0 || timeout < 0) + throw new IllegalArgumentException(); + this.hostname = hostname; this.port = port; this.secure = secure; @@ -471,14 +478,32 @@ public class HTTPConnection { String ttl = SystemProperties.getProperty("classpath.net.http.keepAliveTTL"); - connectionTTL = (ttl != null && ttl.length() > 0) ? - 1000 * Math.max(1, Integer.parseInt(ttl)) : 10000; + connectionTTL = 10000; + if (ttl != null && ttl.length() > 0) + try + { + int v = 1000 * Integer.parseInt(ttl); + if (v >= 0) + connectionTTL = v; + } + catch (NumberFormatException _) + { + // Ignore. + } String mc = SystemProperties.getProperty("http.maxConnections"); - maxConnections = (mc != null && mc.length() > 0) ? - Math.max(Integer.parseInt(mc), 1) : 5; - if (maxConnections < 1) - maxConnections = 1; + maxConnections = 5; + if (mc != null && mc.length() > 0) + try + { + int v = Integer.parseInt(mc); + if (v > 0) + maxConnections = v; + } + catch (NumberFormatException _) + { + // Ignore. + } HTTPConnection c = null; @@ -490,12 +515,23 @@ public class HTTPConnection { c = cc; it.remove(); + // Update the timeout. + if (c.socket != null) + try + { + c.socket.setSoTimeout(timeout); + } + catch (SocketException _) + { + // Ignore. + } break; } } if (c == null) { - c = new HTTPConnection(host, port, secure, connectionTimeout, timeout); + c = new HTTPConnection(host, port, secure, + connectionTimeout, timeout); c.setPool(this); } return c; diff --git a/gnu/java/net/protocol/http/HTTPURLConnection.java b/gnu/java/net/protocol/http/HTTPURLConnection.java index cc68a3bac..6c926b72f 100644 --- a/gnu/java/net/protocol/http/HTTPURLConnection.java +++ b/gnu/java/net/protocol/http/HTTPURLConnection.java @@ -75,7 +75,7 @@ public class HTTPURLConnection // These are package private for use in anonymous inner classes. String proxyHostname; - int proxyPort; + int proxyPort = -1; String agent; boolean keepAlive; @@ -99,18 +99,21 @@ public class HTTPURLConnection { super(url); requestHeaders = new Headers(); - proxyHostname = SystemProperties.getProperty("http.proxyHost"); - if (proxyHostname != null && proxyHostname.length() > 0) + String proxy = SystemProperties.getProperty("http.proxyHost"); + if (proxy != null && proxy.length() > 0) { String port = SystemProperties.getProperty("http.proxyPort"); if (port != null && port.length() > 0) { - proxyPort = Integer.parseInt(port); - } - else - { - proxyHostname = null; - proxyPort = -1; + try + { + proxyPort = Integer.parseInt(port); + proxyHostname = proxy; + } + catch (NumberFormatException _) + { + // Ignore. + } } } agent = SystemProperties.getProperty("http.agent"); @@ -354,11 +357,14 @@ public class HTTPURLConnection HTTPConnection connection; if (keepAlive) { - connection = HTTPConnection.Pool.instance.get(host, port, secure, getConnectTimeout(), 0); + connection = HTTPConnection.Pool.instance.get(host, port, secure, + getConnectTimeout(), + getReadTimeout()); } else { - connection = new HTTPConnection(host, port, secure, 0, getConnectTimeout()); + connection = new HTTPConnection(host, port, secure, + getConnectTimeout(), getReadTimeout()); } return connection; } @@ -662,23 +668,23 @@ public class HTTPURLConnection } /** - * Set the connection timeout speed, in milliseconds, or zero if the timeout + * Set the read timeout, in milliseconds, or zero if the timeout * is to be considered infinite. * * Overloaded. * */ - public void setConnectTimeout(int timeout) + public void setReadTimeout(int timeout) throws IllegalArgumentException { - super.setConnectTimeout( timeout ); - if( connection == null ) + super.setReadTimeout(timeout); + if (connection == null) return; try { - connection.getSocket().setSoTimeout( timeout ); + connection.getSocket().setSoTimeout(timeout); } - catch(IOException se) + catch (IOException se) { // Ignore socket exceptions. } diff --git a/gnu/javax/management/Server.java b/gnu/javax/management/Server.java index 5eecb6c2d..5501b4af7 100644 --- a/gnu/javax/management/Server.java +++ b/gnu/javax/management/Server.java @@ -104,6 +104,11 @@ public class Server { /** + * The name of the delegate bean. + */ + private static final ObjectName DELEGATE_NAME; + + /** * The registered beans, represented as a map of * {@link javax.management.ObjectName}s to * {@link java.lang.Object}s. @@ -121,11 +126,6 @@ public class Server private MBeanServer outer; /** - * The delegate bean. - */ - private MBeanServerDelegate delegate; - - /** * The class loader repository. */ private ClassLoaderRepository repository; @@ -137,6 +137,24 @@ public class Server private Map listeners; /** + * Initialise the delegate name. + */ + static + { + try + { + DELEGATE_NAME = + new ObjectName("JMImplementation:type=MBeanServerDelegate"); + } + catch (MalformedObjectNameException e) + { + throw (Error) + (new InternalError("Failed to construct " + + "the delegate's object name.").initCause(e)); + } + } + + /** * Constructs a new management server using the specified * default domain, delegate bean and outer server. * @@ -153,7 +171,28 @@ public class Server { this.defaultDomain = defaultDomain; this.outer = outer; - this.delegate = delegate; + try + { + registerMBean(delegate, DELEGATE_NAME); + } + catch (InstanceAlreadyExistsException e) + { + throw (Error) + (new InternalError("The delegate bean is " + + "already registered.").initCause(e)); + } + catch (MBeanRegistrationException e) + { + throw (Error) + (new InternalError("The delegate bean's preRegister " + + "methods threw an exception.").initCause(e)); + } + catch (NotCompliantMBeanException e) + { + throw (Error) + (new InternalError("The delegate bean is " + + "not compliant.").initCause(e)); + } } /** @@ -2019,14 +2058,14 @@ public class Server new IllegalArgumentException("The name was null."); throw new RuntimeOperationsException(e); } - Object bean = getBean(name); - checkSecurity(name, null, "unregisterMBean"); - if (bean == delegate) + if (name.equals(DELEGATE_NAME)) { RuntimeException e = new IllegalArgumentException("The delegate can not be unregistered."); throw new RuntimeOperationsException(e); } + Object bean = getBean(name); + checkSecurity(name, null, "unregisterMBean"); MBeanRegistration register = null; if (bean instanceof MBeanRegistration) { diff --git a/java/awt/BasicStroke.java b/java/awt/BasicStroke.java index e6cb87e34..ef6a7f0b7 100644 --- a/java/awt/BasicStroke.java +++ b/java/awt/BasicStroke.java @@ -761,9 +761,13 @@ public class BasicStroke implements Stroke p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; dx = p1[0] - p0[0]; dy = p1[1] - p0[1]; - l = Math.sqrt(dx * dx + dy * dy); - dx = (2.0/3.0)*width*dx/l; - dy = (2.0/3.0)*width*dy/l; + if (dx != 0 && dy != 0) + { + l = Math.sqrt(dx * dx + dy * dy); + dx = (2.0/3.0)*width*dx/l; + dy = (2.0/3.0)*width*dy/l; + } + c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy); c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy); a.add(new CubicSegment(a.last.P2, c1, c2, b.P1)); diff --git a/java/awt/ScrollPane.java b/java/awt/ScrollPane.java index 35a81300d..ec9746f93 100644 --- a/java/awt/ScrollPane.java +++ b/java/awt/ScrollPane.java @@ -338,10 +338,15 @@ getVScrollbarWidth() * Returns the current scroll position of the viewport. * * @return The current scroll position of the viewport. + * + * @throws NullPointerException if the scrollpane does have a child. */ public Point getScrollPosition() { + if (getComponentCount() == 0) + throw new NullPointerException(); + int x = 0; int y = 0; @@ -380,20 +385,35 @@ setScrollPosition(Point scrollPosition) throws IllegalArgumentException * @param x The new X coordinate of the scroll position. * @param y The new Y coordinate of the scroll position. * + * @throws NullPointerException if scrollpane does not have a child. + * * @exception IllegalArgumentException If the specified value is outside * the legal scrolling range. */ public void setScrollPosition(int x, int y) { + if (getComponentCount() == 0) + throw new NullPointerException("child is null"); + + if (x > (int) (getComponent(0).getWidth() - getViewportSize().getWidth())) + x = (int) (getComponent(0).getWidth() - getViewportSize().getWidth()); + if (y > (int) (getComponent(0).getHeight() - getViewportSize().getHeight())) + y = (int) (getComponent(0).getHeight() - getViewportSize().getHeight()); + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + Adjustable h = getHAdjustable(); Adjustable v = getVAdjustable(); - + if (h != null) h.setValue(x); if (v != null) v.setValue(y); - + ScrollPanePeer spp = (ScrollPanePeer)getPeer(); if (spp != null) spp.setScrollPosition(x, y); @@ -505,6 +525,8 @@ layout() p.y = dim.height; setScrollPosition (p); + + list[0].setLocation(new Point()); } } diff --git a/java/awt/geom/Arc2D.java b/java/awt/geom/Arc2D.java index eff34a081..8d5b01cd5 100644 --- a/java/awt/geom/Arc2D.java +++ b/java/awt/geom/Arc2D.java @@ -774,14 +774,9 @@ public abstract class Arc2D extends RectangularShape y = a.getY(); w = a.getWidth(); h = a.getHeight(); - double start = a.getAngleStart() * (Math.PI / 180); - double extent = a.getAngleExtent() * (Math.PI / 180); + double start = Math.toRadians(a.getAngleStart()); + double extent = Math.toRadians(a.getAngleExtent()); - if (extent < 0) - { - extent = -extent; - start = 2 * Math.PI - extent + start; - } this.start = start; this.extent = extent; @@ -790,11 +785,11 @@ public abstract class Arc2D extends RectangularShape limit = -1; else if (extent == 0) limit = type; - else if (extent <= Math.PI / 2.0) + else if (Math.abs(extent) <= Math.PI / 2.0) limit = type + 1; - else if (extent <= Math.PI) + else if (Math.abs(extent) <= Math.PI) limit = type + 2; - else if (extent <= 3.0 * (Math.PI / 2.0)) + else if (Math.abs(extent) <= 3.0 * (Math.PI / 2.0)) limit = type + 3; else limit = type + 4; @@ -909,9 +904,20 @@ public abstract class Arc2D extends RectangularShape double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0); double quad = (Math.PI / 2.0); - double curr_begin = start + (current - 1) * quad; - double curr_extent = Math.min((start + extent) - curr_begin, quad); - double portion_of_a_quadrant = curr_extent / quad; + double curr_begin; + double curr_extent; + if (extent > 0) + { + curr_begin = start + (current - 1) * quad; + curr_extent = Math.min((start + extent) - curr_begin, quad); + } + else + { + curr_begin = start - (current - 1) * quad; + curr_extent = Math.max((start + extent) - curr_begin, -quad); + } + + double portion_of_a_quadrant = Math.abs(curr_extent / quad); double x0 = xmid + rx * Math.cos(curr_begin); double y0 = ymid - ry * Math.sin(curr_begin); @@ -932,7 +938,11 @@ public abstract class Arc2D extends RectangularShape // will *subtract* the y value of this control vector from our first // point. cvec[0] = 0; - cvec[1] = len; + if (extent > 0) + cvec[1] = len; + else + cvec[1] = -len; + trans.scale(rx, ry); trans.rotate(angle); trans.transform(cvec, 0, cvec, 0, 1); @@ -942,7 +952,11 @@ public abstract class Arc2D extends RectangularShape // control vector #2 would, ideally, be sticking out and to the // right, in a first quadrant arc segment. again, subtraction of y. cvec[0] = 0; - cvec[1] = -len; + if (extent > 0) + cvec[1] = -len; + else + cvec[1] = len; + trans.rotate(curr_extent); trans.transform(cvec, 0, cvec, 0, 1); coords[2] = x1 + cvec[0]; diff --git a/java/awt/geom/RectangularShape.java b/java/awt/geom/RectangularShape.java index 8f66dabf2..3ee161541 100644 --- a/java/awt/geom/RectangularShape.java +++ b/java/awt/geom/RectangularShape.java @@ -326,15 +326,12 @@ public abstract class RectangularShape implements Shape, Cloneable /** * Returns a bounding box for this shape, in integer format. Notice that you - * may get a tighter bound with getBounds2D. If the frame is empty, the - * box is the default empty box at the origin. + * may get a tighter bound with getBounds2D. * * @return a bounding box */ public Rectangle getBounds() { - if (isEmpty()) - return new Rectangle(); double x = getX(); double y = getY(); double maxx = Math.ceil(x + getWidth()); diff --git a/java/lang/management/ManagementFactory.java b/java/lang/management/ManagementFactory.java index d9a02ee23..a51ca0f4c 100644 --- a/java/lang/management/ManagementFactory.java +++ b/java/lang/management/ManagementFactory.java @@ -50,9 +50,18 @@ import gnu.java.lang.management.RuntimeMXBeanImpl; import gnu.java.lang.management.ThreadMXBeanImpl; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.logging.LogManager; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; /** * <p> @@ -66,6 +75,11 @@ import javax.management.NotCompliantMBeanException; * <ol> * <li>Calling the appropriate static method of this factory. * </li> + * <li>Using the platform {@link javax.management.MBeanServer} + * to access the beans locally, or an + * {@link javax.management.MBeanServerConnection} for remote + * access. The attributes and operations use the limited + * range of data types specified below.</li> * </ol> * <h2>Open Data Types</h2> * <p> @@ -118,6 +132,60 @@ public class ManagementFactory { /** + * The object name for the class loading bean. + */ + public static final String CLASS_LOADING_MXBEAN_NAME = + "java.lang:type=ClassLoading"; + + /** + * The object name for the compilation bean. + */ + public static final String COMPILATION_MXBEAN_NAME = + "java.lang:type=Compilation"; + + /** + * The domain for the garbage collecting beans. + */ + public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE = + "java.lang:type=GarbageCollector"; + + /** + * The domain for the memory manager beans. + */ + public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE = + "java.lang:type=MemoryManager"; + + /** + * The object name for the memory bean. + */ + public static final String MEMORY_MXBEAN_NAME = + "java.lang:type=Memory"; + + /** + * The domain for the memory pool beans. + */ + public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE = + "java.lang:type=MemoryPool"; + + /** + * The object name for the operating system bean. + */ + public static final String OPERATING_SYSTEM_MXBEAN_NAME = + "java.lang:type=OperatingSystem"; + + /** + * The object name for the runtime bean. + */ + public static final String RUNTIME_MXBEAN_NAME = + "java.lang:type=Runtime"; + + /** + * The object name for the threading bean. + */ + public static final String THREAD_MXBEAN_NAME = + "java.lang:type=Threading"; + + /** * The operating system management bean. */ private static OperatingSystemMXBean osBean; @@ -148,6 +216,11 @@ public class ManagementFactory private static CompilationMXBean compilationBean; /** + * The platform server. + */ + private static MBeanServer platformServer; + + /** * Private constructor to prevent instance creation. */ private ManagementFactory() {} @@ -374,4 +447,106 @@ public class ManagementFactory return gcBeans; } + /** + * <p> + * Returns the platform {@link javax.management.MBeanServer}. On the + * first call to this method, a server instance is retrieved from + * the {@link javax.management.MBeanServerFactory} and each of the + * beans are registered with it. Subsequent calls return the existing + * instance. If the property <code>javax.management.builder.initial</code> + * is set, its value will be used as the name of the class which is used + * to provide the server instance. + * </p> + * <p> + * It is recommended that the platform server is used for other beans as + * well, in order to simplify their discovery and publication. Name conflicts + * should be avoided. + * </p> + * + * @return the platform {@link javax.management.MBeanServer} + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @see javax.management.MBeanServerFactory + * @see javax.management.MBeanServerFactory#createMBeanServer() + */ + public static MBeanServer getPlatformMBeanServer() + { + if (platformServer == null) + { + platformServer = MBeanServerFactory.createMBeanServer(); + try + { + platformServer.registerMBean(getOperatingSystemMXBean(), + new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME)); + platformServer.registerMBean(getRuntimeMXBean(), + new ObjectName(RUNTIME_MXBEAN_NAME)); + platformServer.registerMBean(getClassLoadingMXBean(), + new ObjectName(CLASS_LOADING_MXBEAN_NAME)); + platformServer.registerMBean(getThreadMXBean(), + new ObjectName(THREAD_MXBEAN_NAME)); + platformServer.registerMBean(getMemoryMXBean(), + new ObjectName(MEMORY_MXBEAN_NAME)); + CompilationMXBean compBean = getCompilationMXBean(); + if (compBean != null) + platformServer.registerMBean(compBean, + new ObjectName(COMPILATION_MXBEAN_NAME)); + Iterator beans = getMemoryPoolMXBeans().iterator(); + while (beans.hasNext()) + { + MemoryPoolMXBean bean = (MemoryPoolMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + beans = getMemoryManagerMXBeans().iterator(); + while (beans.hasNext()) + { + MemoryManagerMXBean bean = (MemoryManagerMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + beans = getGarbageCollectorMXBeans().iterator(); + while (beans.hasNext()) + { + GarbageCollectorMXBean bean = (GarbageCollectorMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + platformServer.registerMBean(LogManager.getLoggingMXBean(), + new ObjectName(LogManager.LOGGING_MXBEAN_NAME)); + } + catch (InstanceAlreadyExistsException e) + { + throw (Error) + (new InternalError("One of the management beans is " + + "already registered.").initCause(e)); + } + catch (MBeanRegistrationException e) + { + throw (Error) + (new InternalError("One of the management beans' preRegister " + + "methods threw an exception.").initCause(e)); + } + catch (NotCompliantMBeanException e) + { + throw (Error) + (new InternalError("One of the management beans is " + + "not compliant.").initCause(e)); + } + catch (MalformedObjectNameException e) + { + throw (Error) + (new InternalError("The object name of a management bean is " + + "not compliant.").initCause(e)); + } + } + return platformServer; + } + } diff --git a/java/net/URLConnection.java b/java/net/URLConnection.java index 325ff2329..674058014 100644 --- a/java/net/URLConnection.java +++ b/java/net/URLConnection.java @@ -175,9 +175,14 @@ public abstract class URLConnection private static boolean dateformats_initialized; /** - * The timeout period. + * The connection timeout period. */ - private int timeout; + private int connectTimeout; + + /** + * The read timeout period. + */ + private int readTimeout; /* Cached ParsePosition, used when parsing dates. */ private ParsePosition position; @@ -217,8 +222,8 @@ public abstract class URLConnection } /** - * Returns the connection timeout speed, in milliseconds, or zero if the timeout - * is infinite or not set. + * Returns the connection timeout speed, in milliseconds, or zero if + * the timeout is infinite or not set. * * @return The timeout. * @@ -226,7 +231,7 @@ public abstract class URLConnection */ public int getConnectTimeout() { - return timeout; + return connectTimeout; } /** @@ -236,7 +241,7 @@ public abstract class URLConnection * * Throws an <code>IllegalArgumentException</code> if timeout < 0. * - * @param timeout - The timeout, in milliseconds. + * @param timeout the timeout, in milliseconds. * * @since 1.5 */ @@ -245,7 +250,45 @@ public abstract class URLConnection { if( timeout < 0 ) throw new IllegalArgumentException("Timeout must be 0 or positive."); - this.timeout = timeout; + connectTimeout = timeout; + } + + /** + * Returns the read timeout, in milliseconds, or zero if the timeout + * is infinite or not set. + * + * @return The timeout. + * + * @see #setReadTimeout + * + * @since 1.5 + */ + public int getReadTimeout() + { + return readTimeout; + } + + /** + * Set the read timeout, in milliseconds, or zero if the timeout + * is to be considered infinite. Note that in certain socket + * implementations/platforms this method may not have any effect. + * + * Throws an <code>IllegalArgumentException</code> if timeout < 0. + * + * @param timeout - The timeout, in milliseconds. + * + * @throws IllegalArgumentException if timeout is negative. + * + * @see #getReadTimeout + * + * @since 1.5 + */ + public void setReadTimeout(int timeout) + throws IllegalArgumentException + { + if( timeout < 0 ) + throw new IllegalArgumentException("Timeout must be 0 or positive."); + readTimeout = timeout; } /** diff --git a/javax/management/MBeanServerBuilder.java b/javax/management/MBeanServerBuilder.java new file mode 100644 index 000000000..4e2806829 --- /dev/null +++ b/javax/management/MBeanServerBuilder.java @@ -0,0 +1,102 @@ +/* MBeanServerBuilder.java -- Creates a default management server. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management; + +import gnu.javax.management.Server; + +/** + * Constructs a default implementation of an {@link MBeanServer}. + * The {@link MBeanServerFactory} allows custom implementations of + * {@link MBeanServer} to be used by providing subclasses of this. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class MBeanServerBuilder +{ + + /** + * Constructs a new {@link MBeanServerBuilder}. + */ + public MBeanServerBuilder() + { + } + + /** + * <p> + * Creates a new {@link MBeanServer} implementation with the specified + * default domain, delegate and outer server. The latter is the server + * passed to the {@link MBeanRegistration} interface of management beans, + * allowing an {@link MBeanServer} implementation to wrap another in order + * to provide additional checks, etc. If this value is <code>null</code>, + * <code>this</code> is passed to beans instead. + * </p> + * <p> + * The {@link MBeanServerFactory} calls this method after having first + * created a delegate using the {@link #newMBeanServerDelegate()} method. + * However, the delegate used in the call to this method may not be the + * same as that returned by {@link #newMBeanServerDelegate()} as the factory + * can optionally wrap the delegate before calling this method. + * </p> + * + * @param defaultDomain the default domain used by the new server. + * @param outer the {@link MBeanServer} passed to the {@link MBeanRegistration} + * interface of management beans. + * @param delegate the delegate bean associated with the server, which must + * be registered as a management bean by the server. + * @return a new instance of a server implementation. + */ + public MBeanServer newMBeanServer(String defaultDomain, MBeanServer outer, + MBeanServerDelegate delegate) + { + return new Server(defaultDomain, outer, delegate); + } + + /** + * Creates a new {@link MBeanServerDelegate}, which will be used by + * a management server. The returned delegate may either be used directly + * by the server, or may be further wrapped to add additional checks. + * + * @return a new instance of {@link MBeanServerDelegate}. + */ + public MBeanServerDelegate newMBeanServerDelegate() + { + return new MBeanServerDelegate(); + } + +} diff --git a/javax/management/MBeanServerFactory.java b/javax/management/MBeanServerFactory.java new file mode 100644 index 000000000..accbc56fc --- /dev/null +++ b/javax/management/MBeanServerFactory.java @@ -0,0 +1,413 @@ +/* MBeanServerFactory.java -- Manages server instances. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management; + +import gnu.classpath.SystemProperties; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.management.loading.ClassLoaderRepository; + +/** + * <p> + * Creates and maintains a set of {@link MBeanServer} instances. + * Server instances, as of JMX 1.2, are created using a subclass + * of {@link MBeanServerBuilder}. The exact class used is controlled + * by the property <code>javax.management.builder.initial</code>, + * and allows the instances created by {@link MBeanServerBuilder} + * to be wrapped, thus providing additional functionality. + * </p> + * <p> + * The property is used as follows: + * </p> + * <ol> + * <li>If the property has no value, then an instance of + * {@link MBeanServerBuilder} is used.</li> + * <li>If a value is given, then: + * <ol> + * <li>The class is loaded using + * <code>Thread.currentThread().getContextClassLoader()</code>, or, + * if this is <code>null</code>, by <code>Class.forName()</code>.</li> + * <li><code>Class.newInstance()</code> is used to create an instance + * of the class. The class must be public and have a public empty + * constructor. If an exception is thrown, it is propogated as + * a {@link JMRuntimeException} and no new server instances may be + * created until the property is set to a valid value.</li> + * </ol></li> + * <li>The value is checked on each successive request for a server. + * If it differs from the class of the existing instance of + * {@link MBeanServerBuilder}, then the value is used to create + * a new instance.</li> + * </ol> + */ +public class MBeanServerFactory +{ + + /** + * The last builder instance. + */ + private static MBeanServerBuilder builder; + + /** + * The map of registered servers (identifiers to servers). + */ + private static Map servers; + + /** + * Private constructor to prevent instance creation. + */ + private MBeanServerFactory() {} + + /** + * Returns a server implementation using the default domain name + * of <code>"DefaultDomain"</code>. The default domain name is + * used when the domain name specified by the user is <code>null</code. + * A reference to the created server is retained, so that it can + * be retrieved at a later date using {@link #findMBeanServer}. + * Calling this method is equivalent to calling + * {@link createMBeanServer(String)} with a <code>null</code> value. + * + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + * @see #createMBeanServer(String) + */ + public static MBeanServer createMBeanServer() + { + return createMBeanServer(null); + } + + /** + * Returns a server implementation using the default domain name + * given, or <code>"DefaultDomain"</code> if this is <code>null</code>. + * The default domain name is used when the domain name specified by + * the user is <code>null</code. A reference to the created server is + * retained, so that it can be retrieved at a later date using + * {@link #findMBeanServer}. + * + * @param domain the default domain name of the server. + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + public static MBeanServer createMBeanServer(String domain) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("createMBeanServer")); + MBeanServer server = createServer(domain); + if (servers == null) + servers = new HashMap(); + try + { + ObjectName dn = new + ObjectName("JMImplementation:type=MBeanServerDelegate"); + servers.put(server.getAttribute(dn, "MBeanServerId"), server); + } + catch (MalformedObjectNameException e) + { + throw (Error) + (new InternalError("Malformed delegate bean name.").initCause(e)); + } + catch (MBeanException e) + { + throw (Error) + (new InternalError("Exception in getMBeanServerId().").initCause(e)); + } + catch (AttributeNotFoundException e) + { + throw (Error) + (new InternalError("Could not find MBeanServerId attribute.").initCause(e)); + } + catch (InstanceNotFoundException e) + { + throw (Error) + (new InternalError("Could not find the delegate bean.").initCause(e)); + } + catch (ReflectionException e) + { + throw (Error) + (new InternalError("Could not call getMBeanServerId().").initCause(e)); + } + return server; + } + + /** + * Returns the specified server, or, if <code>id</code> is <code>null</code>, + * a list of all registered servers. A registered server is one that + * was created using {@link #createMBeanServer()} or + * {@link #createMBeanServer(String)} and has not yet been released + * using {@link releaseMBeanServer(MBeanServer)}. + * + * @param id the id of the server to retrieve, or <code>null</code> + * to return all servers. + * @return a list of {@link MBeanServer}s. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("findMBeanServer") + */ + public static ArrayList findMBeanServer(String id) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("findMBeanServer")); + if (id == null) + return new ArrayList(servers.values()); + ArrayList list = new ArrayList(); + MBeanServer server = (MBeanServer) servers.get(id); + if (server != null) + list.add(servers.get(id)); + return list; + } + + /** + * Returns the class loader repository used by the specified server. + * This is equivalent to calling {@link MBeanServer#getClassLoaderRepository()} + * on the given server. + * + * @param server the server whose class loader repository should be + * retrieved. + * @throws NullPointerException if <code>server</code> is <code>null</code>. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanPermission(String,String,ObjectName,String) + * <code>MBeanPermission(null, null, null, + * "getClassLoaderRepository")</code> + */ + public static ClassLoaderRepository getClassLoaderRepository(MBeanServer server) + { + return server.getClassLoaderRepository(); + } + + /** + * Returns a server implementation using the default domain name + * of <code>"DefaultDomain"</code>. The default domain name is + * used when the domain name specified by the user is <code>null</code. + * No reference to the created server is retained, so the server is + * garbage collected when it is no longer used, but it can not be + * retrieved at a later date using {@link #findMBeanServer}. + * Calling this method is equivalent to calling + * {@link newMBeanServer(String)} with a <code>null</code> value. + * + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("newMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + * @see #newMBeanServer(String) + */ + public static MBeanServer newMBeanServer() + { + return newMBeanServer(null); + } + + /** + * Returns a server implementation using the default domain name + * given, or <code>"DefaultDomain"</code> if this is <code>null</code>. + * The default domain name is used when the domain name specified by + * the user is <code>null</code. No reference to the created server is + * retained, so the server is garbage collected when it is no longer + * used, but it can not be retrieved at a later date using + * {@link #findMBeanServer}. + * + * @param domain the default domain name of the server. + * @return a new {@link MBeanServer} instance. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("newMBeanServer") + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + public static MBeanServer newMBeanServer(String domain) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("newMBeanServer")); + return createServer(domain); + } + + /** + * Common method to create a server for the {@link #createMBeanServer(String)} + * and {@link #newMBeanServer(String)} methods above. + * + * @param domain the default domain name of the server. + * @throws JMRuntimeException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which either can not be + * instantiated or provides an implementation that returns + * <code>null</code> from either + * {@link MBeanServerBuilder#newMBeanServerDelegate()} + * or {@link MBeanServerBuilder#newMBeanServer()} + * @throws ClassCastException if the property + * <code>javax.management.builder.initial</code> + * exists but names a class which is not a subclass + * of {@link MBeanServerBuilder}. + */ + private static MBeanServer createServer(String domain) + { + if (domain == null) + domain = "DefaultDomain"; + String builderClass = + SystemProperties.getProperty("javax.management.builder.initial"); + if (builderClass == null) + { + if (builder == null || + builder.getClass() != MBeanServerBuilder.class) + builder = new MBeanServerBuilder(); + } + else if (!(builderClass.equals(builder.getClass().getName()))) + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) + cl = MBeanServerFactory.class.getClassLoader(); + try + { + Class bClass = Class.forName(builderClass, true, cl); + builder = (MBeanServerBuilder) bClass.newInstance(); + } + catch (ClassNotFoundException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be found.")) + .initCause(e); + } + catch (InstantiationException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be instantiated.")) + .initCause(e); + } + catch (IllegalAccessException e) + { + throw (JMRuntimeException) (new JMRuntimeException("The builder class, " + + builderClass + + ", could not be accessed.")) + .initCause(e); + } + } + MBeanServerDelegate delegate = builder.newMBeanServerDelegate(); + if (delegate == null) + throw new JMRuntimeException("A delegate could not be created."); + MBeanServer server = builder.newMBeanServer("DefaultDomain", null, delegate); + if (server == null) + throw new JMRuntimeException("A server could not be created."); + return server; + } + + /** + * Removes the reference to the specified server, thus allowing it to + * be garbage collected. + * + * @param server the server to remove. + * @throws IllegalArgumentException if a reference to the server is not + * held (i.e. it wasn't created by + * {@link #createMBeanServer(String)} + * or this method has already been called + * on it. + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("releaseMBeanServer") + */ + public static void releaseMBeanServer(MBeanServer server) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new MBeanServerPermission("releaseMBeanServer")); + Iterator i = servers.values().iterator(); + while (i.hasNext()) + { + MBeanServer s = (MBeanServer) i.next(); + if (server == s) + { + i.remove(); + return; + } + } + throw new IllegalArgumentException("The server given is not referenced."); + } + + +} diff --git a/javax/management/MBeanServerPermission.java b/javax/management/MBeanServerPermission.java new file mode 100644 index 000000000..e62278144 --- /dev/null +++ b/javax/management/MBeanServerPermission.java @@ -0,0 +1,470 @@ +/* MBeanServerPermission.java -- Permissions controlling server creation. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management; + +import java.security.BasicPermission; +import java.security.Permission; +import java.security.PermissionCollection; + +import java.util.Enumeration; +import java.util.NoSuchElementException; + +/** + * <p> + * Represents the permissions required to perform + * operations provided by the {@link MBeanServerFactory}. + * As with all {@link java.security.Permission} objects, an + * instance of this class either represents a permission + * already held or one that is required to access a + * particular service. In the case of {@link MBeanServerPermission}s, + * implication checks are made using an instance of this class + * when a user requests an operation from the factory, and a + * {@link SecurityManager} is in place. + * </p> + * <p> + * The permission is defined by its name, which may be + * either a <code>'*'</code> (to allow all) or one or + * more of the following, separated by a <code>','</code>: + * </p> + * <ul> + * <li><code>createMBeanServer</code> -- allows a registered + * instance of a server to be obtained from the factory.</li> + * <li><code>findMBeanServer</code> -- allows all or one + * particular server instance to be retrieved from the factory.</li> + * <li><code>newMBeanServer</code> -- allows an unregistered + * instance of a server to be obtained from the factory.</li> + * <li><code>releaseMBeanServer</code> -- allows a reference to + * a server instance to be removed from the factory.</li> + * </ul> + * <p> + * The names may be surrounded by arbitrary amounts of whitespace. + * <code>createMBeanServer</code> implies <code>newMBeanServer</code>. + * </p> + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class MBeanServerPermission + extends BasicPermission +{ + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = -5661980843569388590L; + + /** + * <p> + * Constructs a new {@link MBeanServerPermission} with + * the given name. The name must not be <code>null</code> + * and must be equal to either <code>"*"</code> or a + * comma-separated list of valid permissions. The four + * valid constraints are: + * </p> + * <ol> + * <li><code>createMBeanServer</code></li> + * <li><code>findMBeanServer</code></li> + * <li><code>newMBeanServer</code></li> + * <li><code>releaseMBeanServer</code></li> + * </ol> + * <p> + * Calling this constructor is equivalent to calling + * <code>MBeanPermission(name, null)</code>. + * </p> + * + * @param name the name of this permission. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints. + * @see #MBeanServerPermission(String,String) + */ + public MBeanServerPermission(String name) + { + this(name, null); + } + + /** + * <p> + * Constructs a new {@link MBeanServerPermission} with + * the given name and actions. The actions are unused, + * and must be either <code>null</code> or the empty + * string. The name must not be <code>null</code> + * and must be equal to either <code>"*"</code> or a + * comma-separated list of valid permissions. The four + * valid constraints are: + * </p> + * <ol> + * <li><code>createMBeanServer</code></li> + * <li><code>findMBeanServer</code></li> + * <li><code>newMBeanServer</code></li> + * <li><code>releaseMBeanServer</code></li> + * </ol> + * <p> + * Calling this constructor is equivalent to calling + * <code>MBeanPermission(name, null)</code>. + * </p> + * + * @param name the name of this permission. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints, or if + * <code>actions</code> is not + * <code>null</code> or the + * empty string. + * @see #MBeanServerPermission(String,String) + */ + public MBeanServerPermission(String name, String actions) + { + super(checkName(name), actions); + if (actions != null && actions.length() > 0) + throw new IllegalArgumentException("The supplied action list " + + "was not equal to null or the " + + "empty string."); + } + + /** + * Returns true if the given object is also an {@link MBeanServerPermission} + * with the same name. + * + * @param obj the object to compare with this one. + * @return true if the object is an {@link MBeanPermission} + * with the same name. + */ + public boolean equals(Object obj) + { + if (obj instanceof MBeanServerPermission) + { + MBeanServerPermission o = (MBeanServerPermission) obj; + return o.getName().equals(getName()); + } + return false; + } + + /** + * Returns a unique hash code for this permission. + * This is simply the hashcode of {@link BasicPermission#getName()}. + * + * @return the hashcode of this permission. + */ + public int hashCode() + { + return getName().hashCode(); + } + + /** + * Returns true if this {@link MBeanServerPermission} implies + * the given permission. This occurs if the given permission + * is also an {@link MBeanServerPermission} and its target names + * are a subset of the target names of this permission. Note that + * the name <code>createMBeanServer</code> implies + * <code>newMBeanServer</code>. + * + * @param p the permission to check for implication. + * @return true if this permission implies <code>p</code>. + */ + public boolean implies(Permission p) + { + if (p instanceof MBeanServerPermission) + { + if (getName().equals("*")) + return true; + MBeanServerPermission msp = (MBeanServerPermission) p; + String[] thisCaps = getName().split(","); + String[] mspCaps = msp.getName().split(","); + for (int a = 0; a < mspCaps.length; ++a) + { + boolean found = false; + String mc = mspCaps[a].trim(); + for (int b = 0; b < thisCaps.length; ++b) + { + String tc = thisCaps[b].trim(); + if (tc.equals(mc)) + found = true; + if (tc.equals("createMBeanServer") && + mc.equals("newMBeanServer")) + found = true; + } + if (!found) + return false; + } + return true; + } + return false; + } + + /** + * Returns a {@link PermissionCollection} which stores + * a series of {@link MBeanServerPermission}s as the union + * of their capabilities. + * + * @return a collection for {@link MBeanServerPermission}s. + */ + public PermissionCollection newPermissionCollection() + { + return new MBeanServerPermissionCollection(); + } + + /** + * A collection of {@link MBeanServerPermission}s, stored + * as a single permission with the union of the capabilities + * as its capabilities. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ + private class MBeanServerPermissionCollection + extends PermissionCollection + { + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = -5661980843569388590L; + + /** + * The collected permission. This is <code>null</code> or + * the union of the permissions held by all the collected + * permissions. + */ + private MBeanServerPermission collectionPermission; + + /** + * Adds a new permission by unifying it with the existing + * collection permission. + * + * @param p the permission to add. + * @throws SecurityException if the collection is read only. + * @see #isReadOnly() + * @see #setReadOnly(boolean) + */ + public void add(Permission p) + { + if (isReadOnly()) + throw new SecurityException("This collection is read only."); + if (p instanceof MBeanServerPermission) + { + MBeanServerPermission msp = (MBeanServerPermission) p; + if (collectionPermission == null) + collectionPermission = msp; + else + { + String finalString = collectionPermission.getName(); + String[] cp = finalString.split(","); + String[] np = msp.getName().split(","); + int createms = finalString.indexOf("createMBeanServer"); + int newms = finalString.indexOf("newMBeanServer"); + for (int a = 0; a < np.length; ++a) + { + boolean found = false; + String nps = np[a].trim(); + for (int b = 0; b < cp.length; ++b) + { + String cps = cp[b].trim(); + if (cps.equals(nps)) + found = true; + if (np.equals("newMBeanServer") + && createms != -1) + found = true; + if (np.equals("createMBeanServer") + && newms != -1) + finalString.replace("newMBeanServer", + "createMBeanServer"); + } + if (!found) + finalString += "," + nps; + } + collectionPermission = + new MBeanServerPermission(finalString); + } + } + } + + /** + * Returns an enumeration over the single permission. + * + * @return an enumeration over the collection permission. + */ + public Enumeration elements() + { + return new + MBeanServerPermissionEnumeration(collectionPermission); + } + + /** + * Provides an enumeration over a comma-separated list + * of capabilities. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ + private class MBeanServerPermissionEnumeration + implements Enumeration + { + + /** + * The collected permission. + */ + private MBeanServerPermission p; + + /** + * True if we have returned the permission. + */ + private boolean done; + + /** + * Constructs a new {@link MBeanServerPermissionEnumeration} + * using the given collected permission. + * + * @param p the collected permission. + */ + public MBeanServerPermissionEnumeration(MBeanServerPermission p) + { + this.p = p; + done = false; + } + + /** + * Returns true if there are more capabilities to return. + * + * @return true if there are more capabilities available. + */ + public boolean hasMoreElements() + { + return !done; + } + + /** + * Returns the next capability. + * + * @return the next capability. + */ + public Object nextElement() + { + if (hasMoreElements()) + { + done = true; + return p; + } + else + throw new NoSuchElementException("No more elements are available."); + } + + } + + /** + * Returns true if the collected {@link MBeanServerPermission} + * implies the given permission. This occurs if the given permission + * is also an {@link MBeanServerPermission} and its target names + * are a subset of the target names of this permission. Note that + * the name <code>createMBeanServer</code> implies + * <code>newMBeanServer</code>. + * + * @param p the permission to check for implication. + * @return true if this permission implies <code>p</code>. + */ + public boolean implies(Permission p) + { + return collectionPermission.implies(p); + } + } + + /** + * Checks the name is valid, including removing + * the <code>newMBeanServer</code> permission when + * <code>createMBeanServer</code> is present. + * + * @param name the name to check. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints. + */ + private static String checkName(String name) + { + if (!(name.equals("*"))) + { + String[] constraints = name.split(","); + name = ""; + boolean seenCreate = false; + boolean seenNew = false; + boolean start = true; + for (int a = 0; a < constraints.length; ++a) + { + String next = constraints[a].trim(); + if (!(next.equals("createMBeanServer") || + next.equals("findMBeanServer") || + next.equals("newMBeanServer") || + next.equals("releaseMBeanServer"))) + throw new IllegalArgumentException("An invalid constraint, " + + next + ", was specified."); + if (next.equals("newMBeanServer")) + seenNew = true; + else if (next.equals("createMBeanServer")) + seenCreate = true; + else + { + if (!start) + name += ","; + name += next; + start = false; + } + } + if (seenNew && !seenCreate) + name += (start ? "" : ",") + "newMBeanServer"; + else if (seenCreate) + name += (start ? "" : ",") + "createMBeanServer"; + } + return name; + } + +} + + + + diff --git a/javax/swing/JEditorPane.java b/javax/swing/JEditorPane.java index ab683c7a5..38b0761f0 100644 --- a/javax/swing/JEditorPane.java +++ b/javax/swing/JEditorPane.java @@ -487,6 +487,34 @@ public class JEditorPane extends JTextComponent } /** + * Used to store a mapping for content-type to editor kit class. + */ + private static class EditorKitMapping + { + /** + * The classname of the editor kit. + */ + String className; + + /** + * The classloader with which the kit is to be loaded. + */ + ClassLoader classLoader; + + /** + * Creates a new EditorKitMapping object. + * + * @param cn the classname + * @param cl the classloader + */ + EditorKitMapping(String cn, ClassLoader cl) + { + className = cn; + classLoader = cl; + } + } + + /** * An EditorKit used for plain text. This is the default editor kit for * JEditorPanes. * @@ -632,9 +660,29 @@ public class JEditorPane extends JTextComponent boolean focus_root; + /** + * Maps content-types to editor kit instances. + */ + static HashMap editorKits; + // A mapping between content types and registered EditorKit types static HashMap registerMap; - + + static + { + registerMap = new HashMap(); + editorKits = new HashMap(); + registerEditorKitForContentType("application/rtf", + "javax.swing.text.rtf.RTFEditorKit"); + registerEditorKitForContentType("text/plain", + "javax.swing.JEditorPane$PlainEditorKit"); + registerEditorKitForContentType("text/html", + "javax.swing.text.html.HTMLEditorKit"); + registerEditorKitForContentType("text/rtf", + "javax.swing.text.rtf.RTFEditorKit"); + + } + // A mapping between content types and used EditorKits HashMap editorMap; @@ -675,15 +723,6 @@ public class JEditorPane extends JTextComponent void init() { editorMap = new HashMap(); - registerMap = new HashMap(); - registerEditorKitForContentType("application/rtf", - "javax.swing.text.rtf.RTFEditorKit"); - registerEditorKitForContentType("text/plain", - "javax.swing.JEditorPane$PlainEditorKit"); - registerEditorKitForContentType("text/html", - "javax.swing.text.html.HTMLEditorKit"); - registerEditorKitForContentType("text/rtf", - "javax.swing.text.rtf.RTFEditorKit"); } protected EditorKit createDefaultEditorKit() @@ -703,23 +742,28 @@ public class JEditorPane extends JTextComponent */ public static EditorKit createEditorKitForContentType(String type) { - // TODO: Have to handle the case where a ClassLoader was specified - // when the EditorKit was registered - EditorKit e = null; - String className = (String) registerMap.get(type); - if (className != null) + // Try cached instance. + EditorKit e = (EditorKit) editorKits.get(type); + if (e == null) { - try - { - // XXX - This should actually depend on the classloader - // registered with the type. See registerEditorKitForContentType. - ClassLoader ldr = ClassLoader.getSystemClassLoader(); - e = (EditorKit) Class.forName(className, true, ldr).newInstance(); - } - catch (Exception e2) - { - // TODO: Not sure what to do here. - } + EditorKitMapping m = (EditorKitMapping) registerMap.get(type); + if (m != null) + { + String className = m.className; + ClassLoader loader = m.classLoader; + try + { + e = (EditorKit) loader.loadClass(className).newInstance(); + } + catch (Exception e2) + { + // The reference implementation returns null when class is not + // loadable or instantiatable. + } + } + // Cache this for later retrieval. + if (e != null) + editorKits.put(type, e); } return e; } @@ -780,7 +824,9 @@ public class JEditorPane extends JTextComponent */ public static String getEditorKitClassNameForContentType(String type) { - return (String) registerMap.get(type); + EditorKitMapping m = (EditorKitMapping) registerMap.get(type); + String kitName = m != null ? m.className : null; + return kitName; } /** @@ -803,10 +849,14 @@ public class JEditorPane extends JTextComponent EditorKit e = (EditorKit) editorMap.get(type); // Then check to see if we can create one. if (e == null) - e = createEditorKitForContentType(type); + { + e = createEditorKitForContentType(type); + if (e != null) + setEditorKitForContentType(type, e); + } // Otherwise default to PlainEditorKit. if (e == null) - e = new PlainEditorKit(); + e = createDefaultEditorKit(); return e; } @@ -962,7 +1012,8 @@ public class JEditorPane extends JTextComponent public static void registerEditorKitForContentType(String type, String classname) { - registerMap.put(type, classname); + registerEditorKitForContentType(type, classname, + Thread.currentThread().getContextClassLoader()); } /** @@ -972,7 +1023,7 @@ public class JEditorPane extends JTextComponent String classname, ClassLoader loader) { - // TODO: Implement this properly. + registerMap.put(type, new EditorKitMapping(classname, loader)); } /** diff --git a/javax/swing/border/CompoundBorder.java b/javax/swing/border/CompoundBorder.java index 2ee639cf9..ba2e745aa 100644 --- a/javax/swing/border/CompoundBorder.java +++ b/javax/swing/border/CompoundBorder.java @@ -115,15 +115,24 @@ public class CompoundBorder extends AbstractBorder */ public boolean isBorderOpaque() { - // While it would be safe to assume true for the opacity of - // a null border, this behavior would not be according to - // the API specification. Also, it is pathological to have - // null borders anyway. - if ((insideBorder == null) || (outsideBorder == null)) - return false; - - return insideBorder.isBorderOpaque() - && outsideBorder.isBorderOpaque(); + // Although the API specification states that this method + // returns true if both the inside and outside borders are non-null + // and opaque, and false otherwise, a mauve test shows that if both + // the inside or outside borders are null, then true is returned. + if ((insideBorder == null) && (outsideBorder == null)) + return true; + + // A mauve test shows that if the inside border has a null value, + // then true is returned if the outside border is opaque; if the + // outside border has a null value, then true is returned if the + // inside border is opaque; else, true is returned if both the + // inside and outside borders are opaque. + if (insideBorder == null) + return outsideBorder.isBorderOpaque(); + else if (outsideBorder == null) + return insideBorder.isBorderOpaque(); + else + return insideBorder.isBorderOpaque() && outsideBorder.isBorderOpaque(); } /** diff --git a/javax/swing/text/GlyphView.java b/javax/swing/text/GlyphView.java index d5070a6a9..1e418d2e0 100644 --- a/javax/swing/text/GlyphView.java +++ b/javax/swing/text/GlyphView.java @@ -38,14 +38,21 @@ exception statement from your version. */ package javax.swing.text; +import gnu.classpath.SystemProperties; + import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.font.TextHitInfo; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; import javax.swing.SwingConstants; import javax.swing.event.DocumentEvent; @@ -248,6 +255,158 @@ public class GlyphView extends View implements TabableView, Cloneable } /** + * A GlyphPainter implementation based on TextLayout. This should give + * better performance in Java2D environments. + */ + private static class J2DGlyphPainter + extends GlyphPainter + { + + /** + * The text layout. + */ + TextLayout textLayout; + + /** + * Creates a new J2DGlyphPainter. + * + * @param str the string + * @param font the font + * @param frc the font render context + */ + J2DGlyphPainter(String str, Font font, FontRenderContext frc) + { + textLayout = new TextLayout(str, font, frc); + } + + /** + * Returns null so that GlyphView.checkPainter() creates a new instance. + */ + public GlyphPainter getPainter(GlyphView v, int p0, int p1) + { + return null; + } + + /** + * Delegates to the text layout. + */ + public float getAscent(GlyphView v) + { + return textLayout.getAscent(); + } + + /** + * Delegates to the text layout. + */ + public int getBoundedPosition(GlyphView v, int p0, float x, float len) + { + int pos; + TextHitInfo hit = textLayout.hitTestChar(len, 0); + if (hit.getCharIndex() == -1 && ! textLayout.isLeftToRight()) + pos = v.getEndOffset(); + else + { + pos = hit.isLeadingEdge() ? hit.getInsertionIndex() + : hit.getInsertionIndex() - 1; + pos += v.getStartOffset(); + } + return pos; + } + + /** + * Delegates to the text layout. + */ + public float getDescent(GlyphView v) + { + return textLayout.getDescent(); + } + + /** + * Delegates to the text layout. + */ + public float getHeight(GlyphView view) + { + return textLayout.getAscent() + textLayout.getDescent() + + textLayout.getLeading(); + } + + /** + * Delegates to the text layout. + */ + public float getSpan(GlyphView v, int p0, int p1, TabExpander te, float x) + { + float span; + if (p0 == v.getStartOffset() && p1 == v.getEndOffset()) + span = textLayout.getAdvance(); + else + { + int start = v.getStartOffset(); + int i0 = p0 - start; + int i1 = p1 - start; + TextHitInfo hit0 = TextHitInfo.afterOffset(i0); + TextHitInfo hit1 = TextHitInfo.afterOffset(i1); + float x0 = textLayout.getCaretInfo(hit0)[0]; + float x1 = textLayout.getCaretInfo(hit1)[0]; + span = Math.abs(x1 - x0); + } + return span; + } + + /** + * Delegates to the text layout. + */ + public Shape modelToView(GlyphView v, int pos, Bias b, Shape a) + throws BadLocationException + { + int offs = pos - v.getStartOffset(); + // Create copy here to protect original shape. + Rectangle2D bounds = a.getBounds2D(); + TextHitInfo hit = + b == Position.Bias.Forward ? TextHitInfo.afterOffset(offs) + : TextHitInfo.beforeOffset(offs); + float[] loc = textLayout.getCaretInfo(hit); + bounds.setRect(bounds.getX() + loc[0], bounds.getY(), 1, + bounds.getHeight()); + return bounds; + } + + /** + * Delegates to the text layout. + */ + public void paint(GlyphView view, Graphics g, Shape a, int p0, int p1) + { + // Can't paint this with plain graphics. + if (g instanceof Graphics2D) + { + Graphics2D g2d = (Graphics2D) g; + Rectangle2D b = a instanceof Rectangle2D ? (Rectangle2D) a + : a.getBounds2D(); + float x = (float) b.getX(); + float y = (float) b.getY() + textLayout.getAscent() + + textLayout.getLeading(); + // TODO: Try if clipping makes things faster for narrow views. + textLayout.draw(g2d, x, y); + } + } + + /** + * Delegates to the text layout. + */ + public int viewToModel(GlyphView v, float x, float y, Shape a, + Bias[] biasRet) + { + Rectangle2D bounds = a instanceof Rectangle2D ? (Rectangle2D) a + : a.getBounds2D(); + TextHitInfo hit = textLayout.hitTestChar(x - (float) bounds.getX(), 0); + int pos = hit.getInsertionIndex(); + biasRet[0] = hit.isLeadingEdge() ? Position.Bias.Forward + : Position.Bias.Backward; + return pos + v.getStartOffset(); + } + + } + + /** * The default <code>GlyphPainter</code> used in <code>GlyphView</code>. */ static class DefaultGlyphPainter extends GlyphPainter @@ -532,7 +691,21 @@ public class GlyphView extends View implements TabableView, Cloneable protected void checkPainter() { if (glyphPainter == null) - glyphPainter = new DefaultGlyphPainter(); + { + if ("true".equals( + SystemProperties.getProperty("gnu.javax.swing.noGraphics2D"))) + { + glyphPainter = new DefaultGlyphPainter(); + } + else + { + Segment s = getText(getStartOffset(), getEndOffset()); + glyphPainter = new J2DGlyphPainter(s.toString(), getFont(), + new FontRenderContext(null, + false, + false)); + } + } } /** diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c index 8d8aefe5d..97eb38618 100644 --- a/native/jni/java-nio/gnu_java_nio_VMChannel.c +++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -372,6 +372,19 @@ Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env, } } +/* Return true if fd is in non-blocking mode. */ +static jboolean +is_non_blocking_fd(jint fd) +{ + int opts; + opts = fcntl(fd, F_GETFL); + if (opts == -1) + { + /* Assume blocking on error. */ + return 0; + } + return (opts & O_NONBLOCK) != 0; +} JNIEXPORT jint JNICALL Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env, @@ -418,8 +431,21 @@ Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env, else if (result == -1) { buf.count = 0; - if (errno == EAGAIN) /* Non-blocking */ - result = 0; + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } else if (errno == EBADF) /* Bad fd */ { JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); @@ -580,8 +606,21 @@ Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env, /* Handle the response */ if (result < 0) { - if (errno == EAGAIN) /* Non blocking */ - result = 0; + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } else if (errno == EBADF) /* Bad fd */ { JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); @@ -943,7 +982,17 @@ Java_gnu_java_nio_VMChannel_read__I (JNIEnv *env, errno = tmp_errno; if (-1 == ret) - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + { + if (errno == EAGAIN && !is_non_blocking_fd(fd)) + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + } + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return -1; + } + if (0 == ret) return -1; @@ -1103,6 +1152,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un if (EINPROGRESS == errno) { fd_set wrfds; + FD_ZERO(&wrfds); FD_SET(fd, &wrfds); ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) @@ -1227,6 +1277,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u if (EINPROGRESS == errno) { fd_set wrfds; + FD_ZERO(&wrfds); FD_SET(fd, &wrfds); ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) diff --git a/tools/Makefile.am b/tools/Makefile.am index 7c666dcd5..8f8ae96fe 100755 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,28 +1,24 @@ ## Input file for automake to generate the Makefile.in used by configure -GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip':$(PATH_TO_ASM) +GLIBJ_BOOTCLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip' +GLIBJ_CLASSPATH=asm # Setup the compiler to use the GNU Classpath library we just build if FOUND_GCJX -JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):. +JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath $(GLIBJ_BOOTCLASSPATH) -sourcepath '' -classpath $(GLIBJ_CLASSPATH):. else if FOUND_ECJ -JCOMPILER = $(ECJ) -1.5 -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath . +JCOMPILER = $(ECJ) -1.5 -encoding UTF-8 -bootclasspath $(GLIBJ_BOOTCLASSPATH) -classpath .:$(GLIBJ_CLASSPATH) else error dunno how to setup the JCOMPILER and compile endif endif -if USE_ASM -javah = gjavah -rmic = grmic -endif - if CREATE_WRAPPERS bin_SCRIPTS = bin_PROGRAMS = gappletviewer gjarsigner gkeytool \ - gjar gnative2ascii gserialver $(javah) grmiregistry \ - gtnameserv gorbd grmid $(rmic) + gjar gnative2ascii gserialver gjavah grmiregistry \ + gtnameserv gorbd grmid grmic AM_CPPFLAGS = -Wall \ @@ -33,81 +29,67 @@ AM_CPPFLAGS = -Wall \ gappletviewer_SOURCES = toolwrapper.c gappletviewer_CFLAGS = \ -DTOOLPACKAGE="\"appletviewer\"" \ - -DTOOLNAME="\"gappletviewer\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gappletviewer\"" gjarsigner_SOURCES = toolwrapper.c gjarsigner_CFLAGS = \ -DTOOLPACKAGE="\"jarsigner\"" \ - -DTOOLNAME="\"gjarsigner\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gjarsigner\"" gkeytool_SOURCES = toolwrapper.c gkeytool_CFLAGS = \ -DTOOLPACKAGE="\"keytool\"" \ - -DTOOLNAME="\"gkeytool\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gkeytool\"" gjar_SOURCES = toolwrapper.c gjar_CFLAGS = \ -DTOOLPACKAGE="\"jar\"" \ - -DTOOLNAME="\"gjar\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gjar\"" gnative2ascii_SOURCES = toolwrapper.c gnative2ascii_CFLAGS = \ -DTOOLPACKAGE="\"native2ascii\"" \ - -DTOOLNAME="\"gnative2ascii\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gnative2ascii\"" gserialver_SOURCES = toolwrapper.c gserialver_CFLAGS = \ -DTOOLPACKAGE="\"serialver\"" \ - -DTOOLNAME="\"gserialver\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gserialver\"" grmiregistry_SOURCES = toolwrapper.c grmiregistry_CFLAGS = \ -DTOOLPACKAGE="\"rmiregistry\"" \ - -DTOOLNAME="\"grmiregistry\"" \ - -DASM_JAR="" + -DTOOLNAME="\"grmiregistry\"" gtnameserv_SOURCES = toolwrapper.c gtnameserv_CFLAGS = \ -DTOOLPACKAGE="\"tnameserv\"" \ - -DTOOLNAME="\"gtnameserv\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gtnameserv\"" gorbd_SOURCES = toolwrapper.c gorbd_CFLAGS = \ -DTOOLPACKAGE="\"orbd\"" \ - -DTOOLNAME="\"gorbd\"" \ - -DASM_JAR="" + -DTOOLNAME="\"gorbd\"" grmid_SOURCES = toolwrapper.c grmid_CFLAGS = \ -DTOOLPACKAGE="\"rmid\"" \ - -DTOOLNAME="\"grmid\"" \ - -DASM_JAR="" + -DTOOLNAME="\"grmid\"" -if USE_ASM gjavah_SOURCES = toolwrapper.c gjavah_CFLAGS = \ -DTOOLPACKAGE="\"javah\"" \ - -DTOOLNAME="\"gjavah\"" \ - -DASM_JAR="\":$(PATH_TO_ASM)\"" + -DTOOLNAME="\"gjavah\"" grmic_SOURCES = toolwrapper.c grmic_CFLAGS = \ -DTOOLPACKAGE="\"rmic\"" \ - -DTOOLNAME="\"grmic\"" \ - -DASM_JAR="\":$(PATH_TO_ASM)\"" -endif + -DTOOLNAME="\"grmic\"" else bin_SCRIPTS = gappletviewer gjarsigner gkeytool \ - gjar gnative2ascii gserialver $(javah) grmiregistry \ - gtnameserv gorbd grmid $(rmic) + gjar gnative2ascii gserialver gjavah grmiregistry \ + gtnameserv gorbd grmid grmic bin_PROGRAMS = endif EXTRA_DIST = toolwrapper.c gappletviewer.in gjarsigner.in gkeytool.in \ @@ -115,7 +97,17 @@ EXTRA_DIST = toolwrapper.c gappletviewer.in gjarsigner.in gkeytool.in \ gtnameserv.in gorbd.in grmid.in grmic.in # All our example java source files -TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*/*.java +TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/attrs/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/commons/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/optimizer/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/signature/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/tree/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/tree/analysis/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/util/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/util/attrs/*.java \ + $(srcdir)/external/asm/org/objectweb/asm/xml/*.java # The zip files with classes we want to produce. TOOLS_ZIP = tools.zip @@ -154,40 +146,37 @@ dist-hook: # immediately. And copy the template files we use to the classes dir # so they get also included. $(TOOLS_ZIP): $(TOOLS_JAVA_FILES) - mkdir -p classes/gnu/classpath/tools/appletviewer - mkdir -p classes/gnu/classpath/tools/common - mkdir -p classes/gnu/classpath/tools/getopt - mkdir -p classes/gnu/classpath/tools/jar - mkdir -p classes/gnu/classpath/tools/jarsigner - mkdir -p classes/gnu/classpath/tools/keytool - mkdir -p classes/gnu/classpath/tools/native2ascii - mkdir -p classes/gnu/classpath/tools/orbd - mkdir -p classes/gnu/classpath/tools/rmid - mkdir -p classes/gnu/classpath/tools/rmiregistry - mkdir -p classes/gnu/classpath/tools/serialver - mkdir -p classes/gnu/classpath/tools/tnameserv + @rm -rf classes asm + mkdir classes asm +## Compile ASM separately as it is latin-1 encoded. + find $(srcdir)/external/asm -name '*.java' -print > asm.lst + AC=`echo $(JCOMPILER) | sed -e 's/UTF-8/ISO-8859-1/g'`; \ + $$AC -d asm @asm.lst find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst - if test -z "$(PATH_TO_ASM)"; then \ - mv classes.lst classes.tmp; \ - fgrep -v /javah/ classes.tmp > classes.lst; \ - mv classes.lst classes.tmp; \ - fgrep -v /rmic/ classes.tmp > classes.lst; \ - rm -f classes.tmp;\ - else \ - mkdir -p classes/gnu/classpath/tools/javah; \ - mkdir -p classes/gnu/classpath/tools/rmic/templates; \ - cp $(RMIC_TEMPLATES) classes/gnu/classpath/tools/rmic/templates; \ - fi $(JCOMPILER) -d classes @classes.lst +## Copy over tools resource files. + @list=`cd $(top_srcdir)/resource && find gnu/classpath/tools -name \*.properties -print`; \ + for p in $$list; do \ + dirname=classes/`dirname $$p`; \ + if ! test -d "$$dirname"; then mkdir -p "$$dirname"; fi; \ + echo " cp $(top_srcdir)/resource/$$p classes/$$p"; \ + cp $(top_srcdir)/resource/$$p classes/$$p; \ + done +## First add classpath tools stuff. (cd classes; \ if test "$(ZIP)" != ""; then $(ZIP) -r ../$(TOOLS_ZIP) .; fi; \ if test "$(FASTJAR)" != ""; then $(FASTJAR) cf ../$(TOOLS_ZIP) .; fi; \ cd ..) +## Now add ASM classes. + (cd asm; \ + if test "$(ZIP)" != ""; then $(ZIP) -u -r ../$(TOOLS_ZIP) .; fi; \ + if test "$(FASTJAR)" != ""; then $(FASTJAR) uf ../$(TOOLS_ZIP) .; fi; \ + cd ..) rm -rf classes classes.lst # Zip file be gone! (and make sure the classes are gone too) clean-local: - rm -rf $(TOOLS_ZIP) classes + rm -rf $(TOOLS_ZIP) classes asm asm.lst # FIXME: remove this when GNU Classpath includes a bootstrap VM. installcheck-binSCRIPTS: diff --git a/tools/gjavah.in b/tools/gjavah.in index 0505bdbc2..3140e21e4 100644 --- a/tools/gjavah.in +++ b/tools/gjavah.in @@ -42,6 +42,6 @@ prefix=@prefix@ tools_dir=@datadir@/@PACKAGE@ -tools_cp=${tools_dir}/tools.zip:@PATH_TO_ASM@ +tools_cp=${tools_dir}/tools.zip exec @VM_BINARY@ -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.javah.Main "$@" diff --git a/tools/grmic.in b/tools/grmic.in index 2bb29a721..eabce0e49 100644 --- a/tools/grmic.in +++ b/tools/grmic.in @@ -42,6 +42,6 @@ prefix=@prefix@ tools_dir=@datadir@/@PACKAGE@ -tools_cp=${tools_dir}/tools.zip:@PATH_TO_ASM@ +tools_cp=${tools_dir}/tools.zip exec @VM_BINARY@ -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.rmic.Main "$@" diff --git a/tools/toolwrapper.c b/tools/toolwrapper.c index dd23286c3..41c07c690 100644 --- a/tools/toolwrapper.c +++ b/tools/toolwrapper.c @@ -136,7 +136,7 @@ main (int argc, const char** argv) goto destroy; } - vm_args.options[vm_args.nOptions++].optionString = "-Xbootclasspath/p:" TOOLS_ZIP ASM_JAR; + vm_args.options[vm_args.nOptions++].optionString = "-Xbootclasspath/p:" TOOLS_ZIP; } /* Terminate vm_args.options with a NULL element. */ |