提交 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,21 +285,7 @@ public class AquaImageFactory { ...@@ -287,21 +285,7 @@ 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);
return icon;
if (icon instanceof MultiResolutionImage) {
return icon;
}
int w = icon.getWidth(null);
int h = icon.getHeight(null);
Dimension[] sizes = new Dimension[]{
new Dimension(w, h), new Dimension(2 * w, 2 * h)
};
return new MultiResolutionBufferedImage(icon, sizes, (width, height) ->
AquaUtils.getCImageCreator().createImageFromName(
imageName, width, height));
} }
public static class NineSliceMetrics { public static class NineSliceMetrics {
......
...@@ -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; if (AccessController.doPrivileged(
else { new GetBooleanAction(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"))) {
props[0] = getPrivSysProp(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"); System.err.println(AquaLookAndFeel.sOldPropertyPrefix +
"useScreenMenuBar has been deprecated. Please switch to " +
if (props[0] != null && props[0].equals("true")) { AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar");
System.err.println(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar has been deprecated. Please switch to " + AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); return true;
useScreenMenuBar = true; }
} return false;
}
} catch(final Throwable t) { };
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,8 +166,30 @@ public class SortingFocusTraversalPolicy ...@@ -133,8 +166,30 @@ 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);
Collections.sort(cycle, comparator); if (!legacySortingFTPEnabled ||
!legacySort(cycle, comparator))
{
Collections.sort(cycle, comparator);
}
}
}
private boolean legacySort(List<Component> l, Comparator<? super Component> c) {
if (legacyMergeSortMethod == null)
return false;
Object[] a = l.toArray();
try {
legacyMergeSortMethod.invoke(null, a, c);
} catch (IllegalAccessException | InvocationTargetException e) {
return false;
}
ListIterator<Component> i = l.listIterator();
for (Object e : a) {
i.next();
i.set((Component)e);
} }
return true;
} }
private void enumerateCycle(Container container, List<Component> cycle) { private void enumerateCycle(Container container, List<Component> cycle) {
......
...@@ -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
...@@ -94,9 +95,19 @@ implements java.io.Serializable { ...@@ -94,9 +95,19 @@ implements java.io.Serializable {
*/ */
private void init(byte[] seed) { private void init(byte[] seed) {
try { try {
digest = MessageDigest.getInstance("SHA"); /*
} catch (NoSuchAlgorithmException e) { * Use the local SUN implementation to avoid native
throw new InternalError("internal error: SHA-1 not available.", e); * performance overhead.
*/
digest = MessageDigest.getInstance("SHA", "SUN");
} catch (NoSuchProviderException | NoSuchAlgorithmException e) {
// Fallback to any available.
try {
digest = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException exc) {
throw new InternalError(
"internal error: SHA-1 not available.", exc);
}
} }
if (seed != null) { if (seed != null) {
...@@ -265,9 +276,19 @@ implements java.io.Serializable { ...@@ -265,9 +276,19 @@ implements java.io.Serializable {
s.defaultReadObject (); s.defaultReadObject ();
try { try {
digest = MessageDigest.getInstance("SHA"); /*
} catch (NoSuchAlgorithmException e) { * Use the local SUN implementation to avoid native
throw new InternalError("internal error: SHA-1 not available.", e); * performance overhead.
*/
digest = MessageDigest.getInstance("SHA", "SUN");
} catch (NoSuchProviderException | NoSuchAlgorithmException e) {
// Fallback to any available.
try {
digest = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException exc) {
throw new InternalError(
"internal error: SHA-1 not available.", exc);
}
} }
} }
} }
/* /*
* 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 static enum Platform {
LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
final LaunchMechanism defaultLaunchMechanism;
final Set<LaunchMechanism> validLaunchMechanisms;
Platform(LaunchMechanism ... launchMechanisms) {
this.defaultLaunchMechanism = launchMechanisms[0];
this.validLaunchMechanisms =
EnumSet.copyOf(Arrays.asList(launchMechanisms));
}
private String helperPath(String javahome, String osArch) {
switch (this) {
case SOLARIS:
if (osArch.equals("x86")) { osArch = "i386"; }
else if (osArch.equals("x86_64")) { osArch = "amd64"; }
// fall through...
case LINUX:
case AIX:
return javahome + "/lib/" + osArch + "/jspawnhelper";
case BSD:
return javahome + "/lib/jspawnhelper";
default:
throw new AssertionError("Unsupported platform: " + this);
}
}
private int value; String helperPath() {
LaunchMechanism(int x) {value = x;} 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;
}
);
}
/* On AIX, the default is to spawn */ static Platform get() {
private static final LaunchMechanism launchMechanism; String osName = AccessController.doPrivileged(
private static byte[] helperpath; (PrivilegedAction<String>) () -> System.getProperty("os.name")
);
if (osName.equals("Linux")) { return LINUX; }
if (osName.contains("OS X")) { return BSD; }
if (osName.equals("SunOS")) { return SOLARIS; }
if (osName.equals("AIX")) { return AIX; }
throw new Error(osName + " is not a supported OS platform.");
}
}
private static final Platform platform = Platform.get();
private static final LaunchMechanism launchMechanism = platform.launchMechanism();
private static final byte[] helperpath = toCString(platform.helperPath());
private static byte[] toCString(String s) { 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
...@@ -141,41 +214,28 @@ final class UNIXProcess extends Process { ...@@ -141,41 +214,28 @@ final class UNIXProcess extends Process {
boolean redirectErrorStream) boolean redirectErrorStream)
throws IOException; 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. * The thread pool of "process reaper" daemon threads.
*/ */
private static final Executor processReaperExecutor = private static final Executor processReaperExecutor =
doPrivileged(new PrivilegedAction<Executor>() { doPrivileged((PrivilegedAction<Executor>) () -> {
public Executor run() {
return Executors.newCachedThreadPool ThreadGroup tg = Thread.currentThread().getThreadGroup();
(new ProcessReaperThreadFactory()); while (tg.getParent() != null) tg = tg.getParent();
}}); ThreadGroup systemThreadGroup = tg;
ThreadFactory threadFactory = grimReaper -> {
// Our thread stack requirement is quite modest.
Thread t = new Thread(systemThreadGroup, grimReaper,
"process reaper", 32768);
t.setDaemon(true);
// A small attempt (probably futile) to avoid priority inversion
t.setPriority(Thread.MAX_PRIORITY);
return t;
};
return Executors.newCachedThreadPool(threadFactory);
});
UNIXProcess(final byte[] prog, 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,40 +271,112 @@ final class UNIXProcess extends Process { ...@@ -212,40 +271,112 @@ final class UNIXProcess extends Process {
} }
void initStreams(int[] fds) throws IOException { void initStreams(int[] fds) throws IOException {
stdin = (fds[0] == -1) ? switch (platform) {
ProcessBuilder.NullOutputStream.INSTANCE : case LINUX:
new ProcessPipeOutputStream(fds[0]); case BSD:
stdin = (fds[0] == -1) ?
stdout = (fds[1] == -1) ? ProcessBuilder.NullOutputStream.INSTANCE :
ProcessBuilder.NullInputStream.INSTANCE : new ProcessPipeOutputStream(fds[0]);
new ProcessPipeInputStream(fds[1]);
stdout = (fds[1] == -1) ?
stderr = (fds[2] == -1) ? ProcessBuilder.NullInputStream.INSTANCE :
ProcessBuilder.NullInputStream.INSTANCE : new ProcessPipeInputStream(fds[1]);
new ProcessPipeInputStream(fds[2]);
stderr = (fds[2] == -1) ?
processReaperExecutor.execute(new Runnable() { ProcessBuilder.NullInputStream.INSTANCE :
public void run() { new ProcessPipeInputStream(fds[2]);
int exitcode = waitForProcessExit(pid);
UNIXProcess.this.processExited(exitcode); processReaperExecutor.execute(() -> {
}}); int exitcode = waitForProcessExit(pid);
}
synchronized (this) {
void processExited(int exitcode) { this.exitcode = exitcode;
synchronized (this) { this.hasExited = true;
this.exitcode = exitcode; this.notifyAll();
hasExited = true; }
notifyAll();
if (stdout instanceof ProcessPipeInputStream)
((ProcessPipeInputStream) stdout).processExited();
if (stderr instanceof ProcessPipeInputStream)
((ProcessPipeInputStream) stderr).processExited();
if (stdin instanceof ProcessPipeOutputStream)
((ProcessPipeOutputStream) stdin).processExited();
});
break;
case SOLARIS:
stdin = (fds[0] == -1) ?
ProcessBuilder.NullOutputStream.INSTANCE :
new BufferedOutputStream(
new FileOutputStream(newFileDescriptor(fds[0])));
stdout = (fds[1] == -1) ?
ProcessBuilder.NullInputStream.INSTANCE :
new BufferedInputStream(
stdout_inner_stream =
new DeferredCloseInputStream(
newFileDescriptor(fds[1])));
stderr = (fds[2] == -1) ?
ProcessBuilder.NullInputStream.INSTANCE :
new DeferredCloseInputStream(newFileDescriptor(fds[2]));
/*
* For each subprocess forked a corresponding reaper task
* is submitted. That task is the only thread which waits
* for the subprocess to terminate and it doesn't hold any
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* need no native code).
*/
processReaperExecutor.execute(() -> {
int exitcode = waitForProcessExit(pid);
synchronized (this) {
this.exitcode = exitcode;
this.hasExited = true;
this.notifyAll();
}
});
break;
case AIX:
stdin = (fds[0] == -1) ?
ProcessBuilder.NullOutputStream.INSTANCE :
new ProcessPipeOutputStream(fds[0]);
stdout = (fds[1] == -1) ?
ProcessBuilder.NullInputStream.INSTANCE :
new DeferredCloseProcessPipeInputStream(fds[1]);
stderr = (fds[2] == -1) ?
ProcessBuilder.NullInputStream.INSTANCE :
new DeferredCloseProcessPipeInputStream(fds[2]);
processReaperExecutor.execute(() -> {
int exitcode = waitForProcessExit(pid);
synchronized (this) {
this.exitcode = exitcode;
this.hasExited = true;
this.notifyAll();
}
if (stdout instanceof DeferredCloseProcessPipeInputStream)
((DeferredCloseProcessPipeInputStream) stdout).processExited();
if (stderr instanceof DeferredCloseProcessPipeInputStream)
((DeferredCloseProcessPipeInputStream) stderr).processExited();
if (stdin instanceof ProcessPipeOutputStream)
((ProcessPipeOutputStream) stdin).processExited();
});
break;
default: throw new AssertionError("Unsupported platform: " + platform);
} }
if (stdout instanceof ProcessPipeInputStream)
((ProcessPipeInputStream) stdout).processExited();
if (stderr instanceof ProcessPipeInputStream)
((ProcessPipeInputStream) stderr).processExited();
if (stdin instanceof ProcessPipeOutputStream)
((ProcessPipeOutputStream) stdin).processExited();
} }
public OutputStream getOutputStream() { public OutputStream getOutputStream() {
...@@ -293,20 +424,52 @@ final class UNIXProcess extends Process { ...@@ -293,20 +424,52 @@ 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) {
// There is a risk that pid will be recycled, causing us to switch (platform) {
// kill the wrong process! So we only terminate processes case LINUX:
// that appear to still be running. Even with this check, case BSD:
// there is an unavoidable race condition here, but the window case AIX:
// is very small, and OSes try hard to not recycle pids too // There is a risk that pid will be recycled, causing us to
// soon, so this is quite safe. // kill the wrong process! So we only terminate processes
synchronized (this) { // that appear to still be running. Even with this check,
if (!hasExited) // there is an unavoidable race condition here, but the window
destroyProcess(pid, force); // is very small, and OSes try hard to not recycle pids too
} // soon, so this is quite safe.
try { stdin.close(); } catch (IOException ignored) {} synchronized (this) {
try { stdout.close(); } catch (IOException ignored) {} if (!hasExited)
try { stderr.close(); } catch (IOException ignored) {} destroyProcess(pid, force);
}
try { stdin.close(); } catch (IOException ignored) {}
try { stdout.close(); } catch (IOException ignored) {}
try { stderr.close(); } catch (IOException ignored) {}
break;
case SOLARIS:
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
synchronized (this) {
if (!hasExited)
destroyProcess(pid, force);
try {
stdin.close();
if (stdout_inner_stream != null)
stdout_inner_stream.closeDeferred(stdout);
if (stderr instanceof DeferredCloseInputStream)
((DeferredCloseInputStream) stderr)
.closeDeferred(stderr);
} catch (IOException e) {
// ignore
}
}
break;
default: throw new AssertionError("Unsupported platform: " + platform);
}
} }
public void destroy() { 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,24 +79,16 @@ public class ListHelper implements XScrollbarClient { ...@@ -79,24 +79,16 @@ 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, int SCROLLBAR) {
boolean scrollVert,
boolean scrollHoriz,
Font font,
int maxVisItems,
int SPACE,
int MARGIN,
int BORDER,
int SCROLLBAR) {
this.peer = peer; this.peer = peer;
this.colors = colors; this.colors = colors;
this.multiSelect = multiSelect; this.multiSelect = multiSelect;
...@@ -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,12 +521,9 @@ public class ListHelper implements XScrollbarClient { ...@@ -529,12 +521,9 @@ 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, boolean focused) {
int x, int y, int width, int height,
boolean selected,
boolean focused) {
//System.out.println("LP.pI(): x="+x+" y="+y+" w="+width+" h="+height); //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,8 +133,8 @@ public final class XSelection { ...@@ -134,8 +133,8 @@ 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();
long selection = selectionAtom.getAtom(); long selection = selectionAtom.getAtom();
...@@ -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() {
......
...@@ -598,9 +598,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, ...@@ -598,9 +598,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
*/ */
assert(prog != NULL && argBlock != NULL); assert(prog != NULL && argBlock != NULL);
if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch; if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch;
if ((pprog = getBytes(env, prog)) == NULL) goto Catch; if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
c->argv[0] = pprog; c->argv[0] = pprog;
c->argc = argc + 2; c->argc = argc + 2;
initVectorFromBlock(c->argv+1, pargBlock, argc); initVectorFromBlock(c->argv+1, pargBlock, argc);
...@@ -689,10 +689,11 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, ...@@ -689,10 +689,11 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
closeSafely(childenv[0]); closeSafely(childenv[0]);
closeSafely(childenv[1]); closeSafely(childenv[1]);
releaseBytes(env, prog, pprog); releaseBytes(env, helperpath, phelperpath);
releaseBytes(env, argBlock, pargBlock); releaseBytes(env, prog, pprog);
releaseBytes(env, envBlock, penvBlock); releaseBytes(env, argBlock, pargBlock);
releaseBytes(env, dir, c->pdir); releaseBytes(env, envBlock, penvBlock);
releaseBytes(env, dir, c->pdir);
free(c->argv); free(c->argv);
free(c->envv); free(c->envv);
......
...@@ -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.
先完成此消息的编辑!
想要评论请 注册