Mercurial > hg > openjdk > jdk8u > jdk
changeset 9896:4797cd0713b4 jdk8u40-b02
Merge
author | lana |
---|---|
date | Thu, 14 Aug 2014 13:24:00 -0700 |
parents | 3dc5f41da93c (current diff) c20f9b278918 (diff) |
children | c67acfb24eed d80f14df009d |
files | src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java src/solaris/classes/java/lang/UNIXProcess.java.aix src/solaris/classes/java/lang/UNIXProcess.java.bsd src/solaris/classes/java/lang/UNIXProcess.java.linux src/solaris/classes/java/lang/UNIXProcess.java.solaris |
diffstat | 78 files changed, 2724 insertions(+), 2309 deletions(-) [+] |
line wrap: on
line diff
--- a/make/gensrc/GensrcMisc.gmk Wed Aug 13 14:49:53 2014 -0700 +++ b/make/gensrc/GensrcMisc.gmk Thu Aug 14 13:24:00 2014 -0700 @@ -62,25 +62,6 @@ ########################################################################################## -ifeq ($(OPENJDK_TARGET_OS_API), posix) - UPSUFFIX := $(OPENJDK_TARGET_OS) - ifeq ($(OPENJDK_TARGET_OS), macosx) - UPSUFFIX := bsd - endif - # UNIXProcess.java is different for solaris and linux. We need to copy - # the correct UNIXProcess.java over to $(JDK_OUTPUTDIR)/gensrc/java/lang/. - - $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java: \ - $(JDK_TOPDIR)/src/solaris/classes/java/lang/UNIXProcess.java.$(UPSUFFIX) - $(ECHO) $(LOG_INFO) Copying UNIXProcess.java.$(OPENJDK_TARGET_OS) to java/lang/UNIXProcess.java - $(call install-file) - $(CHMOD) u+rw $@ - - GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java -endif - -########################################################################################## - GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/nio/ch/SocketOptionRegistry.java GENSRC_SOR_SRC := $(JDK_TOPDIR)/src/share/native/sun/nio/ch
--- a/src/macosx/classes/com/apple/laf/AquaImageFactory.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaImageFactory.java Thu Aug 14 13:24:00 2014 -0700 @@ -46,10 +46,8 @@ import com.apple.laf.AquaIcon.SystemIcon; import com.apple.laf.AquaUtils.RecyclableObject; import com.apple.laf.AquaUtils.RecyclableSingleton; -import java.util.Arrays; -import java.util.List; -import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.MultiResolutionImage; +import sun.awt.image.MultiResolutionCachedImage; public class AquaImageFactory { public static IconUIResource getConfirmImageIcon() { @@ -107,9 +105,9 @@ private static final int kAlertIconSize = 64; static IconUIResource getAppIconCompositedOn(final Image background) { - if (background instanceof MultiResolutionBufferedImage) { + if (background instanceof MultiResolutionCachedImage) { int width = background.getWidth(null); - Image mrIconImage = ((MultiResolutionBufferedImage) background).map( + Image mrIconImage = ((MultiResolutionCachedImage) background).map( rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width)); return new IconUIResource(new ImageIcon(mrIconImage)); } @@ -287,21 +285,7 @@ private static Image getNSIcon(String imageName) { Image icon = Toolkit.getDefaultToolkit() .getImage("NSImage://" + imageName); - - if (icon instanceof MultiResolutionImage) { - return icon; - } - - int w = icon.getWidth(null); - int h = icon.getHeight(null); - - Dimension[] sizes = new Dimension[]{ - new Dimension(w, h), new Dimension(2 * w, 2 * h) - }; - - return new MultiResolutionBufferedImage(icon, sizes, (width, height) -> - AquaUtils.getCImageCreator().createImageFromName( - imageName, width, height)); + return icon; } public static class NineSliceMetrics {
--- a/src/macosx/classes/com/apple/laf/AquaMenuBarUI.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaMenuBarUI.java Thu Aug 14 13:24:00 2014 -0700 @@ -26,11 +26,14 @@ package com.apple.laf; import java.awt.*; +import java.security.AccessController; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicMenuBarUI; +import sun.lwawt.macosx.LWCToolkit; +import sun.security.action.GetBooleanAction; import sun.security.action.GetPropertyAction; // MenuBar implementation for Mac L&F @@ -131,28 +134,20 @@ ScreenMenuBar fScreenMenuBar; boolean useScreenMenuBar = getScreenMenuBarProperty(); - private static String getPrivSysProp(final String propName) { - return java.security.AccessController.doPrivileged(new GetPropertyAction(propName)); - } - static boolean getScreenMenuBarProperty() { - final String props[] = new String[]{""}; - - boolean useScreenMenuBar = false; - try { - props[0] = getPrivSysProp(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); - - if (props[0] != null && props[0].equals("true")) useScreenMenuBar = true; - else { - props[0] = getPrivSysProp(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"); - - if (props[0] != null && props[0].equals("true")) { - System.err.println(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar has been deprecated. Please switch to " + AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); - useScreenMenuBar = true; - } - } - } catch(final Throwable t) { }; - - return useScreenMenuBar; + // Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit + if (LWCToolkit.isEmbedded()) return false; + if (AccessController.doPrivileged( + new GetBooleanAction(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"))) { + return true; + } + if (AccessController.doPrivileged( + new GetBooleanAction(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"))) { + System.err.println(AquaLookAndFeel.sOldPropertyPrefix + + "useScreenMenuBar has been deprecated. Please switch to " + + AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); + return true; + } + return false; } }
--- a/src/macosx/classes/com/apple/laf/AquaPainter.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaPainter.java Thu Aug 14 13:24:00 2014 -0700 @@ -174,11 +174,7 @@ bounds, controlState); Image img = cache.getImage(key); if (img == null) { - - Image baseImage = createImage(imgX, imgY, imgW, imgH, bounds, - control, controlState); - - img = new MultiResolutionBufferedImage(baseImage, + img = new MultiResolutionCachedImage(imgW, imgH, (rvWidth, rvHeight) -> createImage(imgX, imgY, rvWidth, rvHeight, bounds, control, controlState));
--- a/src/macosx/classes/com/apple/laf/AquaUtils.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaUtils.java Thu Aug 14 13:24:00 2014 -0700 @@ -48,7 +48,7 @@ import sun.swing.SwingUtilities2; import com.apple.laf.AquaImageFactory.SlicedImageControl; -import sun.awt.image.MultiResolutionBufferedImage; +import sun.awt.image.MultiResolutionCachedImage; final class AquaUtils { @@ -124,8 +124,8 @@ static Image generateLightenedImage(final Image image, final int percent) { final GrayFilter filter = new GrayFilter(true, percent); - return (image instanceof MultiResolutionBufferedImage) - ? ((MultiResolutionBufferedImage) image).map( + return (image instanceof MultiResolutionCachedImage) + ? ((MultiResolutionCachedImage) image).map( rv -> generateLightenedImage(rv, filter)) : generateLightenedImage(image, filter); }
--- a/src/macosx/classes/sun/font/CFontManager.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/sun/font/CFontManager.java Thu Aug 14 13:24:00 2014 -0700 @@ -43,7 +43,7 @@ import sun.misc.ThreadGroupUtils; import sun.lwawt.macosx.*; -public class CFontManager extends SunFontManager { +public final class CFontManager extends SunFontManager { private FontConfigManager fcManager = null; private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>(); @@ -61,20 +61,14 @@ return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts); } - private static String[] defaultPlatformFont = null; - /* * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. */ @Override - public synchronized String[] getDefaultPlatformFont() { - if (defaultPlatformFont == null) { - defaultPlatformFont = new String[2]; - defaultPlatformFont[0] = "Lucida Grande"; - defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc"; - } - return defaultPlatformFont; + protected String[] getDefaultPlatformFont() { + return new String[]{"Lucida Grande", + "/System/Library/Fonts/LucidaGrande.ttc"}; } // This is a way to register any kind of Font2D, not just files and composites.
--- a/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Thu Aug 14 13:24:00 2014 -0700 @@ -94,10 +94,12 @@ @Override public void addDropTarget(DropTarget dt) { + getLwTarget().addDropTarget(dt); } @Override public void removeDropTarget(DropTarget dt) { + getLwTarget().removeDropTarget(dt); } @Override
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java Thu Aug 14 13:24:00 2014 -0700 @@ -105,6 +105,8 @@ private final SecurityWarningWindow warningWindow; + private volatile boolean targetFocusable; + /** * Current modal blocker or null. * @@ -240,13 +242,12 @@ if (!visible && warningWindow != null) { warningWindow.setVisible(false, false); } - + updateFocusableWindowState(); super.setVisibleImpl(visible); // TODO: update graphicsConfig, see 4868278 platformWindow.setVisible(visible); if (isSimpleWindow()) { KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); - if (visible) { if (!getTarget().isAutoRequestFocus()) { return; @@ -397,6 +398,7 @@ @Override public void updateFocusableWindowState() { + targetFocusable = getTarget().isFocusableWindow(); platformWindow.updateFocusableWindowState(); } @@ -1220,13 +1222,13 @@ } private boolean isFocusableWindow() { - boolean focusable = getTarget().isFocusableWindow(); + boolean focusable = targetFocusable; if (isSimpleWindow()) { LWWindowPeer ownerPeer = getOwnerFrameDialog(this); if (ownerPeer == null) { return false; } - return focusable && ownerPeer.getTarget().isFocusableWindow(); + return focusable && ownerPeer.targetFocusable; } return focusable; }
--- a/src/macosx/classes/sun/lwawt/macosx/CImage.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/CImage.java Thu Aug 14 13:24:00 2014 -0700 @@ -32,7 +32,7 @@ import java.util.Arrays; import java.util.List; import sun.awt.image.MultiResolutionImage; -import sun.awt.image.MultiResolutionBufferedImage; +import sun.awt.image.MultiResolutionCachedImage; import sun.awt.image.SunWritableRaster; @@ -60,41 +60,41 @@ // This is used to create a CImage with an NSImage pointer. It MUST be a CFRetained // NSImage, and the CImage takes ownership of the non-GC retain. If callers need the // NSImage themselves, they MUST call retain on the NSImage themselves. - public BufferedImage createImageUsingNativeSize(final long image) { + public Image createImageUsingNativeSize(final long image) { if (image == 0) return null; final Dimension2D size = nativeGetNSImageSize(image); - return createBufferedImage(image, size.getWidth(), size.getHeight()); + return createImage(image, size.getWidth(), size.getHeight()); } // the width and height passed in as a parameter could differ than the width and the height of the NSImage (image), in that case, the image will be scaled - BufferedImage createBufferedImage(long image, double width, double height) { + Image createImage(long image, double width, double height) { if (image == 0) throw new Error("Unable to instantiate CImage with null native image reference."); return createImageWithSize(image, width, height); } - public BufferedImage createImageWithSize(final long image, final double width, final double height) { + public Image createImageWithSize(final long image, final double width, final double height) { final CImage img = new CImage(image); img.resize(width, height); return img.toImage(); } // This is used to create a CImage that represents the icon of the given file. - public BufferedImage createImageOfFile(final String file, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height); + public Image createImageOfFile(final String file, final int width, final int height) { + return createImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height); } - public BufferedImage createImageFromFile(final String file, final double width, final double height) { + public Image createImageFromFile(final String file, final double width, final double height) { final long image = nativeCreateNSImageFromFileContents(file); nativeSetNSImageSize(image, width, height); - return createBufferedImage(image, width, height); + return createImage(image, width, height); } - public BufferedImage createSystemImageFromSelector(final String iconSelector, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height); + public Image createSystemImageFromSelector(final String iconSelector, final int width, final int height) { + return createImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height); } public Image createImageFromName(final String name, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageFromImageName(name), width, height); + return createImage(nativeCreateNSImageFromImageName(name), width, height); } public Image createImageFromName(final String name) { @@ -213,7 +213,7 @@ } /** @return A MultiResolution image created from nsImagePtr, or null. */ - private BufferedImage toImage() { + private Image toImage() { if (ptr == 0) return null; final Dimension2D size = nativeGetNSImageSize(ptr); @@ -224,11 +224,11 @@ = nativeGetNSImageRepresentationSizes(ptr, size.getWidth(), size.getHeight()); - BufferedImage baseImage = toImage(w, h, w, h); - - return sizes == null || sizes.length < 2 ? baseImage - : new MultiResolutionBufferedImage(baseImage, sizes, - (width, height) -> toImage(w, h, width, height)); + return sizes == null || sizes.length < 2 ? + new MultiResolutionCachedImage(w, h, (width, height) + -> toImage(w, h, width, height)) + : new MultiResolutionCachedImage(w, h, sizes, (width, height) + -> toImage(w, h, width, height)); } private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Aug 14 13:24:00 2014 -0700 @@ -686,6 +686,11 @@ @Override public DragSourceContextPeer createDragSourceContextPeer( DragGestureEvent dge) throws InvalidDnDOperationException { + final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); + if (f != null) { + return f.createDragSourceContextPeer(dge); + } + return CDragSourceContextPeer.createDragSourceContextPeer(dge); } @@ -693,6 +698,11 @@ public <T extends DragGestureRecognizer> T createDragGestureRecognizer( Class<T> abstractRecognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl) { + final LightweightFrame f = SunToolkit.getLightweightFrame(c); + if (f != null) { + return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl); + } + DragGestureRecognizer dgr = null; // Create a new mouse drag gesture recognizer if we have a class match: @@ -784,6 +794,13 @@ */ native boolean isApplicationActive(); + /** + * Returns true if AWT toolkit is embedded, false otherwise. + * + * @return true if AWT toolkit is embedded, false otherwise + */ + public static native boolean isEmbedded(); + /************************ * Native methods section ************************/
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m Thu Aug 14 13:24:00 2014 -0700 @@ -1122,7 +1122,10 @@ JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; + NSWindow* hostWindow = [[self->fView window] retain]; jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + [hostWindow release]; + if (focused != NULL) { if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
--- a/src/macosx/native/sun/awt/LWCToolkit.m Wed Aug 13 14:49:53 2014 -0700 +++ b/src/macosx/native/sun/awt/LWCToolkit.m Thu Aug 14 13:24:00 2014 -0700 @@ -452,3 +452,14 @@ } +/* + * Class: sun_lwawt_macosx_LWCToolkit + * Method: isEmbedded + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_sun_lwawt_macosx_LWCToolkit_isEmbedded +(JNIEnv *env, jclass klass) { + return [ThreadUtilities isAWTEmbedded] ? JNI_TRUE : JNI_FALSE; +} +
--- a/src/share/classes/java/awt/EventQueue.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/java/awt/EventQueue.java Thu Aug 14 13:24:00 2014 -0700 @@ -214,6 +214,11 @@ FwDispatcher dispatcher) { eventQueue.setFwDispatcher(dispatcher); } + + @Override + public long getMostRecentEventTime(EventQueue eventQueue) { + return eventQueue.getMostRecentEventTimeImpl(); + } }); }
--- a/src/share/classes/java/awt/event/InputMethodEvent.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/java/awt/event/InputMethodEvent.java Thu Aug 14 13:24:00 2014 -0700 @@ -25,6 +25,10 @@ package java.awt.event; +import sun.awt.AWTAccessor; +import sun.awt.AppContext; +import sun.awt.SunToolkit; + import java.awt.AWTEvent; import java.awt.Component; import java.awt.EventQueue; @@ -217,8 +221,10 @@ public InputMethodEvent(Component source, int id, AttributedCharacterIterator text, int committedCharacterCount, TextHitInfo caret, TextHitInfo visiblePosition) { - this(source, id, EventQueue.getMostRecentEventTime(), text, - committedCharacterCount, caret, visiblePosition); + this(source, id, + getMostRecentEventTimeForSource(source), + text, committedCharacterCount, + caret, visiblePosition); } /** @@ -258,8 +264,9 @@ */ public InputMethodEvent(Component source, int id, TextHitInfo caret, TextHitInfo visiblePosition) { - this(source, id, EventQueue.getMostRecentEventTime(), null, - 0, caret, visiblePosition); + this(source, id, + getMostRecentEventTimeForSource(source), + null, 0, caret, visiblePosition); } /** @@ -410,7 +417,25 @@ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); if (when == 0) { - when = EventQueue.getMostRecentEventTime(); + when = getMostRecentEventTimeForSource(this.source); } } + + /** + * Get the most recent event time in the {@code EventQueue} which the {@code source} + * belongs to. + * + * @param source the source of the event + * @exception IllegalArgumentException if source is null. + * @return most recent event time in the {@code EventQueue} + */ + private static long getMostRecentEventTimeForSource(Object source) { + if (source == null) { + // throw the IllegalArgumentException to conform to EventObject spec + throw new IllegalArgumentException("null source"); + } + AppContext appContext = SunToolkit.targetToAppContext(source); + EventQueue eventQueue = SunToolkit.getSystemEventQueueImplPP(appContext); + return AWTAccessor.getEventQueueAccessor().getMostRecentEventTime(eventQueue); + } }
--- a/src/share/classes/java/time/chrono/JapaneseEra.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/java/time/chrono/JapaneseEra.java Thu Aug 14 13:24:00 2014 -0700 @@ -127,7 +127,7 @@ // the number of defined JapaneseEra constants. // There could be an extra era defined in its configuration. - private static final int N_ERA_CONSTANTS = HEISEI.getValue() + ERA_OFFSET + 1; + private static final int N_ERA_CONSTANTS = HEISEI.getValue() + ERA_OFFSET; /** * Serialization version. @@ -148,7 +148,7 @@ for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) { CalendarDate date = ERA_CONFIG[i].getSinceDate(); LocalDate isoDate = LocalDate.of(date.getYear(), date.getMonth(), date.getDayOfMonth()); - KNOWN_ERAS[i] = new JapaneseEra(i - ERA_OFFSET, isoDate); + KNOWN_ERAS[i] = new JapaneseEra(i - ERA_OFFSET + 1, isoDate); } }; @@ -195,7 +195,7 @@ * @throws DateTimeException if the value is invalid */ public static JapaneseEra of(int japaneseEra) { - if (japaneseEra < MEIJI.eraValue || japaneseEra + ERA_OFFSET - 1 >= KNOWN_ERAS.length) { + if (japaneseEra < MEIJI.eraValue || japaneseEra + ERA_OFFSET > KNOWN_ERAS.length) { throw new DateTimeException("Invalid era: " + japaneseEra); } return KNOWN_ERAS[ordinal(japaneseEra)];
--- a/src/share/classes/java/util/Collections.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/java/util/Collections.java Thu Aug 14 13:24:00 2014 -0700 @@ -2342,7 +2342,7 @@ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { synchronized (mutex) { - return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive)); + return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex); } } } @@ -3486,6 +3486,7 @@ */ @Override public void replaceAll(UnaryOperator<E> operator) { + Objects.requireNonNull(operator); list.replaceAll(e -> typeCheck(operator.apply(e))); }
--- a/src/share/classes/java/util/TimeZone.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/java/util/TimeZone.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -591,8 +591,7 @@ /** * Gets the platform defined TimeZone ID. **/ - private static native String getSystemTimeZoneID(String javaHome, - String country); + private static native String getSystemTimeZoneID(String javaHome); /** * Gets the custom time zone ID based on the GMT offset of the @@ -650,12 +649,10 @@ // if the time zone ID is not set (yet), perform the // platform to Java time zone ID mapping. if (zoneID == null || zoneID.isEmpty()) { - String country = AccessController.doPrivileged( - new GetPropertyAction("user.country")); String javaHome = AccessController.doPrivileged( new GetPropertyAction("java.home")); try { - zoneID = getSystemTimeZoneID(javaHome, country); + zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { zoneID = GMT_ID; }
--- a/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java Thu Aug 14 13:24:00 2014 -0700 @@ -30,6 +30,11 @@ import java.util.*; import java.awt.FocusTraversalPolicy; import sun.util.logging.PlatformLogger; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import sun.security.action.GetPropertyAction; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * A FocusTraversalPolicy that determines traversal order by sorting the @@ -89,6 +94,34 @@ final private int FORWARD_TRAVERSAL = 0; final private int BACKWARD_TRAVERSAL = 1; + /* + * When true (by default), the legacy merge-sort algo is used to sort an FTP cycle. + * When false, the default (tim-sort) algo is used, which may lead to an exception. + * See: JDK-8048887 + */ + private static final boolean legacySortingFTPEnabled; + private static final Method legacyMergeSortMethod; + + static { + legacySortingFTPEnabled = "true".equals(AccessController.doPrivileged( + new GetPropertyAction("swing.legacySortingFTPEnabled", "true"))); + legacyMergeSortMethod = legacySortingFTPEnabled ? + AccessController.doPrivileged(new PrivilegedAction<Method>() { + public Method run() { + try { + Class c = Class.forName("java.util.Arrays"); + Method m = c.getDeclaredMethod("legacyMergeSort", new Class[]{Object[].class, Comparator.class}); + m.setAccessible(true); + return m; + } catch (ClassNotFoundException | NoSuchMethodException e) { + // using default sorting algo + return null; + } + } + }) : + null; + } + /** * Constructs a SortingFocusTraversalPolicy without a Comparator. * Subclasses must set the Comparator using <code>setComparator</code> @@ -133,10 +166,32 @@ private void enumerateAndSortCycle(Container focusCycleRoot, List<Component> cycle) { if (focusCycleRoot.isShowing()) { enumerateCycle(focusCycleRoot, cycle); - Collections.sort(cycle, comparator); + if (!legacySortingFTPEnabled || + !legacySort(cycle, comparator)) + { + Collections.sort(cycle, comparator); + } } } + private boolean legacySort(List<Component> l, Comparator<? super Component> c) { + if (legacyMergeSortMethod == null) + return false; + + Object[] a = l.toArray(); + try { + legacyMergeSortMethod.invoke(null, a, c); + } catch (IllegalAccessException | InvocationTargetException e) { + return false; + } + ListIterator<Component> i = l.listIterator(); + for (Object e : a) { + i.next(); + i.set((Component)e); + } + return true; + } + private void enumerateCycle(Container container, List<Component> cycle) { if (!(container.isVisible() && container.isDisplayable())) { return;
--- a/src/share/classes/sun/awt/AWTAccessor.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/awt/AWTAccessor.java Thu Aug 14 13:24:00 2014 -0700 @@ -504,7 +504,12 @@ /** * Sets the delegate for the EventQueue used by FX/AWT single threaded mode */ - public void setFwDispatcher(EventQueue eventQueue, FwDispatcher dispatcher); + void setFwDispatcher(EventQueue eventQueue, FwDispatcher dispatcher); + + /** + * Gets most recent event time in the EventQueue + */ + long getMostRecentEventTime(EventQueue eventQueue); } /*
--- a/src/share/classes/sun/awt/LightweightFrame.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/awt/LightweightFrame.java Thu Aug 14 13:24:00 2014 -0700 @@ -25,6 +25,7 @@ package sun.awt; +import java.awt.Component; import java.awt.Container; import java.awt.Frame; import java.awt.Graphics; @@ -33,6 +34,13 @@ import java.awt.MenuComponent; import java.awt.Rectangle; import java.awt.Toolkit; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DropTarget; +import java.awt.dnd.InvalidDnDOperationException; +import java.awt.dnd.peer.DragSourceContextPeer; import java.awt.peer.FramePeer; /** @@ -169,4 +177,27 @@ hostW = w; hostH = h; } + + /** + * Create a drag gesture recognizer for the lightweight frame. + */ + public abstract <T extends DragGestureRecognizer> T createDragGestureRecognizer( + Class<T> abstractRecognizerClass, + DragSource ds, Component c, int srcActions, + DragGestureListener dgl); + + /** + * Create a drag source context peer for the lightweight frame. + */ + public abstract DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException; + + /** + * Adds a drop target to the lightweight frame. + */ + public abstract void addDropTarget(DropTarget dt); + + /** + * Removes a drop target from the lightweight frame. + */ + public abstract void removeDropTarget(DropTarget dt); }
--- a/src/share/classes/sun/awt/SunToolkit.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/awt/SunToolkit.java Thu Aug 14 13:24:00 2014 -0700 @@ -2055,6 +2055,19 @@ return isInstanceOf(cls.getSuperclass(), type); } + protected static LightweightFrame getLightweightFrame(Component c) { + for (; c != null; c = c.getParent()) { + if (c instanceof LightweightFrame) { + return (LightweightFrame)c; + } + if (c instanceof Window) { + // Don't traverse owner windows + return null; + } + } + return null; + } + /////////////////////////////////////////////////////////////////////////// // // The following methods help set and identify whether a particular
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/awt/image/AbstractMultiResolutionImage.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.awt.image; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.*; + +/** + * This class provides default implementations for the + * <code>MultiResolutionImage</code> interface. The developer needs only + * to subclass this abstract class and define the <code>getResolutionVariant</code>, + * <code>getResolutionVariants</code>, and <code>getBaseImage</code> methods. + * + * + * For example, + * {@code + * public class CustomMultiResolutionImage extends AbstractMultiResolutionImage { + * + * int baseImageIndex; + * Image[] resolutionVariants; + * + * public CustomMultiResolutionImage(int baseImageIndex, + * Image... resolutionVariants) { + * this.baseImageIndex = baseImageIndex; + * this.resolutionVariants = resolutionVariants; + * } + * + * @Override + * public Image getResolutionVariant(float logicalDPIX, float logicalDPIY, + * float baseImageWidth, float baseImageHeight, + * float destImageWidth, float destImageHeight) { + * // return a resolution variant based on the given logical DPI, + * // base image size, or destination image size + * } + * + * @Override + * public List<Image> getResolutionVariants() { + * return Arrays.asList(resolutionVariants); + * } + * + * protected Image getBaseImage() { + * return resolutionVariants[baseImageIndex]; + * } + * } + * } + * + * @see java.awt.Image + * @see java.awt.image.MultiResolutionImage + * + */ +public abstract class AbstractMultiResolutionImage extends java.awt.Image + implements MultiResolutionImage { + + /** + * @inheritDoc + */ + @Override + public int getWidth(ImageObserver observer) { + return getBaseImage().getWidth(null); + } + + /** + * @inheritDoc + */ + @Override + public int getHeight(ImageObserver observer) { + return getBaseImage().getHeight(null); + } + + /** + * @inheritDoc + */ + @Override + public ImageProducer getSource() { + return getBaseImage().getSource(); + } + + /** + * @inheritDoc + */ + @Override + public Graphics getGraphics() { + return getBaseImage().getGraphics(); + + } + + /** + * @inheritDoc + */ + @Override + public Object getProperty(String name, ImageObserver observer) { + return getBaseImage().getProperty(name, observer); + } + + /** + * @return base image + */ + protected abstract Image getBaseImage(); +}
--- a/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java Wed Aug 13 14:49:53 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package sun.awt.image; - -import java.awt.Dimension; -import java.awt.Image; -import java.awt.Graphics; -import java.awt.geom.Dimension2D; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -public class MultiResolutionBufferedImage extends BufferedImage - implements MultiResolutionImage { - - private final BiFunction<Integer, Integer, Image> mapper; - private final Dimension2D[] sizes; - private int availableInfo; - - public MultiResolutionBufferedImage(Image baseImage, - BiFunction<Integer, Integer, Image> mapper) { - this(baseImage, new Dimension[]{new Dimension( - baseImage.getWidth(null), baseImage.getHeight(null)) - }, mapper); - } - - public MultiResolutionBufferedImage(Image baseImage, - Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) { - super(baseImage.getWidth(null), baseImage.getHeight(null), - BufferedImage.TYPE_INT_ARGB_PRE); - this.sizes = sizes; - this.mapper = mapper; - this.availableInfo = getInfo(baseImage); - Graphics g = getGraphics(); - g.drawImage(baseImage, 0, 0, null); - g.dispose(); - } - - @Override - public Image getResolutionVariant(int width, int height) { - int baseWidth = getWidth(); - int baseHeight = getHeight(); - - if (baseWidth == width && baseHeight == height) { - return this; - } - - ImageCache cache = ImageCache.getInstance(); - ImageCacheKey key = new ImageCacheKey(this, width, height); - Image resolutionVariant = cache.getImage(key); - if (resolutionVariant == null) { - resolutionVariant = mapper.apply(width, height); - cache.setImage(key, resolutionVariant); - preload(resolutionVariant, availableInfo); - } - - return resolutionVariant; - } - - @Override - public List<Image> getResolutionVariants() { - return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size - -> getResolutionVariant((int) size.getWidth(), - (int) size.getHeight())).collect(Collectors.toList()); - } - - public MultiResolutionBufferedImage map(Function<Image, Image> mapper) { - return new MultiResolutionBufferedImage(mapper.apply(this), sizes, - (width, height) -> - mapper.apply(getResolutionVariant(width, height))); - } - - @Override - public int getWidth(ImageObserver observer) { - availableInfo |= ImageObserver.WIDTH; - return super.getWidth(observer); - } - - @Override - public int getHeight(ImageObserver observer) { - availableInfo |= ImageObserver.HEIGHT; - return super.getHeight(observer); - } - - @Override - public Object getProperty(String name, ImageObserver observer) { - availableInfo |= ImageObserver.PROPERTIES; - return super.getProperty(name, observer); - } - - private static int getInfo(Image image) { - if (image instanceof ToolkitImage) { - return ((ToolkitImage) image).getImageRep().check( - (img, infoflags, x, y, w, h) -> false); - } - return 0; - } - - private static void preload(Image image, int availableInfo) { - if (availableInfo != 0 && image instanceof ToolkitImage) { - ((ToolkitImage) image).preload(new ImageObserver() { - int flags = availableInfo; - - @Override - public boolean imageUpdate(Image img, int infoflags, - int x, int y, int width, int height) { - flags &= ~infoflags; - return (flags != 0) && ((infoflags - & (ImageObserver.ERROR | ImageObserver.ABORT)) == 0); - } - }); - } - } - - private static class ImageCacheKey implements ImageCache.PixelsKey { - - private final int pixelCount; - private final int hash; - - private final int w; - private final int h; - private final Image baseImage; - - ImageCacheKey(final Image baseImage, - final int w, final int h) { - this.baseImage = baseImage; - this.w = w; - this.h = h; - this.pixelCount = w * h; - hash = hash(); - } - - @Override - public int getPixelCount() { - return pixelCount; - } - - private int hash() { - int hash = baseImage.hashCode(); - hash = 31 * hash + w; - hash = 31 * hash + h; - return hash; - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ImageCacheKey) { - ImageCacheKey key = (ImageCacheKey) obj; - return baseImage == key.baseImage && w == key.w && h == key.h; - } - return false; - } - } -} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.awt.image; + +import java.awt.Dimension; +import java.awt.Image; +import java.awt.geom.Dimension2D; +import java.awt.image.ImageObserver; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +public class MultiResolutionCachedImage extends AbstractMultiResolutionImage { + + private final int baseImageWidth; + private final int baseImageHeight; + private final Dimension2D[] sizes; + private final BiFunction<Integer, Integer, Image> mapper; + private int availableInfo; + + public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight, + BiFunction<Integer, Integer, Image> mapper) { + this(baseImageWidth, baseImageHeight, new Dimension[]{new Dimension( + baseImageWidth, baseImageHeight) + }, mapper); + } + + public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight, + Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) { + this.baseImageWidth = baseImageWidth; + this.baseImageHeight = baseImageHeight; + this.sizes = (sizes == null) ? null : Arrays.copyOf(sizes, sizes.length); + this.mapper = mapper; + } + + @Override + public Image getResolutionVariant(int width, int height) { + ImageCache cache = ImageCache.getInstance(); + ImageCacheKey key = new ImageCacheKey(this, width, height); + Image resolutionVariant = cache.getImage(key); + if (resolutionVariant == null) { + resolutionVariant = mapper.apply(width, height); + cache.setImage(key, resolutionVariant); + } + preload(resolutionVariant, availableInfo); + return resolutionVariant; + } + + @Override + public List<Image> getResolutionVariants() { + return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size + -> getResolutionVariant((int) size.getWidth(), + (int) size.getHeight())).collect(Collectors.toList()); + } + + public MultiResolutionCachedImage map(Function<Image, Image> mapper) { + return new MultiResolutionCachedImage(baseImageWidth, baseImageHeight, + sizes, (width, height) -> + mapper.apply(getResolutionVariant(width, height))); + } + + @Override + public int getWidth(ImageObserver observer) { + updateInfo(observer, ImageObserver.WIDTH); + return super.getWidth(observer); + } + + @Override + public int getHeight(ImageObserver observer) { + updateInfo(observer, ImageObserver.HEIGHT); + return super.getHeight(observer); + } + + @Override + public Object getProperty(String name, ImageObserver observer) { + updateInfo(observer, ImageObserver.PROPERTIES); + return super.getProperty(name, observer); + } + + @Override + protected Image getBaseImage() { + return getResolutionVariant(baseImageWidth, baseImageHeight); + } + + private void updateInfo(ImageObserver observer, int info) { + availableInfo |= (observer == null) ? ImageObserver.ALLBITS : info; + } + + private static int getInfo(Image image) { + if (image instanceof ToolkitImage) { + return ((ToolkitImage) image).getImageRep().check( + (img, infoflags, x, y, w, h) -> false); + } + return 0; + } + + private static void preload(Image image, int availableInfo) { + if (availableInfo != 0 && image instanceof ToolkitImage) { + ((ToolkitImage) image).preload(new ImageObserver() { + int flags = availableInfo; + + @Override + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + flags &= ~infoflags; + return (flags != 0) && ((infoflags + & (ImageObserver.ERROR | ImageObserver.ABORT)) == 0); + } + }); + } + } + + private static class ImageCacheKey implements ImageCache.PixelsKey { + + private final int pixelCount; + private final int hash; + + private final int w; + private final int h; + private final Image baseImage; + + ImageCacheKey(final Image baseImage, + final int w, final int h) { + this.baseImage = baseImage; + this.w = w; + this.h = h; + this.pixelCount = w * h; + hash = hash(); + } + + @Override + public int getPixelCount() { + return pixelCount; + } + + private int hash() { + int hash = baseImage.hashCode(); + hash = 31 * hash + w; + hash = 31 * hash + h; + return hash; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ImageCacheKey) { + ImageCacheKey key = (ImageCacheKey) obj; + return baseImage == key.baseImage && w == key.w && h == key.h; + } + return false; + } + } +} \ No newline at end of file
--- a/src/share/classes/sun/font/SunFontManager.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/font/SunFontManager.java Thu Aug 14 13:24:00 2014 -0700 @@ -3182,7 +3182,7 @@ * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. */ - public abstract String[] getDefaultPlatformFont(); + protected abstract String[] getDefaultPlatformFont(); // Begin: Refactored from SunGraphicsEnviroment.
--- a/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Thu Aug 14 13:24:00 2014 -0700 @@ -301,7 +301,7 @@ throw new IOException(fe); } try { - ftp.login(user, password.toCharArray()); + ftp.login(user, password == null ? null : password.toCharArray()); } catch (sun.net.ftp.FtpProtocolException e) { ftp.close(); // Backward compatibility
--- a/src/share/classes/sun/security/provider/DigestBase.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/security/provider/DigestBase.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,10 +122,10 @@ } } // compress complete blocks - while (len >= blockSize) { - implCompress(b, ofs); - len -= blockSize; - ofs += blockSize; + if (len >= blockSize) { + int limit = ofs + len; + ofs = implCompressMultiBlock(b, ofs, limit - blockSize); + len = limit - ofs; } // copy remainder to buffer if (len > 0) { @@ -134,6 +134,14 @@ } } + // compress complete blocks + private int implCompressMultiBlock(byte[] b, int ofs, int limit) { + for (; ofs <= limit; ofs += blockSize) { + implCompress(b, ofs); + } + return ofs; + } + // reset this object. See JCA doc. protected final void engineReset() { if (bytesProcessed == 0) {
--- a/src/share/classes/sun/security/provider/SecureRandom.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/security/provider/SecureRandom.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.security.MessageDigest; import java.security.SecureRandomSpi; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; /** * <p>This class provides a crytpographically strong pseudo-random number @@ -94,9 +95,19 @@ */ private void init(byte[] seed) { try { - digest = MessageDigest.getInstance("SHA"); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("internal error: SHA-1 not available.", e); + /* + * Use the local SUN implementation to avoid native + * performance overhead. + */ + digest = MessageDigest.getInstance("SHA", "SUN"); + } catch (NoSuchProviderException | NoSuchAlgorithmException e) { + // Fallback to any available. + try { + digest = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException exc) { + throw new InternalError( + "internal error: SHA-1 not available.", exc); + } } if (seed != null) { @@ -265,9 +276,19 @@ s.defaultReadObject (); try { - digest = MessageDigest.getInstance("SHA"); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("internal error: SHA-1 not available.", e); + /* + * Use the local SUN implementation to avoid native + * performance overhead. + */ + digest = MessageDigest.getInstance("SHA", "SUN"); + } catch (NoSuchProviderException | NoSuchAlgorithmException e) { + // Fallback to any available. + try { + digest = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException exc) { + throw new InternalError( + "internal error: SHA-1 not available.", exc); + } } } }
--- a/src/share/classes/sun/security/smartcardio/CardImpl.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/security/smartcardio/CardImpl.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,9 @@ package sun.security.smartcardio; import java.nio.ByteBuffer; - +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.smartcardio.*; - import static sun.security.smartcardio.PCSC.*; /** @@ -62,6 +62,15 @@ // thread holding exclusive access to the card, or null private volatile Thread exclusiveThread; + // used for platform specific logic + private static final boolean isWindows; + + static { + final String osName = AccessController.doPrivileged( + (PrivilegedAction<String>) () -> System.getProperty("os.name")); + isWindows = osName.startsWith("Windows"); + } + CardImpl(TerminalImpl terminal, String protocol) throws PCSCException { this.terminal = terminal; int sharingMode = SCARD_SHARE_SHARED; @@ -74,7 +83,12 @@ connectProtocol = SCARD_PROTOCOL_T1; } else if (protocol.equalsIgnoreCase("direct")) { // testing - connectProtocol = 0; + + // MSDN states that the preferred protocol can be zero, but doesn't + // specify whether other values are allowed. + // pcsc-lite implementation expects the preferred protocol to be non zero. + connectProtocol = isWindows ? 0 : SCARD_PROTOCOL_RAW; + sharingMode = SCARD_SHARE_DIRECT; } else { throw new IllegalArgumentException("Unsupported protocol " + protocol);
--- a/src/share/classes/sun/security/ssl/DHCrypt.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/security/ssl/DHCrypt.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,7 +188,7 @@ * the same size as the Diffie-Hellman modulus. */ SecretKey getAgreedSecret(BigInteger peerPublicValue, - boolean keyIsValidated) throws IOException { + boolean keyIsValidated) throws SSLHandshakeException { try { KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); DHPublicKeySpec spec = @@ -211,7 +211,8 @@ ka.doPhase(publicKey, true); return ka.generateSecret("TlsPremasterSecret"); } catch (GeneralSecurityException e) { - throw new RuntimeException("Could not generate secret", e); + throw (SSLHandshakeException) new SSLHandshakeException( + "Could not generate secret").initCause(e); } }
--- a/src/share/classes/sun/security/ssl/ECDHCrypt.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/security/ssl/ECDHCrypt.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import javax.crypto.SecretKey; import javax.crypto.KeyAgreement; +import javax.net.ssl.SSLHandshakeException; /** * Helper class for the ECDH key exchange. It generates the appropriate @@ -88,19 +89,20 @@ } // called by ClientHandshaker with either the server's static or ephemeral public key - SecretKey getAgreedSecret(PublicKey peerPublicKey) { + SecretKey getAgreedSecret(PublicKey peerPublicKey) throws SSLHandshakeException { try { KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); ka.init(privateKey); ka.doPhase(peerPublicKey, true); return ka.generateSecret("TlsPremasterSecret"); } catch (GeneralSecurityException e) { - throw new RuntimeException("Could not generate secret", e); + throw (SSLHandshakeException) new SSLHandshakeException( + "Could not generate secret").initCause(e); } } // called by ServerHandshaker - SecretKey getAgreedSecret(byte[] encodedPoint) { + SecretKey getAgreedSecret(byte[] encodedPoint) throws SSLHandshakeException { try { ECParameterSpec params = publicKey.getParams(); ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve()); @@ -108,10 +110,9 @@ ECPublicKeySpec spec = new ECPublicKeySpec(point, params); PublicKey peerPublicKey = kf.generatePublic(spec); return getAgreedSecret(peerPublicKey); - } catch (GeneralSecurityException e) { - throw new RuntimeException("Could not generate secret", e); - } catch (java.io.IOException e) { - throw new RuntimeException("Could not generate secret", e); + } catch (GeneralSecurityException | java.io.IOException e) { + throw (SSLHandshakeException) new SSLHandshakeException( + "Could not generate secret").initCause(e); } }
--- a/src/share/classes/sun/swing/JLightweightFrame.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/swing/JLightweightFrame.java Thu Aug 14 13:24:00 2014 -0700 @@ -37,6 +37,13 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DropTarget; +import java.awt.dnd.InvalidDnDOperationException; +import java.awt.dnd.peer.DragSourceContextPeer; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.image.BufferedImage; @@ -470,4 +477,27 @@ content.setCursor(target.getCursor()); } } + + public <T extends DragGestureRecognizer> T createDragGestureRecognizer( + Class<T> abstractRecognizerClass, + DragSource ds, Component c, int srcActions, + DragGestureListener dgl) + { + return content == null ? null : content.createDragGestureRecognizer( + abstractRecognizerClass, ds, c, srcActions, dgl); + } + + public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { + return content == null ? null : content.createDragSourceContextPeer(dge); + } + + public void addDropTarget(DropTarget dt) { + if (content == null) return; + content.addDropTarget(dt); + } + + public void removeDropTarget(DropTarget dt) { + if (content == null) return; + content.removeDropTarget(dt); + } }
--- a/src/share/classes/sun/swing/LightweightContent.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/classes/sun/swing/LightweightContent.java Thu Aug 14 13:24:00 2014 -0700 @@ -26,7 +26,15 @@ package sun.swing; import javax.swing.JComponent; +import java.awt.Component; import java.awt.Cursor; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DropTarget; +import java.awt.dnd.InvalidDnDOperationException; +import java.awt.dnd.peer.DragSourceContextPeer; /** * The interface by means of which the {@link JLightweightFrame} class @@ -209,4 +217,33 @@ * @param cursor a cursor to set */ default public void setCursor(Cursor cursor) { } + + /** + * Create a drag gesture recognizer for the lightweight frame. + */ + default public <T extends DragGestureRecognizer> T createDragGestureRecognizer( + Class<T> abstractRecognizerClass, + DragSource ds, Component c, int srcActions, + DragGestureListener dgl) + { + return null; + } + + /** + * Create a drag source context peer for the lightweight frame. + */ + default public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException + { + return null; + } + + /** + * Adds a drop target to the lightweight frame. + */ + default public void addDropTarget(DropTarget dt) {} + + /** + * Removes a drop target from the lightweight frame. + */ + default public void removeDropTarget(DropTarget dt) {} }
--- a/src/share/native/java/lang/java_props.h Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/native/java/lang/java_props.h Thu Aug 14 13:24:00 2014 -0700 @@ -117,7 +117,7 @@ char *exceptionList; - char *awt_headless /* java.awt.headless setting, if NULL (default) will not be set */ + char *awt_headless; /* java.awt.headless setting, if NULL (default) will not be set */ #endif } java_props_t;
--- a/src/share/native/java/util/TimeZone.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/native/java/util/TimeZone.c Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,42 +38,28 @@ */ JNIEXPORT jstring JNICALL Java_java_util_TimeZone_getSystemTimeZoneID(JNIEnv *env, jclass ign, - jstring java_home, jstring country) + jstring java_home) { - const char *cname; const char *java_home_dir; char *javaTZ; + jstring jstrJavaTZ = NULL; - if (java_home == NULL) - return NULL; + CHECK_NULL_RETURN(java_home, NULL); java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0); - if (java_home_dir == NULL) - return NULL; - - if (country != NULL) { - cname = JNU_GetStringPlatformChars(env, country, 0); - /* ignore error cases for cname */ - } else { - cname = NULL; - } + CHECK_NULL_RETURN(java_home_dir, NULL); /* * Invoke platform dependent mapping function */ - javaTZ = findJavaTZ_md(java_home_dir, cname); - - free((void *)java_home_dir); - if (cname != NULL) { - free((void *)cname); + javaTZ = findJavaTZ_md(java_home_dir); + if (javaTZ != NULL) { + jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ); + free((void *)javaTZ); } - if (javaTZ != NULL) { - jstring jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ); - free((void *)javaTZ); - return jstrJavaTZ; - } - return NULL; + JNU_ReleaseStringPlatformChars(env, java_home, java_home_dir); + return jstrJavaTZ; } /*
--- a/src/share/native/sun/awt/image/BufImgSurfaceData.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/native/sun/awt/image/BufImgSurfaceData.c Thu Aug 14 13:24:00 2014 -0700 @@ -291,7 +291,12 @@ = (*env)->GetBooleanField(env, bisdo->icm, allGrayID); int *pRgb = (int *) ((*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL)); - CHECK_NULL_RETURN(pRgb, (ColorData*)NULL); + + if (pRgb == NULL) { + free(cData); + return (ColorData*)NULL; + } + cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32); if (allGray == JNI_TRUE) { initInverseGrayLut(pRgb, bisdo->lutsize, cData); @@ -304,7 +309,13 @@ if (JNU_IsNull(env, colorData)) { jlong pData = ptr_to_jlong(cData); colorData = (*env)->NewObjectA(env, clsICMCD, initICMCDmID, (jvalue *)&pData); - JNU_CHECK_EXCEPTION_RETURN(env, (ColorData*)NULL); + + if ((*env)->ExceptionCheck(env)) + { + free(cData); + return (ColorData*)NULL; + } + (*env)->SetObjectField(env, bisdo->icm, colorDataID, colorData); } }
--- a/src/share/native/sun/font/DrawGlyphList.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/share/native/sun/font/DrawGlyphList.c Thu Aug 14 13:24:00 2014 -0700 @@ -52,7 +52,8 @@ GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist) { - int g, bytesNeeded; + int g; + size_t bytesNeeded; jlong *imagePtrs; jfloat* positions = NULL; GlyphInfo *ginfo; @@ -71,6 +72,9 @@ bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len; gbv = (GlyphBlitVector*)malloc(bytesNeeded); + if (gbv == NULL) { + return NULL; + } gbv->numGlyphs = len; gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector)); @@ -479,7 +483,8 @@ */ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist) { - int g, bytesNeeded; + int g; + size_t bytesNeeded; jlong *imagePtrs; jfloat* positions = NULL; GlyphInfo *ginfo; @@ -500,6 +505,9 @@ bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len; gbv = (GlyphBlitVector*)malloc(bytesNeeded); + if (gbv == NULL) { + return NULL; + } gbv->numGlyphs = len; gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/solaris/classes/java/lang/UNIXProcess.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,827 @@ +/* + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.security.AccessController; +import static java.security.AccessController.doPrivileged; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/** + * java.lang.Process subclass in the UNIX environment. + * + * @author Mario Wolczko and Ross Knippel. + * @author Konstantin Kladko (ported to Linux and Bsd) + * @author Martin Buchholz + * @author Volker Simonis (ported to AIX) + */ +final class UNIXProcess extends Process { + private static final sun.misc.JavaIOFileDescriptorAccess fdAccess + = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + + private final int pid; + private int exitcode; + private boolean hasExited; + + private /* final */ OutputStream stdin; + private /* final */ InputStream stdout; + private /* final */ InputStream stderr; + + // only used on Solaris + private /* final */ DeferredCloseInputStream stdout_inner_stream; + + private static enum LaunchMechanism { + // order IS important! + FORK, + POSIX_SPAWN, + VFORK + } + + private static enum Platform { + + LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK), + + BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK), + + SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK), + + AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK); + + final LaunchMechanism defaultLaunchMechanism; + final Set<LaunchMechanism> validLaunchMechanisms; + + Platform(LaunchMechanism ... launchMechanisms) { + this.defaultLaunchMechanism = launchMechanisms[0]; + this.validLaunchMechanisms = + EnumSet.copyOf(Arrays.asList(launchMechanisms)); + } + + private String helperPath(String javahome, String osArch) { + switch (this) { + case SOLARIS: + if (osArch.equals("x86")) { osArch = "i386"; } + else if (osArch.equals("x86_64")) { osArch = "amd64"; } + // fall through... + case LINUX: + case AIX: + return javahome + "/lib/" + osArch + "/jspawnhelper"; + + case BSD: + return javahome + "/lib/jspawnhelper"; + + default: + throw new AssertionError("Unsupported platform: " + this); + } + } + + String helperPath() { + return AccessController.doPrivileged( + (PrivilegedAction<String>) () -> + helperPath(System.getProperty("java.home"), + System.getProperty("os.arch")) + ); + } + + LaunchMechanism launchMechanism() { + return AccessController.doPrivileged( + (PrivilegedAction<LaunchMechanism>) () -> { + String s = System.getProperty( + "jdk.lang.Process.launchMechanism"); + LaunchMechanism lm; + if (s == null) { + lm = defaultLaunchMechanism; + s = lm.name().toLowerCase(Locale.ENGLISH); + } else { + try { + lm = LaunchMechanism.valueOf( + s.toUpperCase(Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + lm = null; + } + } + if (lm == null || !validLaunchMechanisms.contains(lm)) { + throw new Error( + s + " is not a supported " + + "process launch mechanism on this platform." + ); + } + return lm; + } + ); + } + + static Platform get() { + String osName = AccessController.doPrivileged( + (PrivilegedAction<String>) () -> System.getProperty("os.name") + ); + + if (osName.equals("Linux")) { return LINUX; } + if (osName.contains("OS X")) { return BSD; } + if (osName.equals("SunOS")) { return SOLARIS; } + if (osName.equals("AIX")) { return AIX; } + + throw new Error(osName + " is not a supported OS platform."); + } + } + + private static final Platform platform = Platform.get(); + private static final LaunchMechanism launchMechanism = platform.launchMechanism(); + private static final byte[] helperpath = toCString(platform.helperPath()); + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length-1] = (byte)0; + return result; + } + + /* this is for the reaping thread */ + private native int waitForProcessExit(int pid); + + /** + * Creates a process. Depending on the {@code mode} flag, this is done by + * one of the following mechanisms: + * <pre> + * 1 - fork(2) and exec(2) + * 2 - posix_spawn(3P) + * 3 - vfork(2) and exec(2) + * + * (4 - clone(2) and exec(2) - obsolete and currently disabled in native code) + * </pre> + * @param fds an array of three file descriptors. + * Indexes 0, 1, and 2 correspond to standard input, + * standard output and standard error, respectively. On + * input, a value of -1 means to create a pipe to connect + * child and parent processes. On output, a value which + * is not -1 is the parent pipe fd corresponding to the + * pipe which has been created. An element of this array + * is -1 on input if and only if it is <em>not</em> -1 on + * output. + * @return the pid of the subprocess + */ + private native int forkAndExec(int mode, byte[] helperpath, + byte[] prog, + byte[] argBlock, int argc, + byte[] envBlock, int envc, + byte[] dir, + int[] fds, + boolean redirectErrorStream) + throws IOException; + + /** + * The thread pool of "process reaper" daemon threads. + */ + private static final Executor processReaperExecutor = + doPrivileged((PrivilegedAction<Executor>) () -> { + + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + while (tg.getParent() != null) tg = tg.getParent(); + ThreadGroup systemThreadGroup = tg; + + ThreadFactory threadFactory = grimReaper -> { + // Our thread stack requirement is quite modest. + Thread t = new Thread(systemThreadGroup, grimReaper, + "process reaper", 32768); + t.setDaemon(true); + // A small attempt (probably futile) to avoid priority inversion + t.setPriority(Thread.MAX_PRIORITY); + return t; + }; + + return Executors.newCachedThreadPool(threadFactory); + }); + + UNIXProcess(final byte[] prog, + final byte[] argBlock, final int argc, + final byte[] envBlock, final int envc, + final byte[] dir, + final int[] fds, + final boolean redirectErrorStream) + throws IOException { + + pid = forkAndExec(launchMechanism.ordinal() + 1, + helperpath, + prog, + argBlock, argc, + envBlock, envc, + dir, + fds, + redirectErrorStream); + + try { + doPrivileged((PrivilegedExceptionAction<Void>) () -> { + initStreams(fds); + return null; + }); + } catch (PrivilegedActionException ex) { + throw (IOException) ex.getException(); + } + } + + static FileDescriptor newFileDescriptor(int fd) { + FileDescriptor fileDescriptor = new FileDescriptor(); + fdAccess.set(fileDescriptor, fd); + return fileDescriptor; + } + + void initStreams(int[] fds) throws IOException { + switch (platform) { + case LINUX: + case BSD: + stdin = (fds[0] == -1) ? + ProcessBuilder.NullOutputStream.INSTANCE : + new ProcessPipeOutputStream(fds[0]); + + stdout = (fds[1] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ProcessPipeInputStream(fds[1]); + + stderr = (fds[2] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ProcessPipeInputStream(fds[2]); + + processReaperExecutor.execute(() -> { + int exitcode = waitForProcessExit(pid); + + synchronized (this) { + this.exitcode = exitcode; + this.hasExited = true; + this.notifyAll(); + } + + if (stdout instanceof ProcessPipeInputStream) + ((ProcessPipeInputStream) stdout).processExited(); + + if (stderr instanceof ProcessPipeInputStream) + ((ProcessPipeInputStream) stderr).processExited(); + + if (stdin instanceof ProcessPipeOutputStream) + ((ProcessPipeOutputStream) stdin).processExited(); + }); + break; + + case SOLARIS: + stdin = (fds[0] == -1) ? + ProcessBuilder.NullOutputStream.INSTANCE : + new BufferedOutputStream( + new FileOutputStream(newFileDescriptor(fds[0]))); + + stdout = (fds[1] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new BufferedInputStream( + stdout_inner_stream = + new DeferredCloseInputStream( + newFileDescriptor(fds[1]))); + + stderr = (fds[2] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseInputStream(newFileDescriptor(fds[2])); + + /* + * For each subprocess forked a corresponding reaper task + * is submitted. That task is the only thread which waits + * for the subprocess to terminate and it doesn't hold any + * locks while doing so. This design allows waitFor() and + * exitStatus() to be safely executed in parallel (and they + * need no native code). + */ + processReaperExecutor.execute(() -> { + int exitcode = waitForProcessExit(pid); + + synchronized (this) { + this.exitcode = exitcode; + this.hasExited = true; + this.notifyAll(); + } + }); + break; + + case AIX: + stdin = (fds[0] == -1) ? + ProcessBuilder.NullOutputStream.INSTANCE : + new ProcessPipeOutputStream(fds[0]); + + stdout = (fds[1] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseProcessPipeInputStream(fds[1]); + + stderr = (fds[2] == -1) ? + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseProcessPipeInputStream(fds[2]); + + processReaperExecutor.execute(() -> { + int exitcode = waitForProcessExit(pid); + + synchronized (this) { + this.exitcode = exitcode; + this.hasExited = true; + this.notifyAll(); + } + + if (stdout instanceof DeferredCloseProcessPipeInputStream) + ((DeferredCloseProcessPipeInputStream) stdout).processExited(); + + if (stderr instanceof DeferredCloseProcessPipeInputStream) + ((DeferredCloseProcessPipeInputStream) stderr).processExited(); + + if (stdin instanceof ProcessPipeOutputStream) + ((ProcessPipeOutputStream) stdin).processExited(); + }); + break; + + default: throw new AssertionError("Unsupported platform: " + platform); + } + } + + public OutputStream getOutputStream() { + return stdin; + } + + public InputStream getInputStream() { + return stdout; + } + + public InputStream getErrorStream() { + return stderr; + } + + public synchronized int waitFor() throws InterruptedException { + while (!hasExited) { + wait(); + } + return exitcode; + } + + @Override + public synchronized boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException + { + if (hasExited) return true; + if (timeout <= 0) return false; + + long timeoutAsNanos = unit.toNanos(timeout); + long startTime = System.nanoTime(); + long rem = timeoutAsNanos; + + while (!hasExited && (rem > 0)) { + wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); + rem = timeoutAsNanos - (System.nanoTime() - startTime); + } + return hasExited; + } + + public synchronized int exitValue() { + if (!hasExited) { + throw new IllegalThreadStateException("process hasn't exited"); + } + return exitcode; + } + + private static native void destroyProcess(int pid, boolean force); + + private void destroy(boolean force) { + switch (platform) { + case LINUX: + case BSD: + case AIX: + // There is a risk that pid will be recycled, causing us to + // kill the wrong process! So we only terminate processes + // that appear to still be running. Even with this check, + // there is an unavoidable race condition here, but the window + // is very small, and OSes try hard to not recycle pids too + // soon, so this is quite safe. + synchronized (this) { + if (!hasExited) + destroyProcess(pid, force); + } + try { stdin.close(); } catch (IOException ignored) {} + try { stdout.close(); } catch (IOException ignored) {} + try { stderr.close(); } catch (IOException ignored) {} + break; + + case SOLARIS: + // There is a risk that pid will be recycled, causing us to + // kill the wrong process! So we only terminate processes + // that appear to still be running. Even with this check, + // there is an unavoidable race condition here, but the window + // is very small, and OSes try hard to not recycle pids too + // soon, so this is quite safe. + synchronized (this) { + if (!hasExited) + destroyProcess(pid, force); + try { + stdin.close(); + if (stdout_inner_stream != null) + stdout_inner_stream.closeDeferred(stdout); + if (stderr instanceof DeferredCloseInputStream) + ((DeferredCloseInputStream) stderr) + .closeDeferred(stderr); + } catch (IOException e) { + // ignore + } + } + break; + + default: throw new AssertionError("Unsupported platform: " + platform); + } + } + + public void destroy() { + destroy(false); + } + + @Override + public Process destroyForcibly() { + destroy(true); + return this; + } + + @Override + public synchronized boolean isAlive() { + return !hasExited; + } + + private static native void init(); + + static { + init(); + } + + /** + * A buffered input stream for a subprocess pipe file descriptor + * that allows the underlying file descriptor to be reclaimed when + * the process exits, via the processExited hook. + * + * This is tricky because we do not want the user-level InputStream to be + * closed until the user invokes close(), and we need to continue to be + * able to read any buffered data lingering in the OS pipe buffer. + */ + private static class ProcessPipeInputStream extends BufferedInputStream { + private final Object closeLock = new Object(); + + ProcessPipeInputStream(int fd) { + super(new FileInputStream(newFileDescriptor(fd))); + } + private static byte[] drainInputStream(InputStream in) + throws IOException { + int n = 0; + int j; + byte[] a = null; + while ((j = in.available()) > 0) { + a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); + n += in.read(a, n, j); + } + return (a == null || n == a.length) ? a : Arrays.copyOf(a, n); + } + + /** Called by the process reaper thread when the process exits. */ + synchronized void processExited() { + synchronized (closeLock) { + try { + InputStream in = this.in; + // this stream is closed if and only if: in == null + if (in != null) { + byte[] stragglers = drainInputStream(in); + in.close(); + this.in = (stragglers == null) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ByteArrayInputStream(stragglers); + } + } catch (IOException ignored) {} + } + } + + @Override + public void close() throws IOException { + // BufferedInputStream#close() is not synchronized unlike most other + // methods. Synchronizing helps avoid race with processExited(). + synchronized (closeLock) { + super.close(); + } + } + } + + /** + * A buffered output stream for a subprocess pipe file descriptor + * that allows the underlying file descriptor to be reclaimed when + * the process exits, via the processExited hook. + */ + private static class ProcessPipeOutputStream extends BufferedOutputStream { + ProcessPipeOutputStream(int fd) { + super(new FileOutputStream(newFileDescriptor(fd))); + } + + /** Called by the process reaper thread when the process exits. */ + synchronized void processExited() { + OutputStream out = this.out; + if (out != null) { + try { + out.close(); + } catch (IOException ignored) { + // We know of no reason to get an IOException, but if + // we do, there's nothing else to do but carry on. + } + this.out = ProcessBuilder.NullOutputStream.INSTANCE; + } + } + } + + // A FileInputStream that supports the deferment of the actual close + // operation until the last pending I/O operation on the stream has + // finished. This is required on Solaris because we must close the stdin + // and stdout streams in the destroy method in order to reclaim the + // underlying file descriptors. Doing so, however, causes any thread + // currently blocked in a read on one of those streams to receive an + // IOException("Bad file number"), which is incompatible with historical + // behavior. By deferring the close we allow any pending reads to see -1 + // (EOF) as they did before. + // + private static class DeferredCloseInputStream extends FileInputStream + { + DeferredCloseInputStream(FileDescriptor fd) { + super(fd); + } + + private Object lock = new Object(); // For the following fields + private boolean closePending = false; + private int useCount = 0; + private InputStream streamToClose; + + private void raise() { + synchronized (lock) { + useCount++; + } + } + + private void lower() throws IOException { + synchronized (lock) { + useCount--; + if (useCount == 0 && closePending) { + streamToClose.close(); + } + } + } + + // stc is the actual stream to be closed; it might be this object, or + // it might be an upstream object for which this object is downstream. + // + private void closeDeferred(InputStream stc) throws IOException { + synchronized (lock) { + if (useCount == 0) { + stc.close(); + } else { + closePending = true; + streamToClose = stc; + } + } + } + + public void close() throws IOException { + synchronized (lock) { + useCount = 0; + closePending = false; + } + super.close(); + } + + public int read() throws IOException { + raise(); + try { + return super.read(); + } finally { + lower(); + } + } + + public int read(byte[] b) throws IOException { + raise(); + try { + return super.read(b); + } finally { + lower(); + } + } + + public int read(byte[] b, int off, int len) throws IOException { + raise(); + try { + return super.read(b, off, len); + } finally { + lower(); + } + } + + public long skip(long n) throws IOException { + raise(); + try { + return super.skip(n); + } finally { + lower(); + } + } + + public int available() throws IOException { + raise(); + try { + return super.available(); + } finally { + lower(); + } + } + } + + /** + * A buffered input stream for a subprocess pipe file descriptor + * that allows the underlying file descriptor to be reclaimed when + * the process exits, via the processExited hook. + * + * This is tricky because we do not want the user-level InputStream to be + * closed until the user invokes close(), and we need to continue to be + * able to read any buffered data lingering in the OS pipe buffer. + * + * On AIX this is especially tricky, because the 'close()' system call + * will block if another thread is at the same time blocked in a file + * operation (e.g. 'read()') on the same file descriptor. We therefore + * combine 'ProcessPipeInputStream' approach used on Linux and Bsd + * with the DeferredCloseInputStream approach used on Solaris. This means + * that every potentially blocking operation on the file descriptor + * increments a counter before it is executed and decrements it once it + * finishes. The 'close()' operation will only be executed if there are + * no pending operations. Otherwise it is deferred after the last pending + * operation has finished. + * + */ + private static class DeferredCloseProcessPipeInputStream + extends BufferedInputStream { + + private final Object closeLock = new Object(); + private int useCount = 0; + private boolean closePending = false; + + DeferredCloseProcessPipeInputStream(int fd) { + super(new FileInputStream(newFileDescriptor(fd))); + } + + private InputStream drainInputStream(InputStream in) + throws IOException { + int n = 0; + int j; + byte[] a = null; + synchronized (closeLock) { + if (buf == null) // asynchronous close()? + return null; // discard + j = in.available(); + } + while (j > 0) { + a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); + synchronized (closeLock) { + if (buf == null) // asynchronous close()? + return null; // discard + n += in.read(a, n, j); + j = in.available(); + } + } + return (a == null) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n)); + } + + /** Called by the process reaper thread when the process exits. */ + synchronized void processExited() { + try { + InputStream in = this.in; + if (in != null) { + InputStream stragglers = drainInputStream(in); + in.close(); + this.in = stragglers; + } + } catch (IOException ignored) { } + } + + private void raise() { + synchronized (closeLock) { + useCount++; + } + } + + private void lower() throws IOException { + synchronized (closeLock) { + useCount--; + if (useCount == 0 && closePending) { + closePending = false; + super.close(); + } + } + } + + @Override + public int read() throws IOException { + raise(); + try { + return super.read(); + } finally { + lower(); + } + } + + @Override + public int read(byte[] b) throws IOException { + raise(); + try { + return super.read(b); + } finally { + lower(); + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + raise(); + try { + return super.read(b, off, len); + } finally { + lower(); + } + } + + @Override + public long skip(long n) throws IOException { + raise(); + try { + return super.skip(n); + } finally { + lower(); + } + } + + @Override + public int available() throws IOException { + raise(); + try { + return super.available(); + } finally { + lower(); + } + } + + @Override + public void close() throws IOException { + // BufferedInputStream#close() is not synchronized unlike most other + // methods. Synchronizing helps avoid racing with drainInputStream(). + synchronized (closeLock) { + if (useCount == 0) { + super.close(); + } + else { + closePending = true; + } + } + } + } +}
--- a/src/solaris/classes/java/lang/UNIXProcess.java.aix Wed Aug 13 14:49:53 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,504 +0,0 @@ -/* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.concurrent.Executors; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.security.AccessController; -import static java.security.AccessController.doPrivileged; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/** - * java.lang.Process subclass in the UNIX environment. - * - * @author Mario Wolczko and Ross Knippel. - * @author Konstantin Kladko (ported to Linux) - * @author Martin Buchholz - * @author Volker Simonis (ported to AIX) - */ -final class UNIXProcess extends Process { - private static final sun.misc.JavaIOFileDescriptorAccess fdAccess - = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); - - private final int pid; - private int exitcode; - private boolean hasExited; - - private /* final */ OutputStream stdin; - private /* final */ InputStream stdout; - private /* final */ InputStream stderr; - - private static enum LaunchMechanism { - FORK(1), - POSIX_SPAWN(2); - - private int value; - LaunchMechanism(int x) {value = x;} - }; - - /* On AIX, the default is to spawn */ - private static final LaunchMechanism launchMechanism; - private static byte[] helperpath; - - private static byte[] toCString(String s) { - if (s == null) - return null; - byte[] bytes = s.getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length-1] = (byte)0; - return result; - } - - static { - launchMechanism = AccessController.doPrivileged( - new PrivilegedAction<LaunchMechanism>() - { - public LaunchMechanism run() { - String javahome = System.getProperty("java.home"); - String osArch = System.getProperty("os.arch"); - - helperpath = toCString(javahome + "/lib/" + osArch + "/jspawnhelper"); - String s = System.getProperty( - "jdk.lang.Process.launchMechanism", "posix_spawn"); - - try { - return LaunchMechanism.valueOf(s.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new Error(s + " is not a supported " + - "process launch mechanism on this platform."); - } - } - }); - } - - /* this is for the reaping thread */ - private native int waitForProcessExit(int pid); - - /** - * Create a process. Depending on the mode flag, this is done by - * one of the following mechanisms. - * - fork(2) and exec(2) - * - clone(2) and exec(2) - * - vfork(2) and exec(2) - * - * @param fds an array of three file descriptors. - * Indexes 0, 1, and 2 correspond to standard input, - * standard output and standard error, respectively. On - * input, a value of -1 means to create a pipe to connect - * child and parent processes. On output, a value which - * is not -1 is the parent pipe fd corresponding to the - * pipe which has been created. An element of this array - * is -1 on input if and only if it is <em>not</em> -1 on - * output. - * @return the pid of the subprocess - */ - private native int forkAndExec(int mode, byte[] helperpath, - byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - int[] fds, - boolean redirectErrorStream) - throws IOException; - - /** - * The thread factory used to create "process reaper" daemon threads. - */ - private static class ProcessReaperThreadFactory implements ThreadFactory { - private final static ThreadGroup group = getRootThreadGroup(); - - private static ThreadGroup getRootThreadGroup() { - return doPrivileged(new PrivilegedAction<ThreadGroup> () { - public ThreadGroup run() { - ThreadGroup root = Thread.currentThread().getThreadGroup(); - while (root.getParent() != null) - root = root.getParent(); - return root; - }}); - } - - public Thread newThread(Runnable grimReaper) { - // Our thread stack requirement is quite modest. - Thread t = new Thread(group, grimReaper, "process reaper", 32768); - t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); - return t; - } - } - - /** - * The thread pool of "process reaper" daemon threads. - */ - private static final Executor processReaperExecutor = - doPrivileged(new PrivilegedAction<Executor>() { - public Executor run() { - return Executors.newCachedThreadPool - (new ProcessReaperThreadFactory()); - }}); - - UNIXProcess(final byte[] prog, - final byte[] argBlock, final int argc, - final byte[] envBlock, final int envc, - final byte[] dir, - final int[] fds, - final boolean redirectErrorStream) - throws IOException { - - pid = forkAndExec(launchMechanism.value, - helperpath, - prog, - argBlock, argc, - envBlock, envc, - dir, - fds, - redirectErrorStream); - - try { - doPrivileged(new PrivilegedExceptionAction<Void>() { - public Void run() throws IOException { - initStreams(fds); - return null; - }}); - } catch (PrivilegedActionException ex) { - throw (IOException) ex.getException(); - } - } - - static FileDescriptor newFileDescriptor(int fd) { - FileDescriptor fileDescriptor = new FileDescriptor(); - fdAccess.set(fileDescriptor, fd); - return fileDescriptor; - } - - void initStreams(int[] fds) throws IOException { - stdin = (fds[0] == -1) ? - ProcessBuilder.NullOutputStream.INSTANCE : - new ProcessPipeOutputStream(fds[0]); - - stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[1]); - - stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[2]); - - processReaperExecutor.execute(new Runnable() { - public void run() { - int exitcode = waitForProcessExit(pid); - UNIXProcess.this.processExited(exitcode); - }}); - } - - void processExited(int exitcode) { - synchronized (this) { - this.exitcode = exitcode; - hasExited = true; - notifyAll(); - } - - if (stdout instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stdout).processExited(); - - if (stderr instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stderr).processExited(); - - if (stdin instanceof ProcessPipeOutputStream) - ((ProcessPipeOutputStream) stdin).processExited(); - } - - public OutputStream getOutputStream() { - return stdin; - } - - public InputStream getInputStream() { - return stdout; - } - - public InputStream getErrorStream() { - return stderr; - } - - public synchronized int waitFor() throws InterruptedException { - while (!hasExited) { - wait(); - } - return exitcode; - } - - @Override - public synchronized boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - if (hasExited) return true; - if (timeout <= 0) return false; - - long timeoutAsNanos = unit.toNanos(timeout); - long startTime = System.nanoTime(); - long rem = timeoutAsNanos; - - while (!hasExited && (rem > 0)) { - wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); - rem = timeoutAsNanos - (System.nanoTime() - startTime); - } - return hasExited; - } - - public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; - } - - private static native void destroyProcess(int pid, boolean force); - private void destroy(boolean force) { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - synchronized (this) { - if (!hasExited) - destroyProcess(pid, force); - } - try { stdin.close(); } catch (IOException ignored) {} - try { stdout.close(); } catch (IOException ignored) {} - try { stderr.close(); } catch (IOException ignored) {} - } - - public void destroy() { - destroy(false); - } - - @Override - public Process destroyForcibly() { - destroy(true); - return this; - } - - @Override - public synchronized boolean isAlive() { - return !hasExited; - } - - private static native void init(); - - static { - init(); - } - - /** - * A buffered input stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - * - * This is tricky because we do not want the user-level InputStream to be - * closed until the user invokes close(), and we need to continue to be - * able to read any buffered data lingering in the OS pipe buffer. - * - * On AIX this is especially tricky, because the 'close()' system call - * will block if another thread is at the same time blocked in a file - * operation (e.g. 'read()') on the same file descriptor. We therefore - * combine this 'ProcessPipeInputStream' with the DeferredCloseInputStream - * approach used on Solaris (see "UNIXProcess.java.solaris"). This means - * that every potentially blocking operation on the file descriptor - * increments a counter before it is executed and decrements it once it - * finishes. The 'close()' operation will only be executed if there are - * no pending operations. Otherwise it is deferred after the last pending - * operation has finished. - * - */ - static class ProcessPipeInputStream extends BufferedInputStream { - private final Object closeLock = new Object(); - private int useCount = 0; - private boolean closePending = false; - - ProcessPipeInputStream(int fd) { - super(new FileInputStream(newFileDescriptor(fd))); - } - - private InputStream drainInputStream(InputStream in) - throws IOException { - int n = 0; - int j; - byte[] a = null; - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - j = in.available(); - } - while (j > 0) { - a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - n += in.read(a, n, j); - j = in.available(); - } - } - return (a == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n)); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - try { - InputStream in = this.in; - if (in != null) { - InputStream stragglers = drainInputStream(in); - in.close(); - this.in = stragglers; - } - } catch (IOException ignored) { } - } - - private void raise() { - synchronized (closeLock) { - useCount++; - } - } - - private void lower() throws IOException { - synchronized (closeLock) { - useCount--; - if (useCount == 0 && closePending) { - closePending = false; - super.close(); - } - } - } - - @Override - public int read() throws IOException { - raise(); - try { - return super.read(); - } finally { - lower(); - } - } - - @Override - public int read(byte[] b) throws IOException { - raise(); - try { - return super.read(b); - } finally { - lower(); - } - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - raise(); - try { - return super.read(b, off, len); - } finally { - lower(); - } - } - - @Override - public long skip(long n) throws IOException { - raise(); - try { - return super.skip(n); - } finally { - lower(); - } - } - - @Override - public int available() throws IOException { - raise(); - try { - return super.available(); - } finally { - lower(); - } - } - - @Override - public void close() throws IOException { - // BufferedInputStream#close() is not synchronized unlike most other methods. - // Synchronizing helps avoid racing with drainInputStream(). - synchronized (closeLock) { - if (useCount == 0) { - super.close(); - } - else { - closePending = true; - } - } - } - } - - /** - * A buffered output stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - */ - static class ProcessPipeOutputStream extends BufferedOutputStream { - ProcessPipeOutputStream(int fd) { - super(new FileOutputStream(newFileDescriptor(fd))); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - OutputStream out = this.out; - if (out != null) { - try { - out.close(); - } catch (IOException ignored) { - // We know of no reason to get an IOException, but if - // we do, there's nothing else to do but carry on. - } - this.out = ProcessBuilder.NullOutputStream.INSTANCE; - } - } - } -}
--- a/src/solaris/classes/java/lang/UNIXProcess.java.bsd Wed Aug 13 14:49:53 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.concurrent.Executors; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.security.AccessController; -import static java.security.AccessController.doPrivileged; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/** - * java.lang.Process subclass in the UNIX environment. - * - * @author Mario Wolczko and Ross Knippel. - * @author Konstantin Kladko (ported to Bsd) - * @author Martin Buchholz - */ -final class UNIXProcess extends Process { - private static final sun.misc.JavaIOFileDescriptorAccess fdAccess - = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); - - private final int pid; - private int exitcode; - private boolean hasExited; - - private /* final */ OutputStream stdin; - private /* final */ InputStream stdout; - private /* final */ InputStream stderr; - - private static enum LaunchMechanism { - FORK(1), - POSIX_SPAWN(2); - - private int value; - LaunchMechanism(int x) {value = x;} - }; - - /* On BSD, the default is to spawn */ - private static final LaunchMechanism launchMechanism; - private static byte[] helperpath; - - private static byte[] toCString(String s) { - if (s == null) - return null; - byte[] bytes = s.getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length-1] = (byte)0; - return result; - } - - static { - launchMechanism = AccessController.doPrivileged( - new PrivilegedAction<LaunchMechanism>() - { - public LaunchMechanism run() { - String javahome = System.getProperty("java.home"); - - helperpath = toCString(javahome + "/lib/jspawnhelper"); - String s = System.getProperty( - "jdk.lang.Process.launchMechanism", "posix_spawn"); - - try { - return LaunchMechanism.valueOf(s.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new Error(s + " is not a supported " + - "process launch mechanism on this platform."); - } - } - }); - } - - /* this is for the reaping thread */ - private native int waitForProcessExit(int pid); - - /** - * Create a process. Depending on the mode flag, this is done by - * one of the following mechanisms. - * - fork(2) and exec(2) - * - posix_spawn(2) - * - * @param fds an array of three file descriptors. - * Indexes 0, 1, and 2 correspond to standard input, - * standard output and standard error, respectively. On - * input, a value of -1 means to create a pipe to connect - * child and parent processes. On output, a value which - * is not -1 is the parent pipe fd corresponding to the - * pipe which has been created. An element of this array - * is -1 on input if and only if it is <em>not</em> -1 on - * output. - * @return the pid of the subprocess - */ - private native int forkAndExec(int mode, byte[] helperpath, - byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - int[] fds, - boolean redirectErrorStream) - throws IOException; - - /** - * The thread factory used to create "process reaper" daemon threads. - */ - private static class ProcessReaperThreadFactory implements ThreadFactory { - private final static ThreadGroup group = getRootThreadGroup(); - - private static ThreadGroup getRootThreadGroup() { - return doPrivileged(new PrivilegedAction<ThreadGroup> () { - public ThreadGroup run() { - ThreadGroup root = Thread.currentThread().getThreadGroup(); - while (root.getParent() != null) - root = root.getParent(); - return root; - }}); - } - - public Thread newThread(Runnable grimReaper) { - // Our thread stack requirement is quite modest. - Thread t = new Thread(group, grimReaper, "process reaper", 32768); - t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); - return t; - } - } - - /** - * The thread pool of "process reaper" daemon threads. - */ - private static final Executor processReaperExecutor = - doPrivileged(new PrivilegedAction<Executor>() { - public Executor run() { - return Executors.newCachedThreadPool - (new ProcessReaperThreadFactory()); - }}); - - UNIXProcess(final byte[] prog, - final byte[] argBlock, final int argc, - final byte[] envBlock, final int envc, - final byte[] dir, - final int[] fds, - final boolean redirectErrorStream) - throws IOException { - - pid = forkAndExec(launchMechanism.value, - helperpath, - prog, - argBlock, argc, - envBlock, envc, - dir, - fds, - redirectErrorStream); - - try { - doPrivileged(new PrivilegedExceptionAction<Void>() { - public Void run() throws IOException { - initStreams(fds); - return null; - }}); - } catch (PrivilegedActionException ex) { - throw (IOException) ex.getException(); - } - } - - static FileDescriptor newFileDescriptor(int fd) { - FileDescriptor fileDescriptor = new FileDescriptor(); - fdAccess.set(fileDescriptor, fd); - return fileDescriptor; - } - - void initStreams(int[] fds) throws IOException { - stdin = (fds[0] == -1) ? - ProcessBuilder.NullOutputStream.INSTANCE : - new ProcessPipeOutputStream(fds[0]); - - stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[1]); - - stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[2]); - - processReaperExecutor.execute(new Runnable() { - public void run() { - int exitcode = waitForProcessExit(pid); - UNIXProcess.this.processExited(exitcode); - }}); - } - - void processExited(int exitcode) { - synchronized (this) { - this.exitcode = exitcode; - hasExited = true; - notifyAll(); - } - - if (stdout instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stdout).processExited(); - - if (stderr instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stderr).processExited(); - - if (stdin instanceof ProcessPipeOutputStream) - ((ProcessPipeOutputStream) stdin).processExited(); - } - - public OutputStream getOutputStream() { - return stdin; - } - - public InputStream getInputStream() { - return stdout; - } - - public InputStream getErrorStream() { - return stderr; - } - - public synchronized int waitFor() throws InterruptedException { - while (!hasExited) { - wait(); - } - return exitcode; - } - - @Override - public synchronized boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - if (hasExited) return true; - if (timeout <= 0) return false; - - long timeoutAsNanos = unit.toNanos(timeout); - long startTime = System.nanoTime(); - long rem = timeoutAsNanos; - - while (!hasExited && (rem > 0)) { - wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); - rem = timeoutAsNanos - (System.nanoTime() - startTime); - } - return hasExited; - } - - public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; - } - - private static native void destroyProcess(int pid, boolean force); - private void destroy(boolean force) { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - synchronized (this) { - if (!hasExited) - destroyProcess(pid, force); - } - try { stdin.close(); } catch (IOException ignored) {} - try { stdout.close(); } catch (IOException ignored) {} - try { stderr.close(); } catch (IOException ignored) {} - } - - public void destroy() { - destroy(false); - } - - @Override - public Process destroyForcibly() { - destroy(true); - return this; - } - - @Override - public synchronized boolean isAlive() { - return !hasExited; - } - - private static native void init(); - - static { - init(); - } - - /** - * A buffered input stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - * - * This is tricky because we do not want the user-level InputStream to be - * closed until the user invokes close(), and we need to continue to be - * able to read any buffered data lingering in the OS pipe buffer. - */ - static class ProcessPipeInputStream extends BufferedInputStream { - private final Object closeLock = new Object(); - - ProcessPipeInputStream(int fd) { - super(new FileInputStream(newFileDescriptor(fd))); - } - private static byte[] drainInputStream(InputStream in) - throws IOException { - int n = 0; - int j; - byte[] a = null; - while ((j = in.available()) > 0) { - a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); - n += in.read(a, n, j); - } - return (a == null || n == a.length) ? a : Arrays.copyOf(a, n); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - synchronized (closeLock) { - try { - InputStream in = this.in; - // this stream is closed if and only if: in == null - if (in != null) { - byte[] stragglers = drainInputStream(in); - in.close(); - this.in = (stragglers == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(stragglers); - } - } catch (IOException ignored) {} - } - } - - @Override - public void close() throws IOException { - // BufferedInputStream#close() is not synchronized unlike most other methods. - // Synchronizing helps avoid race with processExited(). - synchronized (closeLock) { - super.close(); - } - } - } - - /** - * A buffered output stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - */ - static class ProcessPipeOutputStream extends BufferedOutputStream { - ProcessPipeOutputStream(int fd) { - super(new FileOutputStream(newFileDescriptor(fd))); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - OutputStream out = this.out; - if (out != null) { - try { - out.close(); - } catch (IOException ignored) { - // We know of no reason to get an IOException, but if - // we do, there's nothing else to do but carry on. - } - this.out = ProcessBuilder.NullOutputStream.INSTANCE; - } - } - } -}
--- a/src/solaris/classes/java/lang/UNIXProcess.java.linux Wed Aug 13 14:49:53 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,410 +0,0 @@ -/* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.concurrent.Executors; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.security.AccessController; -import static java.security.AccessController.doPrivileged; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/** - * java.lang.Process subclass in the UNIX environment. - * - * @author Mario Wolczko and Ross Knippel. - * @author Konstantin Kladko (ported to Linux) - * @author Martin Buchholz - */ -final class UNIXProcess extends Process { - private static final sun.misc.JavaIOFileDescriptorAccess fdAccess - = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); - - private final int pid; - private int exitcode; - private boolean hasExited; - - private /* final */ OutputStream stdin; - private /* final */ InputStream stdout; - private /* final */ InputStream stderr; - - private static enum LaunchMechanism { - FORK(1), - VFORK(3); - - private int value; - LaunchMechanism(int x) {value = x;} - }; - - /* default is VFORK on Linux */ - private static final LaunchMechanism launchMechanism; - private static byte[] helperpath; - - private static byte[] toCString(String s) { - if (s == null) - return null; - byte[] bytes = s.getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length-1] = (byte)0; - return result; - } - - static { - launchMechanism = AccessController.doPrivileged( - new PrivilegedAction<LaunchMechanism>() - { - public LaunchMechanism run() { - String javahome = System.getProperty("java.home"); - String osArch = System.getProperty("os.arch"); - - helperpath = toCString(javahome + "/lib/" + osArch + "/jspawnhelper"); - String s = System.getProperty( - "jdk.lang.Process.launchMechanism", "vfork"); - - try { - return LaunchMechanism.valueOf(s.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new Error(s + " is not a supported " + - "process launch mechanism on this platform."); - } - } - }); - } - - /* this is for the reaping thread */ - private native int waitForProcessExit(int pid); - - /** - * Create a process. Depending on the mode flag, this is done by - * one of the following mechanisms. - * - fork(2) and exec(2) - * - clone(2) and exec(2) - * - vfork(2) and exec(2) - * - * @param fds an array of three file descriptors. - * Indexes 0, 1, and 2 correspond to standard input, - * standard output and standard error, respectively. On - * input, a value of -1 means to create a pipe to connect - * child and parent processes. On output, a value which - * is not -1 is the parent pipe fd corresponding to the - * pipe which has been created. An element of this array - * is -1 on input if and only if it is <em>not</em> -1 on - * output. - * @return the pid of the subprocess - */ - private native int forkAndExec(int mode, byte[] helperpath, - byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - int[] fds, - boolean redirectErrorStream) - throws IOException; - - /** - * The thread factory used to create "process reaper" daemon threads. - */ - private static class ProcessReaperThreadFactory implements ThreadFactory { - private final static ThreadGroup group = getRootThreadGroup(); - - private static ThreadGroup getRootThreadGroup() { - return doPrivileged(new PrivilegedAction<ThreadGroup> () { - public ThreadGroup run() { - ThreadGroup root = Thread.currentThread().getThreadGroup(); - while (root.getParent() != null) - root = root.getParent(); - return root; - }}); - } - - public Thread newThread(Runnable grimReaper) { - // Our thread stack requirement is quite modest. - Thread t = new Thread(group, grimReaper, "process reaper", 32768); - t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); - return t; - } - } - - /** - * The thread pool of "process reaper" daemon threads. - */ - private static final Executor processReaperExecutor = - doPrivileged(new PrivilegedAction<Executor>() { - public Executor run() { - return Executors.newCachedThreadPool - (new ProcessReaperThreadFactory()); - }}); - - UNIXProcess(final byte[] prog, - final byte[] argBlock, final int argc, - final byte[] envBlock, final int envc, - final byte[] dir, - final int[] fds, - final boolean redirectErrorStream) - throws IOException { - - pid = forkAndExec(launchMechanism.value, - helperpath, - prog, - argBlock, argc, - envBlock, envc, - dir, - fds, - redirectErrorStream); - - try { - doPrivileged(new PrivilegedExceptionAction<Void>() { - public Void run() throws IOException { - initStreams(fds); - return null; - }}); - } catch (PrivilegedActionException ex) { - throw (IOException) ex.getException(); - } - } - - static FileDescriptor newFileDescriptor(int fd) { - FileDescriptor fileDescriptor = new FileDescriptor(); - fdAccess.set(fileDescriptor, fd); - return fileDescriptor; - } - - void initStreams(int[] fds) throws IOException { - stdin = (fds[0] == -1) ? - ProcessBuilder.NullOutputStream.INSTANCE : - new ProcessPipeOutputStream(fds[0]); - - stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[1]); - - stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[2]); - - processReaperExecutor.execute(new Runnable() { - public void run() { - int exitcode = waitForProcessExit(pid); - UNIXProcess.this.processExited(exitcode); - }}); - } - - void processExited(int exitcode) { - synchronized (this) { - this.exitcode = exitcode; - hasExited = true; - notifyAll(); - } - - if (stdout instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stdout).processExited(); - - if (stderr instanceof ProcessPipeInputStream) - ((ProcessPipeInputStream) stderr).processExited(); - - if (stdin instanceof ProcessPipeOutputStream) - ((ProcessPipeOutputStream) stdin).processExited(); - } - - public OutputStream getOutputStream() { - return stdin; - } - - public InputStream getInputStream() { - return stdout; - } - - public InputStream getErrorStream() { - return stderr; - } - - public synchronized int waitFor() throws InterruptedException { - while (!hasExited) { - wait(); - } - return exitcode; - } - - @Override - public synchronized boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - if (hasExited) return true; - if (timeout <= 0) return false; - - long timeoutAsNanos = unit.toNanos(timeout); - long startTime = System.nanoTime(); - long rem = timeoutAsNanos; - - while (!hasExited && (rem > 0)) { - wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); - rem = timeoutAsNanos - (System.nanoTime() - startTime); - } - return hasExited; - } - - public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; - } - - private static native void destroyProcess(int pid, boolean force); - private void destroy(boolean force) { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - synchronized (this) { - if (!hasExited) - destroyProcess(pid, force); - } - try { stdin.close(); } catch (IOException ignored) {} - try { stdout.close(); } catch (IOException ignored) {} - try { stderr.close(); } catch (IOException ignored) {} - } - - public void destroy() { - destroy(false); - } - - @Override - public Process destroyForcibly() { - destroy(true); - return this; - } - - @Override - public synchronized boolean isAlive() { - return !hasExited; - } - - private static native void init(); - - static { - init(); - } - - /** - * A buffered input stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - * - * This is tricky because we do not want the user-level InputStream to be - * closed until the user invokes close(), and we need to continue to be - * able to read any buffered data lingering in the OS pipe buffer. - */ - static class ProcessPipeInputStream extends BufferedInputStream { - private final Object closeLock = new Object(); - - ProcessPipeInputStream(int fd) { - super(new FileInputStream(newFileDescriptor(fd))); - } - private static byte[] drainInputStream(InputStream in) - throws IOException { - int n = 0; - int j; - byte[] a = null; - while ((j = in.available()) > 0) { - a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); - n += in.read(a, n, j); - } - return (a == null || n == a.length) ? a : Arrays.copyOf(a, n); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - synchronized (closeLock) { - try { - InputStream in = this.in; - // this stream is closed if and only if: in == null - if (in != null) { - byte[] stragglers = drainInputStream(in); - in.close(); - this.in = (stragglers == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(stragglers); - } - } catch (IOException ignored) {} - } - } - - @Override - public void close() throws IOException { - // BufferedInputStream#close() is not synchronized unlike most other methods. - // Synchronizing helps avoid race with processExited(). - synchronized (closeLock) { - super.close(); - } - } - } - - /** - * A buffered output stream for a subprocess pipe file descriptor - * that allows the underlying file descriptor to be reclaimed when - * the process exits, via the processExited hook. - */ - static class ProcessPipeOutputStream extends BufferedOutputStream { - ProcessPipeOutputStream(int fd) { - super(new FileOutputStream(newFileDescriptor(fd))); - } - - /** Called by the process reaper thread when the process exits. */ - synchronized void processExited() { - OutputStream out = this.out; - if (out != null) { - try { - out.close(); - } catch (IOException ignored) { - // We know of no reason to get an IOException, but if - // we do, there's nothing else to do but carry on. - } - this.out = ProcessBuilder.NullOutputStream.INSTANCE; - } - } - } -}
--- a/src/solaris/classes/java/lang/UNIXProcess.java.solaris Wed Aug 13 14:49:53 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,444 +0,0 @@ -/* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.Executors; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.security.AccessController; -import static java.security.AccessController.doPrivileged; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -/* java.lang.Process subclass in the UNIX environment. - * - * @author Mario Wolczko and Ross Knippel. - */ - -final class UNIXProcess extends Process { - private static final sun.misc.JavaIOFileDescriptorAccess fdAccess - = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); - - private final int pid; - private int exitcode; - private boolean hasExited; - - private OutputStream stdin_stream; - private InputStream stdout_stream; - private DeferredCloseInputStream stdout_inner_stream; - private InputStream stderr_stream; - - private static enum LaunchMechanism { - FORK(1), - POSIX_SPAWN(2); - - private int value; - LaunchMechanism(int x) {value = x;} - }; - - /* On Solaris, the default is to spawn */ - private static final LaunchMechanism launchMechanism; - private static byte[] helperpath; - - private static byte[] toCString(String s) { - if (s == null) - return null; - byte[] bytes = s.getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length-1] = (byte)0; - return result; - } - - static { - launchMechanism = AccessController.doPrivileged( - new PrivilegedAction<LaunchMechanism>() - { - public LaunchMechanism run() { - String javahome = System.getProperty("java.home"); - String osArch = System.getProperty("os.arch"); - if (osArch.equals("x86")) { - osArch = "i386"; - } else if (osArch.equals("x86_64")) { - osArch = "amd64"; - } - - helperpath = toCString(javahome + "/lib/" + osArch + "/jspawnhelper"); - String s = System.getProperty( - "jdk.lang.Process.launchMechanism", "posix_spawn"); - - try { - return LaunchMechanism.valueOf(s.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new Error(s + " is not a supported " + - "process launch mechanism on this platform."); - } - } - }); - } - - /* this is for the reaping thread */ - private native int waitForProcessExit(int pid); - - /** - * Create a process. Depending on the mode flag, this is done by - * one of the following mechanisms. - * - fork(2) and exec(2) - * - posix_spawn(2) - * - * @param fds an array of three file descriptors. - * Indexes 0, 1, and 2 correspond to standard input, - * standard output and standard error, respectively. On - * input, a value of -1 means to create a pipe to connect - * child and parent processes. On output, a value which - * is not -1 is the parent pipe fd corresponding to the - * pipe which has been created. An element of this array - * is -1 on input if and only if it is <em>not</em> -1 on - * output. - * @return the pid of the subprocess - */ - private native int forkAndExec(int mode, byte[] helperpath, - byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - int[] fds, - boolean redirectErrorStream) - throws IOException; - - /** - * The thread factory used to create "process reaper" daemon threads. - */ - private static class ProcessReaperThreadFactory implements ThreadFactory { - private final static ThreadGroup group = getRootThreadGroup(); - - private static ThreadGroup getRootThreadGroup() { - return doPrivileged(new PrivilegedAction<ThreadGroup> () { - public ThreadGroup run() { - ThreadGroup root = Thread.currentThread().getThreadGroup(); - while (root.getParent() != null) - root = root.getParent(); - return root; - }}); - } - - public Thread newThread(Runnable grimReaper) { - // Our thread stack requirement is quite modest. - Thread t = new Thread(group, grimReaper, "process reaper", 32768); - t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); - return t; - } - } - - /** - * The thread pool of "process reaper" daemon threads. - */ - private static final Executor processReaperExecutor = - doPrivileged(new PrivilegedAction<Executor>() { - public Executor run() { - return Executors.newCachedThreadPool - (new ProcessReaperThreadFactory()); - }}); - - UNIXProcess(final byte[] prog, - final byte[] argBlock, int argc, - final byte[] envBlock, int envc, - final byte[] dir, - final int[] fds, - final boolean redirectErrorStream) - throws IOException { - pid = forkAndExec(launchMechanism.value, - helperpath, - prog, - argBlock, argc, - envBlock, envc, - dir, - fds, - redirectErrorStream); - - try { - doPrivileged( - new PrivilegedExceptionAction<Void>() { - public Void run() throws IOException { - initStreams(fds); - return null; - } - }); - } catch (PrivilegedActionException ex) { - throw (IOException) ex.getException(); - } - } - - void initStreams(int[] fds) throws IOException { - if (fds[0] == -1) - stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE; - else { - FileDescriptor stdin_fd = new FileDescriptor(); - fdAccess.set(stdin_fd, fds[0]); - stdin_stream = new BufferedOutputStream( - new FileOutputStream(stdin_fd)); - } - - if (fds[1] == -1) - stdout_stream = ProcessBuilder.NullInputStream.INSTANCE; - else { - FileDescriptor stdout_fd = new FileDescriptor(); - fdAccess.set(stdout_fd, fds[1]); - stdout_inner_stream = new DeferredCloseInputStream(stdout_fd); - stdout_stream = new BufferedInputStream(stdout_inner_stream); - } - - if (fds[2] == -1) - stderr_stream = ProcessBuilder.NullInputStream.INSTANCE; - else { - FileDescriptor stderr_fd = new FileDescriptor(); - fdAccess.set(stderr_fd, fds[2]); - stderr_stream = new DeferredCloseInputStream(stderr_fd); - } - - processReaperExecutor.execute(new Runnable() { - public void run() { - int exitcode = waitForProcessExit(pid); - UNIXProcess.this.processExited(exitcode); - }}); - } - - void processExited(int exitcode) { - synchronized (this) { - this.exitcode = exitcode; - hasExited = true; - notifyAll(); - } - } - - public OutputStream getOutputStream() { - return stdin_stream; - } - - public InputStream getInputStream() { - return stdout_stream; - } - - public InputStream getErrorStream() { - return stderr_stream; - } - - public synchronized int waitFor() throws InterruptedException { - while (!hasExited) { - wait(); - } - return exitcode; - } - - @Override - public synchronized boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - if (hasExited) return true; - if (timeout <= 0) return false; - - long timeoutAsNanos = unit.toNanos(timeout); - long startTime = System.nanoTime(); - long rem = timeoutAsNanos; - - while (!hasExited && (rem > 0)) { - wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); - rem = timeoutAsNanos - (System.nanoTime() - startTime); - } - return hasExited; - } - - public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; - } - - private static native void destroyProcess(int pid, boolean force); - private synchronized void destroy(boolean force) { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - if (!hasExited) - destroyProcess(pid, force); - try { - stdin_stream.close(); - if (stdout_inner_stream != null) - stdout_inner_stream.closeDeferred(stdout_stream); - if (stderr_stream instanceof DeferredCloseInputStream) - ((DeferredCloseInputStream) stderr_stream) - .closeDeferred(stderr_stream); - } catch (IOException e) { - // ignore - } - } - - public void destroy() { - destroy(false); - } - - @Override - public Process destroyForcibly() { - destroy(true); - return this; - } - - @Override - public synchronized boolean isAlive() { - return !hasExited; - } - - // A FileInputStream that supports the deferment of the actual close - // operation until the last pending I/O operation on the stream has - // finished. This is required on Solaris because we must close the stdin - // and stdout streams in the destroy method in order to reclaim the - // underlying file descriptors. Doing so, however, causes any thread - // currently blocked in a read on one of those streams to receive an - // IOException("Bad file number"), which is incompatible with historical - // behavior. By deferring the close we allow any pending reads to see -1 - // (EOF) as they did before. - // - private static class DeferredCloseInputStream - extends FileInputStream - { - - private DeferredCloseInputStream(FileDescriptor fd) { - super(fd); - } - - private Object lock = new Object(); // For the following fields - private boolean closePending = false; - private int useCount = 0; - private InputStream streamToClose; - - private void raise() { - synchronized (lock) { - useCount++; - } - } - - private void lower() throws IOException { - synchronized (lock) { - useCount--; - if (useCount == 0 && closePending) { - streamToClose.close(); - } - } - } - - // stc is the actual stream to be closed; it might be this object, or - // it might be an upstream object for which this object is downstream. - // - private void closeDeferred(InputStream stc) throws IOException { - synchronized (lock) { - if (useCount == 0) { - stc.close(); - } else { - closePending = true; - streamToClose = stc; - } - } - } - - public void close() throws IOException { - synchronized (lock) { - useCount = 0; - closePending = false; - } - super.close(); - } - - public int read() throws IOException { - raise(); - try { - return super.read(); - } finally { - lower(); - } - } - - public int read(byte[] b) throws IOException { - raise(); - try { - return super.read(b); - } finally { - lower(); - } - } - - public int read(byte[] b, int off, int len) throws IOException { - raise(); - try { - return super.read(b, off, len); - } finally { - lower(); - } - } - - public long skip(long n) throws IOException { - raise(); - try { - return super.skip(n); - } finally { - lower(); - } - } - - public int available() throws IOException { - raise(); - try { - return super.available(); - } finally { - lower(); - } - } - - } - - private static native void init(); - - static { - init(); - } -}
--- a/src/solaris/classes/sun/awt/X11/ListHelper.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/classes/sun/awt/X11/ListHelper.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * For now, this class manages the list of items and painting thereof, but not * posting of Item or ActionEvents */ -public class ListHelper implements XScrollbarClient { +final class ListHelper implements XScrollbarClient { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.ListHelper"); private final int FOCUS_INSET = 1; @@ -79,24 +79,16 @@ // Holds the true if mouse is dragging outside of the area of the list // The flag is used at the moment of the dragging and releasing mouse // See 6243382 for more information - boolean mouseDraggedOutVertically = false; + private boolean mouseDraggedOutVertically = false; private volatile boolean vsbVisibilityChanged = false; /* * Comment */ - public ListHelper(XWindow peer, - Color[] colors, - int initialSize, - boolean multiSelect, - boolean scrollVert, - boolean scrollHoriz, - Font font, - int maxVisItems, - int SPACE, - int MARGIN, - int BORDER, - int SCROLLBAR) { + ListHelper(XWindow peer, Color[] colors, int initialSize, + boolean multiSelect, boolean scrollVert, boolean scrollHoriz, + Font font, int maxVisItems, int SPACE, int MARGIN, int BORDER, + int SCROLLBAR) { this.peer = peer; this.colors = colors; this.multiSelect = multiSelect; @@ -121,6 +113,7 @@ SCROLLBAR_WIDTH = SCROLLBAR; } + @Override public Component getEventSource() { return peer.getEventSource(); } @@ -129,36 +122,36 @@ /* List management methods */ /**********************************************************************/ - public void add(String item) { + void add(String item) { items.add(item); updateScrollbars(); } - public void add(String item, int index) { + void add(String item, int index) { items.add(index, item); updateScrollbars(); } - public void remove(String item) { + void remove(String item) { // FIXME: need to clean up select list, too? items.remove(item); updateScrollbars(); // Is vsb visible now? } - public void remove(int index) { + void remove(int index) { // FIXME: need to clean up select list, too? items.remove(index); updateScrollbars(); // Is vsb visible now? } - public void removeAll() { + void removeAll() { items.removeAll(items); updateScrollbars(); } - public void setMultiSelect(boolean ms) { + void setMultiSelect(boolean ms) { multiSelect = ms; } @@ -167,7 +160,7 @@ * merely keeps internal track of which items are selected for painting * dealing with target Components happens elsewhere */ - public void select(int index) { + void select(int index) { if (index > getItemCount() - 1) { index = (isEmpty() ? -1 : 0); } @@ -182,13 +175,13 @@ } /* docs */ - public void deselect(int index) { + void deselect(int index) { assert(false); } /* docs */ /* if called for multiselect, return -1 */ - public int getSelectedIndex() { + int getSelectedIndex() { if (!multiSelect) { Integer val = (Integer)selected.get(0); return val.intValue(); @@ -202,21 +195,21 @@ * A getter method for XChoicePeer. * Returns vsbVisiblityChanged value and sets it to false. */ - public boolean checkVsbVisibilityChangedAndReset(){ + boolean checkVsbVisibilityChangedAndReset(){ boolean returnVal = vsbVisibilityChanged; vsbVisibilityChanged = false; return returnVal; } - public boolean isEmpty() { + boolean isEmpty() { return items.isEmpty(); } - public int getItemCount() { + int getItemCount() { return items.size(); } - public String getItem(int index) { + String getItem(int index) { return (String) items.get(index); } @@ -224,15 +217,15 @@ /* GUI-related methods */ /**********************************************************************/ - public void setFocusedIndex(int index) { + void setFocusedIndex(int index) { focusedIndex = index; } - public boolean isFocusedIndex(int index) { + private boolean isFocusedIndex(int index) { return index == focusedIndex; } - public void setFont(Font newFont) { + void setFont(Font newFont) { if (newFont != font) { font = newFont; fm = Toolkit.getDefaultToolkit().getFontMetrics(font); @@ -243,7 +236,7 @@ /* * Returns width of the text of the longest item */ - public int getMaxItemWidth() { + int getMaxItemWidth() { int m = 0; int end = getItemCount(); for(int i = 0 ; i < end ; i++) { @@ -260,7 +253,7 @@ return fm.getHeight() + (2*TEXT_SPACE); } - public int y2index(int y) { + int y2index(int y) { if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("y=" + y +", firstIdx=" + firstDisplayedIndex() +", itemHeight=" + getItemHeight() + ",item_margin=" + ITEM_MARGIN); @@ -275,14 +268,14 @@ public int numItemsDisplayed() {} */ - public int firstDisplayedIndex() { + int firstDisplayedIndex() { if (vsbVis) { return vsb.getValue(); } return 0; } - public int lastDisplayedIndex() { + int lastDisplayedIndex() { // FIXME: need to account for horiz scroll bar if (hsbVis) { assert false : "Implement for horiz scroll bar"; @@ -294,7 +287,7 @@ /* * If the given index is not visible in the List, scroll so that it is. */ - public void makeVisible(int index) { + private void makeVisible(int index) { if (vsbVis) { if (index < firstDisplayedIndex()) { vsb.setValue(index); @@ -306,7 +299,7 @@ } // FIXME: multi-select needs separate focused index - public void up() { + void up() { int curIdx = getSelectedIndex(); int numItems = getItemCount(); int newIdx; @@ -323,12 +316,12 @@ select(newIdx); } - public void down() { + void down() { int newIdx = (getSelectedIndex() + 1) % getItemCount(); select(newIdx); } - public void pageUp() { + void pageUp() { // FIXME: for multi-select, move the focused item, not the selected item if (vsbVis && firstDisplayedIndex() > 0) { if (multiSelect) { @@ -343,7 +336,7 @@ } } } - public void pageDown() { + void pageDown() { if (vsbVis && lastDisplayedIndex() < getItemCount() - 1) { if (multiSelect) { assert false : "Implement pageDown() for multiSelect"; @@ -357,17 +350,17 @@ } } } - public void home() {} - public void end() {} + void home() {} + void end() {} - public boolean isVSBVisible() { return vsbVis; } - public boolean isHSBVisible() { return hsbVis; } + boolean isVSBVisible() { return vsbVis; } + boolean isHSBVisible() { return hsbVis; } - public XVerticalScrollbar getVSB() { return vsb; } - public XHorizontalScrollbar getHSB() { return hsb; } + XVerticalScrollbar getVSB() { return vsb; } + XHorizontalScrollbar getHSB() { return hsb; } - public boolean isInVertSB(Rectangle bounds, int x, int y) { + boolean isInVertSB(Rectangle bounds, int x, int y) { if (vsbVis) { assert vsb != null : "Vert scrollbar is visible, yet is null?"; int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height; @@ -379,7 +372,7 @@ return false; } - public boolean isInHorizSB(Rectangle bounds, int x, int y) { + boolean isInHorizSB(Rectangle bounds, int x, int y) { if (hsbVis) { assert hsb != null : "Horiz scrollbar is visible, yet is null?"; @@ -392,7 +385,7 @@ return false; } - public void handleVSBEvent(MouseEvent e, Rectangle bounds, int x, int y) { + void handleVSBEvent(MouseEvent e, Rectangle bounds, int x, int y) { int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height; vsb.handleMouseEvent(e.getID(), @@ -405,7 +398,7 @@ * Called when items are added/removed. * Update whether the scrollbar is visible or not, scrollbar values */ - void updateScrollbars() { + private void updateScrollbars() { boolean oldVsbVis = vsbVis; vsbVis = vsb != null && items.size() > maxVisItems; if (vsbVis) { @@ -420,10 +413,11 @@ // FIXME: check if added item makes a hsb necessary (if supported, that of course) } - public int getNumItemsDisplayed() { + private int getNumItemsDisplayed() { return items.size() > maxVisItems ? maxVisItems : items.size(); } + @Override public void repaintScrollbarRequest(XScrollbar sb) { Graphics g = peer.getGraphics(); Rectangle bounds = peer.getBounds(); @@ -436,6 +430,7 @@ g.dispose(); } + @Override public void notifyValue(XScrollbar obj, int type, int v, boolean isAdjusting) { if (obj == vsb) { int oldScrollValue = vsb.getValue(); @@ -467,7 +462,7 @@ } } - public void updateColors(Color[] newColors) { + void updateColors(Color[] newColors) { colors = newColors; } @@ -481,7 +476,7 @@ XVerticalScrollbar vsb, XHorizontalScrollbar hsb) { */ - public void paintItems(Graphics g, + void paintItems(Graphics g, Color[] colors, Rectangle bounds) { // paint border @@ -490,17 +485,14 @@ // paint focus? } - public void paintAllItems(Graphics g, + void paintAllItems(Graphics g, Color[] colors, Rectangle bounds) { paintItems(g, colors, bounds, firstDisplayedIndex(), lastDisplayedIndex()); } - public void paintItems(Graphics g, - Color[] colors, - Rectangle bounds, - int first, - int last) { + private void paintItems(Graphics g, Color[] colors, Rectangle bounds, + int first, int last) { peer.flush(); int x = BORDER_WIDTH + ITEM_MARGIN; int width = bounds.width - 2*ITEM_MARGIN - 2*BORDER_WIDTH - (vsbVis ? SCROLLBAR_WIDTH : 0); @@ -529,12 +521,9 @@ /* * comment about what is painted (i.e. the focus rect */ - public void paintItem(Graphics g, - Color[] colors, - String string, - int x, int y, int width, int height, - boolean selected, - boolean focused) { + private void paintItem(Graphics g, Color[] colors, String string, int x, + int y, int width, int height, boolean selected, + boolean focused) { //System.out.println("LP.pI(): x="+x+" y="+y+" w="+width+" h="+height); //g.setColor(colors[BACKGROUND_COLOR]); @@ -575,7 +564,7 @@ //g.clipRect(clip.x, clip.y, clip.width, clip.height); } - boolean isItemSelected(int index) { + private boolean isItemSelected(int index) { Iterator itr = selected.iterator(); while (itr.hasNext()) { Integer val = (Integer)itr.next(); @@ -586,7 +575,7 @@ return false; } - public void paintVSB(Graphics g, Color colors[], Rectangle bounds) { + private void paintVSB(Graphics g, Color colors[], Rectangle bounds) { int height = bounds.height - 2*BORDER_WIDTH - (hsbVis ? (SCROLLBAR_WIDTH-2) : 0); Graphics ng = g.create(); @@ -602,7 +591,7 @@ } } - public void paintHSB(Graphics g, Color colors[], Rectangle bounds) { + private void paintHSB(Graphics g, Color colors[], Rectangle bounds) { }
--- a/src/solaris/classes/sun/awt/X11/XLightweightFramePeer.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/classes/sun/awt/X11/XLightweightFramePeer.java Thu Aug 14 13:24:00 2014 -0700 @@ -26,6 +26,7 @@ package sun.awt.X11; import java.awt.Graphics; +import java.awt.dnd.DropTarget; import sun.awt.LightweightFrame; import sun.swing.JLightweightFrame; @@ -69,4 +70,14 @@ public void updateCursorImmediately() { SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget()); } + + @Override + public void addDropTarget(DropTarget dt) { + getLwTarget().addDropTarget(dt); + } + + @Override + public void removeDropTarget(DropTarget dt) { + getLwTarget().removeDropTarget(dt); + } }
--- a/src/solaris/classes/sun/awt/X11/XSelection.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/classes/sun/awt/X11/XSelection.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ /** * A class which interfaces with the X11 selection service. */ -public final class XSelection { +final class XSelection { /* Maps atoms to XSelection instances. */ private static final Hashtable<XAtom, XSelection> table = new Hashtable<XAtom, XSelection>(); @@ -118,11 +118,10 @@ /** * Creates a selection object. * - * @param atom the selection atom. - * @param clpbrd the corresponding clipoboard - * @exception NullPointerException if atom is <code>null</code>. + * @param atom the selection atom + * @throws NullPointerException if atom is {@code null} */ - public XSelection(XAtom atom) { + XSelection(XAtom atom) { if (atom == null) { throw new NullPointerException("Null atom"); } @@ -134,8 +133,8 @@ return selectionAtom; } - public synchronized boolean setOwner(Transferable contents, Map formatMap, - long[] formats, long time) + synchronized boolean setOwner(Transferable contents, Map formatMap, + long[] formats, long time) { long owner = XWindow.getXAWTRootWindow().getWindow(); long selection = selectionAtom.getAtom(); @@ -433,7 +432,7 @@ return data != null ? data : new byte[0]; } - void validateDataGetter(WindowPropertyGetter propertyGetter) + private void validateDataGetter(WindowPropertyGetter propertyGetter) throws IOException { // The order of checks is important because a property getter
--- a/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Aug 14 13:24:00 2014 -0700 @@ -903,6 +903,11 @@ } public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { + final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); + if (f != null) { + return f.createDragSourceContextPeer(dge); + } + return XDragSourceContextPeer.createDragSourceContextPeer(dge); } @@ -913,6 +918,11 @@ int srcActions, DragGestureListener dgl) { + final LightweightFrame f = SunToolkit.getLightweightFrame(c); + if (f != null) { + return f.createDragGestureRecognizer(recognizerClass, ds, c, srcActions, dgl); + } + if (MouseDragGestureRecognizer.class.equals(recognizerClass)) return (T)new XMouseDragGestureRecognizer(ds, c, srcActions, dgl); else
--- a/src/solaris/classes/sun/awt/X11FontManager.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/classes/sun/awt/X11FontManager.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package sun.awt; import java.awt.GraphicsEnvironment; @@ -29,7 +54,7 @@ /** * The X11 implementation of {@link FontManager}. */ -public class X11FontManager extends SunFontManager { +public final class X11FontManager extends SunFontManager { // constants identifying XLFD and font ID fields private static final int FOUNDRY_FIELD = 1; @@ -129,8 +154,6 @@ */ private static String[] fontdirs = null; - private static String[] defaultPlatformFont = null; - private FontConfigManager fcManager = null; public static X11FontManager getInstance() { @@ -768,11 +791,9 @@ return getFontPathNative(noType1Fonts); } - public String[] getDefaultPlatformFont() { - if (defaultPlatformFont != null) { - return defaultPlatformFont; - } - String[] info = new String[2]; + @Override + protected String[] getDefaultPlatformFont() { + final String[] info = new String[2]; getFontConfigManager().initFontConfigFonts(false); FontConfigManager.FcCompFont[] fontConfigFonts = getFontConfigManager().getFontConfigFonts(); @@ -798,8 +819,7 @@ info[1] = "/dialog.ttf"; } } - defaultPlatformFont = info; - return defaultPlatformFont; + return info; } public synchronized FontConfigManager getFontConfigManager() {
--- a/src/solaris/native/java/lang/UNIXProcess_md.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/native/java/lang/UNIXProcess_md.c Thu Aug 14 13:24:00 2014 -0700 @@ -598,9 +598,9 @@ */ assert(prog != NULL && argBlock != NULL); if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch; - if ((pprog = getBytes(env, prog)) == NULL) goto Catch; - if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; - if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; + if ((pprog = getBytes(env, prog)) == NULL) goto Catch; + if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; + if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; c->argv[0] = pprog; c->argc = argc + 2; initVectorFromBlock(c->argv+1, pargBlock, argc); @@ -689,10 +689,11 @@ closeSafely(childenv[0]); closeSafely(childenv[1]); - releaseBytes(env, prog, pprog); - releaseBytes(env, argBlock, pargBlock); - releaseBytes(env, envBlock, penvBlock); - releaseBytes(env, dir, c->pdir); + releaseBytes(env, helperpath, phelperpath); + releaseBytes(env, prog, pprog); + releaseBytes(env, argBlock, pargBlock); + releaseBytes(env, envBlock, penvBlock); + releaseBytes(env, dir, c->pdir); free(c->argv); free(c->envv);
--- a/src/solaris/native/java/lang/locale_str.h Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/native/java/lang/locale_str.h Thu Aug 14 13:24:00 2014 -0700 @@ -135,7 +135,7 @@ "sr_SP", "sr_YU", "tchinese", "zh_TW", #endif - "" + "", "", }; /* @@ -188,7 +188,7 @@ "japanese", "ja", "korean", "ko", #endif - "", + "", "", }; /* @@ -201,7 +201,7 @@ "iqtelif", "Latn", "latin", "Latn", #endif - "", + "", "", }; /* @@ -212,7 +212,7 @@ "RN", "US", // used on Linux, not clear what it stands for #endif "YU", "CS", // YU has been removed from ISO 3166 - "", + "", "", }; /* @@ -220,5 +220,5 @@ */ static char *variant_names[] = { "nynorsk", "NY", - "", + "", "", };
--- a/src/solaris/native/java/util/TimeZone_md.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/native/java/util/TimeZone_md.c Thu Aug 14 13:24:00 2014 -0700 @@ -652,11 +652,11 @@ * using <java_home>/lib/tzmappings. If the TZ value is not found, it * trys some libc implementation dependent mappings. If it still * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm - * form. `country', which can be null, is not used for UNIX platforms. + * form. */ /*ARGSUSED1*/ char * -findJavaTZ_md(const char *java_home_dir, const char *country) +findJavaTZ_md(const char *java_home_dir) { char *tz; char *javatz = NULL;
--- a/src/solaris/native/java/util/TimeZone_md.h Wed Aug 13 14:49:53 2014 -0700 +++ b/src/solaris/native/java/util/TimeZone_md.h Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef _TIMEZONE_MD_H #define _TIMEZONE_MD_H -char *findJavaTZ_md(const char *java_home_dir, const char *region); +char *findJavaTZ_md(const char *java_home_dir); char *getGMTOffsetID(); #endif
--- a/src/windows/classes/sun/awt/Win32FontManager.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/classes/sun/awt/Win32FontManager.java Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ import java.util.NoSuchElementException; import java.util.StringTokenizer; -import sun.awt.Win32GraphicsEnvironment; import sun.awt.windows.WFontConfiguration; import sun.font.FontManager; import sun.font.SunFontManager; @@ -48,9 +47,7 @@ /** * The X11 implementation of {@link FontManager}. */ -public class Win32FontManager extends SunFontManager { - - private static String[] defaultPlatformFont = null; +public final class Win32FontManager extends SunFontManager { private static TrueTypeFont eudcFont; @@ -215,12 +212,8 @@ protected synchronized native String getFontPath(boolean noType1Fonts); - public String[] getDefaultPlatformFont() { - - if (defaultPlatformFont != null) { - return defaultPlatformFont; - } - + @Override + protected String[] getDefaultPlatformFont() { String[] info = new String[2]; info[0] = "Arial"; info[1] = "c:\\windows\\fonts"; @@ -247,8 +240,7 @@ info[1] = dirs[0]; } info[1] = info[1] + File.separator + "arial.ttf"; - defaultPlatformFont = info; - return defaultPlatformFont; + return info; } /* register only TrueType/OpenType fonts
--- a/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java Thu Aug 14 13:24:00 2014 -0700 @@ -27,6 +27,7 @@ import java.awt.Component; import java.awt.Graphics; +import java.awt.dnd.DropTarget; import java.awt.event.ComponentEvent; import java.awt.event.MouseEvent; @@ -94,4 +95,14 @@ public boolean isLightweightFramePeer() { return true; } + + @Override + public void addDropTarget(DropTarget dt) { + getLwTarget().addDropTarget(dt); + } + + @Override + public void removeDropTarget(DropTarget dt) { + getLwTarget().removeDropTarget(dt); + } }
--- a/src/windows/classes/sun/awt/windows/WToolkit.java Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/classes/sun/awt/windows/WToolkit.java Thu Aug 14 13:24:00 2014 -0700 @@ -843,6 +843,11 @@ @Override public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { + final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); + if (f != null) { + return f.createDragSourceContextPeer(dge); + } + return WDragSourceContextPeer.createDragSourceContextPeer(dge); } @@ -852,6 +857,11 @@ DragSource ds, Component c, int srcActions, DragGestureListener dgl) { + final LightweightFrame f = SunToolkit.getLightweightFrame(c); + if (f != null) { + return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl); + } + if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl); else
--- a/src/windows/native/java/util/TimeZone_md.c Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/java/util/TimeZone_md.c Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -394,31 +394,34 @@ * * value_type is one of the following values: * VALUE_KEY for exact key matching - * VALUE_MAPID for MapID and country-based mapping (this is + * VALUE_MAPID for MapID (this is * required for the old Windows, such as NT 4.0 SP3). */ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName, - char *mapID, const char *country) + char *mapID) { int line; int IDmatched = 0; FILE *fp; char *javaTZName = NULL; char *items[TZ_NITEMS]; - char mapFileName[_MAX_PATH + 1]; + char *mapFileName; char lineBuffer[MAX_ZONE_CHAR * 4]; - char bestMatch[MAX_ZONE_CHAR]; - int noMapID = *mapID == '\0'; /* no mapID on Vista */ + int noMapID = *mapID == '\0'; /* no mapID on Vista and later */ - bestMatch[0] = '\0'; - + mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1); + if (mapFileName == NULL) { + return NULL; + } strcpy(mapFileName, java_home_dir); strcat(mapFileName, MAPPINGS_FILE); if ((fp = fopen(mapFileName, "r")) == NULL) { jio_fprintf(stderr, "can't open %s.\n", mapFileName); + free((void *) mapFileName); return NULL; } + free((void *) mapFileName); line = 0; while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) { @@ -469,18 +472,6 @@ javaTZName = _strdup(items[TZ_JAVA_NAME]); break; } - /* - * Try to find the most likely time zone. - */ - if (*items[TZ_REGION] == '\0') { - strncpy(bestMatch, items[TZ_JAVA_NAME], MAX_ZONE_CHAR); - } else if (country != NULL && strcmp(items[TZ_REGION], country) == 0) { - if (value_type == VALUE_MAPID) { - javaTZName = _strdup(items[TZ_JAVA_NAME]); - break; - } - strncpy(bestMatch, items[TZ_JAVA_NAME], MAX_ZONE_CHAR); - } } else { if (IDmatched == 1) { /* @@ -492,9 +483,6 @@ } fclose(fp); - if (javaTZName == NULL && bestMatch[0] != '\0') { - javaTZName = _strdup(bestMatch); - } return javaTZName; illegal_format: @@ -506,7 +494,7 @@ /* * Detects the platform time zone which maps to a Java time zone ID. */ -char *findJavaTZ_md(const char *java_home_dir, const char *country) +char *findJavaTZ_md(const char *java_home_dir) { char winZoneName[MAX_ZONE_CHAR]; char winMapID[MAX_MAPID_LENGTH]; @@ -521,7 +509,7 @@ std_timezone = _strdup(winZoneName); } else { std_timezone = matchJavaTZ(java_home_dir, result, - winZoneName, winMapID, country); + winZoneName, winMapID); } }
--- a/src/windows/native/java/util/TimeZone_md.h Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/java/util/TimeZone_md.h Thu Aug 14 13:24:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #ifndef _TIMEZONE_MD_H #define _TIMEZONE_MD_H -char *findJavaTZ_md(const char *java_home_dir, const char *region); +char *findJavaTZ_md(const char *java_home_dir); char *getGMTOffsetID(); #endif
--- a/src/windows/native/sun/windows/awt_Component.cpp Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Component.cpp Thu Aug 14 13:24:00 2014 -0700 @@ -467,7 +467,9 @@ jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig"); DASSERT(win32GCCls != NULL); DASSERT(env->IsInstanceOf(compGC, win32GCCls)); - CHECK_NULL(win32GCCls); + if (win32GCCls == NULL) { + throw std::bad_alloc(); + } env->SetObjectField(peer, AwtComponent::peerGCID, compGC); } } @@ -2141,19 +2143,7 @@ } jlong getMessageTimeUTC() { - return windowsToUTC(getMessageTimeWindows()); - } - - // If calling order of GetTickCount and JVM_CurrentTimeMillis - // is swapped, it would sometimes give different result. - // Anyway, we would not always have determinism - // and sortedness of time conversion here (due to Windows's - // timers peculiarities). Having some euristic algorithm might - // help here. - jlong windowsToUTC(DWORD windowsTime) { - jlong offset = ::GetTickCount() - windowsTime; - jlong jvm_time = ::JVM_CurrentTimeMillis(NULL, 0); - return jvm_time - offset; + return ::JVM_CurrentTimeMillis(NULL, 0); } } //TimeHelper @@ -3578,7 +3568,7 @@ SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED, - TimeHelper::windowsToUTC(msg.time), jkey, character, + TimeHelper::getMessageTimeUTC(), jkey, character, modifiers, keyLocation, (jlong)wkey, &msg); // bugid 4724007: Windows does not create a WM_CHAR for the Del key @@ -3588,7 +3578,7 @@ // for Java - we don't want Windows trying to process it). if (jkey == java_awt_event_KeyEvent_VK_DELETE) { SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, - TimeHelper::windowsToUTC(msg.time), + TimeHelper::getMessageTimeUTC(), java_awt_event_KeyEvent_VK_UNDEFINED, character, modifiers, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0); @@ -3620,7 +3610,7 @@ UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED, - TimeHelper::windowsToUTC(msg.time), jkey, character, + TimeHelper::getMessageTimeUTC(), jkey, character, modifiers, keyLocation, (jlong)wkey, &msg); return mrConsume; } @@ -3665,7 +3655,7 @@ jint modifiers = GetJavaModifiers(); SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, - TimeHelper::windowsToUTC(msg.time), + TimeHelper::getMessageTimeUTC(), java_awt_event_KeyEvent_VK_UNDEFINED, unicodeChar, modifiers, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, @@ -3734,7 +3724,7 @@ InitMessage(&msg, message, character, MAKELPARAM(repCnt, flags)); SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, - TimeHelper::windowsToUTC(msg.time), + TimeHelper::getMessageTimeUTC(), java_awt_event_KeyEvent_VK_UNDEFINED, unicodeChar, modifiers, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
--- a/src/windows/native/sun/windows/awt_Cursor.cpp Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Cursor.cpp Thu Aug 14 13:24:00 2014 -0700 @@ -229,9 +229,10 @@ if (cur != NULL) { ::SetCursor(cur); } else { - safe_ExceptionOccurred(env); + if (safe_ExceptionOccurred(env)) { + env->ExceptionClear(); + } } - if (AwtCursor::updateCursorID == NULL) { jclass cls = env->FindClass("sun/awt/windows/WGlobalCursorManager");
--- a/src/windows/native/sun/windows/awt_PrintJob.cpp Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/sun/windows/awt_PrintJob.cpp Thu Aug 14 13:24:00 2014 -0700 @@ -758,6 +758,7 @@ // through print dialog or start of printing // None of those may have happened yet, so call initPrinter() initPrinter(env, self); + JNU_CHECK_EXCEPTION(env); HANDLE hDevNames = AwtPrintControl::getPrintHDName(env, self); HDC hdc = AwtPrintControl::getPrintDC(env, self); @@ -1102,6 +1103,7 @@ jboolean err; initPrinter(env, self); + JNU_CHECK_EXCEPTION(env); // check for collation HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self); @@ -1362,6 +1364,13 @@ } initPrinter(env, self); + if (env->ExceptionCheck()) { + if (dest != NULL) { + JNU_ReleaseStringPlatformChars(env, dest, destination); + } + return JNI_FALSE; + } + HDC printDC = AwtPrintControl::getPrintDC(env, self); SAVE_CONTROLWORD @@ -3827,6 +3836,7 @@ // pixels per inch in y direction jint yRes = GetDeviceCaps(printDC, LOGPIXELSY); err = setIntField(env, self, YRES_STR, yRes); + if (err) return; // x coord of printable area in pixels jint xOrg = GetDeviceCaps(printDC, PHYSICALOFFSETX);
--- a/src/windows/native/sun/windows/awt_TrayIcon.cpp Wed Aug 13 14:49:53 2014 -0700 +++ b/src/windows/native/sun/windows/awt_TrayIcon.cpp Thu Aug 14 13:24:00 2014 -0700 @@ -325,7 +325,7 @@ MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button) { - jlong now = TimeHelper::windowsToUTC(::GetTickCount()); + jlong now = TimeHelper::getMessageTimeUTC(); jint javaModif = AwtComponent::GetJavaModifiers(); if (lastClickTrIc == this && @@ -361,14 +361,14 @@ MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::windowsToUTC(::GetTickCount()), + SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(), x, y, AwtComponent::GetJavaModifiers(), clickCount, (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? TRUE : FALSE), AwtComponent::GetButton(button), &msg); if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED, - TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(), + TimeHelper::getMessageTimeUTC(), x, y, AwtComponent::GetJavaModifiers(), clickCount, JNI_FALSE, AwtComponent::GetButton(button)); } m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state @@ -395,7 +395,7 @@ if ((flags & ALL_MK_BUTTONS) != 0) { m_mouseButtonClickAllowed = 0; } else { - SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y, + SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::getMessageTimeUTC(), x, y, AwtComponent::GetJavaModifiers(), 0, JNI_FALSE, java_awt_event_MouseEvent_NOBUTTON, &msg); } @@ -408,7 +408,7 @@ if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) { MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()), + SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(), AwtComponent::GetJavaModifiers(), &msg); } return mrConsume; @@ -417,14 +417,14 @@ MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y) { static jlong lastKeySelectTime = 0; - jlong now = TimeHelper::windowsToUTC(::GetTickCount()); + jlong now = TimeHelper::getMessageTimeUTC(); // If a user selects a notify icon with the ENTER key, // Shell 5.0 sends double NIN_KEYSELECT notification. if (lastKeySelectTime != now) { MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()), + SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(), AwtComponent::GetJavaModifiers(), &msg); } lastKeySelectTime = now; @@ -441,7 +441,7 @@ if (clickCount == 2) { MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()), + SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(), AwtComponent::GetJavaModifiers(), &msg); } return mrConsume;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Focus/SortingFPT/JDK8048887.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8048887 + @summary Tests SortingFTP for an exception caused by the tim-sort algo. + @author anton.tarasov: area=awt.focus + @run main JDK8040632 +*/ + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.Dimension; +import java.awt.Color; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class JDK8048887 { + + static volatile boolean passed = true; + + public static void main(String[] args) { + JDK8048887 app = new JDK8048887(); + app.start(); + } + + public void start() { + final CountDownLatch latch = new CountDownLatch(1); + + SwingUtilities.invokeLater(() -> { + // Catch the original exception which sounds like: + // java.lang.IllegalArgumentException: Comparison method violates its general contract! + Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + e.printStackTrace(); + if (e instanceof IllegalArgumentException) { + passed = false; + latch.countDown(); + } + } + }); + + TestDialog d = new TestDialog(); + // It's expected that the dialog is focused on start. + // The listener is called after the FTP completes processing and the bug is reproduced or not. + d.addWindowFocusListener(new WindowAdapter() { + public void windowGainedFocus(WindowEvent e) { + latch.countDown(); + } + }); + d.setVisible(true); + }); + + try { + latch.await(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (passed) + System.out.println("Test passed."); + else + throw new RuntimeException("Test failed!"); + } +} + +class TestDialog extends JFrame { + + // The layout of the components reproduces the transitivity issue + // with SortingFocusTraversalPolicy relying on the tim-sort algo. + + private static int[] Xs = new int[] {71, 23, 62, 4, 79, 39, 34, 9, 84, 58, 30, 34, 38, 15, 69, 10, 44, 95, 70, 54, + 44, 62, 77, 64, 70, 83, 31, 48, 96, 54, 40, 3, 60, 58, 3, 20, 94, 54, 26, 19, 48, 47, 12, 70, 86, 43, 71, 97, 19, + 69, 90, 22, 43, 76, 10, 60, 29, 49, 9, 9, 15, 73, 85, 80, 81, 35, 87, 43, 17, 57, 38, 44, 29, 86, 96, 15, 57, 26, + 27, 78, 26, 87, 43, 6, 4, 16, 57, 99, 32, 86, 96, 5, 50, 69, 12, 4, 36, 84, 71, 60, 22, 46, 11, 44, 87, 3, 23, 14, + 43, 25, 32, 44, 11, 18, 77, 2, 51, 87, 88, 53, 69, 37, 14, 10, 25, 73, 39, 33, 91, 51, 96, 9, 74, 66, 70, 42, 72, + 7, 82, 40, 91, 33, 83, 54, 33, 50, 83, 1, 81, 32, 66, 11, 75, 56, 53, 45, 1, 69, 46, 31, 79, 58, 12, 20, 92, 49, + 50, 90, 33, 8, 43, 93, 72, 78, 9, 56, 84, 60, 30, 39, 33, 88, 84, 56, 49, 47, 4, 90, 57, 6, 23, 96, 37, 88, 22, 79, + 35, 80, 45, 55}; + + public TestDialog() { + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + for (int i=0; i < Xs.length; i++) { + gbc.gridx = Xs[i]; + gbc.gridy = 100 - gbc.gridx; + panel.add(new MyComponent(), gbc); + } + getRootPane().getContentPane().add(panel); + pack(); + } + + public static class MyComponent extends JPanel { + private final static Dimension SIZE = new Dimension(1,1); + + public MyComponent() { + setBackground(Color.BLACK); + setOpaque(true); + } + + @Override + public Dimension getPreferredSize() { + return SIZE; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Focus/WindowIsFocusableAccessByThreadsTest/WindowIsFocusableAccessByThreadsTest.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8047288 + @summary Tests method isFocusable of Window component. It should be accessed only from EDT + @author artem.malinko@oracle.com + @library ../../regtesthelpers + @build Util + @run main WindowIsFocusableAccessByThreadsTest +*/ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.util.concurrent.atomic.AtomicBoolean; + +public class WindowIsFocusableAccessByThreadsTest { + private static AtomicBoolean testPassed = new AtomicBoolean(true); + private static volatile TestFrame frame; + private static volatile TestWindow window; + private static volatile Button openWindowBtn; + + public static void main(String[] args) { + frame = new TestFrame("Test EDT access to Window components"); + window = new TestWindow(frame); + + SwingUtilities.invokeLater(WindowIsFocusableAccessByThreadsTest::init); + + Util.waitTillShown(frame); + Robot robot = Util.createRobot(); + Util.clickOnComp(frame, robot, 100); + Util.clickOnComp(openWindowBtn, robot, 100); + + Util.waitTillShown(window); + + if (!testPassed.get()) { + throw new RuntimeException("Window component methods has been accessed not " + + "from Event Dispatching Thread"); + } + } + + private static void init() { + frame.setSize(400, 400); + frame.setLayout(new FlowLayout()); + openWindowBtn = new Button("open window"); + openWindowBtn.addActionListener(e -> { + window.setSize(100, 100); + window.setLocation(400, 100); + window.setVisible(true); + }); + frame.add(openWindowBtn); + frame.setVisible(true); + } + + private static void testThread() { + if (!SwingUtilities.isEventDispatchThread()) { + testPassed.set(false); + } + } + + private static class TestWindow extends Window { + public TestWindow(Frame owner) { + super(owner); + } + + // isFocusable method is final and we can't add this test to it. + // But it invokes getFocusableWindowState and here we can check + // if thread is EDT. + @Override + public boolean getFocusableWindowState() { + testThread(); + return super.getFocusableWindowState(); + } + } + + private static class TestFrame extends Frame { + private TestFrame(String title) throws HeadlessException { + super(title); + } + + // isFocusable method is final and we can't add this test to it. + // But it invokes getFocusableWindowState and here we can check + // if thread is EDT. + @Override + public boolean getFocusableWindowState() { + testThread(); + return super.getFocusableWindowState(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Graphics2D/DrawString/DrawStringCrash.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8043508 + * @summary Drawing a very long string crashes VM + */ + +import java.awt.*; +import java.awt.image.*; + +public class DrawStringCrash { + + public static void main(String[] args) { + StringBuffer sb = new StringBuffer(); + String s = "abcdefghijklmnopqrstuzwxyz"; + for (int x = 0; x < 100000 ; x++) { + sb.append(s); + } + // Now have a string which uses approx 5Mb memory + // Loop again drawing doubling each time until + // we reach 8 billion chars or get OOME which means we can't + // go any further. + // Often there is no crash because Java OOM happens + // long before native heap runs out. + long maxLen = 8L * 1024 * 1024 * 1024; + int len = sb.length(); + + BufferedImage bi = + new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + while (len < maxLen) { + try { + g2d.drawString(s, 20, 20); + } catch (OutOfMemoryError e) { + return; + } + sb.append(sb); + len *= 2; + } + return; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.awt.SunToolkit; + +import java.awt.*; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 8046495 + * @summary Verifies that mouse/key events has always increasing 'when' timestamps + * @author Anton Nashatyrev + * @run main EventWhenTest + */ +public class EventWhenTest { + + private static volatile int eventsCount = 0; + private static volatile boolean failed = false; + + static { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + long lastWhen = 0; + + @Override + public void eventDispatched(AWTEvent event) { + long curWhen; + if (event instanceof KeyEvent) { + curWhen = ((KeyEvent) event).getWhen(); + } else if (event instanceof MouseEvent) { + curWhen = ((MouseEvent) event).getWhen(); + } else { + return; + } + + eventsCount++; + + if (curWhen < lastWhen) { + System.err.println("FAILED: " + curWhen + " < " + lastWhen + + " for " + event); + failed = true; + } else { + lastWhen = curWhen; + } + } + }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); + } + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Frame frame = new Frame(); + + try { + Button b = new Button("Button"); + frame.setBounds(300, 300, 300, 300); + frame.add(b); + frame.setVisible(true); + toolkit.realSync(); + + Robot robot = new Robot(); + robot.mouseMove((int)frame.getLocationOnScreen().getX() + 150, + (int)frame.getLocationOnScreen().getY() + 150); + + eventsCount = 0; + System.out.println("Clicking mouse..."); + for (int i = 0; i < 300 && !failed; i++) { + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Thread.sleep(10); + b.setLabel("Click: " + i); + } + + if (eventsCount == 0) { + throw new RuntimeException("No events were received"); + } + + if (failed) { + throw new RuntimeException("Test failed."); + } + System.out.println("Clicking mouse done: " + eventsCount + " events."); + + b.requestFocusInWindow(); + toolkit.realSync(); + + eventsCount = 0; + System.out.println("Typing a key..."); + for (int i = 0; i < 300 && !failed; i++) { + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + Thread.sleep(10); + b.setLabel("Type: " + i); + } + System.out.println("Key typing done: " + eventsCount + " events."); + + if (eventsCount == 0) { + throw new RuntimeException("No events were received"); + } + + if (failed) { + throw new RuntimeException("Test failed."); + } + + System.out.println("Success!"); + } finally { + frame.dispose(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/im/8041990/bug8041990.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 8041990 + @summary Language specific keys does not work in applets when opened outside the browser + @author Petr Pchelko +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.InputMethodEvent; +import java.awt.font.TextHitInfo; +import java.text.AttributedString; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; + +public class bug8041990 { + private static JFrame frame; + private static JComponent component; + + public static void main(String[] args) throws Exception { + ThreadGroup stubTG = new ThreadGroup(getRootThreadGroup(), "Stub Thread Group"); + ThreadGroup swingTG = new ThreadGroup(getRootThreadGroup(), "SwingTG"); + try { + Thread stubThread = new Thread(stubTG, SunToolkit::createNewAppContext); + stubThread.start(); + stubThread.join(); + + CountDownLatch startSwingLatch = new CountDownLatch(1); + new Thread(swingTG, () -> { + SunToolkit.createNewAppContext(); + SwingUtilities.invokeLater(() -> { + frame = new JFrame(); + component = new JLabel("Test Text"); + frame.add(component); + frame.setBounds(100, 100, 100, 100); + frame.setVisible(true); + startSwingLatch.countDown(); + }); + }).start(); + startSwingLatch.await(); + + AtomicReference<Exception> caughtException = new AtomicReference<>(); + Thread checkThread = new Thread(getRootThreadGroup(), () -> { + try { + // If the bug is present this will throw exception + new InputMethodEvent(component, + InputMethodEvent.CARET_POSITION_CHANGED, + TextHitInfo.leading(0), + TextHitInfo.trailing(0)); + } catch (Exception e) { + caughtException.set(e); + } + }); + checkThread.start(); + checkThread.join(); + + if (caughtException.get() != null) { + throw new RuntimeException("Failed. Caught exception!", caughtException.get()); + } + } finally { + new Thread(swingTG, () -> SwingUtilities.invokeLater(() -> { + if (frame != null) { + frame.dispose(); + } + })).start(); + } + } + + private static ThreadGroup getRootThreadGroup() { + ThreadGroup currentTG = Thread.currentThread().getThreadGroup(); + ThreadGroup parentTG = currentTG.getParent(); + while (parentTG != null) { + currentTG = parentTG; + parentTG = currentTG.getParent(); + } + return currentTG; + } +}
--- a/test/java/lang/ProcessBuilder/Basic.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/java/lang/ProcessBuilder/Basic.java Thu Aug 14 13:24:00 2014 -0700 @@ -2246,9 +2246,9 @@ fail("Test failed: Process exited prematurely"); } long end = System.nanoTime(); - // give waitFor(timeout) a wide berth (100ms) + // give waitFor(timeout) a wide berth (200ms) // Old AIX machines my need a little longer. - if ((end - start) > 100000000L * (AIX.is() ? 4 : 1)) + if ((end - start) > 200000000L * (AIX.is() ? 2 : 1)) fail("Test failed: waitFor took too long (" + (end - start) + "ns)"); p.destroy();
--- a/test/java/lang/ProcessBuilder/SecurityManagerClinit.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/java/lang/ProcessBuilder/SecurityManagerClinit.java Thu Aug 14 13:24:00 2014 -0700 @@ -54,9 +54,6 @@ System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - // A funky contrived security setup, just for bug repro purposes. - java.security.Security.setProperty("package.access", "java.util"); - final Policy policy = new Policy (new FilePermission("<<ALL FILES>>", "execute"),
--- a/test/java/util/Collections/CheckedListReplaceAll.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/java/util/Collections/CheckedListReplaceAll.java Thu Aug 14 13:24:00 2014 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8047795 + * @bug 8047795 8053938 * @summary Ensure that replaceAll operator cannot add bad elements * @author Mike Duigou */ @@ -46,5 +46,16 @@ thwarted.printStackTrace(System.out); System.out.println("Curses! Foiled again!"); } + + unwrapped = Arrays.asList(new Object[]{}); // Empty list + wrapped = Collections.checkedList(unwrapped, Integer.class); + try { + wrapped.replaceAll((UnaryOperator)null); + System.out.printf("Bwahaha! I have defeated you! %s\n", wrapped); + throw new RuntimeException("NPE not thrown when passed a null operator"); + } catch (NullPointerException thwarted) { + thwarted.printStackTrace(System.out); + System.out.println("Curses! Foiled again!"); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Collections/SyncSubMutexes.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8048209 + * @summary Check that Collections.synchronizedNavigableSet().tailSet() is using + * the same lock object as it's source. + * @run testng SyncSubMutexes + */ +import java.lang.reflect.Field; +import java.util.*; +import java.util.Set; +import java.util.Arrays; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.assertSame; + +public class SyncSubMutexes { + + @Test(dataProvider = "Collections") + public void testCollections(Collection<String> instance) { + // nothing to test, no subset methods + } + + @Test(dataProvider = "Lists") + public void testLists(List<String> instance) { + assertSame(getSyncCollectionMutex(instance.subList(0, 1)), getSyncCollectionMutex(instance)); + } + + @Test(dataProvider = "Sets") + public void testSets(Set<String> instance) { + // nothing to test, no subset methods + + } + + @Test(dataProvider = "SortedSets") + public void testSortedSets(SortedSet<String> instance) { + assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); + + } + + @Test(dataProvider = "NavigableSets") + public void testNavigableSets(NavigableSet<String> instance) { + assertSame(getSyncCollectionMutex(instance.descendingSet()), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.headSet("Echo", true)), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie", true)), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", true, "Echo", true)), getSyncCollectionMutex(instance)); + } + + @Test(dataProvider = "Maps") + public void testMaps(Map<String, String> instance) { + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + } + + @Test(dataProvider = "SortedMaps") + public void testSortedMaps(SortedMap<String, String> instance) { + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", "Echo")), getSyncMapMutex(instance)); + } + + @Test(dataProvider = "NavigableMaps") + public void testNavigableMaps(NavigableMap<String, String> instance) { + assertSame(getSyncMapMutex(instance.descendingMap()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.descendingKeySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); + } + + @DataProvider(name = "Collections", parallel = true) + public static Iterator<Object[]> collectionProvider() { + return makeCollections().iterator(); + } + + @DataProvider(name = "Lists", parallel = true) + public static Iterator<Object[]> listProvider() { + return makeLists().iterator(); + } + + @DataProvider(name = "Sets", parallel = true) + public static Iterator<Object[]> setProvider() { + return makeSets().iterator(); + } + + @DataProvider(name = "SortedSets", parallel = true) + public static Iterator<Object[]> sortedsetProvider() { + return makeSortedSets().iterator(); + } + + @DataProvider(name = "NavigableSets", parallel = true) + public static Iterator<Object[]> navigablesetProvider() { + return makeNavigableSets().iterator(); + } + + @DataProvider(name = "Maps", parallel = true) + public static Iterator<Object[]> mapProvider() { + return makeMaps().iterator(); + } + + @DataProvider(name = "SortedMaps", parallel = true) + public static Iterator<Object[]> sortedmapProvider() { + return makeSortedMaps().iterator(); + } + + @DataProvider(name = "NavigableMaps", parallel = true) + public static Iterator<Object[]> navigablemapProvider() { + return makeNavigableMaps().iterator(); + } + + private static final Collection<String> BASE_COLLECTION = Collections.unmodifiableCollection( + Arrays.asList("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf") + ); + private static final Map<String, String> BASE_MAP; + + static { + Map<String, String> map = new HashMap<>(); + for(String each : BASE_COLLECTION) { + map.put(each, "*" + each + "*"); + } + BASE_MAP = Collections.unmodifiableMap(map); + } + + public static Collection<Object[]> makeCollections() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedCollection(new ArrayList<>(BASE_COLLECTION))}); + instances.addAll(makeLists()); + + return instances; + } + + public static Collection<Object[]> makeLists() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION)).subList(1, 2)}); + + return instances; + } + + public static Collection<Object[]> makeSets() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedSet(new TreeSet<>(BASE_COLLECTION))}); + instances.addAll(makeSortedSets()); + return instances; + } + + public static Collection<Object[]> makeSortedSets() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); + instances.addAll(makeNavigableSets()); + + return instances; + } + + public static Collection<Object[]> makeNavigableSets() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).descendingSet().descendingSet()}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", true, "Foxtrot", true)}); + + return instances; + } + + public static Collection<Object[]> makeMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedMap(new HashMap<>(BASE_MAP))}); + instances.addAll(makeSortedMaps()); + + return instances; + } + + public static Collection<Object[]> makeSortedMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP))}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); + instances.addAll(makeNavigableMaps()); + + return instances; + } + + public static Collection<Object[]> makeNavigableMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP))}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP).descendingMap().descendingMap())}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", true, "Foxtrot", true)}); + + return instances; + } + + private static Object getSyncCollectionMutex(Collection<?> from) { + try { + Class<?> synchronizedCollectionClazz = Class.forName("java.util.Collections$SynchronizedCollection"); + Field f = synchronizedCollectionClazz.getDeclaredField("mutex"); + f.setAccessible(true); + return f.get(from); + } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get mutex field.", e); + } + } + + private static Object getSyncMapMutex(Map<?,?> from) { + try { + Class<?> synchronizedMapClazz = Class.forName("java.util.Collections$SynchronizedMap"); + Field f = synchronizedMapClazz.getDeclaredField("mutex"); + f.setAccessible(true); + return f.get(from); + } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get mutex field.", e); + } + } + +}
--- a/test/javax/swing/JMenuItem/8031573/bug8031573.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/javax/swing/JMenuItem/8031573/bug8031573.java Thu Aug 14 13:24:00 2014 -0700 @@ -28,7 +28,7 @@ import javax.swing.SwingUtilities; /* @test - * @bug 8031573 + * @bug 8031573 8040279 * @summary [macosx] Checkmarks of JCheckBoxMenuItems aren't rendered * in high resolution on Retina * @author Alexander Scherbatiy
--- a/test/javax/swing/JOptionPane/8024926/bug8024926.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/javax/swing/JOptionPane/8024926/bug8024926.java Thu Aug 14 13:24:00 2014 -0700 @@ -31,7 +31,7 @@ /** * @test - * @bug 8024926 + * @bug 8024926 8040279 * @summary [macosx] AquaIcon HiDPI support * @author Alexander Scherbatiy * @run applet/manual=yesno bug8024926.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/xml/jaxp/common/8032908/TestFunc.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.w3c.dom.Node; + +public class TestFunc { + + public static String test(Node node) { + String s = node.getTextContent(); + return s; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/xml/jaxp/common/8032908/XSLT.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8032908 + * @summary Test if Node.getTextContent() function correctly returns children + * content + * @compile TestFunc.java XSLT.java + * @run main/othervm XSLT + */ +import java.io.ByteArrayOutputStream; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +public class XSLT { + + static final String XMLTOTRANSFORM = "/in.xml"; + static final String XSLTRANSFORMER = "/test.xsl"; + static final String EXPECTEDRESULT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>ABCDEFG"; + + public static void main(String[] args) throws TransformerException { + ByteArrayOutputStream resStream = new ByteArrayOutputStream(); + TransformerFactory trf = TransformerFactory.newInstance(); + Transformer tr = trf.newTransformer(new StreamSource(System.getProperty("test.src", ".") + XSLTRANSFORMER)); + tr.transform(new StreamSource(System.getProperty("test.src", ".") + XMLTOTRANSFORM), new StreamResult(resStream)); + System.out.println("Transformation completed. Result:" + resStream.toString()); + if (!resStream.toString().equals(EXPECTEDRESULT)) { + throw new RuntimeException("Incorrect transformation result"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/xml/jaxp/common/8032908/in.xml Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<root><elem><level2_0>ABCD</level2_0><level2_1>EFG</level2_1></elem></root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/xml/jaxp/common/8032908/test.xsl Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:transform exclude-result-prefixes="cscdt_ufunc" version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:cscdt_ufunc="http://xml.apache.org/xalan/java"> + <xsl:template match="elem"> + <xsl:value-of select="cscdt_ufunc:TestFunc.test(.)" /> + </xsl:template> +</xsl:transform>
--- a/test/sun/net/ftp/FtpURL.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/sun/net/ftp/FtpURL.java Thu Aug 14 13:24:00 2014 -0700 @@ -483,7 +483,7 @@ // Now let's check the URL handler - url = new URL("ftp://user2:@localhost:" + port + "/%2Fusr/bin;type=d"); + url = new URL("ftp://user2@localhost:" + port + "/%2Fusr/bin;type=d"); con = url.openConnection(); in = new BufferedReader(new InputStreamReader(con.getInputStream())); do {
--- a/test/sun/security/smartcardio/TestAll.java Wed Aug 13 14:49:53 2014 -0700 +++ b/test/sun/security/smartcardio/TestAll.java Thu Aug 14 13:24:00 2014 -0700 @@ -40,6 +40,7 @@ TestMultiplePresent.class, TestPresent.class, TestTransmit.class, + TestDirect.class, }; public static void main(String[] args) throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/smartcardio/TestDirect.java Thu Aug 14 13:24:00 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8046343 + * @summary Make sure that direct protocol is available + * @run main/manual TestDirect + */ + +// This test requires special hardware. + +import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.CardTerminals; +import javax.smartcardio.TerminalFactory; + +public class TestDirect { + public static void main(String[] args) throws Exception { + TerminalFactory terminalFactory = TerminalFactory.getDefault(); + CardTerminals cardTerminals = terminalFactory.terminals(); + CardTerminal cardTerminal = cardTerminals.list().get(0); + Card card = cardTerminal.connect("DIRECT"); + card.disconnect(true); + + System.out.println("OK."); + } +}