提交 3c62fa1b 编写于 作者: L lana

Merge

...@@ -62,25 +62,6 @@ GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/tools/jconsole/Version.java ...@@ -62,25 +62,6 @@ GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/tools/jconsole/Version.java
########################################################################################## ##########################################################################################
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_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/nio/ch/SocketOptionRegistry.java
GENSRC_SOR_SRC := $(JDK_TOPDIR)/src/share/native/sun/nio/ch GENSRC_SOR_SRC := $(JDK_TOPDIR)/src/share/native/sun/nio/ch
......
...@@ -46,10 +46,8 @@ import com.apple.laf.AquaIcon.JRSUIControlSpec; ...@@ -46,10 +46,8 @@ import com.apple.laf.AquaIcon.JRSUIControlSpec;
import com.apple.laf.AquaIcon.SystemIcon; import com.apple.laf.AquaIcon.SystemIcon;
import com.apple.laf.AquaUtils.RecyclableObject; import com.apple.laf.AquaUtils.RecyclableObject;
import com.apple.laf.AquaUtils.RecyclableSingleton; 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.MultiResolutionImage;
import sun.awt.image.MultiResolutionCachedImage;
public class AquaImageFactory { public class AquaImageFactory {
public static IconUIResource getConfirmImageIcon() { public static IconUIResource getConfirmImageIcon() {
...@@ -107,9 +105,9 @@ public class AquaImageFactory { ...@@ -107,9 +105,9 @@ public class AquaImageFactory {
private static final int kAlertIconSize = 64; private static final int kAlertIconSize = 64;
static IconUIResource getAppIconCompositedOn(final Image background) { static IconUIResource getAppIconCompositedOn(final Image background) {
if (background instanceof MultiResolutionBufferedImage) { if (background instanceof MultiResolutionCachedImage) {
int width = background.getWidth(null); int width = background.getWidth(null);
Image mrIconImage = ((MultiResolutionBufferedImage) background).map( Image mrIconImage = ((MultiResolutionCachedImage) background).map(
rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width)); rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width));
return new IconUIResource(new ImageIcon(mrIconImage)); return new IconUIResource(new ImageIcon(mrIconImage));
} }
...@@ -287,23 +285,9 @@ public class AquaImageFactory { ...@@ -287,23 +285,9 @@ public class AquaImageFactory {
private static Image getNSIcon(String imageName) { private static Image getNSIcon(String imageName) {
Image icon = Toolkit.getDefaultToolkit() Image icon = Toolkit.getDefaultToolkit()
.getImage("NSImage://" + imageName); .getImage("NSImage://" + imageName);
if (icon instanceof MultiResolutionImage) {
return icon; 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));
}
public static class NineSliceMetrics { public static class NineSliceMetrics {
public final int wCut, eCut, nCut, sCut; public final int wCut, eCut, nCut, sCut;
public final int minW, minH; public final int minW, minH;
......
...@@ -26,11 +26,14 @@ ...@@ -26,11 +26,14 @@
package com.apple.laf; package com.apple.laf;
import java.awt.*; import java.awt.*;
import java.security.AccessController;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuBarUI; import javax.swing.plaf.basic.BasicMenuBarUI;
import sun.lwawt.macosx.LWCToolkit;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
// MenuBar implementation for Mac L&F // MenuBar implementation for Mac L&F
...@@ -131,28 +134,20 @@ public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvid ...@@ -131,28 +134,20 @@ public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvid
ScreenMenuBar fScreenMenuBar; ScreenMenuBar fScreenMenuBar;
boolean useScreenMenuBar = getScreenMenuBarProperty(); boolean useScreenMenuBar = getScreenMenuBarProperty();
private static String getPrivSysProp(final String propName) {
return java.security.AccessController.doPrivileged(new GetPropertyAction(propName));
}
static boolean getScreenMenuBarProperty() { static boolean getScreenMenuBarProperty() {
final String props[] = new String[]{""}; // Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit
if (LWCToolkit.isEmbedded()) return false;
boolean useScreenMenuBar = false; if (AccessController.doPrivileged(
try { new GetBooleanAction(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"))) {
props[0] = getPrivSysProp(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); return true;
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;
} }
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;
} }
} catch(final Throwable t) { }; return false;
return useScreenMenuBar;
} }
} }
...@@ -174,11 +174,7 @@ abstract class AquaPainter <T extends JRSUIState> { ...@@ -174,11 +174,7 @@ abstract class AquaPainter <T extends JRSUIState> {
bounds, controlState); bounds, controlState);
Image img = cache.getImage(key); Image img = cache.getImage(key);
if (img == null) { if (img == null) {
img = new MultiResolutionCachedImage(imgW, imgH,
Image baseImage = createImage(imgX, imgY, imgW, imgH, bounds,
control, controlState);
img = new MultiResolutionBufferedImage(baseImage,
(rvWidth, rvHeight) -> createImage(imgX, imgY, (rvWidth, rvHeight) -> createImage(imgX, imgY,
rvWidth, rvHeight, bounds, control, controlState)); rvWidth, rvHeight, bounds, control, controlState));
......
...@@ -48,7 +48,7 @@ import sun.security.action.GetPropertyAction; ...@@ -48,7 +48,7 @@ import sun.security.action.GetPropertyAction;
import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2;
import com.apple.laf.AquaImageFactory.SlicedImageControl; import com.apple.laf.AquaImageFactory.SlicedImageControl;
import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.MultiResolutionCachedImage;
final class AquaUtils { final class AquaUtils {
...@@ -124,8 +124,8 @@ final class AquaUtils { ...@@ -124,8 +124,8 @@ final class AquaUtils {
static Image generateLightenedImage(final Image image, final int percent) { static Image generateLightenedImage(final Image image, final int percent) {
final GrayFilter filter = new GrayFilter(true, percent); final GrayFilter filter = new GrayFilter(true, percent);
return (image instanceof MultiResolutionBufferedImage) return (image instanceof MultiResolutionCachedImage)
? ((MultiResolutionBufferedImage) image).map( ? ((MultiResolutionCachedImage) image).map(
rv -> generateLightenedImage(rv, filter)) rv -> generateLightenedImage(rv, filter))
: generateLightenedImage(image, filter); : generateLightenedImage(image, filter);
} }
......
...@@ -43,7 +43,7 @@ import sun.awt.HeadlessToolkit; ...@@ -43,7 +43,7 @@ import sun.awt.HeadlessToolkit;
import sun.misc.ThreadGroupUtils; import sun.misc.ThreadGroupUtils;
import sun.lwawt.macosx.*; import sun.lwawt.macosx.*;
public class CFontManager extends SunFontManager { public final class CFontManager extends SunFontManager {
private FontConfigManager fcManager = null; private FontConfigManager fcManager = null;
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>(); private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
...@@ -61,20 +61,14 @@ public class CFontManager extends SunFontManager { ...@@ -61,20 +61,14 @@ public class CFontManager extends SunFontManager {
return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts); return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts);
} }
private static String[] defaultPlatformFont = null;
/* /*
* Returns an array of two strings. The first element is the * Returns an array of two strings. The first element is the
* name of the font. The second element is the file name. * name of the font. The second element is the file name.
*/ */
@Override @Override
public synchronized String[] getDefaultPlatformFont() { protected String[] getDefaultPlatformFont() {
if (defaultPlatformFont == null) { return new String[]{"Lucida Grande",
defaultPlatformFont = new String[2]; "/System/Library/Fonts/LucidaGrande.ttc"};
defaultPlatformFont[0] = "Lucida Grande";
defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc";
}
return defaultPlatformFont;
} }
// This is a way to register any kind of Font2D, not just files and composites. // This is a way to register any kind of Font2D, not just files and composites.
......
...@@ -94,10 +94,12 @@ public class LWLightweightFramePeer extends LWWindowPeer { ...@@ -94,10 +94,12 @@ public class LWLightweightFramePeer extends LWWindowPeer {
@Override @Override
public void addDropTarget(DropTarget dt) { public void addDropTarget(DropTarget dt) {
getLwTarget().addDropTarget(dt);
} }
@Override @Override
public void removeDropTarget(DropTarget dt) { public void removeDropTarget(DropTarget dt) {
getLwTarget().removeDropTarget(dt);
} }
@Override @Override
......
...@@ -105,6 +105,8 @@ public class LWWindowPeer ...@@ -105,6 +105,8 @@ public class LWWindowPeer
private final SecurityWarningWindow warningWindow; private final SecurityWarningWindow warningWindow;
private volatile boolean targetFocusable;
/** /**
* Current modal blocker or null. * Current modal blocker or null.
* *
...@@ -240,13 +242,12 @@ public class LWWindowPeer ...@@ -240,13 +242,12 @@ public class LWWindowPeer
if (!visible && warningWindow != null) { if (!visible && warningWindow != null) {
warningWindow.setVisible(false, false); warningWindow.setVisible(false, false);
} }
updateFocusableWindowState();
super.setVisibleImpl(visible); super.setVisibleImpl(visible);
// TODO: update graphicsConfig, see 4868278 // TODO: update graphicsConfig, see 4868278
platformWindow.setVisible(visible); platformWindow.setVisible(visible);
if (isSimpleWindow()) { if (isSimpleWindow()) {
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
if (visible) { if (visible) {
if (!getTarget().isAutoRequestFocus()) { if (!getTarget().isAutoRequestFocus()) {
return; return;
...@@ -397,6 +398,7 @@ public class LWWindowPeer ...@@ -397,6 +398,7 @@ public class LWWindowPeer
@Override @Override
public void updateFocusableWindowState() { public void updateFocusableWindowState() {
targetFocusable = getTarget().isFocusableWindow();
platformWindow.updateFocusableWindowState(); platformWindow.updateFocusableWindowState();
} }
...@@ -1220,13 +1222,13 @@ public class LWWindowPeer ...@@ -1220,13 +1222,13 @@ public class LWWindowPeer
} }
private boolean isFocusableWindow() { private boolean isFocusableWindow() {
boolean focusable = getTarget().isFocusableWindow(); boolean focusable = targetFocusable;
if (isSimpleWindow()) { if (isSimpleWindow()) {
LWWindowPeer ownerPeer = getOwnerFrameDialog(this); LWWindowPeer ownerPeer = getOwnerFrameDialog(this);
if (ownerPeer == null) { if (ownerPeer == null) {
return false; return false;
} }
return focusable && ownerPeer.getTarget().isFocusableWindow(); return focusable && ownerPeer.targetFocusable;
} }
return focusable; return focusable;
} }
......
...@@ -32,7 +32,7 @@ import java.awt.image.*; ...@@ -32,7 +32,7 @@ import java.awt.image.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import sun.awt.image.MultiResolutionImage; import sun.awt.image.MultiResolutionImage;
import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.MultiResolutionCachedImage;
import sun.awt.image.SunWritableRaster; import sun.awt.image.SunWritableRaster;
...@@ -60,41 +60,41 @@ public class CImage extends CFRetainedResource { ...@@ -60,41 +60,41 @@ public class CImage extends CFRetainedResource {
// This is used to create a CImage with an NSImage pointer. It MUST be a CFRetained // 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, and the CImage takes ownership of the non-GC retain. If callers need the
// NSImage themselves, they MUST call retain on the NSImage themselves. // 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; if (image == 0) return null;
final Dimension2D size = nativeGetNSImageSize(image); 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 // 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."); if (image == 0) throw new Error("Unable to instantiate CImage with null native image reference.");
return createImageWithSize(image, width, height); 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); final CImage img = new CImage(image);
img.resize(width, height); img.resize(width, height);
return img.toImage(); return img.toImage();
} }
// This is used to create a CImage that represents the icon of the given file. // 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) { public Image createImageOfFile(final String file, final int width, final int height) {
return createBufferedImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, 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); final long image = nativeCreateNSImageFromFileContents(file);
nativeSetNSImageSize(image, width, height); 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) { public Image createSystemImageFromSelector(final String iconSelector, final int width, final int height) {
return createBufferedImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height); return createImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height);
} }
public Image createImageFromName(final String name, final int width, final int 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) { public Image createImageFromName(final String name) {
...@@ -213,7 +213,7 @@ public class CImage extends CFRetainedResource { ...@@ -213,7 +213,7 @@ public class CImage extends CFRetainedResource {
} }
/** @return A MultiResolution image created from nsImagePtr, or null. */ /** @return A MultiResolution image created from nsImagePtr, or null. */
private BufferedImage toImage() { private Image toImage() {
if (ptr == 0) return null; if (ptr == 0) return null;
final Dimension2D size = nativeGetNSImageSize(ptr); final Dimension2D size = nativeGetNSImageSize(ptr);
...@@ -224,11 +224,11 @@ public class CImage extends CFRetainedResource { ...@@ -224,11 +224,11 @@ public class CImage extends CFRetainedResource {
= nativeGetNSImageRepresentationSizes(ptr, = nativeGetNSImageRepresentationSizes(ptr,
size.getWidth(), size.getHeight()); size.getWidth(), size.getHeight());
BufferedImage baseImage = toImage(w, h, w, h); return sizes == null || sizes.length < 2 ?
new MultiResolutionCachedImage(w, h, (width, height)
return sizes == null || sizes.length < 2 ? baseImage -> toImage(w, h, width, height))
: new MultiResolutionBufferedImage(baseImage, sizes, : new MultiResolutionCachedImage(w, h, sizes, (width, height)
(width, height) -> toImage(w, h, width, height)); -> toImage(w, h, width, height));
} }
private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) { private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
......
...@@ -686,6 +686,11 @@ public final class LWCToolkit extends LWToolkit { ...@@ -686,6 +686,11 @@ public final class LWCToolkit extends LWToolkit {
@Override @Override
public DragSourceContextPeer createDragSourceContextPeer( public DragSourceContextPeer createDragSourceContextPeer(
DragGestureEvent dge) throws InvalidDnDOperationException { DragGestureEvent dge) throws InvalidDnDOperationException {
final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent());
if (f != null) {
return f.createDragSourceContextPeer(dge);
}
return CDragSourceContextPeer.createDragSourceContextPeer(dge); return CDragSourceContextPeer.createDragSourceContextPeer(dge);
} }
...@@ -693,6 +698,11 @@ public final class LWCToolkit extends LWToolkit { ...@@ -693,6 +698,11 @@ public final class LWCToolkit extends LWToolkit {
public <T extends DragGestureRecognizer> T createDragGestureRecognizer( public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
Class<T> abstractRecognizerClass, DragSource ds, Component c, Class<T> abstractRecognizerClass, DragSource ds, Component c,
int srcActions, DragGestureListener dgl) { int srcActions, DragGestureListener dgl) {
final LightweightFrame f = SunToolkit.getLightweightFrame(c);
if (f != null) {
return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl);
}
DragGestureRecognizer dgr = null; DragGestureRecognizer dgr = null;
// Create a new mouse drag gesture recognizer if we have a class match: // Create a new mouse drag gesture recognizer if we have a class match:
...@@ -784,6 +794,13 @@ public final class LWCToolkit extends LWToolkit { ...@@ -784,6 +794,13 @@ public final class LWCToolkit extends LWToolkit {
*/ */
native boolean isApplicationActive(); 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 * Native methods section
************************/ ************************/
......
...@@ -1122,7 +1122,10 @@ static NSObject *sAttributeNamesLOCK = nil; ...@@ -1122,7 +1122,10 @@ static NSObject *sAttributeNamesLOCK = nil;
JNIEnv *env = [ThreadUtilities getJNIEnv]; JNIEnv *env = [ThreadUtilities getJNIEnv];
id value = nil; id value = nil;
NSWindow* hostWindow = [[self->fView window] retain];
jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop)
[hostWindow release];
if (focused != NULL) { if (focused != NULL) {
if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
......
...@@ -452,3 +452,14 @@ Java_sun_font_FontManager_populateFontFileNameMap ...@@ -452,3 +452,14 @@ Java_sun_font_FontManager_populateFontFileNameMap
} }
/*
* 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;
}
...@@ -214,6 +214,11 @@ public class EventQueue { ...@@ -214,6 +214,11 @@ public class EventQueue {
FwDispatcher dispatcher) { FwDispatcher dispatcher) {
eventQueue.setFwDispatcher(dispatcher); eventQueue.setFwDispatcher(dispatcher);
} }
@Override
public long getMostRecentEventTime(EventQueue eventQueue) {
return eventQueue.getMostRecentEventTimeImpl();
}
}); });
} }
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
package java.awt.event; package java.awt.event;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import java.awt.AWTEvent; import java.awt.AWTEvent;
import java.awt.Component; import java.awt.Component;
import java.awt.EventQueue; import java.awt.EventQueue;
...@@ -217,8 +221,10 @@ public class InputMethodEvent extends AWTEvent { ...@@ -217,8 +221,10 @@ public class InputMethodEvent extends AWTEvent {
public InputMethodEvent(Component source, int id, public InputMethodEvent(Component source, int id,
AttributedCharacterIterator text, int committedCharacterCount, AttributedCharacterIterator text, int committedCharacterCount,
TextHitInfo caret, TextHitInfo visiblePosition) { TextHitInfo caret, TextHitInfo visiblePosition) {
this(source, id, EventQueue.getMostRecentEventTime(), text, this(source, id,
committedCharacterCount, caret, visiblePosition); getMostRecentEventTimeForSource(source),
text, committedCharacterCount,
caret, visiblePosition);
} }
/** /**
...@@ -258,8 +264,9 @@ public class InputMethodEvent extends AWTEvent { ...@@ -258,8 +264,9 @@ public class InputMethodEvent extends AWTEvent {
*/ */
public InputMethodEvent(Component source, int id, TextHitInfo caret, public InputMethodEvent(Component source, int id, TextHitInfo caret,
TextHitInfo visiblePosition) { TextHitInfo visiblePosition) {
this(source, id, EventQueue.getMostRecentEventTime(), null, this(source, id,
0, caret, visiblePosition); getMostRecentEventTimeForSource(source),
null, 0, caret, visiblePosition);
} }
/** /**
...@@ -410,7 +417,25 @@ public class InputMethodEvent extends AWTEvent { ...@@ -410,7 +417,25 @@ public class InputMethodEvent extends AWTEvent {
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
s.defaultReadObject(); s.defaultReadObject();
if (when == 0) { 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);
} }
} }
...@@ -127,7 +127,7 @@ public final class JapaneseEra ...@@ -127,7 +127,7 @@ public final class JapaneseEra
// the number of defined JapaneseEra constants. // the number of defined JapaneseEra constants.
// There could be an extra era defined in its configuration. // 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. * Serialization version.
...@@ -148,7 +148,7 @@ public final class JapaneseEra ...@@ -148,7 +148,7 @@ public final class JapaneseEra
for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) { for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) {
CalendarDate date = ERA_CONFIG[i].getSinceDate(); CalendarDate date = ERA_CONFIG[i].getSinceDate();
LocalDate isoDate = LocalDate.of(date.getYear(), date.getMonth(), date.getDayOfMonth()); 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 @@ public final class JapaneseEra ...@@ -195,7 +195,7 @@ public final class JapaneseEra
* @throws DateTimeException if the value is invalid * @throws DateTimeException if the value is invalid
*/ */
public static JapaneseEra of(int japaneseEra) { 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); throw new DateTimeException("Invalid era: " + japaneseEra);
} }
return KNOWN_ERAS[ordinal(japaneseEra)]; return KNOWN_ERAS[ordinal(japaneseEra)];
......
...@@ -2342,7 +2342,7 @@ public class Collections { ...@@ -2342,7 +2342,7 @@ public class Collections {
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
synchronized (mutex) { synchronized (mutex) {
return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive)); return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex);
} }
} }
} }
...@@ -3486,6 +3486,7 @@ public class Collections { ...@@ -3486,6 +3486,7 @@ public class Collections {
*/ */
@Override @Override
public void replaceAll(UnaryOperator<E> operator) { public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
list.replaceAll(e -> typeCheck(operator.apply(e))); list.replaceAll(e -> typeCheck(operator.apply(e)));
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -591,8 +591,7 @@ abstract public class TimeZone implements Serializable, Cloneable { ...@@ -591,8 +591,7 @@ abstract public class TimeZone implements Serializable, Cloneable {
/** /**
* Gets the platform defined TimeZone ID. * Gets the platform defined TimeZone ID.
**/ **/
private static native String getSystemTimeZoneID(String javaHome, private static native String getSystemTimeZoneID(String javaHome);
String country);
/** /**
* Gets the custom time zone ID based on the GMT offset of the * Gets the custom time zone ID based on the GMT offset of the
...@@ -650,12 +649,10 @@ abstract public class TimeZone implements Serializable, Cloneable { ...@@ -650,12 +649,10 @@ abstract public class TimeZone implements Serializable, Cloneable {
// if the time zone ID is not set (yet), perform the // if the time zone ID is not set (yet), perform the
// platform to Java time zone ID mapping. // platform to Java time zone ID mapping.
if (zoneID == null || zoneID.isEmpty()) { if (zoneID == null || zoneID.isEmpty()) {
String country = AccessController.doPrivileged(
new GetPropertyAction("user.country"));
String javaHome = AccessController.doPrivileged( String javaHome = AccessController.doPrivileged(
new GetPropertyAction("java.home")); new GetPropertyAction("java.home"));
try { try {
zoneID = getSystemTimeZoneID(javaHome, country); zoneID = getSystemTimeZoneID(javaHome);
if (zoneID == null) { if (zoneID == null) {
zoneID = GMT_ID; zoneID = GMT_ID;
} }
......
...@@ -30,6 +30,11 @@ import java.awt.Window; ...@@ -30,6 +30,11 @@ import java.awt.Window;
import java.util.*; import java.util.*;
import java.awt.FocusTraversalPolicy; import java.awt.FocusTraversalPolicy;
import sun.util.logging.PlatformLogger; 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 * A FocusTraversalPolicy that determines traversal order by sorting the
...@@ -89,6 +94,34 @@ public class SortingFocusTraversalPolicy ...@@ -89,6 +94,34 @@ public class SortingFocusTraversalPolicy
final private int FORWARD_TRAVERSAL = 0; final private int FORWARD_TRAVERSAL = 0;
final private int BACKWARD_TRAVERSAL = 1; 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. * Constructs a SortingFocusTraversalPolicy without a Comparator.
* Subclasses must set the Comparator using <code>setComparator</code> * Subclasses must set the Comparator using <code>setComparator</code>
...@@ -133,9 +166,31 @@ public class SortingFocusTraversalPolicy ...@@ -133,9 +166,31 @@ public class SortingFocusTraversalPolicy
private void enumerateAndSortCycle(Container focusCycleRoot, List<Component> cycle) { private void enumerateAndSortCycle(Container focusCycleRoot, List<Component> cycle) {
if (focusCycleRoot.isShowing()) { if (focusCycleRoot.isShowing()) {
enumerateCycle(focusCycleRoot, cycle); enumerateCycle(focusCycleRoot, cycle);
if (!legacySortingFTPEnabled ||
!legacySort(cycle, comparator))
{
Collections.sort(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) { private void enumerateCycle(Container container, List<Component> cycle) {
if (!(container.isVisible() && container.isDisplayable())) { if (!(container.isVisible() && container.isDisplayable())) {
......
...@@ -504,7 +504,12 @@ public final class AWTAccessor { ...@@ -504,7 +504,12 @@ public final class AWTAccessor {
/** /**
* Sets the delegate for the EventQueue used by FX/AWT single threaded mode * 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);
} }
/* /*
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package sun.awt; package sun.awt;
import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Frame; import java.awt.Frame;
import java.awt.Graphics; import java.awt.Graphics;
...@@ -33,6 +34,13 @@ import java.awt.MenuBar; ...@@ -33,6 +34,13 @@ import java.awt.MenuBar;
import java.awt.MenuComponent; import java.awt.MenuComponent;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Toolkit; 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; import java.awt.peer.FramePeer;
/** /**
...@@ -169,4 +177,27 @@ public abstract class LightweightFrame extends Frame { ...@@ -169,4 +177,27 @@ public abstract class LightweightFrame extends Frame {
hostW = w; hostW = w;
hostH = h; 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);
} }
...@@ -2055,6 +2055,19 @@ public abstract class SunToolkit extends Toolkit ...@@ -2055,6 +2055,19 @@ public abstract class SunToolkit extends Toolkit
return isInstanceOf(cls.getSuperclass(), type); 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 // The following methods help set and identify whether a particular
......
/*
* 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();
}
...@@ -26,9 +26,7 @@ package sun.awt.image; ...@@ -26,9 +26,7 @@ package sun.awt.image;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Image; import java.awt.Image;
import java.awt.Graphics;
import java.awt.geom.Dimension2D; import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver; import java.awt.image.ImageObserver;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -36,50 +34,39 @@ import java.util.function.Function; ...@@ -36,50 +34,39 @@ import java.util.function.Function;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MultiResolutionBufferedImage extends BufferedImage public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
implements MultiResolutionImage {
private final BiFunction<Integer, Integer, Image> mapper; private final int baseImageWidth;
private final int baseImageHeight;
private final Dimension2D[] sizes; private final Dimension2D[] sizes;
private final BiFunction<Integer, Integer, Image> mapper;
private int availableInfo; private int availableInfo;
public MultiResolutionBufferedImage(Image baseImage, public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
BiFunction<Integer, Integer, Image> mapper) { BiFunction<Integer, Integer, Image> mapper) {
this(baseImage, new Dimension[]{new Dimension( this(baseImageWidth, baseImageHeight, new Dimension[]{new Dimension(
baseImage.getWidth(null), baseImage.getHeight(null)) baseImageWidth, baseImageHeight)
}, mapper); }, mapper);
} }
public MultiResolutionBufferedImage(Image baseImage, public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) { Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
super(baseImage.getWidth(null), baseImage.getHeight(null), this.baseImageWidth = baseImageWidth;
BufferedImage.TYPE_INT_ARGB_PRE); this.baseImageHeight = baseImageHeight;
this.sizes = sizes; this.sizes = (sizes == null) ? null : Arrays.copyOf(sizes, sizes.length);
this.mapper = mapper; this.mapper = mapper;
this.availableInfo = getInfo(baseImage);
Graphics g = getGraphics();
g.drawImage(baseImage, 0, 0, null);
g.dispose();
} }
@Override @Override
public Image getResolutionVariant(int width, int height) { public Image getResolutionVariant(int width, int height) {
int baseWidth = getWidth();
int baseHeight = getHeight();
if (baseWidth == width && baseHeight == height) {
return this;
}
ImageCache cache = ImageCache.getInstance(); ImageCache cache = ImageCache.getInstance();
ImageCacheKey key = new ImageCacheKey(this, width, height); ImageCacheKey key = new ImageCacheKey(this, width, height);
Image resolutionVariant = cache.getImage(key); Image resolutionVariant = cache.getImage(key);
if (resolutionVariant == null) { if (resolutionVariant == null) {
resolutionVariant = mapper.apply(width, height); resolutionVariant = mapper.apply(width, height);
cache.setImage(key, resolutionVariant); cache.setImage(key, resolutionVariant);
preload(resolutionVariant, availableInfo);
} }
preload(resolutionVariant, availableInfo);
return resolutionVariant; return resolutionVariant;
} }
...@@ -90,30 +77,39 @@ public class MultiResolutionBufferedImage extends BufferedImage ...@@ -90,30 +77,39 @@ public class MultiResolutionBufferedImage extends BufferedImage
(int) size.getHeight())).collect(Collectors.toList()); (int) size.getHeight())).collect(Collectors.toList());
} }
public MultiResolutionBufferedImage map(Function<Image, Image> mapper) { public MultiResolutionCachedImage map(Function<Image, Image> mapper) {
return new MultiResolutionBufferedImage(mapper.apply(this), sizes, return new MultiResolutionCachedImage(baseImageWidth, baseImageHeight,
(width, height) -> sizes, (width, height) ->
mapper.apply(getResolutionVariant(width, height))); mapper.apply(getResolutionVariant(width, height)));
} }
@Override @Override
public int getWidth(ImageObserver observer) { public int getWidth(ImageObserver observer) {
availableInfo |= ImageObserver.WIDTH; updateInfo(observer, ImageObserver.WIDTH);
return super.getWidth(observer); return super.getWidth(observer);
} }
@Override @Override
public int getHeight(ImageObserver observer) { public int getHeight(ImageObserver observer) {
availableInfo |= ImageObserver.HEIGHT; updateInfo(observer, ImageObserver.HEIGHT);
return super.getHeight(observer); return super.getHeight(observer);
} }
@Override @Override
public Object getProperty(String name, ImageObserver observer) { public Object getProperty(String name, ImageObserver observer) {
availableInfo |= ImageObserver.PROPERTIES; updateInfo(observer, ImageObserver.PROPERTIES);
return super.getProperty(name, observer); 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) { private static int getInfo(Image image) {
if (image instanceof ToolkitImage) { if (image instanceof ToolkitImage) {
return ((ToolkitImage) image).getImageRep().check( return ((ToolkitImage) image).getImageRep().check(
......
...@@ -3182,7 +3182,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { ...@@ -3182,7 +3182,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
* Returns an array of two strings. The first element is the * Returns an array of two strings. The first element is the
* name of the font. The second element is the file name. * name of the font. The second element is the file name.
*/ */
public abstract String[] getDefaultPlatformFont(); protected abstract String[] getDefaultPlatformFont();
// Begin: Refactored from SunGraphicsEnviroment. // Begin: Refactored from SunGraphicsEnviroment.
......
...@@ -301,7 +301,7 @@ public class FtpURLConnection extends URLConnection { ...@@ -301,7 +301,7 @@ public class FtpURLConnection extends URLConnection {
throw new IOException(fe); throw new IOException(fe);
} }
try { try {
ftp.login(user, password.toCharArray()); ftp.login(user, password == null ? null : password.toCharArray());
} catch (sun.net.ftp.FtpProtocolException e) { } catch (sun.net.ftp.FtpProtocolException e) {
ftp.close(); ftp.close();
// Backward compatibility // Backward compatibility
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -122,10 +122,10 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable { ...@@ -122,10 +122,10 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable {
} }
} }
// compress complete blocks // compress complete blocks
while (len >= blockSize) { if (len >= blockSize) {
implCompress(b, ofs); int limit = ofs + len;
len -= blockSize; ofs = implCompressMultiBlock(b, ofs, limit - blockSize);
ofs += blockSize; len = limit - ofs;
} }
// copy remainder to buffer // copy remainder to buffer
if (len > 0) { if (len > 0) {
...@@ -134,6 +134,14 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable { ...@@ -134,6 +134,14 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable {
} }
} }
// 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. // reset this object. See JCA doc.
protected final void engineReset() { protected final void engineReset() {
if (bytesProcessed == 0) { if (bytesProcessed == 0) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,6 +29,7 @@ import java.io.IOException; ...@@ -29,6 +29,7 @@ import java.io.IOException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.SecureRandomSpi; import java.security.SecureRandomSpi;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
/** /**
* <p>This class provides a crytpographically strong pseudo-random number * <p>This class provides a crytpographically strong pseudo-random number
...@@ -93,10 +94,20 @@ implements java.io.Serializable { ...@@ -93,10 +94,20 @@ implements java.io.Serializable {
* and sets the seed, if given. * and sets the seed, if given.
*/ */
private void init(byte[] seed) { private void init(byte[] seed) {
try {
/*
* Use the local SUN implementation to avoid native
* performance overhead.
*/
digest = MessageDigest.getInstance("SHA", "SUN");
} catch (NoSuchProviderException | NoSuchAlgorithmException e) {
// Fallback to any available.
try { try {
digest = MessageDigest.getInstance("SHA"); digest = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException exc) {
throw new InternalError("internal error: SHA-1 not available.", e); throw new InternalError(
"internal error: SHA-1 not available.", exc);
}
} }
if (seed != null) { if (seed != null) {
...@@ -264,10 +275,20 @@ implements java.io.Serializable { ...@@ -264,10 +275,20 @@ implements java.io.Serializable {
s.defaultReadObject (); s.defaultReadObject ();
try {
/*
* Use the local SUN implementation to avoid native
* performance overhead.
*/
digest = MessageDigest.getInstance("SHA", "SUN");
} catch (NoSuchProviderException | NoSuchAlgorithmException e) {
// Fallback to any available.
try { try {
digest = MessageDigest.getInstance("SHA"); digest = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException exc) {
throw new InternalError("internal error: SHA-1 not available.", e); throw new InternalError(
"internal error: SHA-1 not available.", exc);
}
} }
} }
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,9 +26,9 @@ ...@@ -26,9 +26,9 @@
package sun.security.smartcardio; package sun.security.smartcardio;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.smartcardio.*; import javax.smartcardio.*;
import static sun.security.smartcardio.PCSC.*; import static sun.security.smartcardio.PCSC.*;
/** /**
...@@ -62,6 +62,15 @@ final class CardImpl extends Card { ...@@ -62,6 +62,15 @@ final class CardImpl extends Card {
// thread holding exclusive access to the card, or null // thread holding exclusive access to the card, or null
private volatile Thread exclusiveThread; 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 { CardImpl(TerminalImpl terminal, String protocol) throws PCSCException {
this.terminal = terminal; this.terminal = terminal;
int sharingMode = SCARD_SHARE_SHARED; int sharingMode = SCARD_SHARE_SHARED;
...@@ -74,7 +83,12 @@ final class CardImpl extends Card { ...@@ -74,7 +83,12 @@ final class CardImpl extends Card {
connectProtocol = SCARD_PROTOCOL_T1; connectProtocol = SCARD_PROTOCOL_T1;
} else if (protocol.equalsIgnoreCase("direct")) { } else if (protocol.equalsIgnoreCase("direct")) {
// testing // 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; sharingMode = SCARD_SHARE_DIRECT;
} else { } else {
throw new IllegalArgumentException("Unsupported protocol " + protocol); throw new IllegalArgumentException("Unsupported protocol " + protocol);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -188,7 +188,7 @@ final class DHCrypt { ...@@ -188,7 +188,7 @@ final class DHCrypt {
* the same size as the Diffie-Hellman modulus. * the same size as the Diffie-Hellman modulus.
*/ */
SecretKey getAgreedSecret(BigInteger peerPublicValue, SecretKey getAgreedSecret(BigInteger peerPublicValue,
boolean keyIsValidated) throws IOException { boolean keyIsValidated) throws SSLHandshakeException {
try { try {
KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
DHPublicKeySpec spec = DHPublicKeySpec spec =
...@@ -211,7 +211,8 @@ final class DHCrypt { ...@@ -211,7 +211,8 @@ final class DHCrypt {
ka.doPhase(publicKey, true); ka.doPhase(publicKey, true);
return ka.generateSecret("TlsPremasterSecret"); return ka.generateSecret("TlsPremasterSecret");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate secret", e); throw (SSLHandshakeException) new SSLHandshakeException(
"Could not generate secret").initCause(e);
} }
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,6 +31,7 @@ import java.security.spec.*; ...@@ -31,6 +31,7 @@ import java.security.spec.*;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.KeyAgreement; import javax.crypto.KeyAgreement;
import javax.net.ssl.SSLHandshakeException;
/** /**
* Helper class for the ECDH key exchange. It generates the appropriate * Helper class for the ECDH key exchange. It generates the appropriate
...@@ -88,19 +89,20 @@ final class ECDHCrypt { ...@@ -88,19 +89,20 @@ final class ECDHCrypt {
} }
// called by ClientHandshaker with either the server's static or ephemeral public key // called by ClientHandshaker with either the server's static or ephemeral public key
SecretKey getAgreedSecret(PublicKey peerPublicKey) { SecretKey getAgreedSecret(PublicKey peerPublicKey) throws SSLHandshakeException {
try { try {
KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
ka.init(privateKey); ka.init(privateKey);
ka.doPhase(peerPublicKey, true); ka.doPhase(peerPublicKey, true);
return ka.generateSecret("TlsPremasterSecret"); return ka.generateSecret("TlsPremasterSecret");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate secret", e); throw (SSLHandshakeException) new SSLHandshakeException(
"Could not generate secret").initCause(e);
} }
} }
// called by ServerHandshaker // called by ServerHandshaker
SecretKey getAgreedSecret(byte[] encodedPoint) { SecretKey getAgreedSecret(byte[] encodedPoint) throws SSLHandshakeException {
try { try {
ECParameterSpec params = publicKey.getParams(); ECParameterSpec params = publicKey.getParams();
ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve()); ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve());
...@@ -108,10 +110,9 @@ final class ECDHCrypt { ...@@ -108,10 +110,9 @@ final class ECDHCrypt {
ECPublicKeySpec spec = new ECPublicKeySpec(point, params); ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
PublicKey peerPublicKey = kf.generatePublic(spec); PublicKey peerPublicKey = kf.generatePublic(spec);
return getAgreedSecret(peerPublicKey); return getAgreedSecret(peerPublicKey);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException | java.io.IOException e) {
throw new RuntimeException("Could not generate secret", e); throw (SSLHandshakeException) new SSLHandshakeException(
} catch (java.io.IOException e) { "Could not generate secret").initCause(e);
throw new RuntimeException("Could not generate secret", e);
} }
} }
......
...@@ -37,6 +37,13 @@ import java.awt.MouseInfo; ...@@ -37,6 +37,13 @@ import java.awt.MouseInfo;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Window; 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.ContainerEvent;
import java.awt.event.ContainerListener; import java.awt.event.ContainerListener;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
...@@ -470,4 +477,27 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan ...@@ -470,4 +477,27 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
content.setCursor(target.getCursor()); 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);
}
} }
...@@ -26,7 +26,15 @@ ...@@ -26,7 +26,15 @@
package sun.swing; package sun.swing;
import javax.swing.JComponent; import javax.swing.JComponent;
import java.awt.Component;
import java.awt.Cursor; 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 * The interface by means of which the {@link JLightweightFrame} class
...@@ -209,4 +217,33 @@ public interface LightweightContent { ...@@ -209,4 +217,33 @@ public interface LightweightContent {
* @param cursor a cursor to set * @param cursor a cursor to set
*/ */
default public void setCursor(Cursor cursor) { } 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) {}
} }
...@@ -117,7 +117,7 @@ typedef struct { ...@@ -117,7 +117,7 @@ typedef struct {
char *exceptionList; 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 #endif
} java_props_t; } java_props_t;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,42 +38,28 @@ ...@@ -38,42 +38,28 @@
*/ */
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_java_util_TimeZone_getSystemTimeZoneID(JNIEnv *env, jclass ign, 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; const char *java_home_dir;
char *javaTZ; char *javaTZ;
jstring jstrJavaTZ = NULL;
if (java_home == NULL) CHECK_NULL_RETURN(java_home, NULL);
return NULL;
java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0); java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0);
if (java_home_dir == NULL) CHECK_NULL_RETURN(java_home_dir, NULL);
return NULL;
if (country != NULL) {
cname = JNU_GetStringPlatformChars(env, country, 0);
/* ignore error cases for cname */
} else {
cname = NULL;
}
/* /*
* Invoke platform dependent mapping function * Invoke platform dependent mapping function
*/ */
javaTZ = findJavaTZ_md(java_home_dir, cname); javaTZ = findJavaTZ_md(java_home_dir);
free((void *)java_home_dir);
if (cname != NULL) {
free((void *)cname);
}
if (javaTZ != NULL) { if (javaTZ != NULL) {
jstring jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ); jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ);
free((void *)javaTZ); free((void *)javaTZ);
return jstrJavaTZ;
} }
return NULL;
JNU_ReleaseStringPlatformChars(env, java_home, java_home_dir);
return jstrJavaTZ;
} }
/* /*
......
...@@ -291,7 +291,12 @@ static ColorData *BufImg_SetupICM(JNIEnv *env, ...@@ -291,7 +291,12 @@ static ColorData *BufImg_SetupICM(JNIEnv *env,
= (*env)->GetBooleanField(env, bisdo->icm, allGrayID); = (*env)->GetBooleanField(env, bisdo->icm, allGrayID);
int *pRgb = (int *) int *pRgb = (int *)
((*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL)); ((*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); cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32);
if (allGray == JNI_TRUE) { if (allGray == JNI_TRUE) {
initInverseGrayLut(pRgb, bisdo->lutsize, cData); initInverseGrayLut(pRgb, bisdo->lutsize, cData);
...@@ -304,7 +309,13 @@ static ColorData *BufImg_SetupICM(JNIEnv *env, ...@@ -304,7 +309,13 @@ static ColorData *BufImg_SetupICM(JNIEnv *env,
if (JNU_IsNull(env, colorData)) { if (JNU_IsNull(env, colorData)) {
jlong pData = ptr_to_jlong(cData); jlong pData = ptr_to_jlong(cData);
colorData = (*env)->NewObjectA(env, clsICMCD, initICMCDmID, (jvalue *)&pData); 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); (*env)->SetObjectField(env, bisdo->icm, colorDataID, colorData);
} }
} }
......
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist) { GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist) {
int g, bytesNeeded; int g;
size_t bytesNeeded;
jlong *imagePtrs; jlong *imagePtrs;
jfloat* positions = NULL; jfloat* positions = NULL;
GlyphInfo *ginfo; GlyphInfo *ginfo;
...@@ -71,6 +72,9 @@ GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist) { ...@@ -71,6 +72,9 @@ GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist) {
bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len; bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len;
gbv = (GlyphBlitVector*)malloc(bytesNeeded); gbv = (GlyphBlitVector*)malloc(bytesNeeded);
if (gbv == NULL) {
return NULL;
}
gbv->numGlyphs = len; gbv->numGlyphs = len;
gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector)); gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector));
...@@ -479,7 +483,8 @@ Java_sun_java2d_loops_DrawGlyphListLCD_DrawGlyphListLCD ...@@ -479,7 +483,8 @@ Java_sun_java2d_loops_DrawGlyphListLCD_DrawGlyphListLCD
*/ */
GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist) { GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist) {
int g, bytesNeeded; int g;
size_t bytesNeeded;
jlong *imagePtrs; jlong *imagePtrs;
jfloat* positions = NULL; jfloat* positions = NULL;
GlyphInfo *ginfo; GlyphInfo *ginfo;
...@@ -500,6 +505,9 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist) { ...@@ -500,6 +505,9 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist) {
bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len; bytesNeeded = sizeof(GlyphBlitVector)+sizeof(ImageRef)*len;
gbv = (GlyphBlitVector*)malloc(bytesNeeded); gbv = (GlyphBlitVector*)malloc(bytesNeeded);
if (gbv == NULL) {
return NULL;
}
gbv->numGlyphs = len; gbv->numGlyphs = len;
gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector)); gbv->glyphs = (ImageRef*)((unsigned char*)gbv+sizeof(GlyphBlitVector));
......
/* /*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,6 +35,9 @@ import java.io.IOException; ...@@ -35,6 +35,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays; 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.Executors;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
...@@ -49,7 +52,7 @@ import java.security.PrivilegedExceptionAction; ...@@ -49,7 +52,7 @@ import java.security.PrivilegedExceptionAction;
* java.lang.Process subclass in the UNIX environment. * java.lang.Process subclass in the UNIX environment.
* *
* @author Mario Wolczko and Ross Knippel. * @author Mario Wolczko and Ross Knippel.
* @author Konstantin Kladko (ported to Linux) * @author Konstantin Kladko (ported to Linux and Bsd)
* @author Martin Buchholz * @author Martin Buchholz
* @author Volker Simonis (ported to AIX) * @author Volker Simonis (ported to AIX)
*/ */
...@@ -65,17 +68,106 @@ final class UNIXProcess extends Process { ...@@ -65,17 +68,106 @@ final class UNIXProcess extends Process {
private /* final */ InputStream stdout; private /* final */ InputStream stdout;
private /* final */ InputStream stderr; private /* final */ InputStream stderr;
// only used on Solaris
private /* final */ DeferredCloseInputStream stdout_inner_stream;
private static enum LaunchMechanism { private static enum LaunchMechanism {
FORK(1), // order IS important!
POSIX_SPAWN(2); FORK,
POSIX_SPAWN,
VFORK
}
private int value; private static enum Platform {
LaunchMechanism(int x) {value = x;}
}; 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")
);
/* On AIX, the default is to spawn */ if (osName.equals("Linux")) { return LINUX; }
private static final LaunchMechanism launchMechanism; if (osName.contains("OS X")) { return BSD; }
private static byte[] helperpath; 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) { private static byte[] toCString(String s) {
if (s == null) if (s == null)
...@@ -89,38 +181,19 @@ final class UNIXProcess extends Process { ...@@ -89,38 +181,19 @@ final class UNIXProcess extends Process {
return result; 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 */ /* this is for the reaping thread */
private native int waitForProcessExit(int pid); private native int waitForProcessExit(int pid);
/** /**
* Create a process. Depending on the mode flag, this is done by * Creates a process. Depending on the {@code mode} flag, this is done by
* one of the following mechanisms. * one of the following mechanisms:
* - fork(2) and exec(2) * <pre>
* - clone(2) and exec(2) * 1 - fork(2) and exec(2)
* - vfork(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. * @param fds an array of three file descriptors.
* Indexes 0, 1, and 2 correspond to standard input, * Indexes 0, 1, and 2 correspond to standard input,
* standard output and standard error, respectively. On * standard output and standard error, respectively. On
...@@ -142,40 +215,27 @@ final class UNIXProcess extends Process { ...@@ -142,40 +215,27 @@ final class UNIXProcess extends Process {
throws IOException; throws IOException;
/** /**
* The thread factory used to create "process reaper" daemon threads. * The thread pool of "process reaper" daemon threads.
*/ */
private static class ProcessReaperThreadFactory implements ThreadFactory { private static final Executor processReaperExecutor =
private final static ThreadGroup group = getRootThreadGroup(); doPrivileged((PrivilegedAction<Executor>) () -> {
private static ThreadGroup getRootThreadGroup() { ThreadGroup tg = Thread.currentThread().getThreadGroup();
return doPrivileged(new PrivilegedAction<ThreadGroup> () { while (tg.getParent() != null) tg = tg.getParent();
public ThreadGroup run() { ThreadGroup systemThreadGroup = tg;
ThreadGroup root = Thread.currentThread().getThreadGroup();
while (root.getParent() != null)
root = root.getParent();
return root;
}});
}
public Thread newThread(Runnable grimReaper) { ThreadFactory threadFactory = grimReaper -> {
// Our thread stack requirement is quite modest. // Our thread stack requirement is quite modest.
Thread t = new Thread(group, grimReaper, "process reaper", 32768); Thread t = new Thread(systemThreadGroup, grimReaper,
"process reaper", 32768);
t.setDaemon(true); t.setDaemon(true);
// A small attempt (probably futile) to avoid priority inversion // A small attempt (probably futile) to avoid priority inversion
t.setPriority(Thread.MAX_PRIORITY); t.setPriority(Thread.MAX_PRIORITY);
return t; return t;
} };
}
/** return Executors.newCachedThreadPool(threadFactory);
* 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, UNIXProcess(final byte[] prog,
final byte[] argBlock, final int argc, final byte[] argBlock, final int argc,
...@@ -185,7 +245,7 @@ final class UNIXProcess extends Process { ...@@ -185,7 +245,7 @@ final class UNIXProcess extends Process {
final boolean redirectErrorStream) final boolean redirectErrorStream)
throws IOException { throws IOException {
pid = forkAndExec(launchMechanism.value, pid = forkAndExec(launchMechanism.ordinal() + 1,
helperpath, helperpath,
prog, prog,
argBlock, argc, argBlock, argc,
...@@ -195,11 +255,10 @@ final class UNIXProcess extends Process { ...@@ -195,11 +255,10 @@ final class UNIXProcess extends Process {
redirectErrorStream); redirectErrorStream);
try { try {
doPrivileged(new PrivilegedExceptionAction<Void>() { doPrivileged((PrivilegedExceptionAction<Void>) () -> {
public Void run() throws IOException {
initStreams(fds); initStreams(fds);
return null; return null;
}}); });
} catch (PrivilegedActionException ex) { } catch (PrivilegedActionException ex) {
throw (IOException) ex.getException(); throw (IOException) ex.getException();
} }
...@@ -212,6 +271,9 @@ final class UNIXProcess extends Process { ...@@ -212,6 +271,9 @@ final class UNIXProcess extends Process {
} }
void initStreams(int[] fds) throws IOException { void initStreams(int[] fds) throws IOException {
switch (platform) {
case LINUX:
case BSD:
stdin = (fds[0] == -1) ? stdin = (fds[0] == -1) ?
ProcessBuilder.NullOutputStream.INSTANCE : ProcessBuilder.NullOutputStream.INSTANCE :
new ProcessPipeOutputStream(fds[0]); new ProcessPipeOutputStream(fds[0]);
...@@ -224,18 +286,13 @@ final class UNIXProcess extends Process { ...@@ -224,18 +286,13 @@ final class UNIXProcess extends Process {
ProcessBuilder.NullInputStream.INSTANCE : ProcessBuilder.NullInputStream.INSTANCE :
new ProcessPipeInputStream(fds[2]); new ProcessPipeInputStream(fds[2]);
processReaperExecutor.execute(new Runnable() { processReaperExecutor.execute(() -> {
public void run() {
int exitcode = waitForProcessExit(pid); int exitcode = waitForProcessExit(pid);
UNIXProcess.this.processExited(exitcode);
}});
}
void processExited(int exitcode) {
synchronized (this) { synchronized (this) {
this.exitcode = exitcode; this.exitcode = exitcode;
hasExited = true; this.hasExited = true;
notifyAll(); this.notifyAll();
} }
if (stdout instanceof ProcessPipeInputStream) if (stdout instanceof ProcessPipeInputStream)
...@@ -246,6 +303,80 @@ final class UNIXProcess extends Process { ...@@ -246,6 +303,80 @@ final class UNIXProcess extends Process {
if (stdin instanceof ProcessPipeOutputStream) if (stdin instanceof ProcessPipeOutputStream)
((ProcessPipeOutputStream) stdin).processExited(); ((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() { public OutputStream getOutputStream() {
...@@ -293,7 +424,12 @@ final class UNIXProcess extends Process { ...@@ -293,7 +424,12 @@ final class UNIXProcess extends Process {
} }
private static native void destroyProcess(int pid, boolean force); private static native void destroyProcess(int pid, boolean force);
private void destroy(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 // There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes // kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check, // that appear to still be running. Even with this check,
...@@ -307,6 +443,33 @@ final class UNIXProcess extends Process { ...@@ -307,6 +443,33 @@ final class UNIXProcess extends Process {
try { stdin.close(); } catch (IOException ignored) {} try { stdin.close(); } catch (IOException ignored) {}
try { stdout.close(); } catch (IOException ignored) {} try { stdout.close(); } catch (IOException ignored) {}
try { stderr.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() { public void destroy() {
...@@ -330,6 +493,189 @@ final class UNIXProcess extends Process { ...@@ -330,6 +493,189 @@ final class UNIXProcess extends Process {
init(); 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 * A buffered input stream for a subprocess pipe file descriptor
* that allows the underlying file descriptor to be reclaimed when * that allows the underlying file descriptor to be reclaimed when
...@@ -342,8 +688,8 @@ final class UNIXProcess extends Process { ...@@ -342,8 +688,8 @@ final class UNIXProcess extends Process {
* On AIX this is especially tricky, because the 'close()' system call * 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 * 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 * operation (e.g. 'read()') on the same file descriptor. We therefore
* combine this 'ProcessPipeInputStream' with the DeferredCloseInputStream * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
* approach used on Solaris (see "UNIXProcess.java.solaris"). This means * with the DeferredCloseInputStream approach used on Solaris. This means
* that every potentially blocking operation on the file descriptor * that every potentially blocking operation on the file descriptor
* increments a counter before it is executed and decrements it once it * increments a counter before it is executed and decrements it once it
* finishes. The 'close()' operation will only be executed if there are * finishes. The 'close()' operation will only be executed if there are
...@@ -351,12 +697,14 @@ final class UNIXProcess extends Process { ...@@ -351,12 +697,14 @@ final class UNIXProcess extends Process {
* operation has finished. * operation has finished.
* *
*/ */
static class ProcessPipeInputStream extends BufferedInputStream { private static class DeferredCloseProcessPipeInputStream
extends BufferedInputStream {
private final Object closeLock = new Object(); private final Object closeLock = new Object();
private int useCount = 0; private int useCount = 0;
private boolean closePending = false; private boolean closePending = false;
ProcessPipeInputStream(int fd) { DeferredCloseProcessPipeInputStream(int fd) {
super(new FileInputStream(newFileDescriptor(fd))); super(new FileInputStream(newFileDescriptor(fd)));
} }
...@@ -464,8 +812,8 @@ final class UNIXProcess extends Process { ...@@ -464,8 +812,8 @@ final class UNIXProcess extends Process {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
// BufferedInputStream#close() is not synchronized unlike most other methods. // BufferedInputStream#close() is not synchronized unlike most other
// Synchronizing helps avoid racing with drainInputStream(). // methods. Synchronizing helps avoid racing with drainInputStream().
synchronized (closeLock) { synchronized (closeLock) {
if (useCount == 0) { if (useCount == 0) {
super.close(); super.close();
...@@ -476,29 +824,4 @@ final class UNIXProcess extends Process { ...@@ -476,29 +824,4 @@ final class UNIXProcess extends Process {
} }
} }
} }
/**
* 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;
}
}
}
} }
/*
* 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;
}
}
}
}
/*
* 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;
}
}
}
}
/*
* 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();
}
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -40,7 +40,7 @@ import sun.util.logging.PlatformLogger; ...@@ -40,7 +40,7 @@ import sun.util.logging.PlatformLogger;
* For now, this class manages the list of items and painting thereof, but not * For now, this class manages the list of items and painting thereof, but not
* posting of Item or ActionEvents * 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 static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.ListHelper");
private final int FOCUS_INSET = 1; private final int FOCUS_INSET = 1;
...@@ -79,23 +79,15 @@ public class ListHelper implements XScrollbarClient { ...@@ -79,23 +79,15 @@ public class ListHelper implements XScrollbarClient {
// Holds the true if mouse is dragging outside of the area of the list // 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 // The flag is used at the moment of the dragging and releasing mouse
// See 6243382 for more information // See 6243382 for more information
boolean mouseDraggedOutVertically = false; private boolean mouseDraggedOutVertically = false;
private volatile boolean vsbVisibilityChanged = false; private volatile boolean vsbVisibilityChanged = false;
/* /*
* Comment * Comment
*/ */
public ListHelper(XWindow peer, ListHelper(XWindow peer, Color[] colors, int initialSize,
Color[] colors, boolean multiSelect, boolean scrollVert, boolean scrollHoriz,
int initialSize, Font font, int maxVisItems, int SPACE, int MARGIN, int BORDER,
boolean multiSelect,
boolean scrollVert,
boolean scrollHoriz,
Font font,
int maxVisItems,
int SPACE,
int MARGIN,
int BORDER,
int SCROLLBAR) { int SCROLLBAR) {
this.peer = peer; this.peer = peer;
this.colors = colors; this.colors = colors;
...@@ -121,6 +113,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -121,6 +113,7 @@ public class ListHelper implements XScrollbarClient {
SCROLLBAR_WIDTH = SCROLLBAR; SCROLLBAR_WIDTH = SCROLLBAR;
} }
@Override
public Component getEventSource() { public Component getEventSource() {
return peer.getEventSource(); return peer.getEventSource();
} }
...@@ -129,36 +122,36 @@ public class ListHelper implements XScrollbarClient { ...@@ -129,36 +122,36 @@ public class ListHelper implements XScrollbarClient {
/* List management methods */ /* List management methods */
/**********************************************************************/ /**********************************************************************/
public void add(String item) { void add(String item) {
items.add(item); items.add(item);
updateScrollbars(); updateScrollbars();
} }
public void add(String item, int index) { void add(String item, int index) {
items.add(index, item); items.add(index, item);
updateScrollbars(); updateScrollbars();
} }
public void remove(String item) { void remove(String item) {
// FIXME: need to clean up select list, too? // FIXME: need to clean up select list, too?
items.remove(item); items.remove(item);
updateScrollbars(); updateScrollbars();
// Is vsb visible now? // Is vsb visible now?
} }
public void remove(int index) { void remove(int index) {
// FIXME: need to clean up select list, too? // FIXME: need to clean up select list, too?
items.remove(index); items.remove(index);
updateScrollbars(); updateScrollbars();
// Is vsb visible now? // Is vsb visible now?
} }
public void removeAll() { void removeAll() {
items.removeAll(items); items.removeAll(items);
updateScrollbars(); updateScrollbars();
} }
public void setMultiSelect(boolean ms) { void setMultiSelect(boolean ms) {
multiSelect = ms; multiSelect = ms;
} }
...@@ -167,7 +160,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -167,7 +160,7 @@ public class ListHelper implements XScrollbarClient {
* merely keeps internal track of which items are selected for painting * merely keeps internal track of which items are selected for painting
* dealing with target Components happens elsewhere * dealing with target Components happens elsewhere
*/ */
public void select(int index) { void select(int index) {
if (index > getItemCount() - 1) { if (index > getItemCount() - 1) {
index = (isEmpty() ? -1 : 0); index = (isEmpty() ? -1 : 0);
} }
...@@ -182,13 +175,13 @@ public class ListHelper implements XScrollbarClient { ...@@ -182,13 +175,13 @@ public class ListHelper implements XScrollbarClient {
} }
/* docs */ /* docs */
public void deselect(int index) { void deselect(int index) {
assert(false); assert(false);
} }
/* docs */ /* docs */
/* if called for multiselect, return -1 */ /* if called for multiselect, return -1 */
public int getSelectedIndex() { int getSelectedIndex() {
if (!multiSelect) { if (!multiSelect) {
Integer val = (Integer)selected.get(0); Integer val = (Integer)selected.get(0);
return val.intValue(); return val.intValue();
...@@ -202,21 +195,21 @@ public class ListHelper implements XScrollbarClient { ...@@ -202,21 +195,21 @@ public class ListHelper implements XScrollbarClient {
* A getter method for XChoicePeer. * A getter method for XChoicePeer.
* Returns vsbVisiblityChanged value and sets it to false. * Returns vsbVisiblityChanged value and sets it to false.
*/ */
public boolean checkVsbVisibilityChangedAndReset(){ boolean checkVsbVisibilityChangedAndReset(){
boolean returnVal = vsbVisibilityChanged; boolean returnVal = vsbVisibilityChanged;
vsbVisibilityChanged = false; vsbVisibilityChanged = false;
return returnVal; return returnVal;
} }
public boolean isEmpty() { boolean isEmpty() {
return items.isEmpty(); return items.isEmpty();
} }
public int getItemCount() { int getItemCount() {
return items.size(); return items.size();
} }
public String getItem(int index) { String getItem(int index) {
return (String) items.get(index); return (String) items.get(index);
} }
...@@ -224,15 +217,15 @@ public class ListHelper implements XScrollbarClient { ...@@ -224,15 +217,15 @@ public class ListHelper implements XScrollbarClient {
/* GUI-related methods */ /* GUI-related methods */
/**********************************************************************/ /**********************************************************************/
public void setFocusedIndex(int index) { void setFocusedIndex(int index) {
focusedIndex = index; focusedIndex = index;
} }
public boolean isFocusedIndex(int index) { private boolean isFocusedIndex(int index) {
return index == focusedIndex; return index == focusedIndex;
} }
public void setFont(Font newFont) { void setFont(Font newFont) {
if (newFont != font) { if (newFont != font) {
font = newFont; font = newFont;
fm = Toolkit.getDefaultToolkit().getFontMetrics(font); fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
...@@ -243,7 +236,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -243,7 +236,7 @@ public class ListHelper implements XScrollbarClient {
/* /*
* Returns width of the text of the longest item * Returns width of the text of the longest item
*/ */
public int getMaxItemWidth() { int getMaxItemWidth() {
int m = 0; int m = 0;
int end = getItemCount(); int end = getItemCount();
for(int i = 0 ; i < end ; i++) { for(int i = 0 ; i < end ; i++) {
...@@ -260,7 +253,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -260,7 +253,7 @@ public class ListHelper implements XScrollbarClient {
return fm.getHeight() + (2*TEXT_SPACE); return fm.getHeight() + (2*TEXT_SPACE);
} }
public int y2index(int y) { int y2index(int y) {
if (log.isLoggable(PlatformLogger.Level.FINE)) { if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("y=" + y +", firstIdx=" + firstDisplayedIndex() +", itemHeight=" + getItemHeight() log.fine("y=" + y +", firstIdx=" + firstDisplayedIndex() +", itemHeight=" + getItemHeight()
+ ",item_margin=" + ITEM_MARGIN); + ",item_margin=" + ITEM_MARGIN);
...@@ -275,14 +268,14 @@ public class ListHelper implements XScrollbarClient { ...@@ -275,14 +268,14 @@ public class ListHelper implements XScrollbarClient {
public int numItemsDisplayed() {} public int numItemsDisplayed() {}
*/ */
public int firstDisplayedIndex() { int firstDisplayedIndex() {
if (vsbVis) { if (vsbVis) {
return vsb.getValue(); return vsb.getValue();
} }
return 0; return 0;
} }
public int lastDisplayedIndex() { int lastDisplayedIndex() {
// FIXME: need to account for horiz scroll bar // FIXME: need to account for horiz scroll bar
if (hsbVis) { if (hsbVis) {
assert false : "Implement for horiz scroll bar"; assert false : "Implement for horiz scroll bar";
...@@ -294,7 +287,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -294,7 +287,7 @@ public class ListHelper implements XScrollbarClient {
/* /*
* If the given index is not visible in the List, scroll so that it is. * 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 (vsbVis) {
if (index < firstDisplayedIndex()) { if (index < firstDisplayedIndex()) {
vsb.setValue(index); vsb.setValue(index);
...@@ -306,7 +299,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -306,7 +299,7 @@ public class ListHelper implements XScrollbarClient {
} }
// FIXME: multi-select needs separate focused index // FIXME: multi-select needs separate focused index
public void up() { void up() {
int curIdx = getSelectedIndex(); int curIdx = getSelectedIndex();
int numItems = getItemCount(); int numItems = getItemCount();
int newIdx; int newIdx;
...@@ -323,12 +316,12 @@ public class ListHelper implements XScrollbarClient { ...@@ -323,12 +316,12 @@ public class ListHelper implements XScrollbarClient {
select(newIdx); select(newIdx);
} }
public void down() { void down() {
int newIdx = (getSelectedIndex() + 1) % getItemCount(); int newIdx = (getSelectedIndex() + 1) % getItemCount();
select(newIdx); select(newIdx);
} }
public void pageUp() { void pageUp() {
// FIXME: for multi-select, move the focused item, not the selected item // FIXME: for multi-select, move the focused item, not the selected item
if (vsbVis && firstDisplayedIndex() > 0) { if (vsbVis && firstDisplayedIndex() > 0) {
if (multiSelect) { if (multiSelect) {
...@@ -343,7 +336,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -343,7 +336,7 @@ public class ListHelper implements XScrollbarClient {
} }
} }
} }
public void pageDown() { void pageDown() {
if (vsbVis && lastDisplayedIndex() < getItemCount() - 1) { if (vsbVis && lastDisplayedIndex() < getItemCount() - 1) {
if (multiSelect) { if (multiSelect) {
assert false : "Implement pageDown() for multiSelect"; assert false : "Implement pageDown() for multiSelect";
...@@ -357,17 +350,17 @@ public class ListHelper implements XScrollbarClient { ...@@ -357,17 +350,17 @@ public class ListHelper implements XScrollbarClient {
} }
} }
} }
public void home() {} void home() {}
public void end() {} void end() {}
public boolean isVSBVisible() { return vsbVis; } boolean isVSBVisible() { return vsbVis; }
public boolean isHSBVisible() { return hsbVis; } boolean isHSBVisible() { return hsbVis; }
public XVerticalScrollbar getVSB() { return vsb; } XVerticalScrollbar getVSB() { return vsb; }
public XHorizontalScrollbar getHSB() { return hsb; } XHorizontalScrollbar getHSB() { return hsb; }
public boolean isInVertSB(Rectangle bounds, int x, int y) { boolean isInVertSB(Rectangle bounds, int x, int y) {
if (vsbVis) { if (vsbVis) {
assert vsb != null : "Vert scrollbar is visible, yet is null?"; assert vsb != null : "Vert scrollbar is visible, yet is null?";
int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height; int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height;
...@@ -379,7 +372,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -379,7 +372,7 @@ public class ListHelper implements XScrollbarClient {
return false; return false;
} }
public boolean isInHorizSB(Rectangle bounds, int x, int y) { boolean isInHorizSB(Rectangle bounds, int x, int y) {
if (hsbVis) { if (hsbVis) {
assert hsb != null : "Horiz scrollbar is visible, yet is null?"; assert hsb != null : "Horiz scrollbar is visible, yet is null?";
...@@ -392,7 +385,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -392,7 +385,7 @@ public class ListHelper implements XScrollbarClient {
return false; 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; int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height;
vsb.handleMouseEvent(e.getID(), vsb.handleMouseEvent(e.getID(),
...@@ -405,7 +398,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -405,7 +398,7 @@ public class ListHelper implements XScrollbarClient {
* Called when items are added/removed. * Called when items are added/removed.
* Update whether the scrollbar is visible or not, scrollbar values * Update whether the scrollbar is visible or not, scrollbar values
*/ */
void updateScrollbars() { private void updateScrollbars() {
boolean oldVsbVis = vsbVis; boolean oldVsbVis = vsbVis;
vsbVis = vsb != null && items.size() > maxVisItems; vsbVis = vsb != null && items.size() > maxVisItems;
if (vsbVis) { if (vsbVis) {
...@@ -420,10 +413,11 @@ public class ListHelper implements XScrollbarClient { ...@@ -420,10 +413,11 @@ public class ListHelper implements XScrollbarClient {
// FIXME: check if added item makes a hsb necessary (if supported, that of course) // 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(); return items.size() > maxVisItems ? maxVisItems : items.size();
} }
@Override
public void repaintScrollbarRequest(XScrollbar sb) { public void repaintScrollbarRequest(XScrollbar sb) {
Graphics g = peer.getGraphics(); Graphics g = peer.getGraphics();
Rectangle bounds = peer.getBounds(); Rectangle bounds = peer.getBounds();
...@@ -436,6 +430,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -436,6 +430,7 @@ public class ListHelper implements XScrollbarClient {
g.dispose(); g.dispose();
} }
@Override
public void notifyValue(XScrollbar obj, int type, int v, boolean isAdjusting) { public void notifyValue(XScrollbar obj, int type, int v, boolean isAdjusting) {
if (obj == vsb) { if (obj == vsb) {
int oldScrollValue = vsb.getValue(); int oldScrollValue = vsb.getValue();
...@@ -467,7 +462,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -467,7 +462,7 @@ public class ListHelper implements XScrollbarClient {
} }
} }
public void updateColors(Color[] newColors) { void updateColors(Color[] newColors) {
colors = newColors; colors = newColors;
} }
...@@ -481,7 +476,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -481,7 +476,7 @@ public class ListHelper implements XScrollbarClient {
XVerticalScrollbar vsb, XVerticalScrollbar vsb,
XHorizontalScrollbar hsb) { XHorizontalScrollbar hsb) {
*/ */
public void paintItems(Graphics g, void paintItems(Graphics g,
Color[] colors, Color[] colors,
Rectangle bounds) { Rectangle bounds) {
// paint border // paint border
...@@ -490,17 +485,14 @@ public class ListHelper implements XScrollbarClient { ...@@ -490,17 +485,14 @@ public class ListHelper implements XScrollbarClient {
// paint focus? // paint focus?
} }
public void paintAllItems(Graphics g, void paintAllItems(Graphics g,
Color[] colors, Color[] colors,
Rectangle bounds) { Rectangle bounds) {
paintItems(g, colors, bounds, paintItems(g, colors, bounds,
firstDisplayedIndex(), lastDisplayedIndex()); firstDisplayedIndex(), lastDisplayedIndex());
} }
public void paintItems(Graphics g, private void paintItems(Graphics g, Color[] colors, Rectangle bounds,
Color[] colors, int first, int last) {
Rectangle bounds,
int first,
int last) {
peer.flush(); peer.flush();
int x = BORDER_WIDTH + ITEM_MARGIN; int x = BORDER_WIDTH + ITEM_MARGIN;
int width = bounds.width - 2*ITEM_MARGIN - 2*BORDER_WIDTH - (vsbVis ? SCROLLBAR_WIDTH : 0); int width = bounds.width - 2*ITEM_MARGIN - 2*BORDER_WIDTH - (vsbVis ? SCROLLBAR_WIDTH : 0);
...@@ -529,11 +521,8 @@ public class ListHelper implements XScrollbarClient { ...@@ -529,11 +521,8 @@ public class ListHelper implements XScrollbarClient {
/* /*
* comment about what is painted (i.e. the focus rect * comment about what is painted (i.e. the focus rect
*/ */
public void paintItem(Graphics g, private void paintItem(Graphics g, Color[] colors, String string, int x,
Color[] colors, int y, int width, int height, boolean selected,
String string,
int x, int y, int width, int height,
boolean selected,
boolean focused) { boolean focused) {
//System.out.println("LP.pI(): x="+x+" y="+y+" w="+width+" h="+height); //System.out.println("LP.pI(): x="+x+" y="+y+" w="+width+" h="+height);
//g.setColor(colors[BACKGROUND_COLOR]); //g.setColor(colors[BACKGROUND_COLOR]);
...@@ -575,7 +564,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -575,7 +564,7 @@ public class ListHelper implements XScrollbarClient {
//g.clipRect(clip.x, clip.y, clip.width, clip.height); //g.clipRect(clip.x, clip.y, clip.width, clip.height);
} }
boolean isItemSelected(int index) { private boolean isItemSelected(int index) {
Iterator itr = selected.iterator(); Iterator itr = selected.iterator();
while (itr.hasNext()) { while (itr.hasNext()) {
Integer val = (Integer)itr.next(); Integer val = (Integer)itr.next();
...@@ -586,7 +575,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -586,7 +575,7 @@ public class ListHelper implements XScrollbarClient {
return false; 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); int height = bounds.height - 2*BORDER_WIDTH - (hsbVis ? (SCROLLBAR_WIDTH-2) : 0);
Graphics ng = g.create(); Graphics ng = g.create();
...@@ -602,7 +591,7 @@ public class ListHelper implements XScrollbarClient { ...@@ -602,7 +591,7 @@ public class ListHelper implements XScrollbarClient {
} }
} }
public void paintHSB(Graphics g, Color colors[], Rectangle bounds) { private void paintHSB(Graphics g, Color colors[], Rectangle bounds) {
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package sun.awt.X11; package sun.awt.X11;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.dnd.DropTarget;
import sun.awt.LightweightFrame; import sun.awt.LightweightFrame;
import sun.swing.JLightweightFrame; import sun.swing.JLightweightFrame;
...@@ -69,4 +70,14 @@ public class XLightweightFramePeer extends XFramePeer { ...@@ -69,4 +70,14 @@ public class XLightweightFramePeer extends XFramePeer {
public void updateCursorImmediately() { public void updateCursorImmediately() {
SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget()); SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget());
} }
@Override
public void addDropTarget(DropTarget dt) {
getLwTarget().addDropTarget(dt);
}
@Override
public void removeDropTarget(DropTarget dt) {
getLwTarget().removeDropTarget(dt);
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -42,7 +42,7 @@ import sun.awt.datatransfer.DataTransferer; ...@@ -42,7 +42,7 @@ import sun.awt.datatransfer.DataTransferer;
/** /**
* A class which interfaces with the X11 selection service. * A class which interfaces with the X11 selection service.
*/ */
public final class XSelection { final class XSelection {
/* Maps atoms to XSelection instances. */ /* Maps atoms to XSelection instances. */
private static final Hashtable<XAtom, XSelection> table = new Hashtable<XAtom, XSelection>(); private static final Hashtable<XAtom, XSelection> table = new Hashtable<XAtom, XSelection>();
...@@ -118,11 +118,10 @@ public final class XSelection { ...@@ -118,11 +118,10 @@ public final class XSelection {
/** /**
* Creates a selection object. * Creates a selection object.
* *
* @param atom the selection atom. * @param atom the selection atom
* @param clpbrd the corresponding clipoboard * @throws NullPointerException if atom is {@code null}
* @exception NullPointerException if atom is <code>null</code>.
*/ */
public XSelection(XAtom atom) { XSelection(XAtom atom) {
if (atom == null) { if (atom == null) {
throw new NullPointerException("Null atom"); throw new NullPointerException("Null atom");
} }
...@@ -134,7 +133,7 @@ public final class XSelection { ...@@ -134,7 +133,7 @@ public final class XSelection {
return selectionAtom; return selectionAtom;
} }
public synchronized boolean setOwner(Transferable contents, Map formatMap, synchronized boolean setOwner(Transferable contents, Map formatMap,
long[] formats, long time) long[] formats, long time)
{ {
long owner = XWindow.getXAWTRootWindow().getWindow(); long owner = XWindow.getXAWTRootWindow().getWindow();
...@@ -433,7 +432,7 @@ public final class XSelection { ...@@ -433,7 +432,7 @@ public final class XSelection {
return data != null ? data : new byte[0]; return data != null ? data : new byte[0];
} }
void validateDataGetter(WindowPropertyGetter propertyGetter) private void validateDataGetter(WindowPropertyGetter propertyGetter)
throws IOException throws IOException
{ {
// The order of checks is important because a property getter // The order of checks is important because a property getter
......
...@@ -903,6 +903,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -903,6 +903,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
} }
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 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); return XDragSourceContextPeer.createDragSourceContextPeer(dge);
} }
...@@ -913,6 +918,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -913,6 +918,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
int srcActions, int srcActions,
DragGestureListener dgl) DragGestureListener dgl)
{ {
final LightweightFrame f = SunToolkit.getLightweightFrame(c);
if (f != null) {
return f.createDragGestureRecognizer(recognizerClass, ds, c, srcActions, dgl);
}
if (MouseDragGestureRecognizer.class.equals(recognizerClass)) if (MouseDragGestureRecognizer.class.equals(recognizerClass))
return (T)new XMouseDragGestureRecognizer(ds, c, srcActions, dgl); return (T)new XMouseDragGestureRecognizer(ds, c, srcActions, dgl);
else else
......
/*
* 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; package sun.awt;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
...@@ -29,7 +54,7 @@ import sun.util.logging.PlatformLogger; ...@@ -29,7 +54,7 @@ import sun.util.logging.PlatformLogger;
/** /**
* The X11 implementation of {@link FontManager}. * The X11 implementation of {@link FontManager}.
*/ */
public class X11FontManager extends SunFontManager { public final class X11FontManager extends SunFontManager {
// constants identifying XLFD and font ID fields // constants identifying XLFD and font ID fields
private static final int FOUNDRY_FIELD = 1; private static final int FOUNDRY_FIELD = 1;
...@@ -129,8 +154,6 @@ public class X11FontManager extends SunFontManager { ...@@ -129,8 +154,6 @@ public class X11FontManager extends SunFontManager {
*/ */
private static String[] fontdirs = null; private static String[] fontdirs = null;
private static String[] defaultPlatformFont = null;
private FontConfigManager fcManager = null; private FontConfigManager fcManager = null;
public static X11FontManager getInstance() { public static X11FontManager getInstance() {
...@@ -768,11 +791,9 @@ public class X11FontManager extends SunFontManager { ...@@ -768,11 +791,9 @@ public class X11FontManager extends SunFontManager {
return getFontPathNative(noType1Fonts); return getFontPathNative(noType1Fonts);
} }
public String[] getDefaultPlatformFont() { @Override
if (defaultPlatformFont != null) { protected String[] getDefaultPlatformFont() {
return defaultPlatformFont; final String[] info = new String[2];
}
String[] info = new String[2];
getFontConfigManager().initFontConfigFonts(false); getFontConfigManager().initFontConfigFonts(false);
FontConfigManager.FcCompFont[] fontConfigFonts = FontConfigManager.FcCompFont[] fontConfigFonts =
getFontConfigManager().getFontConfigFonts(); getFontConfigManager().getFontConfigFonts();
...@@ -798,8 +819,7 @@ public class X11FontManager extends SunFontManager { ...@@ -798,8 +819,7 @@ public class X11FontManager extends SunFontManager {
info[1] = "/dialog.ttf"; info[1] = "/dialog.ttf";
} }
} }
defaultPlatformFont = info; return info;
return defaultPlatformFont;
} }
public synchronized FontConfigManager getFontConfigManager() { public synchronized FontConfigManager getFontConfigManager() {
......
...@@ -689,6 +689,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, ...@@ -689,6 +689,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
closeSafely(childenv[0]); closeSafely(childenv[0]);
closeSafely(childenv[1]); closeSafely(childenv[1]);
releaseBytes(env, helperpath, phelperpath);
releaseBytes(env, prog, pprog); releaseBytes(env, prog, pprog);
releaseBytes(env, argBlock, pargBlock); releaseBytes(env, argBlock, pargBlock);
releaseBytes(env, envBlock, penvBlock); releaseBytes(env, envBlock, penvBlock);
......
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
"sr_SP", "sr_YU", "sr_SP", "sr_YU",
"tchinese", "zh_TW", "tchinese", "zh_TW",
#endif #endif
"" "", "",
}; };
/* /*
...@@ -188,7 +188,7 @@ static char *language_names[] = { ...@@ -188,7 +188,7 @@ static char *language_names[] = {
"japanese", "ja", "japanese", "ja",
"korean", "ko", "korean", "ko",
#endif #endif
"", "", "",
}; };
/* /*
...@@ -201,7 +201,7 @@ static char *script_names[] = { ...@@ -201,7 +201,7 @@ static char *script_names[] = {
"iqtelif", "Latn", "iqtelif", "Latn",
"latin", "Latn", "latin", "Latn",
#endif #endif
"", "", "",
}; };
/* /*
...@@ -212,7 +212,7 @@ static char *country_names[] = { ...@@ -212,7 +212,7 @@ static char *country_names[] = {
"RN", "US", // used on Linux, not clear what it stands for "RN", "US", // used on Linux, not clear what it stands for
#endif #endif
"YU", "CS", // YU has been removed from ISO 3166 "YU", "CS", // YU has been removed from ISO 3166
"", "", "",
}; };
/* /*
...@@ -220,5 +220,5 @@ static char *country_names[] = { ...@@ -220,5 +220,5 @@ static char *country_names[] = {
*/ */
static char *variant_names[] = { static char *variant_names[] = {
"nynorsk", "NY", "nynorsk", "NY",
"", "", "",
}; };
...@@ -652,11 +652,11 @@ static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz ...@@ -652,11 +652,11 @@ static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz
* using <java_home>/lib/tzmappings. If the TZ value is not found, it * using <java_home>/lib/tzmappings. If the TZ value is not found, it
* trys some libc implementation dependent mappings. If it still * 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 * 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*/ /*ARGSUSED1*/
char * char *
findJavaTZ_md(const char *java_home_dir, const char *country) findJavaTZ_md(const char *java_home_dir)
{ {
char *tz; char *tz;
char *javatz = NULL; char *javatz = NULL;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#ifndef _TIMEZONE_MD_H #ifndef _TIMEZONE_MD_H
#define _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(); char *getGMTOffsetID();
#endif #endif
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -37,7 +37,6 @@ import java.util.Locale; ...@@ -37,7 +37,6 @@ import java.util.Locale;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import sun.awt.Win32GraphicsEnvironment;
import sun.awt.windows.WFontConfiguration; import sun.awt.windows.WFontConfiguration;
import sun.font.FontManager; import sun.font.FontManager;
import sun.font.SunFontManager; import sun.font.SunFontManager;
...@@ -48,9 +47,7 @@ import sun.java2d.SunGraphicsEnvironment; ...@@ -48,9 +47,7 @@ import sun.java2d.SunGraphicsEnvironment;
/** /**
* The X11 implementation of {@link FontManager}. * The X11 implementation of {@link FontManager}.
*/ */
public class Win32FontManager extends SunFontManager { public final class Win32FontManager extends SunFontManager {
private static String[] defaultPlatformFont = null;
private static TrueTypeFont eudcFont; private static TrueTypeFont eudcFont;
...@@ -215,12 +212,8 @@ public class Win32FontManager extends SunFontManager { ...@@ -215,12 +212,8 @@ public class Win32FontManager extends SunFontManager {
protected synchronized native String getFontPath(boolean noType1Fonts); protected synchronized native String getFontPath(boolean noType1Fonts);
public String[] getDefaultPlatformFont() { @Override
protected String[] getDefaultPlatformFont() {
if (defaultPlatformFont != null) {
return defaultPlatformFont;
}
String[] info = new String[2]; String[] info = new String[2];
info[0] = "Arial"; info[0] = "Arial";
info[1] = "c:\\windows\\fonts"; info[1] = "c:\\windows\\fonts";
...@@ -247,8 +240,7 @@ public class Win32FontManager extends SunFontManager { ...@@ -247,8 +240,7 @@ public class Win32FontManager extends SunFontManager {
info[1] = dirs[0]; info[1] = dirs[0];
} }
info[1] = info[1] + File.separator + "arial.ttf"; info[1] = info[1] + File.separator + "arial.ttf";
defaultPlatformFont = info; return info;
return defaultPlatformFont;
} }
/* register only TrueType/OpenType fonts /* register only TrueType/OpenType fonts
......
...@@ -27,6 +27,7 @@ package sun.awt.windows; ...@@ -27,6 +27,7 @@ package sun.awt.windows;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.dnd.DropTarget;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
...@@ -94,4 +95,14 @@ public class WLightweightFramePeer extends WFramePeer { ...@@ -94,4 +95,14 @@ public class WLightweightFramePeer extends WFramePeer {
public boolean isLightweightFramePeer() { public boolean isLightweightFramePeer() {
return true; return true;
} }
@Override
public void addDropTarget(DropTarget dt) {
getLwTarget().addDropTarget(dt);
}
@Override
public void removeDropTarget(DropTarget dt) {
getLwTarget().removeDropTarget(dt);
}
} }
...@@ -843,6 +843,11 @@ public final class WToolkit extends SunToolkit implements Runnable { ...@@ -843,6 +843,11 @@ public final class WToolkit extends SunToolkit implements Runnable {
@Override @Override
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 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); return WDragSourceContextPeer.createDragSourceContextPeer(dge);
} }
...@@ -852,6 +857,11 @@ public final class WToolkit extends SunToolkit implements Runnable { ...@@ -852,6 +857,11 @@ public final class WToolkit extends SunToolkit implements Runnable {
DragSource ds, Component c, int srcActions, DragSource ds, Component c, int srcActions,
DragGestureListener dgl) DragGestureListener dgl)
{ {
final LightweightFrame f = SunToolkit.getLightweightFrame(c);
if (f != null) {
return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl);
}
if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass))
return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl); return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl);
else else
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -394,31 +394,34 @@ static int getWinTimeZone(char *winZoneName, char *winMapID) ...@@ -394,31 +394,34 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
* *
* value_type is one of the following values: * value_type is one of the following values:
* VALUE_KEY for exact key matching * 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). * required for the old Windows, such as NT 4.0 SP3).
*/ */
static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName, static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName,
char *mapID, const char *country) char *mapID)
{ {
int line; int line;
int IDmatched = 0; int IDmatched = 0;
FILE *fp; FILE *fp;
char *javaTZName = NULL; char *javaTZName = NULL;
char *items[TZ_NITEMS]; char *items[TZ_NITEMS];
char mapFileName[_MAX_PATH + 1]; char *mapFileName;
char lineBuffer[MAX_ZONE_CHAR * 4]; char lineBuffer[MAX_ZONE_CHAR * 4];
char bestMatch[MAX_ZONE_CHAR]; int noMapID = *mapID == '\0'; /* no mapID on Vista and later */
int noMapID = *mapID == '\0'; /* no mapID on Vista */
bestMatch[0] = '\0';
mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1);
if (mapFileName == NULL) {
return NULL;
}
strcpy(mapFileName, java_home_dir); strcpy(mapFileName, java_home_dir);
strcat(mapFileName, MAPPINGS_FILE); strcat(mapFileName, MAPPINGS_FILE);
if ((fp = fopen(mapFileName, "r")) == NULL) { if ((fp = fopen(mapFileName, "r")) == NULL) {
jio_fprintf(stderr, "can't open %s.\n", mapFileName); jio_fprintf(stderr, "can't open %s.\n", mapFileName);
free((void *) mapFileName);
return NULL; return NULL;
} }
free((void *) mapFileName);
line = 0; line = 0;
while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) { while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) {
...@@ -469,18 +472,6 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName ...@@ -469,18 +472,6 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
javaTZName = _strdup(items[TZ_JAVA_NAME]); javaTZName = _strdup(items[TZ_JAVA_NAME]);
break; 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 { } else {
if (IDmatched == 1) { if (IDmatched == 1) {
/* /*
...@@ -492,9 +483,6 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName ...@@ -492,9 +483,6 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
} }
fclose(fp); fclose(fp);
if (javaTZName == NULL && bestMatch[0] != '\0') {
javaTZName = _strdup(bestMatch);
}
return javaTZName; return javaTZName;
illegal_format: illegal_format:
...@@ -506,7 +494,7 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName ...@@ -506,7 +494,7 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName
/* /*
* Detects the platform time zone which maps to a Java time zone ID. * 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 winZoneName[MAX_ZONE_CHAR];
char winMapID[MAX_MAPID_LENGTH]; char winMapID[MAX_MAPID_LENGTH];
...@@ -521,7 +509,7 @@ char *findJavaTZ_md(const char *java_home_dir, const char *country) ...@@ -521,7 +509,7 @@ char *findJavaTZ_md(const char *java_home_dir, const char *country)
std_timezone = _strdup(winZoneName); std_timezone = _strdup(winZoneName);
} else { } else {
std_timezone = matchJavaTZ(java_home_dir, result, std_timezone = matchJavaTZ(java_home_dir, result,
winZoneName, winMapID, country); winZoneName, winMapID);
} }
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#ifndef _TIMEZONE_MD_H #ifndef _TIMEZONE_MD_H
#define _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(); char *getGMTOffsetID();
#endif #endif
...@@ -467,7 +467,9 @@ void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer) ...@@ -467,7 +467,9 @@ void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer)
jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig"); jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig");
DASSERT(win32GCCls != NULL); DASSERT(win32GCCls != NULL);
DASSERT(env->IsInstanceOf(compGC, win32GCCls)); DASSERT(env->IsInstanceOf(compGC, win32GCCls));
CHECK_NULL(win32GCCls); if (win32GCCls == NULL) {
throw std::bad_alloc();
}
env->SetObjectField(peer, AwtComponent::peerGCID, compGC); env->SetObjectField(peer, AwtComponent::peerGCID, compGC);
} }
} }
...@@ -2141,19 +2143,7 @@ namespace TimeHelper { ...@@ -2141,19 +2143,7 @@ namespace TimeHelper {
} }
jlong getMessageTimeUTC() { jlong getMessageTimeUTC() {
return windowsToUTC(getMessageTimeWindows()); return ::JVM_CurrentTimeMillis(NULL, 0);
}
// 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;
} }
} //TimeHelper } //TimeHelper
...@@ -3578,7 +3568,7 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, ...@@ -3578,7 +3568,7 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED, SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
TimeHelper::windowsToUTC(msg.time), jkey, character, TimeHelper::getMessageTimeUTC(), jkey, character,
modifiers, keyLocation, (jlong)wkey, &msg); modifiers, keyLocation, (jlong)wkey, &msg);
// bugid 4724007: Windows does not create a WM_CHAR for the Del key // bugid 4724007: Windows does not create a WM_CHAR for the Del key
...@@ -3588,7 +3578,7 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, ...@@ -3588,7 +3578,7 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
// for Java - we don't want Windows trying to process it). // for Java - we don't want Windows trying to process it).
if (jkey == java_awt_event_KeyEvent_VK_DELETE) { if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
TimeHelper::windowsToUTC(msg.time), TimeHelper::getMessageTimeUTC(),
java_awt_event_KeyEvent_VK_UNDEFINED, java_awt_event_KeyEvent_VK_UNDEFINED,
character, modifiers, character, modifiers,
java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0); java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
...@@ -3620,7 +3610,7 @@ MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt, ...@@ -3620,7 +3610,7 @@ MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED, SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
TimeHelper::windowsToUTC(msg.time), jkey, character, TimeHelper::getMessageTimeUTC(), jkey, character,
modifiers, keyLocation, (jlong)wkey, &msg); modifiers, keyLocation, (jlong)wkey, &msg);
return mrConsume; return mrConsume;
} }
...@@ -3665,7 +3655,7 @@ MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL ...@@ -3665,7 +3655,7 @@ MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL
jint modifiers = GetJavaModifiers(); jint modifiers = GetJavaModifiers();
SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
TimeHelper::windowsToUTC(msg.time), TimeHelper::getMessageTimeUTC(),
java_awt_event_KeyEvent_VK_UNDEFINED, java_awt_event_KeyEvent_VK_UNDEFINED,
unicodeChar, modifiers, unicodeChar, modifiers,
java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
...@@ -3734,7 +3724,7 @@ MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags, ...@@ -3734,7 +3724,7 @@ MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
InitMessage(&msg, message, character, InitMessage(&msg, message, character,
MAKELPARAM(repCnt, flags)); MAKELPARAM(repCnt, flags));
SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
TimeHelper::windowsToUTC(msg.time), TimeHelper::getMessageTimeUTC(),
java_awt_event_KeyEvent_VK_UNDEFINED, java_awt_event_KeyEvent_VK_UNDEFINED,
unicodeChar, modifiers, unicodeChar, modifiers,
java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
......
...@@ -229,9 +229,10 @@ void AwtCursor::UpdateCursor(AwtComponent *comp) { ...@@ -229,9 +229,10 @@ void AwtCursor::UpdateCursor(AwtComponent *comp) {
if (cur != NULL) { if (cur != NULL) {
::SetCursor(cur); ::SetCursor(cur);
} else { } else {
safe_ExceptionOccurred(env); if (safe_ExceptionOccurred(env)) {
env->ExceptionClear();
}
} }
if (AwtCursor::updateCursorID == NULL) { if (AwtCursor::updateCursorID == NULL) {
jclass cls = jclass cls =
env->FindClass("sun/awt/windows/WGlobalCursorManager"); env->FindClass("sun/awt/windows/WGlobalCursorManager");
......
...@@ -758,6 +758,7 @@ Java_sun_awt_windows_WPrinterJob_getDefaultPage(JNIEnv *env, jobject self, ...@@ -758,6 +758,7 @@ Java_sun_awt_windows_WPrinterJob_getDefaultPage(JNIEnv *env, jobject self,
// through print dialog or start of printing // through print dialog or start of printing
// None of those may have happened yet, so call initPrinter() // None of those may have happened yet, so call initPrinter()
initPrinter(env, self); initPrinter(env, self);
JNU_CHECK_EXCEPTION(env);
HANDLE hDevNames = AwtPrintControl::getPrintHDName(env, self); HANDLE hDevNames = AwtPrintControl::getPrintHDName(env, self);
HDC hdc = AwtPrintControl::getPrintDC(env, self); HDC hdc = AwtPrintControl::getPrintDC(env, self);
...@@ -1102,6 +1103,7 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) { ...@@ -1102,6 +1103,7 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) {
jboolean err; jboolean err;
initPrinter(env, self); initPrinter(env, self);
JNU_CHECK_EXCEPTION(env);
// check for collation // check for collation
HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self); HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self);
...@@ -1362,6 +1364,13 @@ Java_sun_awt_windows_WPrinterJob__1startDoc(JNIEnv *env, jobject self, ...@@ -1362,6 +1364,13 @@ Java_sun_awt_windows_WPrinterJob__1startDoc(JNIEnv *env, jobject self,
} }
initPrinter(env, self); initPrinter(env, self);
if (env->ExceptionCheck()) {
if (dest != NULL) {
JNU_ReleaseStringPlatformChars(env, dest, destination);
}
return JNI_FALSE;
}
HDC printDC = AwtPrintControl::getPrintDC(env, self); HDC printDC = AwtPrintControl::getPrintDC(env, self);
SAVE_CONTROLWORD SAVE_CONTROLWORD
...@@ -3827,6 +3836,7 @@ void setCapabilities(JNIEnv *env, jobject self, HDC printDC) { ...@@ -3827,6 +3836,7 @@ void setCapabilities(JNIEnv *env, jobject self, HDC printDC) {
// pixels per inch in y direction // pixels per inch in y direction
jint yRes = GetDeviceCaps(printDC, LOGPIXELSY); jint yRes = GetDeviceCaps(printDC, LOGPIXELSY);
err = setIntField(env, self, YRES_STR, yRes); err = setIntField(env, self, YRES_STR, yRes);
if (err) return;
// x coord of printable area in pixels // x coord of printable area in pixels
jint xOrg = GetDeviceCaps(printDC, PHYSICALOFFSETX); jint xOrg = GetDeviceCaps(printDC, PHYSICALOFFSETX);
......
...@@ -325,7 +325,7 @@ static int clickCount = 0; ...@@ -325,7 +325,7 @@ static int clickCount = 0;
MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button) MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
{ {
jlong now = TimeHelper::windowsToUTC(::GetTickCount()); jlong now = TimeHelper::getMessageTimeUTC();
jint javaModif = AwtComponent::GetJavaModifiers(); jint javaModif = AwtComponent::GetJavaModifiers();
if (lastClickTrIc == this && if (lastClickTrIc == this &&
...@@ -361,14 +361,14 @@ MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button) ...@@ -361,14 +361,14 @@ MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button)
MSG msg; MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 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, x, y, AwtComponent::GetJavaModifiers(), clickCount,
(AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
TRUE : FALSE), AwtComponent::GetButton(button), &msg); TRUE : FALSE), AwtComponent::GetButton(button), &msg);
if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state
SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED, 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)); clickCount, JNI_FALSE, AwtComponent::GetButton(button));
} }
m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state
...@@ -395,7 +395,7 @@ MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y) ...@@ -395,7 +395,7 @@ MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y)
if ((flags & ALL_MK_BUTTONS) != 0) { if ((flags & ALL_MK_BUTTONS) != 0) {
m_mouseButtonClickAllowed = 0; m_mouseButtonClickAllowed = 0;
} else { } 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, AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,
java_awt_event_MouseEvent_NOBUTTON, &msg); java_awt_event_MouseEvent_NOBUTTON, &msg);
} }
...@@ -408,7 +408,7 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y) ...@@ -408,7 +408,7 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y)
if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) { if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
MSG msg; MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 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); AwtComponent::GetJavaModifiers(), &msg);
} }
return mrConsume; return mrConsume;
...@@ -417,14 +417,14 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y) ...@@ -417,14 +417,14 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y)
MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y) MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y)
{ {
static jlong lastKeySelectTime = 0; static jlong lastKeySelectTime = 0;
jlong now = TimeHelper::windowsToUTC(::GetTickCount()); jlong now = TimeHelper::getMessageTimeUTC();
// If a user selects a notify icon with the ENTER key, // If a user selects a notify icon with the ENTER key,
// Shell 5.0 sends double NIN_KEYSELECT notification. // Shell 5.0 sends double NIN_KEYSELECT notification.
if (lastKeySelectTime != now) { if (lastKeySelectTime != now) {
MSG msg; MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 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); AwtComponent::GetJavaModifiers(), &msg);
} }
lastKeySelectTime = now; lastKeySelectTime = now;
...@@ -441,7 +441,7 @@ MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y) ...@@ -441,7 +441,7 @@ MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y)
if (clickCount == 2) { if (clickCount == 2) {
MSG msg; MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 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); AwtComponent::GetJavaModifiers(), &msg);
} }
return mrConsume; return mrConsume;
......
/*
* 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;
}
}
}
/*
* 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();
}
}
}
/*
* 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;
}
}
/*
* 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();
}
}
}
/*
* 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;
}
}
...@@ -2246,9 +2246,9 @@ public class Basic { ...@@ -2246,9 +2246,9 @@ public class Basic {
fail("Test failed: Process exited prematurely"); fail("Test failed: Process exited prematurely");
} }
long end = System.nanoTime(); 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. // 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)"); fail("Test failed: waitFor took too long (" + (end - start) + "ns)");
p.destroy(); p.destroy();
......
...@@ -54,9 +54,6 @@ public class SecurityManagerClinit { ...@@ -54,9 +54,6 @@ public class SecurityManagerClinit {
System.getProperty("java.home") + System.getProperty("java.home") +
File.separator + "bin" + File.separator + "java"; 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 = final Policy policy =
new Policy new Policy
(new FilePermission("<<ALL FILES>>", "execute"), (new FilePermission("<<ALL FILES>>", "execute"),
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8047795 * @bug 8047795 8053938
* @summary Ensure that replaceAll operator cannot add bad elements * @summary Ensure that replaceAll operator cannot add bad elements
* @author Mike Duigou * @author Mike Duigou
*/ */
...@@ -46,5 +46,16 @@ public class CheckedListReplaceAll { ...@@ -46,5 +46,16 @@ public class CheckedListReplaceAll {
thwarted.printStackTrace(System.out); thwarted.printStackTrace(System.out);
System.out.println("Curses! Foiled again!"); 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!");
}
} }
} }
/*
* 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);
}
}
}
...@@ -28,7 +28,7 @@ import javax.swing.JMenuBar; ...@@ -28,7 +28,7 @@ import javax.swing.JMenuBar;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
/* @test /* @test
* @bug 8031573 * @bug 8031573 8040279
* @summary [macosx] Checkmarks of JCheckBoxMenuItems aren't rendered * @summary [macosx] Checkmarks of JCheckBoxMenuItems aren't rendered
* in high resolution on Retina * in high resolution on Retina
* @author Alexander Scherbatiy * @author Alexander Scherbatiy
......
...@@ -31,7 +31,7 @@ import sun.awt.OSInfo; ...@@ -31,7 +31,7 @@ import sun.awt.OSInfo;
/** /**
* @test * @test
* @bug 8024926 * @bug 8024926 8040279
* @summary [macosx] AquaIcon HiDPI support * @summary [macosx] AquaIcon HiDPI support
* @author Alexander Scherbatiy * @author Alexander Scherbatiy
* @run applet/manual=yesno bug8024926.html * @run applet/manual=yesno bug8024926.html
......
/*
* 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;
}
}
/*
* 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");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<root><elem><level2_0>ABCD</level2_0><level2_1>EFG</level2_1></elem></root>
<?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>
...@@ -483,7 +483,7 @@ public class FtpURL { ...@@ -483,7 +483,7 @@ public class FtpURL {
// Now let's check the URL handler // 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(); con = url.openConnection();
in = new BufferedReader(new InputStreamReader(con.getInputStream())); in = new BufferedReader(new InputStreamReader(con.getInputStream()));
do { do {
......
...@@ -40,6 +40,7 @@ public class TestAll { ...@@ -40,6 +40,7 @@ public class TestAll {
TestMultiplePresent.class, TestMultiplePresent.class,
TestPresent.class, TestPresent.class,
TestTransmit.class, TestTransmit.class,
TestDirect.class,
}; };
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
......
/*
* 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.");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册