mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-07 00:48:38 +00:00
Merge
This commit is contained in:
commit
c25444afe2
@ -49,11 +49,11 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
|
||||
private FilterComboBoxModel filterComboBoxModel;
|
||||
|
||||
protected JList directoryList = null;
|
||||
protected JList fileList = null;
|
||||
protected JList<File> directoryList = null;
|
||||
protected JList<File> fileList = null;
|
||||
|
||||
protected JTextField pathField = null;
|
||||
protected JComboBox filterComboBox = null;
|
||||
protected JComboBox<FileFilter> filterComboBox = null;
|
||||
protected JTextField filenameTextField = null;
|
||||
|
||||
private static final Dimension hstrut10 = new Dimension(10, 1);
|
||||
@ -337,7 +337,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
align(l);
|
||||
leftPanel.add(l);
|
||||
|
||||
filterComboBox = new JComboBox() {
|
||||
filterComboBox = new JComboBox<FileFilter>() {
|
||||
public Dimension getMaximumSize() {
|
||||
Dimension d = super.getMaximumSize();
|
||||
d.height = getPreferredSize().height;
|
||||
@ -557,7 +557,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
}
|
||||
|
||||
protected JScrollPane createFilesList() {
|
||||
fileList = new JList();
|
||||
fileList = new JList<File>();
|
||||
|
||||
if(getFileChooser().isMultiSelectionEnabled()) {
|
||||
fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
@ -576,7 +576,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) {
|
||||
int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint());
|
||||
if (index >= 0) {
|
||||
File file = (File) fileList.getModel().getElementAt(index);
|
||||
File file = fileList.getModel().getElementAt(index);
|
||||
setFileName(chooser.getName(file));
|
||||
}
|
||||
}
|
||||
@ -593,7 +593,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
}
|
||||
|
||||
protected JScrollPane createDirectoryList() {
|
||||
directoryList = new JList();
|
||||
directoryList = new JList<File>();
|
||||
align(directoryList);
|
||||
|
||||
directoryList.setCellRenderer(new DirectoryCellRenderer());
|
||||
@ -658,7 +658,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
}
|
||||
}
|
||||
|
||||
protected class MotifDirectoryListModel extends AbstractListModel implements ListDataListener {
|
||||
protected class MotifDirectoryListModel extends AbstractListModel<File> implements ListDataListener {
|
||||
public MotifDirectoryListModel() {
|
||||
getModel().addListDataListener(this);
|
||||
}
|
||||
@ -667,7 +667,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
return getModel().getDirectories().size();
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public File getElementAt(int index) {
|
||||
return getModel().getDirectories().elementAt(index);
|
||||
}
|
||||
|
||||
@ -694,7 +694,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
|
||||
}
|
||||
|
||||
protected class MotifFileListModel extends AbstractListModel implements ListDataListener {
|
||||
protected class MotifFileListModel extends AbstractListModel<File> implements ListDataListener {
|
||||
public MotifFileListModel() {
|
||||
getModel().addListDataListener(this);
|
||||
}
|
||||
@ -711,7 +711,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
return getModel().getFiles().indexOf(o);
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public File getElementAt(int index) {
|
||||
return getModel().getFiles().elementAt(index);
|
||||
}
|
||||
|
||||
@ -773,7 +773,8 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
/**
|
||||
* Data model for a type-face selection combo-box.
|
||||
*/
|
||||
protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
|
||||
protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,
|
||||
PropertyChangeListener {
|
||||
protected FileFilter[] filters;
|
||||
protected FilterComboBoxModel() {
|
||||
super();
|
||||
@ -826,7 +827,7 @@ public class MotifFileChooserUI extends BasicFileChooserUI {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public FileFilter getElementAt(int index) {
|
||||
if(index > getSize() - 1) {
|
||||
// This shouldn't happen. Try to recover gracefully.
|
||||
return getFileChooser().getFileFilter();
|
||||
|
||||
@ -60,7 +60,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
private JPanel centerPanel;
|
||||
|
||||
private JLabel lookInLabel;
|
||||
private JComboBox directoryComboBox;
|
||||
private JComboBox<File> directoryComboBox;
|
||||
private DirectoryComboBoxModel directoryComboBoxModel;
|
||||
private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();
|
||||
|
||||
@ -76,7 +76,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
private JPanel buttonPanel;
|
||||
private JPanel bottomPanel;
|
||||
|
||||
private JComboBox filterComboBox;
|
||||
private JComboBox<FileFilter> filterComboBox;
|
||||
|
||||
private static final Dimension hstrut10 = new Dimension(10, 1);
|
||||
|
||||
@ -245,7 +245,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
topPanel.add(Box.createRigidArea(new Dimension(8,0)));
|
||||
|
||||
// CurrentDir ComboBox
|
||||
directoryComboBox = new JComboBox() {
|
||||
directoryComboBox = new JComboBox<File>() {
|
||||
public Dimension getMinimumSize() {
|
||||
Dimension d = super.getMinimumSize();
|
||||
d.width = 60;
|
||||
@ -445,7 +445,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
|
||||
filterComboBoxModel = createFilterComboBoxModel();
|
||||
fc.addPropertyChangeListener(filterComboBoxModel);
|
||||
filterComboBox = new JComboBox(filterComboBoxModel);
|
||||
filterComboBox = new JComboBox<FileFilter>(filterComboBoxModel);
|
||||
ftl.setLabelFor(filterComboBox);
|
||||
filterComboBox.setRenderer(createFilterComboBoxRenderer());
|
||||
fileAndFilterPanel.add(filterComboBox);
|
||||
@ -1032,7 +1032,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
/**
|
||||
* Data model for a type-face selection combo-box.
|
||||
*/
|
||||
protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
|
||||
protected class DirectoryComboBoxModel extends AbstractListModel<File> implements ComboBoxModel<File> {
|
||||
Vector<File> directories = new Vector<File>();
|
||||
int[] depths = null;
|
||||
File selectedDirectory = null;
|
||||
@ -1149,7 +1149,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
return directories.size();
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public File getElementAt(int index) {
|
||||
return directories.elementAt(index);
|
||||
}
|
||||
}
|
||||
@ -1189,7 +1189,8 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
/**
|
||||
* Data model for a type-face selection combo-box.
|
||||
*/
|
||||
protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
|
||||
protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,
|
||||
PropertyChangeListener {
|
||||
protected FileFilter[] filters;
|
||||
protected FilterComboBoxModel() {
|
||||
super();
|
||||
@ -1242,7 +1243,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public FileFilter getElementAt(int index) {
|
||||
if(index > getSize() - 1) {
|
||||
// This shouldn't happen. Try to recover gracefully.
|
||||
return getFileChooser().getFileFilter();
|
||||
|
||||
@ -81,19 +81,22 @@ public class WindowsTreeUI extends BasicTreeUI {
|
||||
else {
|
||||
Rectangle beginRect = getPathBounds(tree, getPathForRow
|
||||
(tree, beginRow));
|
||||
Rectangle testRect = beginRect;
|
||||
int beginY = beginRect.y;
|
||||
int maxY = beginY + visRect.height;
|
||||
if (beginRect != null) {
|
||||
Rectangle testRect = beginRect;
|
||||
int beginY = beginRect.y;
|
||||
int maxY = beginY + visRect.height;
|
||||
|
||||
for(int counter = beginRow + 1; counter <= endRow; counter++) {
|
||||
testRect = getPathBounds(tree,
|
||||
getPathForRow(tree, counter));
|
||||
if((testRect.y + testRect.height) > maxY)
|
||||
counter = endRow;
|
||||
for(int counter = beginRow + 1; counter <= endRow; counter++) {
|
||||
testRect = getPathBounds(tree,
|
||||
getPathForRow(tree, counter));
|
||||
if(testRect != null && (testRect.y + testRect.height) > maxY) {
|
||||
counter = endRow;
|
||||
}
|
||||
}
|
||||
tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1,
|
||||
testRect.y + testRect.height-
|
||||
beginY));
|
||||
}
|
||||
tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1,
|
||||
testRect.y + testRect.height-
|
||||
beginY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.awt;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.peer.ScrollPanePeer;
|
||||
@ -156,6 +158,12 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable {
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
initIDs();
|
||||
}
|
||||
AWTAccessor.setScrollPaneAdjustableAccessor(new AWTAccessor.ScrollPaneAdjustableAccessor() {
|
||||
public void setTypedValue(final ScrollPaneAdjustable adj,
|
||||
final int v, final int type) {
|
||||
adj.setTypedValue(v, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -247,10 +247,6 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
MethodType needConversion = MethodType.methodType(needReturn, haveReturn);
|
||||
adjustReturn = MethodHandles.identity(needReturn).asType(needConversion);
|
||||
}
|
||||
if (!canCollectArguments(adjustReturn.type(), target.type(), 0, false)) {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
throw new InternalError("NYI");
|
||||
}
|
||||
return makeCollectArguments(adjustReturn, target, 0, false);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, 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.invoke;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
|
||||
/**
|
||||
* Unary function composition, useful for many small plumbing jobs.
|
||||
* The invoke method takes a single reference argument, and returns a reference
|
||||
* Internally, it first calls the {@code filter} method on the argument,
|
||||
* Making up the difference between the raw method type and the
|
||||
* final method type is the responsibility of a JVM-level adapter.
|
||||
* @author jrose
|
||||
*/
|
||||
class FilterOneArgument extends BoundMethodHandle {
|
||||
protected final MethodHandle filter; // Object -> Object
|
||||
protected final MethodHandle target; // Object -> Object
|
||||
|
||||
@Override
|
||||
String debugString() {
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
protected Object invoke(Object argument) throws Throwable {
|
||||
Object filteredArgument = filter.invokeExact(argument);
|
||||
return target.invokeExact(filteredArgument);
|
||||
}
|
||||
|
||||
private static final MethodHandle INVOKE;
|
||||
static {
|
||||
try {
|
||||
INVOKE =
|
||||
IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
|
||||
MethodType.genericMethodType(1));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw uncaughtException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
|
||||
super(INVOKE);
|
||||
this.filter = filter;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
static {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
|
||||
}
|
||||
|
||||
public static MethodHandle make(MethodHandle filter, MethodHandle target) {
|
||||
if (filter == null) return target;
|
||||
if (target == null) return filter;
|
||||
return new FilterOneArgument(filter, target);
|
||||
}
|
||||
|
||||
// MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
|
||||
// MethodHandle filter = make(filter1, filter2);
|
||||
// return make(filter, target);
|
||||
// }
|
||||
}
|
||||
@ -1,633 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, 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.invoke;
|
||||
|
||||
import sun.invoke.util.ValueConversions;
|
||||
import sun.invoke.util.Wrapper;
|
||||
import java.lang.reflect.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
|
||||
/**
|
||||
* Adapters which mediate between incoming calls which are generic
|
||||
* and outgoing calls which are not. Any call can be represented generically
|
||||
* boxing up its arguments, and (on return) unboxing the return value.
|
||||
* <p>
|
||||
* A call is "generic" (in MethodHandle terms) if its MethodType features
|
||||
* only Object arguments. A non-generic call therefore features
|
||||
* primitives and/or reference types other than Object.
|
||||
* An adapter has types for its incoming and outgoing calls.
|
||||
* The incoming call type is simply determined by the adapter's type
|
||||
* (the MethodType it presents to callers). The outgoing call type
|
||||
* is determined by the adapter's target (a MethodHandle that the adapter
|
||||
* either binds internally or else takes as a leading argument).
|
||||
* (To stretch the term, adapter-like method handles may have multiple
|
||||
* targets or be polymorphic across multiple call types.)
|
||||
* @author jrose
|
||||
*/
|
||||
class FromGeneric {
|
||||
// type for the outgoing call (may have primitives, etc.)
|
||||
private final MethodType targetType;
|
||||
// type of the outgoing call internal to the adapter
|
||||
private final MethodType internalType;
|
||||
// prototype adapter (clone and customize for each new target!)
|
||||
private final Adapter adapter;
|
||||
// entry point for adapter (Adapter mh, a...) => ...
|
||||
private final MethodHandle entryPoint;
|
||||
// unboxing invoker of type (MH, Object**N) => raw return value
|
||||
// it makes up the difference of internalType => targetType
|
||||
private final MethodHandle unboxingInvoker;
|
||||
// conversion which boxes a the target's raw return value
|
||||
private final MethodHandle returnConversion;
|
||||
|
||||
/** Compute and cache information common to all unboxing adapters
|
||||
* that can call out to targets of the erasure-family of the given erased type.
|
||||
*/
|
||||
private FromGeneric(MethodType targetType) {
|
||||
this.targetType = targetType;
|
||||
MethodType internalType0;
|
||||
// the target invoker will generally need casts on reference arguments
|
||||
Adapter ad = findAdapter(internalType0 = targetType.erase());
|
||||
if (ad != null) {
|
||||
// Immediate hit to exactly the adapter we want,
|
||||
// with no monkeying around with primitive types.
|
||||
this.internalType = internalType0;
|
||||
this.adapter = ad;
|
||||
this.entryPoint = ad.prototypeEntryPoint();
|
||||
this.returnConversion = computeReturnConversion(targetType, internalType0);
|
||||
this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
|
||||
return;
|
||||
}
|
||||
|
||||
// outgoing primitive arguments will be wrapped; unwrap them
|
||||
MethodType primsAsObj = targetType.form().primArgsAsBoxes();
|
||||
MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
|
||||
if (objArgsRawRet != targetType)
|
||||
ad = findAdapter(internalType0 = objArgsRawRet);
|
||||
if (ad == null) {
|
||||
ad = buildAdapterFromBytecodes(internalType0 = targetType);
|
||||
}
|
||||
this.internalType = internalType0;
|
||||
this.adapter = ad;
|
||||
MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
|
||||
this.entryPoint = ad.prototypeEntryPoint();
|
||||
this.returnConversion = computeReturnConversion(targetType, internalType0);
|
||||
this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
|
||||
}
|
||||
|
||||
static {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
|
||||
}
|
||||
|
||||
/**
|
||||
* The typed target will be called according to targetType.
|
||||
* The adapter code will in fact see the raw result from internalType,
|
||||
* and must box it into an object. Produce a converter for this.
|
||||
*/
|
||||
private static MethodHandle computeReturnConversion(
|
||||
MethodType targetType, MethodType internalType) {
|
||||
Class<?> tret = targetType.returnType();
|
||||
Class<?> iret = internalType.returnType();
|
||||
Wrapper wrap = Wrapper.forBasicType(tret);
|
||||
if (!iret.isPrimitive()) {
|
||||
assert(iret == Object.class);
|
||||
return ValueConversions.identity();
|
||||
} else if (wrap.primitiveType() == iret) {
|
||||
return ValueConversions.box(wrap);
|
||||
} else {
|
||||
assert(tret == double.class ? iret == long.class : iret == int.class);
|
||||
return ValueConversions.boxRaw(wrap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The typed target will need an exact invocation point; provide it here.
|
||||
* The adapter will possibly need to make a slightly different call,
|
||||
* so adapt the invoker. This way, the logic for making up the
|
||||
* difference between what the adapter can call and what the target
|
||||
* needs can be cached once per type.
|
||||
*/
|
||||
private static MethodHandle computeUnboxingInvoker(
|
||||
MethodType targetType, MethodType internalType) {
|
||||
// All the adapters we have here have reference-untyped internal calls.
|
||||
assert(internalType == internalType.erase());
|
||||
MethodHandle invoker = targetType.invokers().exactInvoker();
|
||||
// cast all narrow reference types, unbox all primitive arguments:
|
||||
MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
|
||||
MethodHandle fixArgs = MethodHandleImpl.convertArguments(
|
||||
invoker, Invokers.invokerType(fixArgsType),
|
||||
invoker.type(), 0);
|
||||
if (fixArgs == null)
|
||||
throw new InternalError("bad fixArgs");
|
||||
// reinterpret the calling sequence as raw:
|
||||
MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
|
||||
Invokers.invokerType(internalType), fixArgs);
|
||||
if (retyper == null)
|
||||
throw new InternalError("bad retyper");
|
||||
return retyper;
|
||||
}
|
||||
|
||||
Adapter makeInstance(MethodHandle typedTarget) {
|
||||
MethodType type = typedTarget.type();
|
||||
if (type == targetType) {
|
||||
return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
|
||||
}
|
||||
// my erased-type is not exactly the same as the desired type
|
||||
assert(type.erase() == targetType); // else we are busted
|
||||
MethodHandle invoker = computeUnboxingInvoker(type, internalType);
|
||||
return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
|
||||
}
|
||||
|
||||
/** Build an adapter of the given generic type, which invokes typedTarget
|
||||
* on the incoming arguments, after unboxing as necessary.
|
||||
* The return value is boxed if necessary.
|
||||
* @param typedTarget the target
|
||||
* @return an adapter method handle
|
||||
*/
|
||||
public static MethodHandle make(MethodHandle typedTarget) {
|
||||
MethodType type = typedTarget.type();
|
||||
if (type == type.generic()) return typedTarget;
|
||||
return FromGeneric.of(type).makeInstance(typedTarget);
|
||||
}
|
||||
|
||||
/** Return the adapter information for this type's erasure. */
|
||||
static FromGeneric of(MethodType type) {
|
||||
MethodTypeForm form = type.form();
|
||||
FromGeneric fromGen = form.fromGeneric;
|
||||
if (fromGen == null)
|
||||
form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
|
||||
return fromGen;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "FromGeneric"+targetType;
|
||||
}
|
||||
|
||||
/* Create an adapter that handles spreading calls for the given type. */
|
||||
static Adapter findAdapter(MethodType internalType) {
|
||||
MethodType entryType = internalType.generic();
|
||||
MethodTypeForm form = internalType.form();
|
||||
Class<?> rtype = internalType.returnType();
|
||||
int argc = form.parameterCount();
|
||||
int lac = form.longPrimitiveParameterCount();
|
||||
int iac = form.primitiveParameterCount() - lac;
|
||||
String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
|
||||
String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
|
||||
String cname0 = rawReturn + argc;
|
||||
String cname1 = "A" + argc;
|
||||
String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
|
||||
String iname = "invoke_"+cname0+intsAndLongs;
|
||||
// e.g., D5I2, D5, L5I2, L5; invoke_D5
|
||||
for (String cname : cnames) {
|
||||
Class<? extends Adapter> acls = Adapter.findSubClass(cname);
|
||||
if (acls == null) continue;
|
||||
// see if it has the required invoke method
|
||||
MethodHandle entryPoint = null;
|
||||
try {
|
||||
entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
}
|
||||
if (entryPoint == null) continue;
|
||||
Constructor<? extends Adapter> ctor = null;
|
||||
try {
|
||||
ctor = acls.getDeclaredConstructor(MethodHandle.class);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
if (ctor == null) continue;
|
||||
try {
|
||||
// Produce an instance configured as a prototype.
|
||||
return ctor.newInstance(entryPoint);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
} catch (InvocationTargetException wex) {
|
||||
Throwable ex = wex.getTargetException();
|
||||
if (ex instanceof Error) throw (Error)ex;
|
||||
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
|
||||
} catch (InstantiationException ex) {
|
||||
} catch (IllegalAccessException ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Adapter buildAdapterFromBytecodes(MethodType internalType) {
|
||||
throw new UnsupportedOperationException("NYI "+internalType);
|
||||
}
|
||||
|
||||
/**
|
||||
* This adapter takes some untyped arguments, and returns an untyped result.
|
||||
* Internally, it applies the invoker to the target, which causes the
|
||||
* objects to be unboxed; the result is a raw type in L/I/J/F/D.
|
||||
* This result is passed to convert, which is responsible for
|
||||
* converting the raw result into a boxed object.
|
||||
* The invoker is kept separate from the target because it can be
|
||||
* generated once per type erasure family, and reused across adapters.
|
||||
*/
|
||||
static abstract class Adapter extends BoundMethodHandle {
|
||||
/*
|
||||
* class X<<R,int N>> extends Adapter {
|
||||
* (MH, Object**N)=>raw(R) invoker;
|
||||
* (any**N)=>R target;
|
||||
* raw(R)=>Object convert;
|
||||
* Object invoke(Object**N a) = convert(invoker(target, a...))
|
||||
* }
|
||||
*/
|
||||
protected final MethodHandle invoker; // (MH, Object**N) => raw(R)
|
||||
protected final MethodHandle convert; // raw(R) => Object
|
||||
protected final MethodHandle target; // (any**N) => R
|
||||
|
||||
@Override
|
||||
String debugString() {
|
||||
return addTypeString(target, this);
|
||||
}
|
||||
|
||||
protected boolean isPrototype() { return target == null; }
|
||||
protected Adapter(MethodHandle entryPoint) {
|
||||
this(entryPoint, null, entryPoint, null);
|
||||
assert(isPrototype());
|
||||
}
|
||||
protected MethodHandle prototypeEntryPoint() {
|
||||
if (!isPrototype()) throw new InternalError();
|
||||
return convert;
|
||||
}
|
||||
|
||||
protected Adapter(MethodHandle entryPoint,
|
||||
MethodHandle invoker, MethodHandle convert, MethodHandle target) {
|
||||
super(entryPoint);
|
||||
this.invoker = invoker;
|
||||
this.convert = convert;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/** Make a copy of self, with new fields. */
|
||||
protected abstract Adapter makeInstance(MethodHandle entryPoint,
|
||||
MethodHandle invoker, MethodHandle convert, MethodHandle target);
|
||||
// { return new ThisType(entryPoint, convert, target); }
|
||||
|
||||
/// Conversions on the value returned from the target.
|
||||
protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
|
||||
protected Object convert_I(int result) throws Throwable { return convert.invokeExact(result); }
|
||||
protected Object convert_J(long result) throws Throwable { return convert.invokeExact(result); }
|
||||
protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); }
|
||||
protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
|
||||
|
||||
static private final String CLASS_PREFIX; // "java.lang.invoke.FromGeneric$"
|
||||
static {
|
||||
String aname = Adapter.class.getName();
|
||||
String sname = Adapter.class.getSimpleName();
|
||||
if (!aname.endsWith(sname)) throw new InternalError();
|
||||
CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
|
||||
}
|
||||
/** Find a sibing class of Adapter. */
|
||||
static Class<? extends Adapter> findSubClass(String name) {
|
||||
String cname = Adapter.CLASS_PREFIX + name;
|
||||
try {
|
||||
return Class.forName(cname).asSubclass(Adapter.class);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
return null;
|
||||
} catch (ClassCastException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* generated classes follow this pattern:
|
||||
static class xA2 extends Adapter {
|
||||
protected xA2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new xA2(e, i, c, t); }
|
||||
protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
|
||||
}
|
||||
// */
|
||||
|
||||
/*
|
||||
: SHELL; n=FromGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
|
||||
//{{{
|
||||
import java.util.*;
|
||||
class genclasses {
|
||||
static String[] TYPES = { "Object", "int ", "long ", "float ", "double" };
|
||||
static String[] WRAPS = { " ", "(Integer)", "(Long) ", "(Float) ", "(Double) " };
|
||||
static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
|
||||
static String[][] TEMPLATES = { {
|
||||
"@for@ arity=0..10 rcat<=4 nrefs<=99 nints=0 nlongs=0",
|
||||
" //@each-cat@",
|
||||
" static class @cat@ extends Adapter {",
|
||||
" protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
|
||||
" protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
|
||||
" { super(e, i, c, t); }",
|
||||
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
|
||||
" { return new @cat@(e, i, c, t); }",
|
||||
" //@each-R@",
|
||||
" protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
|
||||
" //@end-R@",
|
||||
" }",
|
||||
} };
|
||||
static final String NEWLINE_INDENT = "\n ";
|
||||
enum VAR {
|
||||
cat, catN, R, Rc, W, av, Tvav, Ovav;
|
||||
public final String pattern = "@"+toString().replace('_','.')+"@";
|
||||
public String binding;
|
||||
static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
|
||||
int nargs = nrefs + nints + nlongs;
|
||||
if (topLevel)
|
||||
VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
|
||||
VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
|
||||
VAR.R.binding = TYPES[rcat];
|
||||
VAR.Rc.binding = TCHARS[rcat];
|
||||
VAR.W.binding = WRAPS[rcat];
|
||||
String[] Tv = new String[nargs];
|
||||
String[] av = new String[nargs];
|
||||
String[] Tvav = new String[nargs];
|
||||
String[] Ovav = new String[nargs];
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
|
||||
Tv[i] = TYPES[tcat];
|
||||
av[i] = arg(i);
|
||||
Tvav[i] = param(Tv[i], av[i]);
|
||||
Ovav[i] = param("Object", av[i]);
|
||||
}
|
||||
VAR.av.binding = comma(", ", av);
|
||||
VAR.Tvav.binding = comma(Tvav);
|
||||
VAR.Ovav.binding = comma(Ovav);
|
||||
}
|
||||
static String arg(int i) { return "a"+i; }
|
||||
static String param(String t, String a) { return t+" "+a; }
|
||||
static String comma(String[] v) { return comma("", v); }
|
||||
static String comma(String sep, String[] v) {
|
||||
if (v.length == 0) return "";
|
||||
String res = sep+v[0];
|
||||
for (int i = 1; i < v.length; i++) res += ", "+v[i];
|
||||
return res;
|
||||
}
|
||||
static String transform(String string) {
|
||||
for (VAR var : values())
|
||||
string = string.replaceAll(var.pattern, var.binding);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
static String[] stringsIn(String[] strings, int beg, int end) {
|
||||
return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
|
||||
}
|
||||
static String[] stringsBefore(String[] strings, int pos) {
|
||||
return stringsIn(strings, 0, pos);
|
||||
}
|
||||
static String[] stringsAfter(String[] strings, int pos) {
|
||||
return stringsIn(strings, pos, strings.length);
|
||||
}
|
||||
static int indexAfter(String[] strings, int pos, String tag) {
|
||||
return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
|
||||
}
|
||||
static int indexBefore(String[] strings, int pos, String tag) {
|
||||
for (int i = pos, end = strings.length; ; i++) {
|
||||
if (i == end || strings[i].endsWith(tag)) return i;
|
||||
}
|
||||
}
|
||||
static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
|
||||
static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
|
||||
static HashSet<String> done = new HashSet<String>();
|
||||
public static void main(String... av) {
|
||||
for (String[] template : TEMPLATES) {
|
||||
int forLinesLimit = indexBefore(template, 0, "@each-cat@");
|
||||
String[] forLines = stringsBefore(template, forLinesLimit);
|
||||
template = stringsAfter(template, forLinesLimit);
|
||||
for (String forLine : forLines)
|
||||
expandTemplate(forLine, template);
|
||||
}
|
||||
}
|
||||
static void expandTemplate(String forLine, String[] template) {
|
||||
String[] params = forLine.split("[^0-9]+");
|
||||
if (params[0].length() == 0) params = stringsAfter(params, 1);
|
||||
System.out.println("//params="+Arrays.asList(params));
|
||||
int pcur = 0;
|
||||
MIN_ARITY = Integer.valueOf(params[pcur++]);
|
||||
MAX_ARITY = Integer.valueOf(params[pcur++]);
|
||||
MAX_RCAT = Integer.valueOf(params[pcur++]);
|
||||
MAX_REFS = Integer.valueOf(params[pcur++]);
|
||||
MAX_INTS = Integer.valueOf(params[pcur++]);
|
||||
MAX_LONGS = Integer.valueOf(params[pcur++]);
|
||||
if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
|
||||
if (MAX_RCAT >= TYPES.length) MAX_RCAT = TYPES.length - 1;
|
||||
ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
|
||||
ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
|
||||
for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
|
||||
for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
|
||||
expandTemplate(template, true, rcat, nargs, 0, 0);
|
||||
if (ALL_ARG_TYPES) break;
|
||||
expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
|
||||
if (ALL_RETURN_TYPES) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static String catstr(int rcat, int nrefs, int nints, int nlongs) {
|
||||
int nargs = nrefs + nints + nlongs;
|
||||
String cat = TCHARS[rcat] + nargs;
|
||||
if (!ALL_ARG_TYPES) cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
|
||||
return cat;
|
||||
}
|
||||
static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
|
||||
for (int isLong = 0; isLong <= 1; isLong++) {
|
||||
for (int nprims = 1; nprims <= nargs; nprims++) {
|
||||
int nrefs = nargs - nprims;
|
||||
int nints = ((1-isLong) * nprims);
|
||||
int nlongs = (isLong * nprims);
|
||||
expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void expandTemplate(String[] template, boolean topLevel,
|
||||
int rcat, int nrefs, int nints, int nlongs) {
|
||||
int nargs = nrefs + nints + nlongs;
|
||||
if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS) return;
|
||||
VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
|
||||
if (topLevel && !done.add(VAR.cat.binding)) {
|
||||
System.out.println(" //repeat "+VAR.cat.binding);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < template.length; i++) {
|
||||
String line = template[i];
|
||||
if (line.endsWith("@each-cat@")) {
|
||||
// ignore
|
||||
} else if (line.endsWith("@each-R@")) {
|
||||
int blockEnd = indexAfter(template, i, "@end-R@");
|
||||
String[] block = stringsIn(template, i+1, blockEnd-1);
|
||||
for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
|
||||
expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
|
||||
VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
|
||||
i = blockEnd-1; continue;
|
||||
} else if (line.endsWith("@each-Tv@")) {
|
||||
int blockEnd = indexAfter(template, i, "@end-Tv@");
|
||||
String[] block = stringsIn(template, i+1, blockEnd-1);
|
||||
expandTemplate(block, false, rcat, nrefs, nints, nlongs);
|
||||
expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
|
||||
VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
|
||||
i = blockEnd-1; continue;
|
||||
} else {
|
||||
System.out.println(VAR.transform(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//}}} */
|
||||
//params=[0, 10, 4, 99, 0, 0]
|
||||
static class A0 extends Adapter {
|
||||
protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A0(e, i, c, t); }
|
||||
protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
|
||||
protected Object invoke_I0() throws Throwable { return convert_I((int) invoker.invokeExact(target)); }
|
||||
protected Object invoke_J0() throws Throwable { return convert_J((long) invoker.invokeExact(target)); }
|
||||
protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
|
||||
protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
|
||||
}
|
||||
static class A1 extends Adapter {
|
||||
protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A1(e, i, c, t); }
|
||||
protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
|
||||
protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0)); }
|
||||
protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0)); }
|
||||
protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
|
||||
protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); }
|
||||
}
|
||||
static class A2 extends Adapter {
|
||||
protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A2(e, i, c, t); }
|
||||
protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
|
||||
protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
|
||||
}
|
||||
static class A3 extends Adapter {
|
||||
protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A3(e, i, c, t); }
|
||||
protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
|
||||
protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2)); }
|
||||
protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2)); }
|
||||
protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
|
||||
protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
|
||||
}
|
||||
static class A4 extends Adapter {
|
||||
protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A4(e, i, c, t); }
|
||||
protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
|
||||
protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3)); }
|
||||
protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3)); }
|
||||
protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
|
||||
protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); }
|
||||
}
|
||||
static class A5 extends Adapter {
|
||||
protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A5(e, i, c, t); }
|
||||
protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
|
||||
protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
|
||||
protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
|
||||
protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
|
||||
protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
|
||||
}
|
||||
static class A6 extends Adapter {
|
||||
protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A6(e, i, c, t); }
|
||||
protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
|
||||
protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
|
||||
protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
|
||||
protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
|
||||
protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
|
||||
}
|
||||
static class A7 extends Adapter {
|
||||
protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A7(e, i, c, t); }
|
||||
protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
|
||||
protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
|
||||
protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
|
||||
protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
|
||||
protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
|
||||
}
|
||||
static class A8 extends Adapter {
|
||||
protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A8(e, i, c, t); }
|
||||
protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
|
||||
protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
|
||||
protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
|
||||
protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
|
||||
protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
|
||||
}
|
||||
static class A9 extends Adapter {
|
||||
protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A9(e, i, c, t); }
|
||||
protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
|
||||
protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
|
||||
protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
|
||||
protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
|
||||
protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
|
||||
}
|
||||
static class A10 extends Adapter {
|
||||
protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
|
||||
protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ super(e, i, c, t); }
|
||||
protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
|
||||
{ return new A10(e, i, c, t); }
|
||||
protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
|
||||
protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
|
||||
protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
|
||||
protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
|
||||
protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
|
||||
}
|
||||
}
|
||||
@ -102,172 +102,46 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodType rawConType = rawConstructor.type();
|
||||
Class<?> allocateClass = rawConType.parameterType(0);
|
||||
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
|
||||
if (AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)) {
|
||||
// allocator(arg...)
|
||||
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
|
||||
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
|
||||
MethodHandle returner = MethodHandles.identity(allocateClass);
|
||||
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
|
||||
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
|
||||
return fold;
|
||||
}
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodHandle allocator
|
||||
= AllocateObject.make(allocateClass, rawConstructor);
|
||||
assert(allocator.type()
|
||||
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
|
||||
return allocator;
|
||||
assert(AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true));
|
||||
// allocator(arg...)
|
||||
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
|
||||
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
|
||||
MethodHandle returner = MethodHandles.identity(allocateClass);
|
||||
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
|
||||
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
|
||||
return fold;
|
||||
}
|
||||
|
||||
static final class AllocateObject<C> extends BoundMethodHandle {
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
private final Class<C> allocateClass;
|
||||
private final MethodHandle rawConstructor;
|
||||
|
||||
private AllocateObject(MethodHandle invoker,
|
||||
Class<C> allocateClass, MethodHandle rawConstructor) {
|
||||
super(invoker);
|
||||
this.allocateClass = allocateClass;
|
||||
this.rawConstructor = rawConstructor;
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
}
|
||||
// for allocation only:
|
||||
private AllocateObject(Class<C> allocateClass) {
|
||||
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
|
||||
this.allocateClass = allocateClass;
|
||||
this.rawConstructor = null;
|
||||
}
|
||||
static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodType rawConType = rawConstructor.type();
|
||||
assert(rawConType.parameterType(0) == allocateClass);
|
||||
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
|
||||
int nargs = rawConType.parameterCount() - 1;
|
||||
if (nargs < INVOKES.length) {
|
||||
MethodHandle invoke = INVOKES[nargs];
|
||||
MethodType conType = CON_TYPES[nargs];
|
||||
MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, 0);
|
||||
if (gcon == null) return null;
|
||||
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
|
||||
assert(galloc.type() == newType.generic());
|
||||
return convertArguments(galloc, newType, galloc.type(), 0);
|
||||
} else {
|
||||
MethodHandle invoke = VARARGS_INVOKE;
|
||||
MethodType conType = CON_TYPES[nargs];
|
||||
MethodHandle gcon = spreadArgumentsFromPos(rawConstructor, conType, 1);
|
||||
if (gcon == null) return null;
|
||||
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
|
||||
return collectArguments(galloc, newType, 1, null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
String debugString() {
|
||||
return addTypeString(allocateClass.getSimpleName(), this);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private C allocate() throws InstantiationException {
|
||||
return (C) unsafe.allocateInstance(allocateClass);
|
||||
}
|
||||
private C invoke_V(Object... av) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, av);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L0() throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L1(Object a0) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L2(Object a0, Object a1) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
return obj;
|
||||
}
|
||||
static MethodHandle[] makeInvokes() {
|
||||
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
|
||||
MethodHandles.Lookup lookup = IMPL_LOOKUP;
|
||||
for (;;) {
|
||||
int nargs = invokes.size();
|
||||
String name = "invoke_L"+nargs;
|
||||
MethodHandle invoke = null;
|
||||
try {
|
||||
invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
}
|
||||
if (invoke == null) break;
|
||||
invokes.add(invoke);
|
||||
}
|
||||
assert(invokes.size() == 9); // current number of methods
|
||||
return invokes.toArray(new MethodHandle[0]);
|
||||
};
|
||||
static final MethodHandle[] INVOKES = makeInvokes();
|
||||
// For testing use this:
|
||||
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
|
||||
static final MethodHandle VARARGS_INVOKE;
|
||||
static final MethodHandle ALLOCATE;
|
||||
static {
|
||||
try {
|
||||
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
|
||||
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw uncaughtException(ex);
|
||||
}
|
||||
}
|
||||
// Corresponding generic constructor types:
|
||||
static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
|
||||
static {
|
||||
for (int i = 0; i < INVOKES.length; i++)
|
||||
CON_TYPES[i] = makeConType(INVOKES[i]);
|
||||
}
|
||||
static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
|
||||
static MethodType makeConType(MethodHandle invoke) {
|
||||
MethodType invType = invoke.type();
|
||||
return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@ -757,26 +631,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
return target;
|
||||
if (oldType.parameterCount() != newType.parameterCount())
|
||||
throw newIllegalArgumentException("mismatched parameter count", oldType, newType);
|
||||
MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target, level);
|
||||
if (res != null)
|
||||
return res;
|
||||
// We can come here in the case of target(int)void => (Object)void,
|
||||
// because the unboxing logic for Object => int is complex.
|
||||
int argc = oldType.parameterCount();
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
// The JVM can't do it directly, so fill in the gap with a Java adapter.
|
||||
// TO DO: figure out what to put here from case-by-case experience
|
||||
// Use a heavier method: Convert all the arguments to Object,
|
||||
// then back to the desired types. We might have to use Java-based
|
||||
// method handles to do this.
|
||||
MethodType objType = MethodType.genericMethodType(argc);
|
||||
MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target, level);
|
||||
if (objTarget == null)
|
||||
objTarget = FromGeneric.make(target);
|
||||
res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget, level);
|
||||
if (res != null)
|
||||
return res;
|
||||
return ToGeneric.make(newType, objTarget);
|
||||
return AdapterMethodHandle.makePairwiseConvert(newType, target, level);
|
||||
}
|
||||
|
||||
static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) {
|
||||
@ -829,19 +684,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
// oldType // (a..., b...)=>r
|
||||
assert(newType.parameterCount() == collectArg + colType.parameterCount());
|
||||
assert(oldType.parameterCount() == collectArg + 1);
|
||||
MethodHandle result = null;
|
||||
if (AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false)) {
|
||||
result = AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false);
|
||||
}
|
||||
if (result == null) {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, 0);
|
||||
MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, 0);
|
||||
if (gtarget == null || gcollector == null) return null;
|
||||
MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
|
||||
result = convertArguments(gresult, newType, gresult.type(), 0);
|
||||
}
|
||||
return result;
|
||||
assert(AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false));
|
||||
return AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false);
|
||||
}
|
||||
|
||||
static MethodHandle filterArgument(MethodHandle target,
|
||||
@ -850,32 +694,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodType ttype = target.type();
|
||||
MethodType ftype = filter.type();
|
||||
assert(ftype.parameterCount() == 1);
|
||||
MethodHandle result = null;
|
||||
if (AdapterMethodHandle.canCollectArguments(ttype, ftype, pos, false)) {
|
||||
result = AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
|
||||
if (result != null) return result;
|
||||
}
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodType rtype = ttype.changeParameterType(pos, ftype.parameterType(0));
|
||||
MethodType gttype = ttype.generic();
|
||||
if (ttype != gttype) {
|
||||
target = convertArguments(target, gttype, ttype, 0);
|
||||
ttype = gttype;
|
||||
}
|
||||
MethodType gftype = ftype.generic();
|
||||
if (ftype != gftype) {
|
||||
filter = convertArguments(filter, gftype, ftype, 0);
|
||||
ftype = gftype;
|
||||
}
|
||||
if (ftype == ttype) {
|
||||
// simple unary case
|
||||
result = FilterOneArgument.make(filter, target);
|
||||
} else {
|
||||
result = FilterGeneric.makeArgumentFilter(pos, filter, target);
|
||||
}
|
||||
if (result.type() != rtype)
|
||||
result = result.asType(rtype);
|
||||
return result;
|
||||
return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
|
||||
}
|
||||
|
||||
static MethodHandle foldArguments(MethodHandle target,
|
||||
@ -884,155 +703,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodHandle combiner) {
|
||||
MethodType oldType = target.type();
|
||||
MethodType ctype = combiner.type();
|
||||
if (AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true)) {
|
||||
MethodHandle res = AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true);
|
||||
if (res != null) return res;
|
||||
}
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
if (foldPos != 0) return null;
|
||||
MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, 0);
|
||||
MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, 0);
|
||||
if (ctype.returnType() == void.class) {
|
||||
gtarget = dropArguments(gtarget, oldType.generic().insertParameterTypes(foldPos, Object.class), foldPos);
|
||||
}
|
||||
if (gtarget == null || gcombiner == null) return null;
|
||||
MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
|
||||
return convertArguments(gresult, newType, gresult.type(), 0);
|
||||
assert(AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true));
|
||||
return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true);
|
||||
}
|
||||
|
||||
static
|
||||
MethodHandle dropArguments(MethodHandle target,
|
||||
MethodType newType, int argnum) {
|
||||
int drops = newType.parameterCount() - target.type().parameterCount();
|
||||
MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
|
||||
if (res != null)
|
||||
return res;
|
||||
throw new UnsupportedOperationException("NYI");
|
||||
}
|
||||
|
||||
private static class GuardWithTest extends BoundMethodHandle {
|
||||
private final MethodHandle test, target, fallback;
|
||||
private GuardWithTest(MethodHandle invoker,
|
||||
MethodHandle test, MethodHandle target, MethodHandle fallback) {
|
||||
super(invoker);
|
||||
this.test = test;
|
||||
this.target = target;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
static boolean preferRicochetFrame(MethodType type) {
|
||||
return true; // always use RF if available
|
||||
}
|
||||
static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
|
||||
MethodType type = target.type();
|
||||
int nargs = type.parameterCount();
|
||||
if (nargs < INVOKES.length) {
|
||||
if (preferRicochetFrame(type))
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodHandle invoke = INVOKES[nargs];
|
||||
MethodType gtype = type.generic();
|
||||
assert(invoke.type().dropParameterTypes(0,1) == gtype);
|
||||
// Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
|
||||
MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 2);
|
||||
MethodHandle gtarget = convertArguments(target, gtype, type, 2);
|
||||
MethodHandle gfallback = convertArguments(fallback, gtype, type, 2);
|
||||
if (gtest == null || gtarget == null || gfallback == null) return null;
|
||||
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
|
||||
return convertArguments(gguard, type, gtype, 2);
|
||||
} else {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodHandle invoke = VARARGS_INVOKE;
|
||||
MethodType gtype = MethodType.genericMethodType(1);
|
||||
assert(invoke.type().dropParameterTypes(0,1) == gtype);
|
||||
MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
|
||||
MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
|
||||
MethodHandle gfallback = spreadArgumentsFromPos(fallback, gtype, 0);
|
||||
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
|
||||
if (gtest == null || gtarget == null || gfallback == null) return null;
|
||||
return collectArguments(gguard, type, 0, null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
String debugString() {
|
||||
return addTypeString(target, this);
|
||||
}
|
||||
private Object invoke_V(Object... av) throws Throwable {
|
||||
if ((boolean) test.invokeExact(av))
|
||||
return target.invokeExact(av);
|
||||
return fallback.invokeExact(av);
|
||||
}
|
||||
private Object invoke_L0() throws Throwable {
|
||||
if ((boolean) test.invokeExact())
|
||||
return target.invokeExact();
|
||||
return fallback.invokeExact();
|
||||
}
|
||||
private Object invoke_L1(Object a0) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0))
|
||||
return target.invokeExact(a0);
|
||||
return fallback.invokeExact(a0);
|
||||
}
|
||||
private Object invoke_L2(Object a0, Object a1) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1))
|
||||
return target.invokeExact(a0, a1);
|
||||
return fallback.invokeExact(a0, a1);
|
||||
}
|
||||
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2))
|
||||
return target.invokeExact(a0, a1, a2);
|
||||
return fallback.invokeExact(a0, a1, a2);
|
||||
}
|
||||
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2, a3))
|
||||
return target.invokeExact(a0, a1, a2, a3);
|
||||
return fallback.invokeExact(a0, a1, a2, a3);
|
||||
}
|
||||
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
|
||||
return target.invokeExact(a0, a1, a2, a3, a4);
|
||||
return fallback.invokeExact(a0, a1, a2, a3, a4);
|
||||
}
|
||||
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5);
|
||||
return fallback.invokeExact(a0, a1, a2, a3, a4, a5);
|
||||
}
|
||||
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
|
||||
return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
|
||||
if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
static MethodHandle[] makeInvokes() {
|
||||
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
|
||||
MethodHandles.Lookup lookup = IMPL_LOOKUP;
|
||||
for (;;) {
|
||||
int nargs = invokes.size();
|
||||
String name = "invoke_L"+nargs;
|
||||
MethodHandle invoke = null;
|
||||
try {
|
||||
invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
}
|
||||
if (invoke == null) break;
|
||||
invokes.add(invoke);
|
||||
}
|
||||
assert(invokes.size() == 9); // current number of methods
|
||||
return invokes.toArray(new MethodHandle[0]);
|
||||
};
|
||||
static final MethodHandle[] INVOKES = makeInvokes();
|
||||
// For testing use this:
|
||||
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
|
||||
static final MethodHandle VARARGS_INVOKE;
|
||||
static {
|
||||
try {
|
||||
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw uncaughtException(ex);
|
||||
}
|
||||
}
|
||||
return AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
|
||||
}
|
||||
|
||||
static
|
||||
@ -1065,21 +744,18 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
assert(test.type().returnType() == boolean.class);
|
||||
MethodType targetType = target.type();
|
||||
MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class);
|
||||
if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)
|
||||
&& GuardWithTest.preferRicochetFrame(targetType)) {
|
||||
// working backwards, as usual:
|
||||
assert(target.type().equals(fallback.type()));
|
||||
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
|
||||
MethodHandle select = selectAlternative();
|
||||
select = bindArgument(select, 2, fallback);
|
||||
select = bindArgument(select, 1, target);
|
||||
// select(z: boolean) => (z ? target : fallback)
|
||||
MethodHandle filter = filterArgument(tailcall, 0, select);
|
||||
assert(filter.type().parameterType(0) == boolean.class);
|
||||
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
|
||||
return fold;
|
||||
}
|
||||
return GuardWithTest.make(test, target, fallback);
|
||||
assert(AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true));
|
||||
// working backwards, as usual:
|
||||
assert(target.type().equals(fallback.type()));
|
||||
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
|
||||
MethodHandle select = selectAlternative();
|
||||
select = bindArgument(select, 2, fallback);
|
||||
select = bindArgument(select, 1, target);
|
||||
// select(z: boolean) => (z ? target : fallback)
|
||||
MethodHandle filter = filterArgument(tailcall, 0, select);
|
||||
assert(filter.type().parameterType(0) == boolean.class);
|
||||
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
|
||||
return fold;
|
||||
}
|
||||
|
||||
private static class GuardWithCatch extends BoundMethodHandle {
|
||||
|
||||
@ -391,13 +391,4 @@ class MethodHandleNatives {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This assertion marks code which was written before ricochet frames were implemented.
|
||||
* Such code will go away when the ports catch up.
|
||||
*/
|
||||
static boolean workaroundWithoutRicochetFrames() {
|
||||
assert(!HAVE_RICOCHET_FRAMES) : "this code should not be executed if `-XX:+UseRicochetFrames is enabled";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ package java.lang.invoke;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import sun.invoke.WrapperInstance;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that help adapt
|
||||
@ -134,14 +135,19 @@ public class MethodHandleProxies {
|
||||
//
|
||||
public static
|
||||
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
|
||||
// POC implementation only; violates the above contract several ways
|
||||
final Method sm = getSingleMethod(intfc);
|
||||
if (sm == null)
|
||||
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
|
||||
throw new IllegalArgumentException("not a public interface: "+intfc.getName());
|
||||
final Method[] methods = getSingleNameMethods(intfc);
|
||||
if (methods == null)
|
||||
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
|
||||
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
|
||||
MethodHandle checkTarget = target.asType(smMT); // make throw WMT
|
||||
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
|
||||
final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
|
||||
final MethodHandle[] vaTargets = new MethodHandle[methods.length];
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Method sm = methods[i];
|
||||
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
|
||||
MethodHandle checkTarget = target.asType(smMT); // make throw WMT
|
||||
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
|
||||
vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
|
||||
}
|
||||
return intfc.cast(Proxy.newProxyInstance(
|
||||
intfc.getClassLoader(),
|
||||
new Class[]{ intfc, WrapperInstance.class },
|
||||
@ -152,13 +158,15 @@ public class MethodHandleProxies {
|
||||
throw new AssertionError();
|
||||
}
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (method.equals(methods[i]))
|
||||
return vaTargets[i].invokeExact(args);
|
||||
}
|
||||
if (method.getDeclaringClass() == WrapperInstance.class)
|
||||
return getArg(method.getName());
|
||||
if (method.equals(sm))
|
||||
return vaTarget.invokeExact(args);
|
||||
if (isObjectMethod(method))
|
||||
return callObjectMethod(this, method, args);
|
||||
throw new InternalError();
|
||||
return callObjectMethod(proxy, method, args);
|
||||
throw new InternalError("bad proxy method: "+method);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@ -241,17 +249,20 @@ public class MethodHandleProxies {
|
||||
}
|
||||
|
||||
private static
|
||||
Method getSingleMethod(Class<?> intfc) {
|
||||
if (!intfc.isInterface()) return null;
|
||||
Method sm = null;
|
||||
Method[] getSingleNameMethods(Class<?> intfc) {
|
||||
ArrayList<Method> methods = new ArrayList<Method>();
|
||||
String uniqueName = null;
|
||||
for (Method m : intfc.getMethods()) {
|
||||
int mod = m.getModifiers();
|
||||
if (Modifier.isAbstract(mod)) {
|
||||
if (sm != null && !isObjectMethod(sm))
|
||||
return null; // too many abstract methods
|
||||
sm = m;
|
||||
}
|
||||
if (isObjectMethod(m)) continue;
|
||||
if (!Modifier.isAbstract(m.getModifiers())) continue;
|
||||
String mname = m.getName();
|
||||
if (uniqueName == null)
|
||||
uniqueName = mname;
|
||||
else if (!uniqueName.equals(mname))
|
||||
return null; // too many abstract methods
|
||||
methods.add(m);
|
||||
}
|
||||
return sm;
|
||||
if (uniqueName == null) return null;
|
||||
return methods.toArray(new Method[methods.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1995,16 +1995,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
|
||||
// lambda( arg...) { target(arg...) } )
|
||||
MethodType newType = targetType.changeReturnType(filterType.returnType());
|
||||
MethodHandle result = null;
|
||||
if (AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false)) {
|
||||
result = AdapterMethodHandle.makeCollectArguments(filter, target, 0, false);
|
||||
if (result != null) return result;
|
||||
}
|
||||
// FIXME: Too many nodes here.
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
|
||||
MethodHandle returner = dropArguments(filter, filterValues, targetType.parameterList());
|
||||
result = foldArguments(returner, target);
|
||||
assert(result.type().equals(newType));
|
||||
return result;
|
||||
assert(AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false));
|
||||
return AdapterMethodHandle.makeCollectArguments(filter, target, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -56,10 +56,6 @@ class MethodTypeForm {
|
||||
/*lazy*/ MethodType primsAtEnd; // reorder primitives to the end
|
||||
|
||||
// Cached adapter information:
|
||||
/*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o
|
||||
/*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
|
||||
/*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
|
||||
/*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
|
||||
/*lazy*/ MethodHandle genericInvoker; // hook for inexact invoke
|
||||
|
||||
public MethodType erasedType() {
|
||||
|
||||
@ -1,682 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, 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.invoke;
|
||||
|
||||
import sun.invoke.util.ValueConversions;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
|
||||
/**
|
||||
* Generic spread adapter.
|
||||
* Expands a final argument into multiple (zero or more) arguments, keeping the others the same.
|
||||
* @author jrose
|
||||
*/
|
||||
class SpreadGeneric {
|
||||
// type for the outgoing call
|
||||
private final MethodType targetType;
|
||||
// number of arguments to spread
|
||||
private final int spreadCount;
|
||||
// prototype adapter (clone and customize for each new target!)
|
||||
private final Adapter adapter;
|
||||
// entry point for adapter (Adapter mh, a...) => ...
|
||||
private final MethodHandle entryPoint;
|
||||
|
||||
/** Compute and cache information common to all spreading adapters
|
||||
* that accept calls of the given (generic) type.
|
||||
*/
|
||||
private SpreadGeneric(MethodType targetType, int spreadCount) {
|
||||
assert(targetType == targetType.generic());
|
||||
this.targetType = targetType;
|
||||
this.spreadCount = spreadCount;
|
||||
// the target invoker will generally need casts on reference arguments
|
||||
MethodHandle[] ep = { null };
|
||||
Adapter ad = findAdapter(this, ep);
|
||||
if (ad != null) {
|
||||
this.adapter = ad;
|
||||
this.entryPoint = ep[0];
|
||||
return;
|
||||
}
|
||||
this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep);
|
||||
this.entryPoint = ep[0];
|
||||
}
|
||||
|
||||
static {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
|
||||
}
|
||||
|
||||
/** From targetType remove the last spreadCount arguments, and instead
|
||||
* append a simple Object argument.
|
||||
*/
|
||||
static MethodType preSpreadType(MethodType targetType, int spreadCount) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Class<?>> params = new ArrayList(targetType.parameterList());
|
||||
int outargs = params.size();
|
||||
params.subList(outargs - spreadCount, outargs).clear();
|
||||
params.add(Object.class);
|
||||
return MethodType.methodType(targetType.returnType(), params);
|
||||
}
|
||||
|
||||
MethodHandle makeInstance(MethodHandle target) {
|
||||
MethodType type = target.type();
|
||||
if (type != targetType) {
|
||||
throw new UnsupportedOperationException("NYI type="+type);
|
||||
}
|
||||
return adapter.makeInstance(this, target);
|
||||
}
|
||||
|
||||
/** Build an adapter of the given generic type, which invokes typedTarget
|
||||
* on the incoming arguments, after unboxing as necessary.
|
||||
* The return value is boxed if necessary.
|
||||
* @param genericType the required type of the result
|
||||
* @param typedTarget the target
|
||||
* @return an adapter method handle
|
||||
*/
|
||||
public static MethodHandle make(MethodHandle target, int spreadCount) {
|
||||
MethodType type = target.type();
|
||||
MethodType gtype = type.generic();
|
||||
if (type == gtype) {
|
||||
return SpreadGeneric.of(type, spreadCount).makeInstance(target);
|
||||
} else {
|
||||
MethodHandle gtarget = FromGeneric.make(target);
|
||||
assert(gtarget.type() == gtype);
|
||||
MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget);
|
||||
return ToGeneric.make(preSpreadType(type, spreadCount), gspread);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the adapter information for this type's erasure. */
|
||||
static SpreadGeneric of(MethodType targetType, int spreadCount) {
|
||||
if (targetType != targetType.generic())
|
||||
throw new UnsupportedOperationException("NYI type="+targetType);
|
||||
MethodTypeForm form = targetType.form();
|
||||
int outcount = form.parameterCount();
|
||||
assert(spreadCount <= outcount);
|
||||
SpreadGeneric[] spreadGens = form.spreadGeneric;
|
||||
if (spreadGens == null)
|
||||
form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1];
|
||||
SpreadGeneric spreadGen = spreadGens[spreadCount];
|
||||
if (spreadGen == null)
|
||||
spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount);
|
||||
return spreadGen;
|
||||
}
|
||||
|
||||
String debugString() {
|
||||
return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
|
||||
}
|
||||
|
||||
// This mini-api is called from an Adapter to manage the spread.
|
||||
/** A check/coercion that happens once before any selections. */
|
||||
protected Object check(Object av, int n) {
|
||||
checkSpreadArgument(av, n);
|
||||
return av;
|
||||
}
|
||||
|
||||
/** The selection operator for spreading; note that it takes Object not Object[]. */
|
||||
protected Object select(Object av, int n) {
|
||||
return ((Object[])av)[n];
|
||||
}
|
||||
/*
|
||||
protected int select_I(Object av, int n) {
|
||||
// maybe return ((int[])select)[n]
|
||||
throw new UnsupportedOperationException("subclass resp.");
|
||||
}
|
||||
protected int select_J(Object av, int n) {
|
||||
// maybe return ((long[])select)[n]
|
||||
throw new UnsupportedOperationException("subclass resp.");
|
||||
}
|
||||
// */
|
||||
|
||||
/* Create an adapter that handles spreading calls for the given type. */
|
||||
static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) {
|
||||
MethodType targetType = outer.targetType;
|
||||
int spreadCount = outer.spreadCount;
|
||||
int outargs = targetType.parameterCount();
|
||||
int inargs = outargs - spreadCount;
|
||||
if (inargs < 0) return null;
|
||||
MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av
|
||||
String cname1 = "S" + outargs;
|
||||
String[] cnames = { cname1 };
|
||||
String iname = "invoke_S"+spreadCount;
|
||||
// e.g., D5I2, D5, L5I2, L5; invoke_D5
|
||||
for (String cname : cnames) {
|
||||
Class<? extends Adapter> acls = Adapter.findSubClass(cname);
|
||||
if (acls == null) continue;
|
||||
// see if it has the required invoke method
|
||||
MethodHandle entryPoint = null;
|
||||
try {
|
||||
entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
}
|
||||
if (entryPoint == null) continue;
|
||||
Constructor<? extends Adapter> ctor = null;
|
||||
try {
|
||||
ctor = acls.getDeclaredConstructor(SpreadGeneric.class);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
if (ctor == null) continue;
|
||||
try {
|
||||
// Produce an instance configured as a prototype.
|
||||
Adapter ad = ctor.newInstance(outer);
|
||||
ep[0] = entryPoint;
|
||||
return ad;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
} catch (InvocationTargetException wex) {
|
||||
Throwable ex = wex.getTargetException();
|
||||
if (ex instanceof Error) throw (Error)ex;
|
||||
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
|
||||
} catch (InstantiationException ex) {
|
||||
} catch (IllegalAccessException ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Adapter buildAdapterFromBytecodes(MethodType targetType,
|
||||
int spreadCount, MethodHandle[] ep) {
|
||||
throw new UnsupportedOperationException("NYI");
|
||||
}
|
||||
|
||||
/**
|
||||
* This adapter takes some untyped arguments, and returns an untyped result.
|
||||
* Internally, it applies the invoker to the target, which causes the
|
||||
* objects to be unboxed; the result is a raw type in L/I/J/F/D.
|
||||
* This result is passed to convert, which is responsible for
|
||||
* converting the raw result into a boxed object.
|
||||
* The invoker is kept separate from the target because it can be
|
||||
* generated once per type erasure family, and reused across adapters.
|
||||
*/
|
||||
static abstract class Adapter extends BoundMethodHandle {
|
||||
/*
|
||||
* class X<<R,int M,int N>> extends Adapter {
|
||||
* (Object**N)=>R target;
|
||||
* static int S = N-M;
|
||||
* Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]);
|
||||
* }
|
||||
*/
|
||||
protected final SpreadGeneric outer;
|
||||
protected final MethodHandle target; // (any**N) => R
|
||||
|
||||
@Override
|
||||
String debugString() {
|
||||
return addTypeString(target, this);
|
||||
}
|
||||
|
||||
static final MethodHandle NO_ENTRY = ValueConversions.identity();
|
||||
|
||||
protected boolean isPrototype() { return target == null; }
|
||||
protected Adapter(SpreadGeneric outer) {
|
||||
super(NO_ENTRY);
|
||||
this.outer = outer;
|
||||
this.target = null;
|
||||
assert(isPrototype());
|
||||
}
|
||||
|
||||
protected Adapter(SpreadGeneric outer, MethodHandle target) {
|
||||
super(outer.entryPoint);
|
||||
this.outer = outer;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/** Make a copy of self, with new fields. */
|
||||
protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target);
|
||||
// { return new ThisType(outer, target); }
|
||||
|
||||
protected Object check(Object av, int n) {
|
||||
return outer.check(av, n);
|
||||
}
|
||||
protected Object select(Object av, int n) {
|
||||
return outer.select(av, n);
|
||||
}
|
||||
|
||||
static private final String CLASS_PREFIX; // "java.lang.invoke.SpreadGeneric$"
|
||||
static {
|
||||
String aname = Adapter.class.getName();
|
||||
String sname = Adapter.class.getSimpleName();
|
||||
if (!aname.endsWith(sname)) throw new InternalError();
|
||||
CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
|
||||
}
|
||||
/** Find a sibing class of Adapter. */
|
||||
static Class<? extends Adapter> findSubClass(String name) {
|
||||
String cname = Adapter.CLASS_PREFIX + name;
|
||||
try {
|
||||
return Class.forName(cname).asSubclass(Adapter.class);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
return null;
|
||||
} catch (ClassCastException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* generated classes follow this pattern:
|
||||
static class xS2 extends Adapter {
|
||||
protected xS2(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
|
||||
return target.invokeExact(a0, a1)); }
|
||||
protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
}
|
||||
// */
|
||||
|
||||
/*
|
||||
: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
|
||||
//{{{
|
||||
import java.util.*;
|
||||
class genclasses {
|
||||
static String[][] TEMPLATES = { {
|
||||
"@for@ N=0..10",
|
||||
" //@each-cat@",
|
||||
" static class @cat@ extends Adapter {",
|
||||
" protected @cat@(SpreadGeneric outer) { super(outer); } // to build prototype",
|
||||
" protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
|
||||
" protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
|
||||
" protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
|
||||
" return target.invokeExact(@av@); }",
|
||||
" //@each-S@",
|
||||
" protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
|
||||
" return target.invokeExact(@av,@@sv@); }",
|
||||
" //@end-S@",
|
||||
" }",
|
||||
} };
|
||||
static final String NEWLINE_INDENT = "\n ";
|
||||
enum VAR {
|
||||
cat, N, S, av, av_, Tvav_, sv;
|
||||
public final String pattern = "@"+toString().replace('_','.')+"@";
|
||||
public String binding = toString();
|
||||
static void makeBindings(boolean topLevel, int outargs, int spread) {
|
||||
int inargs = outargs - spread;
|
||||
VAR.cat.binding = "S"+outargs;
|
||||
VAR.N.binding = String.valueOf(outargs); // outgoing arg count
|
||||
VAR.S.binding = String.valueOf(spread); // spread count
|
||||
String[] av = new String[inargs];
|
||||
String[] Tvav = new String[inargs];
|
||||
for (int i = 0; i < inargs; i++) {
|
||||
av[i] = arg(i);
|
||||
Tvav[i] = param("Object", av[i]);
|
||||
}
|
||||
VAR.av.binding = comma(av);
|
||||
VAR.av_.binding = comma(av, ", ");
|
||||
VAR.Tvav_.binding = comma(Tvav, ", ");
|
||||
String[] sv = new String[spread];
|
||||
for (int i = 0; i < spread; i++) {
|
||||
String spc = "";
|
||||
if (i % 4 == 0) spc = NEWLINE_INDENT;
|
||||
sv[i] = spc+"super.select(av,"+i+")";
|
||||
}
|
||||
VAR.sv.binding = comma(sv);
|
||||
}
|
||||
static String arg(int i) { return "a"+i; }
|
||||
static String param(String t, String a) { return t+" "+a; }
|
||||
static String comma(String[] v) { return comma(v, ""); }
|
||||
static String comma(String[] v, String sep) {
|
||||
if (v.length == 0) return "";
|
||||
String res = v[0];
|
||||
for (int i = 1; i < v.length; i++) res += ", "+v[i];
|
||||
return res + sep;
|
||||
}
|
||||
static String transform(String string) {
|
||||
for (VAR var : values())
|
||||
string = string.replaceAll(var.pattern, var.binding);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
static String[] stringsIn(String[] strings, int beg, int end) {
|
||||
return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
|
||||
}
|
||||
static String[] stringsBefore(String[] strings, int pos) {
|
||||
return stringsIn(strings, 0, pos);
|
||||
}
|
||||
static String[] stringsAfter(String[] strings, int pos) {
|
||||
return stringsIn(strings, pos, strings.length);
|
||||
}
|
||||
static int indexAfter(String[] strings, int pos, String tag) {
|
||||
return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
|
||||
}
|
||||
static int indexBefore(String[] strings, int pos, String tag) {
|
||||
for (int i = pos, end = strings.length; ; i++) {
|
||||
if (i == end || strings[i].endsWith(tag)) return i;
|
||||
}
|
||||
}
|
||||
static int MIN_ARITY, MAX_ARITY;
|
||||
public static void main(String... av) {
|
||||
for (String[] template : TEMPLATES) {
|
||||
int forLinesLimit = indexBefore(template, 0, "@each-cat@");
|
||||
String[] forLines = stringsBefore(template, forLinesLimit);
|
||||
template = stringsAfter(template, forLinesLimit);
|
||||
for (String forLine : forLines)
|
||||
expandTemplate(forLine, template);
|
||||
}
|
||||
}
|
||||
static void expandTemplate(String forLine, String[] template) {
|
||||
String[] params = forLine.split("[^0-9]+");
|
||||
if (params[0].length() == 0) params = stringsAfter(params, 1);
|
||||
System.out.println("//params="+Arrays.asList(params));
|
||||
int pcur = 0;
|
||||
MIN_ARITY = Integer.valueOf(params[pcur++]);
|
||||
MAX_ARITY = Integer.valueOf(params[pcur++]);
|
||||
if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
|
||||
for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) {
|
||||
expandTemplate(template, true, outargs, 0);
|
||||
}
|
||||
}
|
||||
static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) {
|
||||
VAR.makeBindings(topLevel, outargs, spread);
|
||||
for (int i = 0; i < template.length; i++) {
|
||||
String line = template[i];
|
||||
if (line.endsWith("@each-cat@")) {
|
||||
// ignore
|
||||
} else if (line.endsWith("@each-S@")) {
|
||||
int blockEnd = indexAfter(template, i, "@end-S@");
|
||||
String[] block = stringsIn(template, i+1, blockEnd-1);
|
||||
for (int spread1 = spread+1; spread1 <= outargs; spread1++)
|
||||
expandTemplate(block, false, outargs, spread1);
|
||||
VAR.makeBindings(topLevel, outargs, spread);
|
||||
i = blockEnd-1; continue;
|
||||
} else {
|
||||
System.out.println(VAR.transform(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//}}} */
|
||||
//params=[0, 10]
|
||||
static class S0 extends Adapter {
|
||||
protected S0(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
|
||||
protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(); }
|
||||
}
|
||||
static class S1 extends Adapter {
|
||||
protected S1(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0); }
|
||||
protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(
|
||||
super.select(av,0)); }
|
||||
}
|
||||
static class S2 extends Adapter {
|
||||
protected S2(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1); }
|
||||
protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
}
|
||||
static class S3 extends Adapter {
|
||||
protected S3(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
}
|
||||
static class S4 extends Adapter {
|
||||
protected S4(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
}
|
||||
static class S5 extends Adapter {
|
||||
protected S5(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
}
|
||||
static class S6 extends Adapter {
|
||||
protected S6(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5)); }
|
||||
}
|
||||
static class S7 extends Adapter {
|
||||
protected S7(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5)); }
|
||||
protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6)); }
|
||||
}
|
||||
static class S8 extends Adapter {
|
||||
protected S8(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5)); }
|
||||
protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6)); }
|
||||
protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
|
||||
}
|
||||
static class S9 extends Adapter {
|
||||
protected S9(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5)); }
|
||||
protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6)); }
|
||||
protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
|
||||
protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
|
||||
super.select(av,8)); }
|
||||
}
|
||||
static class S10 extends Adapter {
|
||||
protected S10(SpreadGeneric outer) { super(outer); } // to build prototype
|
||||
protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
|
||||
protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
|
||||
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
|
||||
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
super.select(av,0)); }
|
||||
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
|
||||
super.select(av,0), super.select(av,1)); }
|
||||
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2)); }
|
||||
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4, a5,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
|
||||
protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
|
||||
return target.invokeExact(a0, a1, a2, a3, a4,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4)); }
|
||||
protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
|
||||
return target.invokeExact(a0, a1, a2, a3,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5)); }
|
||||
protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
|
||||
return target.invokeExact(a0, a1, a2,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6)); }
|
||||
protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
|
||||
return target.invokeExact(a0, a1,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
|
||||
protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
|
||||
return target.invokeExact(a0,
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
|
||||
super.select(av,8)); }
|
||||
protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
|
||||
return target.invokeExact(
|
||||
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
|
||||
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
|
||||
super.select(av,8), super.select(av,9)); }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -63,8 +63,7 @@ import java.io.Serializable;
|
||||
public class BasicComboPopup extends JPopupMenu implements ComboPopup {
|
||||
// An empty ListMode, this is used when the UI changes to allow
|
||||
// the JList to be gc'ed.
|
||||
private static class EmptyListModelClass implements ListModel,
|
||||
Serializable {
|
||||
private static class EmptyListModelClass implements ListModel<Object>, Serializable {
|
||||
public int getSize() { return 0; }
|
||||
public Object getElementAt(int index) { return null; }
|
||||
public void addListDataListener(ListDataListener l) {}
|
||||
|
||||
@ -810,10 +810,7 @@ public class BasicFileChooserUI extends FileChooserUI {
|
||||
putValue(Action.ACTION_COMMAND_KEY, FilePane.ACTION_CHANGE_TO_PARENT_DIRECTORY);
|
||||
}
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if (focusOwner == null || !(focusOwner instanceof javax.swing.text.JTextComponent)) {
|
||||
getFileChooser().changeToParentDirectory();
|
||||
}
|
||||
getFileChooser().changeToParentDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -444,7 +444,7 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements
|
||||
* renderer installed on a Synth combo box is a JLabel. If this is changed,
|
||||
* then an assert will fail in SynthFileChooserUIImpl
|
||||
*/
|
||||
private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer, UIResource {
|
||||
private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer<Object>, UIResource {
|
||||
public SynthComboBoxRenderer() {
|
||||
super();
|
||||
setName("ComboBox.renderer");
|
||||
@ -452,7 +452,7 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value,
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
setName("ComboBox.listRenderer");
|
||||
SynthLookAndFeel.resetSelectedUI();
|
||||
|
||||
@ -725,11 +725,11 @@ public class FormView extends ComponentView implements ActionListener {
|
||||
}
|
||||
Object m = attr.getAttribute(StyleConstants.ModelAttribute);
|
||||
if (m instanceof OptionListModel) {
|
||||
OptionListModel model = (OptionListModel)m;
|
||||
OptionListModel<Option> model = (OptionListModel<Option>) m;
|
||||
|
||||
for (int i = 0; i < model.getSize(); i++) {
|
||||
if (model.isSelectedIndex(i)) {
|
||||
Option option = (Option) model.getElementAt(i);
|
||||
Option option = model.getElementAt(i);
|
||||
appendBuffer(buffer, name, option.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3358,13 +3358,13 @@ public class HTMLDocument extends DefaultStyledDocument {
|
||||
1);
|
||||
boolean multiple = attr.getAttribute(HTML.Attribute.MULTIPLE) != null;
|
||||
if ((size > 1) || multiple) {
|
||||
OptionListModel m = new OptionListModel();
|
||||
OptionListModel<Option> m = new OptionListModel<Option>();
|
||||
if (multiple) {
|
||||
m.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
}
|
||||
selectModel = m;
|
||||
} else {
|
||||
selectModel = new OptionComboBoxModel();
|
||||
selectModel = new OptionComboBoxModel<Option>();
|
||||
}
|
||||
attr.addAttribute(StyleConstants.ModelAttribute,
|
||||
selectModel);
|
||||
@ -3376,14 +3376,14 @@ public class HTMLDocument extends DefaultStyledDocument {
|
||||
option = new Option(attr);
|
||||
|
||||
if (selectModel instanceof OptionListModel) {
|
||||
OptionListModel m = (OptionListModel)selectModel;
|
||||
OptionListModel<Option> m = (OptionListModel<Option>) selectModel;
|
||||
m.addElement(option);
|
||||
if (option.isSelected()) {
|
||||
m.addSelectionInterval(optionCount, optionCount);
|
||||
m.setInitialSelection(optionCount);
|
||||
}
|
||||
} else if (selectModel instanceof OptionComboBoxModel) {
|
||||
OptionComboBoxModel m = (OptionComboBoxModel)selectModel;
|
||||
OptionComboBoxModel<Option> m = (OptionComboBoxModel<Option>) selectModel;
|
||||
m.addElement(option);
|
||||
if (option.isSelected()) {
|
||||
m.setSelectedItem(option);
|
||||
|
||||
@ -527,17 +527,17 @@ public class HTMLWriter extends AbstractWriter {
|
||||
Object model = attr.getAttribute(StyleConstants.ModelAttribute);
|
||||
incrIndent();
|
||||
if (model instanceof OptionListModel) {
|
||||
OptionListModel listModel = (OptionListModel)model;
|
||||
OptionListModel<Option> listModel = (OptionListModel<Option>) model;
|
||||
int size = listModel.getSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Option option = (Option)listModel.getElementAt(i);
|
||||
Option option = listModel.getElementAt(i);
|
||||
writeOption(option);
|
||||
}
|
||||
} else if (model instanceof OptionComboBoxModel) {
|
||||
OptionComboBoxModel comboBoxModel = (OptionComboBoxModel)model;
|
||||
OptionComboBoxModel<Option> comboBoxModel = (OptionComboBoxModel<Option>) model;
|
||||
int size = comboBoxModel.getSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Option option = (Option)comboBoxModel.getElementAt(i);
|
||||
Option option = comboBoxModel.getElementAt(i);
|
||||
writeOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
package javax.swing.text.html;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@ -41,7 +40,7 @@ import java.io.Serializable;
|
||||
@author Sunita Mani
|
||||
*/
|
||||
|
||||
class OptionComboBoxModel extends DefaultComboBoxModel implements Serializable {
|
||||
class OptionComboBoxModel<E> extends DefaultComboBoxModel<E> implements Serializable {
|
||||
|
||||
private Option selectedOption = null;
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@ package javax.swing.text.html;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import java.util.EventListener;
|
||||
import java.util.BitSet;
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -44,7 +43,7 @@ import java.io.Serializable;
|
||||
@author Sunita Mani
|
||||
*/
|
||||
|
||||
class OptionListModel extends DefaultListModel implements ListSelectionModel, Serializable {
|
||||
class OptionListModel<E> extends DefaultListModel<E> implements ListSelectionModel, Serializable {
|
||||
|
||||
|
||||
private static final int MIN = -1;
|
||||
|
||||
@ -25,15 +25,12 @@
|
||||
|
||||
package sun.awt;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlContext;
|
||||
|
||||
/**
|
||||
@ -470,6 +467,17 @@ public final class AWTAccessor {
|
||||
boolean isMultipleMode(FileDialog fileDialog);
|
||||
}
|
||||
|
||||
/*
|
||||
* An accessor for the ScrollPaneAdjustable class.
|
||||
*/
|
||||
public interface ScrollPaneAdjustableAccessor {
|
||||
/*
|
||||
* Sets the value of this scrollbar to the specified value.
|
||||
*/
|
||||
void setTypedValue(final ScrollPaneAdjustable adj, final int v,
|
||||
final int type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessor instances are initialized in the static initializers of
|
||||
* corresponding AWT classes by using setters defined below.
|
||||
@ -485,6 +493,7 @@ public final class AWTAccessor {
|
||||
private static EventQueueAccessor eventQueueAccessor;
|
||||
private static PopupMenuAccessor popupMenuAccessor;
|
||||
private static FileDialogAccessor fileDialogAccessor;
|
||||
private static ScrollPaneAdjustableAccessor scrollPaneAdjustableAccessor;
|
||||
|
||||
/*
|
||||
* Set an accessor object for the java.awt.Component class.
|
||||
@ -675,4 +684,21 @@ public final class AWTAccessor {
|
||||
return fileDialogAccessor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an accessor object for the java.awt.ScrollPaneAdjustable class.
|
||||
*/
|
||||
public static void setScrollPaneAdjustableAccessor(ScrollPaneAdjustableAccessor adj) {
|
||||
scrollPaneAdjustableAccessor = adj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the accessor object for the java.awt.ScrollPaneAdjustable
|
||||
* class.
|
||||
*/
|
||||
public static ScrollPaneAdjustableAccessor getScrollPaneAdjustableAccessor() {
|
||||
if (scrollPaneAdjustableAccessor == null) {
|
||||
unsafe.ensureClassInitialized(ScrollPaneAdjustable.class);
|
||||
}
|
||||
return scrollPaneAdjustableAccessor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,12 +127,8 @@ public abstract class RenderingEngine {
|
||||
try {
|
||||
Class cls = Class.forName(ductusREClass);
|
||||
return cls.newInstance();
|
||||
} catch (ClassNotFoundException x) {
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
// not found
|
||||
} catch (IllegalAccessException x) {
|
||||
// should not reach here
|
||||
} catch (InstantiationException x) {
|
||||
// should not reach here
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -570,7 +570,7 @@ public class FilePane extends JPanel implements PropertyChangeListener {
|
||||
public JPanel createList() {
|
||||
JPanel p = new JPanel(new BorderLayout());
|
||||
final JFileChooser fileChooser = getFileChooser();
|
||||
final JList list = new JList() {
|
||||
final JList<Object> list = new JList<Object>() {
|
||||
public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
|
||||
ListModel model = getModel();
|
||||
int max = model.getSize();
|
||||
@ -641,7 +641,7 @@ public class FilePane extends JPanel implements PropertyChangeListener {
|
||||
/**
|
||||
* This model allows for sorting JList
|
||||
*/
|
||||
private class SortableListModel extends AbstractListModel
|
||||
private class SortableListModel extends AbstractListModel<Object>
|
||||
implements TableModelListener, RowSorterListener {
|
||||
|
||||
public SortableListModel() {
|
||||
|
||||
@ -60,7 +60,7 @@ import sun.swing.*;
|
||||
*/
|
||||
public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
private JLabel lookInLabel;
|
||||
private JComboBox directoryComboBox;
|
||||
private JComboBox<File> directoryComboBox;
|
||||
private DirectoryComboBoxModel directoryComboBoxModel;
|
||||
private Action directoryComboBoxAction = new DirectoryComboBoxAction();
|
||||
|
||||
@ -77,10 +77,9 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
private JPanel buttonPanel;
|
||||
private JPanel bottomPanel;
|
||||
|
||||
private JComboBox filterComboBox;
|
||||
private JComboBox<FileFilter> filterComboBox;
|
||||
|
||||
private static final Dimension hstrut5 = new Dimension(5, 1);
|
||||
private static final Dimension vstrut5 = new Dimension(1, 5);
|
||||
|
||||
private static final Insets shrinkwrap = new Insets(0,0,0,0);
|
||||
|
||||
@ -217,7 +216,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS);
|
||||
|
||||
// CurrentDir ComboBox
|
||||
directoryComboBox = new JComboBox();
|
||||
directoryComboBox = new JComboBox<File>();
|
||||
directoryComboBox.getAccessibleContext().setAccessibleDescription(lookInLabelText);
|
||||
directoryComboBox.putClientProperty( "JComboBox.isTableCellEditor", Boolean.TRUE );
|
||||
lookInLabel.setLabelFor(directoryComboBox);
|
||||
@ -394,7 +393,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
|
||||
filterComboBoxModel = createFilterComboBoxModel();
|
||||
fc.addPropertyChangeListener(filterComboBoxModel);
|
||||
filterComboBox = new JComboBox(filterComboBoxModel);
|
||||
filterComboBox = new JComboBox<FileFilter>(filterComboBoxModel);
|
||||
filterComboBox.getAccessibleContext().setAccessibleDescription(filesOfTypeLabelText);
|
||||
filesOfTypeLabel.setLabelFor(filterComboBox);
|
||||
filterComboBox.setRenderer(createFilterComboBoxRenderer());
|
||||
@ -671,16 +670,16 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
// looking combo boxes.
|
||||
// So what we do here is delegate most jobs to the "real" or original renderer,
|
||||
// and simply monkey with the icon and text of the renderer.
|
||||
private class DirectoryComboBoxRenderer implements ListCellRenderer {
|
||||
private ListCellRenderer delegate;
|
||||
private class DirectoryComboBoxRenderer implements ListCellRenderer<File> {
|
||||
private ListCellRenderer<? super File> delegate;
|
||||
IndentIcon ii = new IndentIcon();
|
||||
|
||||
private DirectoryComboBoxRenderer(ListCellRenderer delegate) {
|
||||
private DirectoryComboBoxRenderer(ListCellRenderer<? super File> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
public Component getListCellRendererComponent(JList<? extends File> list, File value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
assert c instanceof JLabel;
|
||||
@ -689,9 +688,8 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
label.setText("");
|
||||
return label;
|
||||
}
|
||||
File directory = (File) value;
|
||||
label.setText(getFileChooser().getName(directory));
|
||||
Icon icon = getFileChooser().getIcon(directory);
|
||||
label.setText(getFileChooser().getName(value));
|
||||
Icon icon = getFileChooser().getIcon(value);
|
||||
ii.icon = icon;
|
||||
ii.depth = directoryComboBoxModel.getDepth(index);
|
||||
label.setIcon(ii);
|
||||
@ -736,7 +734,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
/**
|
||||
* Data model for a type-face selection combo-box.
|
||||
*/
|
||||
protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
|
||||
protected class DirectoryComboBoxModel extends AbstractListModel<File> implements ComboBoxModel<File> {
|
||||
Vector<File> directories = new Vector<File>();
|
||||
int[] depths = null;
|
||||
File selectedDirectory = null;
|
||||
@ -857,7 +855,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
return directories.size();
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public File getElementAt(int index) {
|
||||
return directories.elementAt(index);
|
||||
}
|
||||
}
|
||||
@ -890,18 +888,19 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
/**
|
||||
* Render different type sizes and styles.
|
||||
*/
|
||||
public class FilterComboBoxRenderer implements ListCellRenderer {
|
||||
private ListCellRenderer delegate;
|
||||
private FilterComboBoxRenderer(ListCellRenderer delegate) {
|
||||
public class FilterComboBoxRenderer implements ListCellRenderer<FileFilter> {
|
||||
private ListCellRenderer<? super FileFilter> delegate;
|
||||
private FilterComboBoxRenderer(ListCellRenderer<? super FileFilter> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
public Component getListCellRendererComponent(JList<? extends FileFilter> list, FileFilter value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
String text = null;
|
||||
if (value != null && value instanceof FileFilter) {
|
||||
text = ((FileFilter) value).getDescription();
|
||||
if (value != null) {
|
||||
text = value.getDescription();
|
||||
}
|
||||
|
||||
//this should always be true, since SynthComboBoxUI's SynthComboBoxRenderer
|
||||
@ -924,7 +923,8 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
/**
|
||||
* Data model for a type-face selection combo-box.
|
||||
*/
|
||||
protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
|
||||
protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,
|
||||
PropertyChangeListener {
|
||||
protected FileFilter[] filters;
|
||||
protected FilterComboBoxModel() {
|
||||
super();
|
||||
@ -977,7 +977,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
public FileFilter getElementAt(int index) {
|
||||
if(index > getSize() - 1) {
|
||||
// This shouldn't happen. Try to recover gracefully.
|
||||
return getFileChooser().getFileFilter();
|
||||
|
||||
@ -47,15 +47,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.CellRendererPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.text.BadLocationException;
|
||||
@ -336,7 +328,22 @@ public class TextComponentPrintable implements CountingPrintable {
|
||||
assert SwingUtilities.isEventDispatchThread();
|
||||
|
||||
JTextComponent ret = null;
|
||||
if (textComponent instanceof JTextField) {
|
||||
if (textComponent instanceof JPasswordField) {
|
||||
ret =
|
||||
new JPasswordField() {
|
||||
{
|
||||
setEchoChar(((JPasswordField) textComponent).getEchoChar());
|
||||
setHorizontalAlignment(
|
||||
((JTextField) textComponent).getHorizontalAlignment());
|
||||
}
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font font) {
|
||||
return (frc.get() == null)
|
||||
? super.getFontMetrics(font)
|
||||
: FontDesignMetrics.getMetrics(font, frc.get());
|
||||
}
|
||||
};
|
||||
} else if (textComponent instanceof JTextField) {
|
||||
ret =
|
||||
new JTextField() {
|
||||
{
|
||||
|
||||
@ -2690,6 +2690,7 @@ public class BidiBase {
|
||||
public void setPara(AttributedCharacterIterator paragraph)
|
||||
{
|
||||
byte paraLvl;
|
||||
char ch = paragraph.first();
|
||||
Boolean runDirection =
|
||||
(Boolean) paragraph.getAttribute(TextAttributeConstants.RUN_DIRECTION);
|
||||
Object shaper = paragraph.getAttribute(TextAttributeConstants.NUMERIC_SHAPING);
|
||||
@ -2705,7 +2706,6 @@ public class BidiBase {
|
||||
byte[] embeddingLevels = new byte[len];
|
||||
char[] txt = new char[len];
|
||||
int i = 0;
|
||||
char ch = paragraph.first();
|
||||
while (ch != AttributedCharacterIterator.DONE) {
|
||||
txt[i] = ch;
|
||||
Integer embedding =
|
||||
@ -3411,18 +3411,21 @@ public class BidiBase {
|
||||
* Display the bidi internal state, used in debugging.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
StringBuilder buf = new StringBuilder(getClass().getName());
|
||||
|
||||
buf.append("[dir: " + direction);
|
||||
buf.append(" baselevel: " + paraLevel);
|
||||
buf.append(" length: " + length);
|
||||
buf.append("[dir: ");
|
||||
buf.append(direction);
|
||||
buf.append(" baselevel: ");
|
||||
buf.append(paraLevel);
|
||||
buf.append(" length: ");
|
||||
buf.append(length);
|
||||
buf.append(" runs: ");
|
||||
if (levels == null) {
|
||||
buf.append("null");
|
||||
buf.append("none");
|
||||
} else {
|
||||
buf.append('[');
|
||||
buf.append(levels[0]);
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
for (int i = 1; i < levels.length; i++) {
|
||||
buf.append(' ');
|
||||
buf.append(levels[i]);
|
||||
}
|
||||
@ -3430,12 +3433,11 @@ public class BidiBase {
|
||||
}
|
||||
buf.append(" text: [0x");
|
||||
buf.append(Integer.toHexString(text[0]));
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
for (int i = 1; i < text.length; i++) {
|
||||
buf.append(" 0x");
|
||||
buf.append(Integer.toHexString(text[i]));
|
||||
}
|
||||
buf.append(']');
|
||||
buf.append(']');
|
||||
buf.append("]]");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "java_awt_AlphaComposite.h"
|
||||
|
||||
#include "SurfaceData.h"
|
||||
@ -484,7 +486,9 @@ extern struct _CompositeTypes {
|
||||
#define ArraySize(A) (sizeof(A) / sizeof(A[0]))
|
||||
|
||||
#define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b)))
|
||||
#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, (y)*(yinc) + (x)*(xinc))
|
||||
#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, \
|
||||
((ptrdiff_t)(y))*(yinc) + \
|
||||
((ptrdiff_t)(x))*(xinc))
|
||||
|
||||
/*
|
||||
* The function to call with an array of NativePrimitive structures
|
||||
|
||||
@ -33,12 +33,9 @@ import java.awt.event.ActionEvent;
|
||||
import javax.swing.plaf.basic.*;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
|
||||
boolean pressed;
|
||||
boolean armed;
|
||||
|
||||
private boolean pressed;
|
||||
private boolean armed;
|
||||
private Insets focusInsets;
|
||||
private Insets borderInsets;
|
||||
private Insets contentAreaInsets;
|
||||
@ -86,11 +83,6 @@ public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
this.label = label;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
paint(g,target);
|
||||
}
|
||||
|
||||
public void setBackground(Color c) {
|
||||
updateMotifColors(c);
|
||||
super.setBackground(c);
|
||||
@ -133,16 +125,10 @@ public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
case MouseEvent.MOUSE_ENTERED:
|
||||
if (pressed)
|
||||
armed = true;
|
||||
// repaint();
|
||||
|
||||
break;
|
||||
|
||||
case MouseEvent.MOUSE_EXITED:
|
||||
armed = false;
|
||||
// repaint();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,18 +195,14 @@ public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
public Dimension minimumSize() {
|
||||
return getMinimumSize();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This method is called from Toolkit Thread and so it should not call any client code
|
||||
|
||||
*/
|
||||
public void paint(Graphics g, Component c)
|
||||
{
|
||||
if (!disposed && (g != null))
|
||||
{
|
||||
/**
|
||||
* This method is called from Toolkit Thread and so it should not call any
|
||||
* client code.
|
||||
*/
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
if (!disposed) {
|
||||
Dimension size = getPeerSize();
|
||||
|
||||
g.setColor( getPeerBackground() ); /* erase the existing button remains */
|
||||
g.fillRect(0,0, size.width , size.height);
|
||||
paintBorder(g,borderInsets.left,
|
||||
@ -239,11 +221,9 @@ public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
|
||||
viewRect.width = size.width - (contentAreaInsets.left+contentAreaInsets.right);
|
||||
viewRect.height = size.height - (contentAreaInsets.top+contentAreaInsets.bottom);
|
||||
|
||||
viewRect.x = contentAreaInsets.left;
|
||||
viewRect.y = contentAreaInsets.right;
|
||||
viewRect.y = contentAreaInsets.top;
|
||||
String llabel = (label != null) ? label : "";
|
||||
|
||||
// layout the text and icon
|
||||
String text = SwingUtilities.layoutCompoundLabel(
|
||||
fm, llabel, null,
|
||||
@ -309,10 +289,9 @@ public class XButtonPeer extends XComponentPeer implements ButtonPeer {
|
||||
else {
|
||||
/*** paint the text disabled ***/
|
||||
g.setColor(getPeerBackground().brighter());
|
||||
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(g,text, mnemonicIndex,
|
||||
textRect.x, textRect.y + fm.getAscent());
|
||||
g.setColor(c.getBackground().darker());
|
||||
g.setColor(getPeerBackground().darker());
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(g,text, mnemonicIndex,
|
||||
textRect.x - 1, textRect.y + fm.getAscent() - 1);
|
||||
}
|
||||
|
||||
@ -297,40 +297,33 @@ class XCheckboxPeer extends XComponentPeer implements CheckboxPeer {
|
||||
|
||||
double fsize = (double) checkBoxSize;
|
||||
myCheckMark = AffineTransform.getScaleInstance(fsize / MASTER_SIZE, fsize / MASTER_SIZE).createTransformedShape(MASTER_CHECKMARK);
|
||||
|
||||
}
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
//layout();
|
||||
Dimension size = getPeerSize();
|
||||
Font f = getPeerFont();
|
||||
flush();
|
||||
g.setColor(getPeerBackground()); // erase the existing button
|
||||
g.fillRect(0,0, size.width, size.height);
|
||||
if (label != null) {
|
||||
g.setFont(f);
|
||||
paintText(g, textRect, label);
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
if (g != null) {
|
||||
//layout();
|
||||
Dimension size = getPeerSize();
|
||||
Font f = getPeerFont();
|
||||
|
||||
flush();
|
||||
g.setColor(getPeerBackground()); // erase the existing button
|
||||
g.fillRect(0,0, size.width, size.height);
|
||||
|
||||
if (label != null) {
|
||||
g.setFont(f);
|
||||
paintText(g, textRect, label);
|
||||
}
|
||||
|
||||
if (hasFocus()) {
|
||||
paintFocus(g,
|
||||
focusRect.x,
|
||||
focusRect.y,
|
||||
focusRect.width,
|
||||
focusRect.height);
|
||||
}
|
||||
|
||||
// Paint the checkbox or radio button
|
||||
if (checkBoxGroup == null) {
|
||||
paintCheckbox(g, cbX, cbY, checkBoxSize, checkBoxSize);
|
||||
}
|
||||
else {
|
||||
paintRadioButton(g, cbX, cbY, checkBoxSize, checkBoxSize);
|
||||
}
|
||||
|
||||
if (hasFocus()) {
|
||||
paintFocus(g,
|
||||
focusRect.x,
|
||||
focusRect.y,
|
||||
focusRect.width,
|
||||
focusRect.height);
|
||||
}
|
||||
// Paint the checkbox or radio button
|
||||
if (checkBoxGroup == null) {
|
||||
paintCheckbox(g, cbX, cbY, checkBoxSize, checkBoxSize);
|
||||
}
|
||||
else {
|
||||
paintRadioButton(g, cbX, cbY, checkBoxSize, checkBoxSize);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
@ -550,10 +550,10 @@ public class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelS
|
||||
/**
|
||||
* Paint the choice
|
||||
*/
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
flush();
|
||||
Dimension size = getPeerSize();
|
||||
|
||||
// TODO: when mouse is down over button, widget should be drawn depressed
|
||||
g.setColor(getPeerBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
@ -912,16 +912,22 @@ public class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelS
|
||||
/*
|
||||
* fillRect with current Background color on the whole dropdown list.
|
||||
*/
|
||||
public void paintBackground(){
|
||||
Graphics g = getGraphics();
|
||||
g.setColor(getPeerBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
public void paintBackground() {
|
||||
final Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
g.setColor(getPeerBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 6405689. In some cases we should erase background to eliminate painting
|
||||
* artefacts.
|
||||
*/
|
||||
@Override
|
||||
public void repaint() {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
@ -931,8 +937,8 @@ public class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelS
|
||||
}
|
||||
super.repaint();
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
public void paintPeer(Graphics g) {
|
||||
//System.out.println("UC.paint()");
|
||||
Choice choice = (Choice)target;
|
||||
Color colors[] = XChoicePeer.this.getGUIcolors();
|
||||
|
||||
@ -38,7 +38,6 @@ import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.SystemColor;
|
||||
import java.awt.Toolkit;
|
||||
@ -59,15 +58,11 @@ import java.awt.image.ImageProducer;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.awt.peer.LightweightPeer;
|
||||
import java.lang.reflect.*;
|
||||
import java.security.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import sun.awt.*;
|
||||
import sun.awt.event.IgnorePaintEvent;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
@ -428,27 +423,23 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
|
||||
public void disable() {
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
super.paint(g);
|
||||
// allow target to change the picture
|
||||
target.paint(g);
|
||||
}
|
||||
public void repaint(long tm, int x, int y, int width, int height) {
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
public Graphics getGraphics() {
|
||||
return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void print(Graphics g) {
|
||||
// clear rect here to emulate X clears rect before Expose
|
||||
g.setColor(target.getBackground());
|
||||
g.fillRect(0, 0, target.getWidth(), target.getHeight());
|
||||
g.setColor(target.getForeground());
|
||||
// paint peer
|
||||
paint(g);
|
||||
paintPeer(g);
|
||||
// allow target to change the picture
|
||||
target.print(g);
|
||||
}
|
||||
|
||||
@ -85,7 +85,8 @@ class XLabelPeer extends XComponentPeer implements LabelPeer {
|
||||
*/
|
||||
// NOTE: This method is called by privileged threads.
|
||||
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
int textX = 0;
|
||||
int textY = 0;
|
||||
g.setColor(getPeerBackground());
|
||||
|
||||
@ -363,9 +363,7 @@ class XListPeer extends XComponentPeer implements ListPeer, XScrollbarClient {
|
||||
return Math.min(items.size()-1, itemsInWindow()-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void repaintScrollbarRequest(XScrollbar scrollbar) {
|
||||
Graphics g = getGraphics();
|
||||
if (scrollbar == hsb) {
|
||||
repaint(PAINT_HSCROLL);
|
||||
}
|
||||
@ -373,9 +371,6 @@ class XListPeer extends XComponentPeer implements ListPeer, XScrollbarClient {
|
||||
repaint(PAINT_VSCROLL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Overridden for performance
|
||||
*/
|
||||
@ -410,18 +405,20 @@ class XListPeer extends XComponentPeer implements ListPeer, XScrollbarClient {
|
||||
* @param distance the distance to copy the source area
|
||||
*/
|
||||
private void repaint(int firstItem, int lastItem, int options, Rectangle source, Point distance) {
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
painter.paint(g, firstItem, lastItem, options, source, distance);
|
||||
} finally {
|
||||
g.dispose();
|
||||
final Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
painter.paint(g, firstItem, lastItem, options, source, distance);
|
||||
target.paint(g);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
painter.paint(g, getFirstVisibleItem(), getLastVisibleItem(), PAINT_ALL);
|
||||
}
|
||||
|
||||
public boolean isFocusable() { return true; }
|
||||
|
||||
// TODO: share/promote the Focus methods?
|
||||
|
||||
@ -415,7 +415,7 @@ public class XMenuBarPeer extends XBaseMenuWindow implements MenuBarPeer {
|
||||
* Overriden XWindow painting & printing
|
||||
*
|
||||
************************************************/
|
||||
public void paint(Graphics g) {
|
||||
public void paintPeer(Graphics g) {
|
||||
resetColors();
|
||||
/* Calculate menubar dimension. */
|
||||
int width = getWidth();
|
||||
|
||||
@ -432,9 +432,9 @@ public class XMenuWindow extends XBaseMenuWindow {
|
||||
/**
|
||||
* Paints menu window
|
||||
*/
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
public void paintPeer(Graphics g) {
|
||||
resetColors();
|
||||
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
|
||||
@ -60,14 +60,13 @@ public class XPanelPeer extends XCanvasPeer implements PanelPeer {
|
||||
public Insets getInsets() {
|
||||
return new Insets(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
/* SunGraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
|
||||
runComponents(((Container)target).getComponents(), g,
|
||||
SunGraphicsCallback.LIGHTWEIGHTS |
|
||||
SunGraphicsCallback.HEAVYWEIGHTS);
|
||||
*/ }
|
||||
SunGraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
|
||||
runComponents(((Container)target).getComponents(), g,
|
||||
SunGraphicsCallback.LIGHTWEIGHTS |
|
||||
SunGraphicsCallback.HEAVYWEIGHTS);
|
||||
}
|
||||
public void print(Graphics g) {
|
||||
super.print(g);
|
||||
SunGraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
|
||||
|
||||
@ -53,9 +53,9 @@ class XRepaintArea extends RepaintArea {
|
||||
*/
|
||||
protected void updateComponent(Component comp, Graphics g) {
|
||||
if (comp != null) {
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
final XComponentPeer peer = (XComponentPeer) comp.getPeer();
|
||||
if (peer != null) {
|
||||
peer.paint(g);
|
||||
peer.paintPeer(g);
|
||||
}
|
||||
super.updateComponent(comp, g);
|
||||
}
|
||||
@ -66,9 +66,9 @@ class XRepaintArea extends RepaintArea {
|
||||
*/
|
||||
protected void paintComponent(Component comp, Graphics g) {
|
||||
if (comp != null) {
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
final XComponentPeer peer = (XComponentPeer) comp.getPeer();
|
||||
if (peer != null) {
|
||||
peer.paint(g);
|
||||
peer.paintPeer(g);
|
||||
}
|
||||
super.paintComponent(comp, g);
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@ import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.peer.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
class XScrollPanePeer extends XComponentPeer implements ScrollPanePeer, XScrollbarClient {
|
||||
@ -41,9 +43,7 @@ class XScrollPanePeer extends XComponentPeer implements ScrollPanePeer, XScrollb
|
||||
public final static int VERTICAL = 1 << 0;
|
||||
public final static int HORIZONTAL = 1 << 1;
|
||||
|
||||
private static Method m_setValue;
|
||||
static {
|
||||
m_setValue = SunToolkit.getMethod(ScrollPaneAdjustable.class, "setTypedValue", new Class[] {Integer.TYPE, Integer.TYPE});
|
||||
SCROLLBAR = XToolkit.getUIDefaults().getInt("ScrollBar.defaultWidth");
|
||||
}
|
||||
|
||||
@ -293,10 +293,12 @@ class XScrollPanePeer extends XComponentPeer implements ScrollPanePeer, XScrollb
|
||||
setAdjustableValue(hadj, hsb.getValue(), type);
|
||||
sx = -(hsb.getValue());
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
paintHorScrollbar(g, colors, true);
|
||||
} finally {
|
||||
g.dispose();
|
||||
if (g != null) {
|
||||
try {
|
||||
paintHorScrollbar(g, colors, true);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flag & VERTICAL) != 0) {
|
||||
@ -305,36 +307,38 @@ class XScrollPanePeer extends XComponentPeer implements ScrollPanePeer, XScrollb
|
||||
setAdjustableValue(vadj, vsb.getValue(), type);
|
||||
sy = -(vsb.getValue());
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
paintVerScrollbar(g, colors, true);
|
||||
} finally {
|
||||
g.dispose();
|
||||
if (g != null) {
|
||||
try {
|
||||
paintVerScrollbar(g, colors, true);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c.move(sx, sy);
|
||||
}
|
||||
|
||||
void setAdjustableValue(ScrollPaneAdjustable adj, int value, int type) {
|
||||
try {
|
||||
m_setValue.invoke(adj, new Object[] {Integer.valueOf(value), Integer.valueOf(type)});
|
||||
} catch (IllegalAccessException iae) {
|
||||
adj.setValue(value);
|
||||
} catch (IllegalArgumentException iae2) {
|
||||
adj.setValue(value);
|
||||
} catch (InvocationTargetException ite) {
|
||||
adj.setValue(value);
|
||||
ite.getCause().printStackTrace();
|
||||
private void setAdjustableValue(final ScrollPaneAdjustable adj, final int value,
|
||||
final int type) {
|
||||
AWTAccessor.getScrollPaneAdjustableAccessor().setTypedValue(adj, value,
|
||||
type);
|
||||
}
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
final Color[] colors = getGUIcolors();
|
||||
g.setColor(colors[BACKGROUND_COLOR]);
|
||||
final int h = height - hsbSpace;
|
||||
final int w = width - vsbSpace;
|
||||
g.fillRect(0, 0, w, h);
|
||||
// paint rectangular region between scrollbars
|
||||
g.fillRect(w, h, vsbSpace, hsbSpace);
|
||||
if (MARGIN > 0) {
|
||||
draw3DRect(g, colors, 0, 0, w - 1, h - 1, false);
|
||||
}
|
||||
paintScrollBars(g, colors);
|
||||
}
|
||||
|
||||
|
||||
public void paint(Graphics g) {
|
||||
paintComponent(g);
|
||||
}
|
||||
|
||||
|
||||
void paintScrollBars(Graphics g, Color[] colors) {
|
||||
private void paintScrollBars(Graphics g, Color[] colors) {
|
||||
if (vsbSpace > 0) {
|
||||
paintVerScrollbar(g, colors, true);
|
||||
// paint the whole scrollbar
|
||||
@ -345,51 +349,32 @@ class XScrollPanePeer extends XComponentPeer implements ScrollPanePeer, XScrollb
|
||||
// paint the whole scrollbar
|
||||
}
|
||||
}
|
||||
|
||||
void repaintScrollBars() {
|
||||
Graphics g = getGraphics();
|
||||
Color colors[] = getGUIcolors();
|
||||
if (g != null) {
|
||||
paintScrollBars(g,colors);
|
||||
}
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
public void repaintScrollbarRequest(XScrollbar sb) {
|
||||
Graphics g = getGraphics();
|
||||
Color colors[] = getGUIcolors();
|
||||
if (g != null) {
|
||||
if (sb == vsb) {
|
||||
paintVerScrollbar(g,colors,true);
|
||||
}
|
||||
else if (sb == hsb) {
|
||||
paintHorScrollbar(g,colors,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the scrollpane.
|
||||
*/
|
||||
public void paintComponent(Graphics g) {
|
||||
|
||||
void repaintScrollBars() {
|
||||
Graphics g = getGraphics();
|
||||
Color colors[] = getGUIcolors();
|
||||
g.setColor(colors[BACKGROUND_COLOR]);
|
||||
int h = height - hsbSpace;
|
||||
int w = width - vsbSpace;
|
||||
|
||||
g.fillRect(0, 0, w, h);
|
||||
|
||||
// paint rectangular region between scrollbars
|
||||
g.fillRect(w, h, vsbSpace, hsbSpace);
|
||||
|
||||
if (MARGIN > 0) {
|
||||
draw3DRect(g, colors, 0, 0, w - 1, h - 1, false);
|
||||
if (g != null) {
|
||||
try {
|
||||
paintScrollBars(g, colors);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void repaintScrollbarRequest(XScrollbar sb) {
|
||||
Graphics g = getGraphics();
|
||||
Color colors[] = getGUIcolors();
|
||||
if (g != null) {
|
||||
try {
|
||||
if (sb == vsb) {
|
||||
paintVerScrollbar(g, colors, true);
|
||||
} else if (sb == hsb) {
|
||||
paintHorScrollbar(g, colors, true);
|
||||
}
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
paintScrollBars(g,colors);
|
||||
}
|
||||
|
||||
public void handleEvent(java.awt.AWTEvent e) {
|
||||
super.handleEvent(e);
|
||||
|
||||
|
||||
@ -90,18 +90,12 @@ class XScrollbarPeer extends XComponentPeer implements ScrollbarPeer, XScrollbar
|
||||
? new Dimension(getDefaultDimension(), DEFAULT_LENGTH)
|
||||
: new Dimension(DEFAULT_LENGTH, getDefaultDimension());
|
||||
}
|
||||
|
||||
public void repaint() {
|
||||
Graphics g = getGraphics();
|
||||
if (g != null) paint(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the scrollbar.
|
||||
*/
|
||||
public void paint(Graphics g) {
|
||||
Scrollbar sb = (Scrollbar)target;
|
||||
Color colors[] = getGUIcolors();
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
final Color[] colors = getGUIcolors();
|
||||
g.setColor(colors[BACKGROUND_COLOR]);
|
||||
tsb.paint(g, colors, true);
|
||||
// paint the whole scrollbar
|
||||
|
||||
@ -185,11 +185,8 @@ class XTextAreaPeer extends XComponentPeer implements TextAreaPeer {
|
||||
*/
|
||||
@Override
|
||||
public void pSetCursor(Cursor cursor, boolean ignoreSubComponents) {
|
||||
Point onScreen = getLocationOnScreen();
|
||||
if (ignoreSubComponents ||
|
||||
javaMouseEventHandler == null ||
|
||||
onScreen == null)
|
||||
{
|
||||
javaMouseEventHandler == null) {
|
||||
super.pSetCursor(cursor, true);
|
||||
return;
|
||||
}
|
||||
@ -197,6 +194,7 @@ class XTextAreaPeer extends XComponentPeer implements TextAreaPeer {
|
||||
Point cursorPos = new Point();
|
||||
((XGlobalCursorManager)XGlobalCursorManager.getCursorManager()).getCursorPos(cursorPos);
|
||||
|
||||
final Point onScreen = getLocationOnScreen();
|
||||
Point localPoint = new Point(cursorPos.x - onScreen.x, cursorPos.y - onScreen.y );
|
||||
|
||||
javaMouseEventHandler.setPointerToUnderPoint(localPoint);
|
||||
@ -300,15 +298,14 @@ class XTextAreaPeer extends XComponentPeer implements TextAreaPeer {
|
||||
* Paint the component
|
||||
* this method is called when the repaint instruction has been used
|
||||
*/
|
||||
|
||||
public void repaint() {
|
||||
if (textPane != null) {
|
||||
//textPane.validate();
|
||||
textPane.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
if (textPane != null) {
|
||||
textPane.paint(g);
|
||||
}
|
||||
|
||||
@ -370,12 +370,11 @@ public class XTextFieldPeer extends XComponentPeer implements TextFieldPeer {
|
||||
public void repaint() {
|
||||
if (xtext != null) xtext.repaint();
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
@Override
|
||||
void paintPeer(final Graphics g) {
|
||||
if (xtext != null) xtext.paint(g);
|
||||
}
|
||||
|
||||
|
||||
public void print(Graphics g) {
|
||||
if (xtext != null) {
|
||||
xtext.print(g);
|
||||
|
||||
@ -241,16 +241,19 @@ class XWarningWindow extends XWindow {
|
||||
Font getFont () {
|
||||
return ownerWindow.getFont();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repaint() {
|
||||
Rectangle bounds = getBounds();
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
paint(g, 0, 0, bounds.width, bounds.height);
|
||||
} finally {
|
||||
g.dispose();
|
||||
final Rectangle bounds = getBounds();
|
||||
final Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
paint(g, 0, 0, bounds.width, bounds.height);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleExposeEvent(XEvent xev) {
|
||||
super.handleExposeEvent(xev);
|
||||
@ -263,11 +266,13 @@ class XWarningWindow extends XWindow {
|
||||
SunToolkit.executeOnEventHandlerThread(target,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
paint(g, x, y, width, height);
|
||||
} finally {
|
||||
g.dispose();
|
||||
final Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
paint(g, x, y, width, height);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -502,9 +502,8 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
public boolean isEmbedded() {
|
||||
return embedded;
|
||||
}
|
||||
|
||||
public void repaint(int x,int y, int width, int height) {
|
||||
if (!isVisible()) {
|
||||
if (!isVisible() || getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
Graphics g = getGraphics();
|
||||
@ -517,12 +516,11 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void repaint() {
|
||||
if (!isVisible()) {
|
||||
void repaint() {
|
||||
if (!isVisible() || getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
Graphics g = getGraphics();
|
||||
final Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
paint(g);
|
||||
@ -531,10 +529,13 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void paint(Graphics g) {
|
||||
public void paint(final Graphics g) {
|
||||
// paint peer
|
||||
paintPeer(g);
|
||||
}
|
||||
|
||||
void paintPeer(final Graphics g) {
|
||||
}
|
||||
//used by Peers to avoid flickering withing paint()
|
||||
protected void flush(){
|
||||
XToolkit.awtLock();
|
||||
|
||||
@ -347,6 +347,11 @@ public class FontConfigManager {
|
||||
name = name.toLowerCase();
|
||||
|
||||
initFontConfigFonts(false);
|
||||
if (fontConfigFonts == null) {
|
||||
// This avoids an immediate NPE if fontconfig look up failed
|
||||
// but doesn't guarantee this is a recoverable situation.
|
||||
return null;
|
||||
}
|
||||
|
||||
FcCompFont fcInfo = null;
|
||||
for (int i=0; i<fontConfigFonts.length; i++) {
|
||||
|
||||
@ -183,7 +183,9 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer {
|
||||
*/
|
||||
private static native void initIDs();
|
||||
|
||||
// Needed for MenuComponentPeer.
|
||||
public void setFont(Font f) {
|
||||
private native void _setFont(Font f);
|
||||
|
||||
public void setFont(final Font f) {
|
||||
_setFont(f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@ package sun.awt.windows;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.peer.ScrollPanePeer;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.PeerEvent;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
@ -169,8 +171,6 @@ class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer {
|
||||
}
|
||||
}
|
||||
|
||||
native void setTypedValue(ScrollPaneAdjustable adjustable, int newpos, int type);
|
||||
|
||||
/*
|
||||
* Runnable for the ScrollEvent that performs the adjustment.
|
||||
*/
|
||||
@ -247,8 +247,9 @@ class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer {
|
||||
// Fix for 4075484 - consider type information when creating AdjustmentEvent
|
||||
// We can't just call adj.setValue() because it creates AdjustmentEvent with type=TRACK
|
||||
// Instead, we call private method setTypedValue of ScrollPaneAdjustable.
|
||||
// Because ScrollPaneAdjustable is in another package we should call it through native code.
|
||||
setTypedValue(adj, newpos, type);
|
||||
AWTAccessor.getScrollPaneAdjustableAccessor().setTypedValue(adj,
|
||||
newpos,
|
||||
type);
|
||||
|
||||
// Paint the exposed area right away. To do this - find
|
||||
// the heavyweight ancestor of the scroll child.
|
||||
|
||||
@ -396,12 +396,6 @@ LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message,
|
||||
|
||||
DASSERT(::IsWindow(hwnd));
|
||||
|
||||
// This branch is required for the proper work of AwtComponent::GetComponent() method
|
||||
// while hovering drop-down list
|
||||
if (message == WmAwtIsComponent) {
|
||||
return (LRESULT)TRUE;
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_LBUTTONDOWN: {
|
||||
DWORD curPos = ::GetMessagePos();
|
||||
|
||||
@ -364,6 +364,7 @@ AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
|
||||
AwtComponent *component =
|
||||
(AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||
DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
|
||||
DASSERT(!component || component->GetHWnd() == hWnd );
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
@ -119,6 +119,41 @@ done:
|
||||
return menu;
|
||||
}
|
||||
|
||||
void AwtMenu::UpdateLayout()
|
||||
{
|
||||
UpdateLayout(GetHMenu());
|
||||
RedrawMenuBar();
|
||||
}
|
||||
|
||||
void AwtMenu::UpdateLayout(const HMENU hmenu)
|
||||
{
|
||||
const int nMenuItemCount = ::GetMenuItemCount(hmenu);
|
||||
static MENUITEMINFO mii;
|
||||
for (int idx = 0; idx < nMenuItemCount; ++idx) {
|
||||
memset(&mii, 0, sizeof(mii));
|
||||
mii.cbSize = sizeof(mii);
|
||||
mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID
|
||||
| MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
|
||||
if (::GetMenuItemInfo(hmenu, idx, TRUE, &mii)) {
|
||||
VERIFY(::RemoveMenu(hmenu, idx, MF_BYPOSITION));
|
||||
VERIFY(::InsertMenuItem(hmenu, idx, TRUE, &mii));
|
||||
if (mii.hSubMenu != NULL) {
|
||||
UpdateLayout(mii.hSubMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AwtMenu::UpdateContainerLayout()
|
||||
{
|
||||
AwtMenu* menu = GetMenuContainer();
|
||||
if (menu != NULL) {
|
||||
menu->UpdateLayout();
|
||||
} else {
|
||||
UpdateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
AwtMenuBar* AwtMenu::GetMenuBar() {
|
||||
return (GetMenuContainer() == NULL) ? NULL : GetMenuContainer()->GetMenuBar();
|
||||
}
|
||||
|
||||
@ -72,6 +72,8 @@ public:
|
||||
virtual AwtMenuBar* GetMenuBar();
|
||||
|
||||
void AddSeparator();
|
||||
virtual void UpdateContainerLayout();
|
||||
void UpdateLayout();
|
||||
virtual void AddItem(AwtMenuItem *item);
|
||||
virtual void DeleteItem(UINT index);
|
||||
|
||||
@ -103,6 +105,7 @@ protected:
|
||||
virtual void RemoveCmdID() { /* do nothing */ }
|
||||
|
||||
private:
|
||||
void UpdateLayout(const HMENU hmenu);
|
||||
HMENU m_hMenu;
|
||||
};
|
||||
|
||||
|
||||
@ -198,7 +198,15 @@ void AwtMenuBar::DeleteItem(UINT index)
|
||||
if (hOwnerWnd != NULL) {
|
||||
VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE));
|
||||
}
|
||||
::DrawMenuBar(GetOwnerHWnd());
|
||||
RedrawMenuBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the menu changes after the system has created the window,
|
||||
* this function must be called to draw the changed menu bar.
|
||||
*/
|
||||
void AwtMenuBar::RedrawMenuBar() {
|
||||
VERIFY(::DrawMenuBar(GetOwnerHWnd()));
|
||||
}
|
||||
|
||||
LRESULT AwtMenuBar::WinThreadExecProc(ExecuteArgs * args)
|
||||
@ -232,7 +240,7 @@ void AwtMenuBar::_AddMenu(void *param)
|
||||
if (::IsWindow(m->GetOwnerHWnd()))
|
||||
{
|
||||
/* The menu was already created and added during peer creation -- redraw */
|
||||
::DrawMenuBar(m->GetOwnerHWnd());
|
||||
m->RedrawMenuBar();
|
||||
}
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
|
||||
@ -65,6 +65,7 @@ public:
|
||||
INLINE AwtFrame* GetFrame() { return m_frame; }
|
||||
|
||||
virtual HWND GetOwnerHWnd();
|
||||
virtual void RedrawMenuBar();
|
||||
|
||||
AwtMenuItem* GetItem(jobject target, long index);
|
||||
int CountItem(jobject menuBar);
|
||||
|
||||
@ -626,7 +626,7 @@ void AwtMenuItem::SetLabel(LPCTSTR sb)
|
||||
mii.dwTypeData = (LPTSTR)(*sb);
|
||||
|
||||
// find index by menu item id
|
||||
int nMenuItemCount = ::GetMenuItemCount(hMenu);;
|
||||
int nMenuItemCount = ::GetMenuItemCount(hMenu);
|
||||
int idx;
|
||||
for (idx = 0; (idx < nMenuItemCount); idx++) {
|
||||
memset(&mii1, 0, sizeof(MENUITEMINFO));
|
||||
@ -639,10 +639,7 @@ void AwtMenuItem::SetLabel(LPCTSTR sb)
|
||||
::RemoveMenu(hMenu, idx, MF_BYPOSITION);
|
||||
::InsertMenuItem(hMenu, idx, TRUE, &mii);
|
||||
|
||||
// Redraw menu bar if it was affected.
|
||||
if (menu->GetMenuBar() == menu) {
|
||||
::DrawMenuBar(menu->GetOwnerHWnd());
|
||||
}
|
||||
RedrawMenuBar();
|
||||
}
|
||||
|
||||
void AwtMenuItem::Enable(BOOL isEnabled)
|
||||
@ -658,10 +655,7 @@ void AwtMenuItem::Enable(BOOL isEnabled)
|
||||
MF_BYCOMMAND | (isEnabled ? MF_ENABLED : MF_GRAYED))
|
||||
!= 0xFFFFFFFF);
|
||||
|
||||
// Redraw menu bar if it was affected.
|
||||
if (menu->GetMenuBar() == menu) {
|
||||
::DrawMenuBar(menu->GetOwnerHWnd());
|
||||
}
|
||||
RedrawMenuBar();
|
||||
}
|
||||
|
||||
void AwtMenuItem::SetState(BOOL isChecked)
|
||||
@ -676,23 +670,31 @@ void AwtMenuItem::SetState(BOOL isChecked)
|
||||
MF_BYCOMMAND | (isChecked ? MF_CHECKED : MF_UNCHECKED))
|
||||
!= 0xFFFFFFFF);
|
||||
|
||||
// Redraw menu bar if it was affected.
|
||||
if (menu->GetMenuBar() == menu) {
|
||||
::DrawMenuBar(menu->GetOwnerHWnd());
|
||||
RedrawMenuBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the menu changes after the system has created the window,
|
||||
* this function must be called to draw the changed menu bar.
|
||||
*/
|
||||
void AwtMenuItem::RedrawMenuBar() {
|
||||
AwtMenu* menu = GetMenuContainer();
|
||||
if (menu != NULL && menu->GetMenuBar() == menu){
|
||||
menu->RedrawMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void AwtMenuItem::UpdateContainerLayout() {
|
||||
AwtMenu* menu = GetMenuContainer();
|
||||
if (menu != NULL) {
|
||||
DASSERT(menu != NULL && GetID() >= 0);
|
||||
menu->UpdateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT AwtMenuItem::WinThreadExecProc(ExecuteArgs * args)
|
||||
{
|
||||
switch( args->cmdId ) {
|
||||
case MENUITEM_SETLABEL:
|
||||
{
|
||||
LPCTSTR sb = (LPCTSTR)args->param1;
|
||||
DASSERT(!IsBadStringPtr(sb, 20));
|
||||
this->SetLabel(sb);
|
||||
}
|
||||
break;
|
||||
|
||||
case MENUITEM_ENABLE:
|
||||
{
|
||||
BOOL isEnabled = (BOOL)args->param1;
|
||||
@ -714,75 +716,98 @@ LRESULT AwtMenuItem::WinThreadExecProc(ExecuteArgs * args)
|
||||
return 0L;
|
||||
}
|
||||
|
||||
void AwtMenuItem::_SetLabel(void *param)
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
void AwtMenuItem::_SetLabel(void *param) {
|
||||
if (AwtToolkit::IsMainThread()) {
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
|
||||
SetLabelStruct *sls = (SetLabelStruct *)param;
|
||||
jobject self = sls->menuitem;
|
||||
jstring label = sls->label;
|
||||
SetLabelStruct *sls = (SetLabelStruct *)param;
|
||||
jobject self = sls->menuitem;
|
||||
jstring label = sls->label;
|
||||
|
||||
int badAlloc = 0;
|
||||
AwtMenuItem *m = NULL;
|
||||
int badAlloc = 0;
|
||||
AwtMenuItem *m = NULL;
|
||||
|
||||
PDATA pData;
|
||||
JNI_CHECK_PEER_GOTO(self, ret);
|
||||
m = (AwtMenuItem *)pData;
|
||||
PDATA pData;
|
||||
JNI_CHECK_PEER_GOTO(self, ret);
|
||||
m = (AwtMenuItem *)pData;
|
||||
// if (::IsWindow(m->GetOwnerHWnd()))
|
||||
{
|
||||
// fix for bug 4251036 MenuItem setLabel(null/"") behaves differently
|
||||
// under Win32 and Solaris
|
||||
jstring empty = NULL;
|
||||
if (JNU_IsNull(env, label))
|
||||
{
|
||||
empty = JNU_NewStringPlatform(env, TEXT(""));
|
||||
}
|
||||
LPCTSTR labelPtr;
|
||||
if (empty != NULL)
|
||||
{
|
||||
labelPtr = JNU_GetStringPlatformChars(env, empty, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
labelPtr = JNU_GetStringPlatformChars(env, label, 0);
|
||||
}
|
||||
if (labelPtr == NULL)
|
||||
{
|
||||
badAlloc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteArgs args;
|
||||
args.cmdId = MENUITEM_SETLABEL;
|
||||
args.param1 = (LPARAM)labelPtr;
|
||||
m->WinThreadExecProc(&args);
|
||||
// fix for bug 4251036 MenuItem setLabel(null/"") behaves differently
|
||||
// under Win32 and Solaris
|
||||
jstring empty = NULL;
|
||||
if (JNU_IsNull(env, label))
|
||||
{
|
||||
empty = JNU_NewStringPlatform(env, TEXT(""));
|
||||
}
|
||||
LPCTSTR labelPtr;
|
||||
if (empty != NULL)
|
||||
{
|
||||
JNU_ReleaseStringPlatformChars(env, empty, labelPtr);
|
||||
labelPtr = JNU_GetStringPlatformChars(env, empty, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
JNU_ReleaseStringPlatformChars(env, label, labelPtr);
|
||||
labelPtr = JNU_GetStringPlatformChars(env, label, 0);
|
||||
}
|
||||
if (labelPtr == NULL)
|
||||
{
|
||||
badAlloc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DASSERT(!IsBadStringPtr(labelPtr, 20));
|
||||
m->SetLabel(labelPtr);
|
||||
if (empty != NULL)
|
||||
{
|
||||
JNU_ReleaseStringPlatformChars(env, empty, labelPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
JNU_ReleaseStringPlatformChars(env, label, labelPtr);
|
||||
}
|
||||
}
|
||||
if (empty != NULL)
|
||||
{
|
||||
env->DeleteLocalRef(empty);
|
||||
}
|
||||
}
|
||||
if (empty != NULL)
|
||||
{
|
||||
env->DeleteLocalRef(empty);
|
||||
}
|
||||
}
|
||||
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
if (label != NULL)
|
||||
{
|
||||
env->DeleteGlobalRef(label);
|
||||
env->DeleteGlobalRef(self);
|
||||
if (label != NULL)
|
||||
{
|
||||
env->DeleteGlobalRef(label);
|
||||
}
|
||||
|
||||
delete sls;
|
||||
|
||||
if (badAlloc)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
} else {
|
||||
AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_SetLabel, param);
|
||||
}
|
||||
}
|
||||
|
||||
delete sls;
|
||||
void AwtMenuItem::_UpdateLayout(void *param)
|
||||
{
|
||||
if (AwtToolkit::IsMainThread()) {
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
|
||||
if (badAlloc)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
jobject self = (jobject)param;
|
||||
|
||||
AwtMenuItem *m = NULL;
|
||||
|
||||
PDATA pData;
|
||||
JNI_CHECK_PEER_GOTO(self, ret);
|
||||
|
||||
m = (AwtMenuItem *)pData;
|
||||
|
||||
m->UpdateContainerLayout();
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
} else {
|
||||
AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_UpdateLayout, param);
|
||||
}
|
||||
}
|
||||
|
||||
@ -883,8 +908,8 @@ extern "C" {
|
||||
|
||||
/*
|
||||
* Class: sun_awt_windows_WMenuItemPeer
|
||||
* Method: _setLabel
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
* Method: initIDs
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_windows_WMenuItemPeer_initIDs(JNIEnv *env, jclass cls)
|
||||
@ -925,6 +950,26 @@ Java_sun_awt_windows_WMenuItemPeer__1setLabel(JNIEnv *env, jobject self,
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_windows_WMenuItemPeer
|
||||
* Method: _setFont
|
||||
* Signature: (Ljava/awt/Font;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_windows_WMenuItemPeer__1setFont(JNIEnv *env, jobject self, jobject)
|
||||
{
|
||||
TRY;
|
||||
|
||||
jobject selfGlobalRef = env->NewGlobalRef(self);
|
||||
|
||||
// Current implementation of AwtMenuItem get font attribute from the peer
|
||||
// directly, so we ignore it here, but update current menu layout.
|
||||
AwtToolkit::GetInstance().SyncCall(AwtMenuItem::_UpdateLayout, selfGlobalRef);
|
||||
// selfGlobalRef is deleted in _UpdateLayout
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_windows_WMenuItemPeer
|
||||
* Method: create
|
||||
|
||||
@ -48,7 +48,6 @@ class AwtMenuItem : public AwtObject {
|
||||
public:
|
||||
// id's for methods executed on toolkit thread
|
||||
enum {
|
||||
MENUITEM_SETLABEL,
|
||||
MENUITEM_ENABLE,
|
||||
MENUITEM_SETSTATE,
|
||||
MENUITEM_LAST
|
||||
@ -78,7 +77,6 @@ public:
|
||||
|
||||
virtual LPCTSTR GetClassName();
|
||||
|
||||
void AwtMenuItem::LinkObjects(jobject peer);
|
||||
static AwtMenuItem* Create(jobject self, jobject menu);
|
||||
|
||||
INLINE AwtMenu* GetMenuContainer() { return m_menuContainer; }
|
||||
@ -148,6 +146,8 @@ public:
|
||||
|
||||
void SetLabel(LPCTSTR sb);
|
||||
virtual void Enable(BOOL isEnabled);
|
||||
virtual void UpdateContainerLayout();
|
||||
virtual void RedrawMenuBar();
|
||||
void SetState(BOOL isChecked);
|
||||
|
||||
/*
|
||||
@ -163,6 +163,7 @@ public:
|
||||
|
||||
// invoked on Toolkit thread
|
||||
static void _SetLabel(void *param);
|
||||
static void _UpdateLayout(void *param);
|
||||
|
||||
protected:
|
||||
AwtMenu* m_menuContainer; /* The menu object containing this item */
|
||||
|
||||
@ -4137,7 +4137,7 @@ Java_sun_awt_windows_WPrinterJob_initIDs(JNIEnv *env, jclass cls)
|
||||
|
||||
AwtPrintDialog::controlID =
|
||||
env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;");
|
||||
jclass printDialogPeerClass = env->FindClass("Lsun/awt/windows/WPrintDialogPeer;");
|
||||
jclass printDialogPeerClass = env->FindClass("sun/awt/windows/WPrintDialogPeer");
|
||||
AwtPrintDialog::setHWndMID =
|
||||
env->GetMethodID(printDialogPeerClass, "setHWnd", "(J)V");
|
||||
|
||||
|
||||
@ -808,29 +808,4 @@ Java_sun_awt_windows_WScrollPanePeer_setSpans(JNIEnv *env, jobject self,
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_windows_WScrollPanePeer
|
||||
* Method: setTypedValue
|
||||
* Signature: (Ljava/awt/ScrollPaneAdjustable;II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_windows_WScrollPanePeer_setTypedValue(JNIEnv *env, jobject peer, jobject adjustable, jint value, jint type)
|
||||
{
|
||||
// need this global ref to make the class unloadable (see 6500204)
|
||||
static jclass scrollPaneAdj;
|
||||
static jmethodID setTypedValueMID = 0;
|
||||
if (setTypedValueMID == NULL) {
|
||||
jclass clazz = env->FindClass("java/awt/ScrollPaneAdjustable");
|
||||
if (safe_ExceptionOccurred(env)) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
}
|
||||
setTypedValueMID = env->GetMethodID(clazz, "setTypedValue", "(II)V");
|
||||
scrollPaneAdj = (jclass) env->NewGlobalRef(clazz);
|
||||
env->DeleteLocalRef(clazz);
|
||||
DASSERT(setTypedValueMID != NULL);
|
||||
}
|
||||
env->CallVoidMethod(adjustable, setTypedValueMID, value, type);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
@ -1444,7 +1444,6 @@ BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg)
|
||||
AwtComponent* mouseComp =
|
||||
AwtComponent::GetComponent(hWndFromPoint);
|
||||
// Need extra copies for non-client area issues
|
||||
AwtComponent* mouseWheelComp = mouseComp;
|
||||
HWND hWndForWheel = hWndFromPoint;
|
||||
|
||||
// If the point under the mouse isn't in the client area,
|
||||
@ -1510,9 +1509,9 @@ BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg)
|
||||
*/
|
||||
|
||||
if (msg.message == WM_MOUSEWHEEL &&
|
||||
mouseWheelComp != NULL) { //i.e. mouse is over client area for this
|
||||
//window
|
||||
msg.hwnd = hWndForWheel;
|
||||
AwtToolkit::MainThread() == ::GetWindowThreadProcessId(hWndForWheel, NULL)) {
|
||||
//i.e. mouse is over client area for this window
|
||||
msg.hwnd = hWndForWheel;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 7050935
|
||||
@summary closed/java/awt/Choice/WheelEventsConsumed/WheelEventsConsumed.html fails on win32
|
||||
@author Oleg Pekhovskiy: area=awt-choice
|
||||
@run main ChoiceMouseWheelTest
|
||||
*/
|
||||
|
||||
import test.java.awt.regtesthelpers.Util;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class ChoiceMouseWheelTest extends Frame {
|
||||
|
||||
private volatile boolean itemChanged = false;
|
||||
private volatile boolean wheelMoved = false;
|
||||
private volatile boolean frameExited = false;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ChoiceMouseWheelTest();
|
||||
}
|
||||
|
||||
ChoiceMouseWheelTest() {
|
||||
super("ChoiceMouseWheelTest");
|
||||
setLayout(new FlowLayout());
|
||||
|
||||
Choice choice = new Choice();
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
for(Integer i = 0; i < 50; i++) {
|
||||
choice.add(i.toString());
|
||||
}
|
||||
|
||||
choice.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
itemChanged = true;
|
||||
}
|
||||
});
|
||||
choice.addMouseWheelListener(new MouseWheelListener() {
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
wheelMoved = true;
|
||||
}
|
||||
});
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
frameExited = true;
|
||||
}
|
||||
});
|
||||
|
||||
add(choice);
|
||||
setSize(200, 300);
|
||||
setVisible(true);
|
||||
toFront();
|
||||
|
||||
try {
|
||||
Robot robot = new Robot();
|
||||
robot.setAutoDelay(20);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
Point pt = choice.getLocationOnScreen();
|
||||
Dimension size = choice.getSize();
|
||||
int x = pt.x + size.width / 3;
|
||||
robot.mouseMove(x, pt.y + size.height / 2);
|
||||
|
||||
// Test mouse wheel over the choice
|
||||
String name = Toolkit.getDefaultToolkit().getClass().getName();
|
||||
if(!name.equals("sun.awt.X11.XToolkit")) { // mouse wheel doesn't work for the choice on X11, so skip it
|
||||
robot.mouseWheel(1);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
if(!wheelMoved || !itemChanged) {
|
||||
throw new RuntimeException("Mouse Wheel over the choice failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// Test mouse wheel over the drop-down list
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
Util.waitForIdle(robot);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
int y = getLocationOnScreen().y + getSize().height;
|
||||
while(!frameExited && y >= 0) { // move to the bottom of drop-down list
|
||||
robot.mouseMove(x, --y);
|
||||
Util.waitForIdle(robot);
|
||||
}
|
||||
|
||||
if(x < 0) {
|
||||
throw new RuntimeException("Could not enter drop-down list!");
|
||||
}
|
||||
|
||||
y -= choice.getHeight() / 2;
|
||||
robot.mouseMove(x, y); // move to the last visible item in the drop-down list
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
robot.mouseWheel(choice.getItemCount()); // wheel to the last item
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
// click the last item
|
||||
itemChanged = false;
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
Util.waitForIdle(robot);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
if(!itemChanged || choice.getSelectedIndex() != choice.getItemCount() - 1) {
|
||||
throw new RuntimeException("Mouse Wheel scroll position error!");
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
|
||||
} catch (AWTException e) {
|
||||
throw new RuntimeException("AWTException occurred - problem creating robot!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
301
jdk/test/java/awt/Component/PaintAll/PaintAll.java
Normal file
301
jdk/test/java/awt/Component/PaintAll/PaintAll.java
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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.Button;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Checkbox;
|
||||
import java.awt.Choice;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Label;
|
||||
import java.awt.List;
|
||||
import java.awt.Panel;
|
||||
import java.awt.ScrollPane;
|
||||
import java.awt.Scrollbar;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.TextField;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 6596915
|
||||
@summary Test Component.paintAll() method
|
||||
@author sergey.bylokhov@oracle.com: area=awt.component
|
||||
@run main PaintAll
|
||||
*/
|
||||
public class PaintAll {
|
||||
|
||||
private static volatile boolean lwPainted;
|
||||
private static volatile boolean buttonPainted;
|
||||
private static volatile boolean canvasPainted;
|
||||
private static volatile boolean checkboxPainted;
|
||||
private static volatile boolean choicePainted;
|
||||
private static volatile boolean containerPainted;
|
||||
private static volatile boolean framePainted;
|
||||
private static volatile boolean labelPainted;
|
||||
private static volatile boolean listPainted;
|
||||
private static volatile boolean panelPainted;
|
||||
private static volatile boolean scrollbarPainted;
|
||||
private static volatile boolean scrollPanePainted;
|
||||
private static volatile boolean textAreaPainted;
|
||||
private static volatile boolean textFieldPainted;
|
||||
|
||||
private static final Button buttonStub = new Button() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
buttonPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Canvas canvasStub = new Canvas() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
canvasPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Checkbox checkboxStub = new Checkbox() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
checkboxPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Choice choiceStub = new Choice() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
choicePainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Component lwComponentStub = new Component() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
lwPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Container containerStub = new Container() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
containerPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Frame frame = new Frame() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
super.paint(g);
|
||||
framePainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Label labelStub = new Label() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
labelPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final List listStub = new List() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
listPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Panel panelStub = new Panel() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
panelPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Scrollbar scrollbarStub = new Scrollbar() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
scrollbarPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final ScrollPane scrollPaneStub = new ScrollPane() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
scrollPanePainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final TextArea textAreaStub = new TextArea() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
textAreaPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final TextField textFieldStub = new TextField() {
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
textFieldPainted = true;
|
||||
}
|
||||
};
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
//Frame initialisation
|
||||
final BufferedImage graphicsProducer =
|
||||
new BufferedImage(BufferedImage.TYPE_INT_ARGB, 1, 1);
|
||||
|
||||
final Graphics g = graphicsProducer.getGraphics();
|
||||
|
||||
frame.setLayout(new GridLayout());
|
||||
frame.add(buttonStub);
|
||||
frame.add(canvasStub);
|
||||
frame.add(checkboxStub);
|
||||
frame.add(choiceStub);
|
||||
frame.add(lwComponentStub);
|
||||
frame.add(containerStub);
|
||||
frame.add(labelStub);
|
||||
frame.add(listStub);
|
||||
frame.add(panelStub);
|
||||
frame.add(scrollbarStub);
|
||||
frame.add(scrollPaneStub);
|
||||
frame.add(textAreaStub);
|
||||
frame.add(textFieldStub);
|
||||
frame.setSize(new Dimension(500, 500));
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
sleep();
|
||||
|
||||
//Check results.
|
||||
validation();
|
||||
|
||||
//Reset all flags to 'false'.
|
||||
initPaintedFlags();
|
||||
|
||||
//Tested method.
|
||||
frame.paintAll(g);
|
||||
sleep();
|
||||
|
||||
//Check results.
|
||||
validation();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private static void initPaintedFlags() {
|
||||
lwPainted = false;
|
||||
buttonPainted = false;
|
||||
canvasPainted = false;
|
||||
checkboxPainted = false;
|
||||
choicePainted = false;
|
||||
containerPainted = false;
|
||||
framePainted = false;
|
||||
labelPainted = false;
|
||||
listPainted = false;
|
||||
panelPainted = false;
|
||||
scrollbarPainted = false;
|
||||
scrollPanePainted = false;
|
||||
textAreaPainted = false;
|
||||
textFieldPainted = false;
|
||||
}
|
||||
|
||||
private static void validation() {
|
||||
if (!buttonPainted) {
|
||||
fail("Paint is not called a Button "
|
||||
+ "when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!canvasPainted) {
|
||||
fail("Paint is not called a Canvas "
|
||||
+ "when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!checkboxPainted) {
|
||||
fail("Paint is not called a Checkbox "
|
||||
+ "when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!choicePainted) {
|
||||
fail("Paint is not called a Choice "
|
||||
+ "when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!lwPainted) {
|
||||
fail("Paint is not called on a lightweight"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!containerPainted) {
|
||||
fail("Paint is not called on a Container"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!labelPainted) {
|
||||
fail("Paint is not called on a Label"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!listPainted) {
|
||||
fail("Paint is not called on a List"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!panelPainted) {
|
||||
fail("Paint is not called on a Panel"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!scrollbarPainted) {
|
||||
fail("Paint is not called on a Scrollbar"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!scrollPanePainted) {
|
||||
fail("Paint is not called on a ScrollPane"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!textAreaPainted) {
|
||||
fail("Paint is not called on a TextArea"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!textFieldPainted) {
|
||||
fail("Paint is not called on a TextField"
|
||||
+ " subcomponent when paintAll() invoked on a parent");
|
||||
}
|
||||
if (!framePainted) {
|
||||
fail("Paint is not called on a Frame when paintAll()");
|
||||
}
|
||||
}
|
||||
|
||||
private static void sleep() {
|
||||
((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
|
||||
try {
|
||||
Thread.sleep(500L);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void fail(final String message) {
|
||||
cleanup();
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
private static void cleanup() {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
@ -69,6 +69,7 @@ public class JavaDocExamplesTest {
|
||||
testDropArguments();
|
||||
testFilterArguments();
|
||||
testFoldArguments();
|
||||
testFoldArguments2();
|
||||
testMethodHandlesSummary();
|
||||
testAsSpreader();
|
||||
testAsCollector();
|
||||
@ -490,6 +491,47 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
|
||||
}}
|
||||
}
|
||||
|
||||
@Test public void testFoldArguments2() throws Throwable {
|
||||
{{
|
||||
{} /// JAVADOC
|
||||
// argument-based dispatch for methods of the form boolean x.___(y: String)
|
||||
Lookup lookup = publicLookup();
|
||||
// first, a tracing hack:
|
||||
MethodHandle println = lookup.findVirtual(java.io.PrintStream.class, "println", methodType(void.class, String.class));
|
||||
MethodHandle arrayToString = lookup.findStatic(Arrays.class, "toString", methodType(String.class, Object[].class));
|
||||
MethodHandle concat = lookup.findVirtual(String.class, "concat", methodType(String.class, String.class));
|
||||
MethodHandle arrayToString_DIS = filterReturnValue(arrayToString, concat.bindTo("DIS:"));
|
||||
MethodHandle arrayToString_INV = filterReturnValue(arrayToString, concat.bindTo("INV:"));
|
||||
MethodHandle printArgs_DIS = filterReturnValue(arrayToString_DIS, println.bindTo(System.out)).asVarargsCollector(Object[].class);
|
||||
MethodHandle printArgs_INV = filterReturnValue(arrayToString_INV, println.bindTo(System.out)).asVarargsCollector(Object[].class);
|
||||
// metaobject protocol:
|
||||
MethodType mtype = methodType(boolean.class, String.class);
|
||||
MethodHandle findVirtual = lookup.findVirtual(Lookup.class,
|
||||
"findVirtual", methodType(MethodHandle.class, Class.class, String.class, MethodType.class));
|
||||
MethodHandle getClass = lookup.findVirtual(Object.class,
|
||||
"getClass", methodType(Class.class));
|
||||
MethodHandle dispatch = findVirtual;
|
||||
dispatch = filterArguments(dispatch, 1, getClass);
|
||||
dispatch = insertArguments(dispatch, 3, mtype);
|
||||
dispatch = dispatch.bindTo(lookup);
|
||||
assertEquals(methodType(MethodHandle.class, Object.class, String.class), dispatch.type());
|
||||
MethodHandle invoker = invoker(mtype.insertParameterTypes(0, Object.class));
|
||||
// wrap tracing around the dispatch and invoke steps:
|
||||
dispatch = foldArguments(dispatch, printArgs_DIS.asType(dispatch.type().changeReturnType(void.class)));
|
||||
invoker = foldArguments(invoker, printArgs_INV.asType(invoker.type().changeReturnType(void.class)));
|
||||
invoker = dropArguments(invoker, 2, String.class); // ignore selector
|
||||
// compose the dispatcher and the invoker:
|
||||
MethodHandle invokeDispatched = foldArguments(invoker, dispatch);
|
||||
Object x = "football", y = new java.util.Scanner("bar");
|
||||
assert( (boolean) invokeDispatched.invokeExact(x, "startsWith", "foo"));
|
||||
assert(!(boolean) invokeDispatched.invokeExact(x, "startsWith", "#"));
|
||||
assert( (boolean) invokeDispatched.invokeExact(x, "endsWith", "all"));
|
||||
assert(!(boolean) invokeDispatched.invokeExact(x, "endsWith", "foo"));
|
||||
assert( (boolean) invokeDispatched.invokeExact(y, "hasNext", "[abc]+[rst]"));
|
||||
assert(!(boolean) invokeDispatched.invokeExact(y, "hasNext", "[123]+[789]"));
|
||||
}}
|
||||
}
|
||||
|
||||
/* ---- TEMPLATE ----
|
||||
@Test public void testFoo() throws Throwable {
|
||||
{{
|
||||
|
||||
@ -37,7 +37,6 @@ import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
|
||||
/**
|
||||
@ -45,10 +44,13 @@ import static org.junit.Assume.*;
|
||||
* @author jrose
|
||||
*/
|
||||
public class MethodHandlesTest {
|
||||
static final Class<?> THIS_CLASS = MethodHandlesTest.class;
|
||||
// How much output?
|
||||
static int verbosity = 0;
|
||||
static {
|
||||
String vstr = System.getProperty("test.java.lang.invoke.MethodHandlesTest.verbosity");
|
||||
String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity");
|
||||
if (vstr == null)
|
||||
vstr = System.getProperty(THIS_CLASS.getName()+".verbosity");
|
||||
if (vstr != null) verbosity = Integer.parseInt(vstr);
|
||||
}
|
||||
|
||||
@ -58,9 +60,9 @@ public class MethodHandlesTest {
|
||||
static boolean CAN_SKIP_WORKING = false;
|
||||
//static { CAN_SKIP_WORKING = true; }
|
||||
|
||||
// Set true to test more calls. If false, some tests are just
|
||||
// lookups, without exercising the actual method handle.
|
||||
static boolean DO_MORE_CALLS = true;
|
||||
// Set 'true' to do about 15x fewer tests, especially those redundant with RicochetTest.
|
||||
// This might be useful with -Xcomp stress tests that compile all method handles.
|
||||
static boolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY");
|
||||
|
||||
@Test
|
||||
public void testFirst() throws Throwable {
|
||||
@ -70,37 +72,37 @@ public class MethodHandlesTest {
|
||||
}
|
||||
|
||||
// current failures
|
||||
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
|
||||
@Test //@Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
|
||||
public void testFail_1() throws Throwable {
|
||||
// AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
|
||||
testSpreadArguments(int.class, 0, 6);
|
||||
}
|
||||
@Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
|
||||
@Test //@Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
|
||||
public void testFail_2() throws Throwable {
|
||||
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
|
||||
testSpreadArguments(Object.class, 0, 2);
|
||||
}
|
||||
@Test @Ignore("IllArgEx failure in call to ToGeneric.make")
|
||||
@Test //@Ignore("IllArgEx failure in call to ToGeneric.make")
|
||||
public void testFail_3() throws Throwable {
|
||||
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
|
||||
testSpreadArguments(int.class, 1, 2);
|
||||
}
|
||||
@Test @Ignore("IllArgEx failure in call to ToGeneric.make")
|
||||
@Test //@Ignore("IllArgEx failure in call to ToGeneric.make")
|
||||
public void testFail_4() throws Throwable {
|
||||
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
|
||||
testCollectArguments(int.class, 1, 2);
|
||||
}
|
||||
@Test @Ignore("cannot collect leading primitive types")
|
||||
@Test //@Ignore("cannot collect leading primitive types")
|
||||
public void testFail_5() throws Throwable {
|
||||
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
|
||||
testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
|
||||
}
|
||||
@Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
|
||||
@Test //@Ignore("should not insert arguments beyond MethodHandlePushLimit")
|
||||
public void testFail_6() throws Throwable {
|
||||
// ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
|
||||
testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
|
||||
}
|
||||
@Test @Ignore("permuteArguments has trouble with double slots")
|
||||
@Test //@Ignore("permuteArguments has trouble with double slots")
|
||||
public void testFail_7() throws Throwable {
|
||||
testPermuteArguments(new Object[]{10, 200L},
|
||||
new Class<?>[]{Integer.class, long.class},
|
||||
@ -123,7 +125,7 @@ public class MethodHandlesTest {
|
||||
testPermuteArguments(new Object[]{10, 200L, 5000L},
|
||||
new Class<?>[]{Integer.class, long.class, long.class},
|
||||
new int[]{2,2,0,1});
|
||||
testPermuteArguments(4, Integer.class, 2, long.class, 6);
|
||||
//testPermuteArguments(4, Integer.class, 2, long.class, 6);
|
||||
}
|
||||
static final int MAX_ARG_INCREASE = 3;
|
||||
|
||||
@ -167,7 +169,7 @@ public class MethodHandlesTest {
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
int posTests = allPosTests, negTests = allNegTests;
|
||||
if (verbosity >= 2 && (posTests | negTests) != 0) {
|
||||
if (verbosity >= 0 && (posTests | negTests) != 0) {
|
||||
System.out.println();
|
||||
if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
|
||||
if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
|
||||
@ -383,6 +385,13 @@ public class MethodHandlesTest {
|
||||
MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
|
||||
return target.asType(ttype2);
|
||||
}
|
||||
static MethodHandle addTrailingArgs(MethodHandle target, int nargs, Class<?> argClass) {
|
||||
int targetLen = target.type().parameterCount();
|
||||
int extra = (nargs - targetLen);
|
||||
if (extra <= 0) return target;
|
||||
List<Class<?>> fakeArgs = Collections.<Class<?>>nCopies(extra, argClass);
|
||||
return MethodHandles.dropArguments(target, targetLen, fakeArgs);
|
||||
}
|
||||
|
||||
// This lookup is good for all members in and under MethodHandlesTest.
|
||||
static final Lookup PRIVATE = MethodHandles.lookup();
|
||||
@ -419,6 +428,10 @@ public class MethodHandlesTest {
|
||||
public static Object s6(int x, long y) { return called("s6", x, y); }
|
||||
public static Object s7(float x, double y) { return called("s7", x, y); }
|
||||
|
||||
// for testing findConstructor:
|
||||
public Example(String x, int y) { this.name = x+y; called("Example.<init>", x, y); }
|
||||
public Example(int x, String y) { this.name = x+y; called("Example.<init>", x, y); }
|
||||
|
||||
static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial
|
||||
}
|
||||
static final Lookup EXAMPLE = Example.EXAMPLE;
|
||||
@ -521,7 +534,6 @@ public class MethodHandlesTest {
|
||||
if (!positive) return; // negative test failed as expected
|
||||
assertEquals(type, target.type());
|
||||
assertNameStringContains(target, name);
|
||||
if (!DO_MORE_CALLS && lookup != PRIVATE) return;
|
||||
Object[] args = randomArgs(params);
|
||||
printCalled(target, name, args);
|
||||
target.invokeWithArguments(args);
|
||||
@ -604,7 +616,6 @@ public class MethodHandlesTest {
|
||||
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
|
||||
assertEquals(typeWithSelf, target.type());
|
||||
assertNameStringContains(target, methodName);
|
||||
if (!DO_MORE_CALLS && lookup != PRIVATE) return;
|
||||
Object[] argsWithSelf = randomArgs(paramsWithSelf);
|
||||
if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc);
|
||||
printCalled(target, name, argsWithSelf);
|
||||
@ -666,13 +677,49 @@ public class MethodHandlesTest {
|
||||
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
|
||||
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
|
||||
assertNameStringContains(target, name);
|
||||
if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return;
|
||||
Object[] args = randomArgs(paramsWithSelf);
|
||||
printCalled(target, name, args);
|
||||
target.invokeWithArguments(args);
|
||||
assertCalled(name, args);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindConstructor() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("findConstructor");
|
||||
testFindConstructor(true, EXAMPLE, Example.class);
|
||||
testFindConstructor(true, EXAMPLE, Example.class, int.class);
|
||||
testFindConstructor(true, EXAMPLE, Example.class, String.class);
|
||||
}
|
||||
void testFindConstructor(boolean positive, Lookup lookup,
|
||||
Class<?> defc, Class<?>... params) throws Throwable {
|
||||
countTest(positive);
|
||||
MethodType type = MethodType.methodType(void.class, params);
|
||||
MethodHandle target = null;
|
||||
Exception noAccess = null;
|
||||
try {
|
||||
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" <init>"+type);
|
||||
target = lookup.findConstructor(defc, type);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
noAccess = ex;
|
||||
assertTrue(noAccess instanceof IllegalAccessException);
|
||||
}
|
||||
if (verbosity >= 3)
|
||||
System.out.println("findConstructor "+defc.getName()+".<init>/"+type+" => "+target
|
||||
+(target == null ? "" : target.type())
|
||||
+(noAccess == null ? "" : " !! "+noAccess));
|
||||
if (positive && noAccess != null) throw noAccess;
|
||||
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
|
||||
if (!positive) return; // negative test failed as expected
|
||||
assertEquals(type.changeReturnType(defc), target.type());
|
||||
Object[] args = randomArgs(params);
|
||||
printCalled(target, defc.getSimpleName(), args);
|
||||
Object obj = target.invokeWithArguments(args);
|
||||
if (!(defc == Example.class && params.length < 2))
|
||||
assertCalled(defc.getSimpleName()+".<init>", args);
|
||||
assertTrue("instance of "+defc.getName(), defc.isInstance(obj));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBind() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
@ -956,6 +1003,8 @@ public class MethodHandlesTest {
|
||||
|
||||
public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
|
||||
Object fieldRef, Object value, int testMode0) throws Throwable {
|
||||
if (verbosity >= 4)
|
||||
System.out.println("testAccessor"+Arrays.asList(positive, lookup, fieldRef, value, testMode0));
|
||||
boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
|
||||
int testMode = testMode0 & ~TEST_SETTER;
|
||||
boolean isStatic;
|
||||
@ -1150,7 +1199,7 @@ public class MethodHandlesTest {
|
||||
|
||||
public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
|
||||
countTest(true);
|
||||
if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
|
||||
if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
|
||||
Class<?> arrayType = array.getClass();
|
||||
Class<?> elemType = arrayType.getComponentType();
|
||||
MethodType expType = !testSetter
|
||||
@ -1326,9 +1375,10 @@ public class MethodHandlesTest {
|
||||
public void testPermuteArguments() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("permuteArguments");
|
||||
testPermuteArguments(4, Integer.class, 2, long.class, 6);
|
||||
if (CAN_TEST_LIGHTLY) return;
|
||||
testPermuteArguments(4, Integer.class, 2, String.class, 0);
|
||||
testPermuteArguments(6, Integer.class, 0, null, 30);
|
||||
//testPermuteArguments(4, Integer.class, 2, long.class, 6); // FIXME Fail_7
|
||||
}
|
||||
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
|
||||
if (verbosity >= 2)
|
||||
@ -1354,7 +1404,9 @@ public class MethodHandlesTest {
|
||||
casStep++;
|
||||
testPermuteArguments(args, types, outargs, numcases, casStep);
|
||||
numcases *= inargs;
|
||||
if (CAN_TEST_LIGHTLY && outargs < max-2) continue;
|
||||
if (dilution > 10 && outargs >= 4) {
|
||||
if (CAN_TEST_LIGHTLY) continue;
|
||||
int[] reorder = new int[outargs];
|
||||
// Do some special patterns, which we probably missed.
|
||||
// Replication of a single argument or argument pair.
|
||||
@ -1392,6 +1444,7 @@ public class MethodHandlesTest {
|
||||
reorder[i] = c % inargs;
|
||||
c /= inargs;
|
||||
}
|
||||
if (CAN_TEST_LIGHTLY && outargs >= 3 && (reorder[0] == reorder[1] || reorder[1] == reorder[2])) continue;
|
||||
testPermuteArguments(args, types, reorder);
|
||||
}
|
||||
}
|
||||
@ -1464,12 +1517,13 @@ public class MethodHandlesTest {
|
||||
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
|
||||
if (verbosity >= 3)
|
||||
System.out.println("spreadArguments "+argType);
|
||||
// FIXME: enable _adapter_spread_args and fix Fail_2
|
||||
for (int nargs = 0; nargs < 10; nargs++) {
|
||||
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1
|
||||
for (int pos = 0; pos < nargs; pos++) {
|
||||
if (argType == int.class && pos > 0) continue; // FIXME Fail_3
|
||||
testSpreadArguments(argType, pos, nargs);
|
||||
for (int nargs = 0; nargs < 50; nargs++) {
|
||||
if (CAN_TEST_LIGHTLY && nargs > 7) break;
|
||||
for (int pos = 0; pos <= nargs; pos++) {
|
||||
if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
|
||||
if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
|
||||
continue;
|
||||
testSpreadArguments(argType, pos, nargs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1557,9 +1611,12 @@ public class MethodHandlesTest {
|
||||
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
|
||||
if (verbosity >= 3)
|
||||
System.out.println("collectArguments "+argType);
|
||||
for (int nargs = 0; nargs < 10; nargs++) {
|
||||
for (int pos = 0; pos < nargs; pos++) {
|
||||
if (argType == int.class) continue; // FIXME Fail_4
|
||||
for (int nargs = 0; nargs < 50; nargs++) {
|
||||
if (CAN_TEST_LIGHTLY && nargs > 7) break;
|
||||
for (int pos = 0; pos <= nargs; pos++) {
|
||||
if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
|
||||
if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
|
||||
continue;
|
||||
testCollectArguments(argType, pos, nargs);
|
||||
}
|
||||
}
|
||||
@ -1593,10 +1650,15 @@ public class MethodHandlesTest {
|
||||
public void testInsertArguments() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("insertArguments");
|
||||
for (int nargs = 0; nargs <= 4; nargs++) {
|
||||
for (int ins = 0; ins <= 4; ins++) {
|
||||
if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6
|
||||
for (int nargs = 0; nargs < 50; nargs++) {
|
||||
if (CAN_TEST_LIGHTLY && nargs > 7) break;
|
||||
for (int ins = 0; ins <= nargs; ins++) {
|
||||
if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3)
|
||||
continue;
|
||||
for (int pos = 0; pos <= nargs; pos++) {
|
||||
if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
|
||||
continue;
|
||||
if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
|
||||
testInsertArguments(nargs, pos, ins);
|
||||
}
|
||||
}
|
||||
@ -1634,8 +1696,8 @@ public class MethodHandlesTest {
|
||||
for (Class<?> rtype : new Class[] { Object.class,
|
||||
List.class,
|
||||
int.class,
|
||||
//byte.class, //FIXME: add this
|
||||
//long.class, //FIXME: add this
|
||||
byte.class,
|
||||
long.class,
|
||||
CharSequence.class,
|
||||
String.class }) {
|
||||
testFilterReturnValue(nargs, rtype);
|
||||
@ -1780,6 +1842,7 @@ public class MethodHandlesTest {
|
||||
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
|
||||
Set<MethodType> done = new HashSet<MethodType>();
|
||||
for (int i = 0; i <= 6; i++) {
|
||||
if (CAN_TEST_LIGHTLY && i > 3) break;
|
||||
MethodType gtype = MethodType.genericMethodType(i);
|
||||
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
|
||||
for (int j = -1; j < i; j++) {
|
||||
@ -1790,7 +1853,6 @@ public class MethodHandlesTest {
|
||||
continue;
|
||||
else
|
||||
type = type.changeParameterType(j, argType);
|
||||
if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
|
||||
if (done.add(type))
|
||||
testInvokers(type);
|
||||
MethodType vtype = type.changeReturnType(void.class);
|
||||
@ -1890,6 +1952,7 @@ public class MethodHandlesTest {
|
||||
}
|
||||
for (int k = 0; k <= nargs; k++) {
|
||||
// varargs invoker #0..N
|
||||
if (CAN_TEST_LIGHTLY && (k > 1 || k < nargs - 1)) continue;
|
||||
countTest();
|
||||
calledLog.clear();
|
||||
inv = MethodHandles.spreadInvoker(type, k);
|
||||
@ -1933,6 +1996,7 @@ public class MethodHandlesTest {
|
||||
}
|
||||
|
||||
private static final String MISSING_ARG = "missingArg";
|
||||
private static final String MISSING_ARG_2 = "missingArg#2";
|
||||
static Object targetIfEquals() {
|
||||
return called("targetIfEquals");
|
||||
}
|
||||
@ -1968,28 +2032,39 @@ public class MethodHandlesTest {
|
||||
public void testGuardWithTest() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("guardWithTest");
|
||||
for (int nargs = 0; nargs <= 3; nargs++) {
|
||||
if (nargs != 2) continue; // FIXME: test more later
|
||||
for (int nargs = 0; nargs <= 50; nargs++) {
|
||||
if (CAN_TEST_LIGHTLY && nargs > 7) break;
|
||||
testGuardWithTest(nargs, Object.class);
|
||||
testGuardWithTest(nargs, String.class);
|
||||
}
|
||||
}
|
||||
void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
|
||||
testGuardWithTest(nargs, 0, argClass);
|
||||
if (nargs <= 5 || nargs % 10 == 3) {
|
||||
for (int testDrops = 1; testDrops <= nargs; testDrops++)
|
||||
testGuardWithTest(nargs, testDrops, argClass);
|
||||
}
|
||||
}
|
||||
void testGuardWithTest(int nargs, int testDrops, Class<?> argClass) throws Throwable {
|
||||
countTest();
|
||||
int nargs1 = Math.min(3, nargs);
|
||||
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
|
||||
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs));
|
||||
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs));
|
||||
while (test.type().parameterCount() < nargs)
|
||||
test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
|
||||
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1));
|
||||
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1));
|
||||
while (test.type().parameterCount() > nargs)
|
||||
// 0: test = constant(MISSING_ARG.equals(MISSING_ARG))
|
||||
// 1: test = lambda (_) MISSING_ARG.equals(_)
|
||||
test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
|
||||
if (argClass != Object.class) {
|
||||
test = changeArgTypes(test, argClass);
|
||||
target = changeArgTypes(target, argClass);
|
||||
fallback = changeArgTypes(fallback, argClass);
|
||||
}
|
||||
MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
|
||||
assertEquals(target.type(), mh.type());
|
||||
int testArgs = nargs - testDrops;
|
||||
assert(testArgs >= 0);
|
||||
test = addTrailingArgs(test, Math.min(testArgs, nargs), argClass);
|
||||
target = addTrailingArgs(target, nargs, argClass);
|
||||
fallback = addTrailingArgs(fallback, nargs, argClass);
|
||||
Object[][] argLists = {
|
||||
{ },
|
||||
{ "foo" }, { MISSING_ARG },
|
||||
@ -1997,7 +2072,19 @@ public class MethodHandlesTest {
|
||||
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" }
|
||||
};
|
||||
for (Object[] argList : argLists) {
|
||||
if (argList.length != nargs) continue;
|
||||
Object[] argList1 = argList;
|
||||
if (argList.length != nargs) {
|
||||
if (argList.length != nargs1) continue;
|
||||
argList1 = Arrays.copyOf(argList, nargs);
|
||||
Arrays.fill(argList1, nargs1, nargs, MISSING_ARG_2);
|
||||
}
|
||||
MethodHandle test1 = test;
|
||||
if (test1.type().parameterCount() > testArgs) {
|
||||
int pc = test1.type().parameterCount();
|
||||
test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc));
|
||||
}
|
||||
MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback);
|
||||
assertEquals(target.type(), mh.type());
|
||||
boolean equals;
|
||||
switch (nargs) {
|
||||
case 0: equals = true; break;
|
||||
@ -2007,7 +2094,7 @@ public class MethodHandlesTest {
|
||||
String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
|
||||
if (verbosity >= 3)
|
||||
System.out.println(logEntry(willCall, argList));
|
||||
Object result = mh.invokeWithArguments(argList);
|
||||
Object result = mh.invokeWithArguments(argList1);
|
||||
assertCalled(willCall, argList);
|
||||
}
|
||||
}
|
||||
@ -2016,49 +2103,102 @@ public class MethodHandlesTest {
|
||||
public void testCatchException() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("catchException");
|
||||
for (int nargs = 2; nargs <= 6; nargs++) {
|
||||
for (int ti = 0; ti <= 1; ti++) {
|
||||
boolean throwIt = (ti != 0);
|
||||
testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
|
||||
testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
|
||||
testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
|
||||
for (int nargs = 0; nargs < 40; nargs++) {
|
||||
if (CAN_TEST_LIGHTLY && nargs > 7) break;
|
||||
for (int throwMode = 0; throwMode < THROW_MODE_LIMIT; throwMode++) {
|
||||
testCatchException(int.class, new ClassCastException("testing"), throwMode, nargs);
|
||||
if (CAN_TEST_LIGHTLY && nargs > 3) continue;
|
||||
testCatchException(void.class, new java.io.IOException("testing"), throwMode, nargs);
|
||||
testCatchException(String.class, new LinkageError("testing"), throwMode, nargs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4;
|
||||
|
||||
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable {
|
||||
testCatchException(returnType, thrown, throwMode, nargs, 0);
|
||||
if (nargs <= 5 || nargs % 10 == 3) {
|
||||
for (int catchDrops = 1; catchDrops <= nargs; catchDrops++)
|
||||
testCatchException(returnType, thrown, throwMode, nargs, catchDrops);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Throwable>
|
||||
Object throwOrReturn(Object normal, T exception) throws T {
|
||||
if (exception != null) throw exception;
|
||||
if (exception != null) {
|
||||
called("throwOrReturn/throw", normal, exception);
|
||||
throw exception;
|
||||
}
|
||||
called("throwOrReturn/normal", normal, exception);
|
||||
return normal;
|
||||
}
|
||||
private int fakeIdentityCount;
|
||||
private Object fakeIdentity(Object x) {
|
||||
System.out.println("should throw through this!");
|
||||
fakeIdentityCount++;
|
||||
return x;
|
||||
}
|
||||
|
||||
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
|
||||
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable {
|
||||
countTest();
|
||||
if (verbosity >= 3)
|
||||
System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
|
||||
System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops);
|
||||
Class<? extends Throwable> exType = thrown.getClass();
|
||||
if (throwMode > THROW_CAUGHT) thrown = new UnsupportedOperationException("do not catch this");
|
||||
MethodHandle throwOrReturn
|
||||
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
|
||||
MethodType.methodType(Object.class, Object.class, Throwable.class));
|
||||
if (throwMode == THROW_THROUGH_ADAPTER) {
|
||||
MethodHandle fakeIdentity
|
||||
= PRIVATE.findVirtual(MethodHandlesTest.class, "fakeIdentity",
|
||||
MethodType.methodType(Object.class, Object.class)).bindTo(this);
|
||||
for (int i = 0; i < 10; i++)
|
||||
throwOrReturn = MethodHandles.filterReturnValue(throwOrReturn, fakeIdentity);
|
||||
}
|
||||
int nargs1 = Math.max(2, nargs);
|
||||
MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
|
||||
while (thrower.type().parameterCount() < nargs)
|
||||
thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
|
||||
MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
|
||||
MethodHandle target = MethodHandles.catchException(thrower,
|
||||
thrown.getClass(), catcher);
|
||||
assertEquals(thrower.type(), target.type());
|
||||
//System.out.println("catching with "+target+" : "+throwOrReturn);
|
||||
thrower = addTrailingArgs(thrower, nargs, Object.class);
|
||||
int catchArgc = 1 + nargs - catchDrops;
|
||||
MethodHandle catcher = varargsList(catchArgc).asType(MethodType.genericMethodType(catchArgc));
|
||||
Object[] args = randomArgs(nargs, Object.class);
|
||||
args[1] = (throwIt ? thrown : null);
|
||||
Object returned = target.invokeWithArguments(args);
|
||||
Object arg0 = MISSING_ARG;
|
||||
Object arg1 = (throwMode == THROW_NOTHING) ? (Throwable) null : thrown;
|
||||
if (nargs > 0) arg0 = args[0];
|
||||
if (nargs > 1) args[1] = arg1;
|
||||
assertEquals(nargs1, thrower.type().parameterCount());
|
||||
if (nargs < nargs1) {
|
||||
Object[] appendArgs = { arg0, arg1 };
|
||||
appendArgs = Arrays.copyOfRange(appendArgs, nargs, nargs1);
|
||||
thrower = MethodHandles.insertArguments(thrower, nargs, appendArgs);
|
||||
}
|
||||
assertEquals(nargs, thrower.type().parameterCount());
|
||||
MethodHandle target = MethodHandles.catchException(thrower, exType, catcher);
|
||||
assertEquals(thrower.type(), target.type());
|
||||
assertEquals(nargs, target.type().parameterCount());
|
||||
//System.out.println("catching with "+target+" : "+throwOrReturn);
|
||||
Object returned;
|
||||
try {
|
||||
returned = target.invokeWithArguments(args);
|
||||
} catch (Throwable ex) {
|
||||
assertSame("must get the out-of-band exception", thrown, ex);
|
||||
if (throwMode <= THROW_CAUGHT)
|
||||
assertEquals(THROW_UNCAUGHT, throwMode);
|
||||
returned = ex;
|
||||
}
|
||||
assertCalled("throwOrReturn/"+(throwMode == THROW_NOTHING ? "normal" : "throw"), arg0, arg1);
|
||||
//System.out.println("return from "+target+" : "+returned);
|
||||
if (!throwIt) {
|
||||
assertSame(args[0], returned);
|
||||
} else {
|
||||
if (throwMode == THROW_NOTHING) {
|
||||
assertSame(arg0, returned);
|
||||
} else if (throwMode == THROW_CAUGHT) {
|
||||
List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
|
||||
// catcher receives an initial subsequence of target arguments:
|
||||
catchArgs.subList(nargs - catchDrops, nargs).clear();
|
||||
// catcher also receives the exception, prepended:
|
||||
catchArgs.add(0, thrown);
|
||||
assertEquals(catchArgs, returned);
|
||||
}
|
||||
assertEquals(0, fakeIdentityCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -2092,6 +2232,48 @@ public class MethodHandlesTest {
|
||||
assertSame(thrown, caught);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterfaceCast() throws Throwable {
|
||||
for (Class<?> ctype : new Class<?>[]{ Object.class, String.class, CharSequence.class, Number.class, Iterable.class}) {
|
||||
testInterfaceCast(ctype, false, false);
|
||||
testInterfaceCast(ctype, true, false);
|
||||
testInterfaceCast(ctype, false, true);
|
||||
testInterfaceCast(ctype, true, true);
|
||||
}
|
||||
}
|
||||
public void testInterfaceCast(Class<?> ctype, boolean doret, boolean docast) throws Throwable {
|
||||
String str = "normal return value";
|
||||
MethodHandle mh = MethodHandles.identity(String.class);
|
||||
MethodType mt = mh.type();
|
||||
if (doret) mt = mt.changeReturnType(ctype);
|
||||
else mt = mt.changeParameterType(0, ctype);
|
||||
if (docast) mh = MethodHandles.explicitCastArguments(mh, mt);
|
||||
else mh = mh.asType(mt);
|
||||
// this bit is needed to make the interface types disappear for invokeWithArguments:
|
||||
mh = MethodHandles.explicitCastArguments(mh, mt.generic());
|
||||
boolean expectFail = !ctype.isInstance(str);
|
||||
if (ctype.isInterface()) {
|
||||
// special rules: interfaces slide by more frequently
|
||||
if (docast || !doret) expectFail = false;
|
||||
}
|
||||
Object res;
|
||||
try {
|
||||
res = mh.invokeWithArguments(str);
|
||||
} catch (Exception ex) {
|
||||
res = ex;
|
||||
}
|
||||
boolean sawFail = !(res instanceof String);
|
||||
if (sawFail != expectFail) {
|
||||
System.out.println("*** testInterfaceCast: "+mh+" was "+mt+" => "+res+(docast ? " (explicitCastArguments)" : ""));
|
||||
}
|
||||
if (!sawFail) {
|
||||
assertFalse(res.toString(), expectFail);
|
||||
assertEquals(str, res);
|
||||
} else {
|
||||
assertTrue(res.toString(), expectFail);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCastFailure() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
@ -2234,47 +2416,106 @@ public class MethodHandlesTest {
|
||||
static void runForRunnable() {
|
||||
called("runForRunnable");
|
||||
}
|
||||
private interface Fooable {
|
||||
Object foo(Fooable x, Object y);
|
||||
// this is for randomArg:
|
||||
public class Impl implements Fooable {
|
||||
public Object foo(Fooable x, Object y) {
|
||||
throw new RuntimeException("do not call");
|
||||
}
|
||||
final String name;
|
||||
public Impl() { name = "Fooable#"+nextArg(); }
|
||||
@Override public String toString() { return name; }
|
||||
}
|
||||
public interface Fooable {
|
||||
// overloads:
|
||||
Object foo(Object x, String y);
|
||||
List foo(String x, int y);
|
||||
Object foo(String x);
|
||||
}
|
||||
static Object fooForFooable(Fooable x, Object y) {
|
||||
return called("fooForFooable", x, y);
|
||||
static Object fooForFooable(String x, Object... y) {
|
||||
return called("fooForFooable/"+x, y);
|
||||
}
|
||||
private static class MyCheckedException extends Exception {
|
||||
public static class MyCheckedException extends Exception {
|
||||
}
|
||||
private interface WillThrow {
|
||||
public interface WillThrow {
|
||||
void willThrow() throws MyCheckedException;
|
||||
}
|
||||
/*non-public*/ interface PrivateRunnable {
|
||||
public void run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsInstance() throws Throwable {
|
||||
public void testAsInterfaceInstance() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("testAsInterfaceInstance");
|
||||
Lookup lookup = MethodHandles.lookup();
|
||||
// test typical case: Runnable.run
|
||||
{
|
||||
countTest();
|
||||
if (verbosity >= 2) System.out.println("Runnable");
|
||||
MethodType mt = MethodType.methodType(void.class);
|
||||
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
|
||||
Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh);
|
||||
proxy.run();
|
||||
assertCalled("runForRunnable");
|
||||
}
|
||||
// well known single-name overloaded interface: Appendable.append
|
||||
{
|
||||
MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
|
||||
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
|
||||
Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh);
|
||||
Object[] args = randomArgs(mt.parameterArray());
|
||||
Object result = proxy.foo((Fooable) args[0], args[1]);
|
||||
assertCalled("fooForFooable", args);
|
||||
assertEquals(result, logEntry("fooForFooable", args));
|
||||
countTest();
|
||||
if (verbosity >= 2) System.out.println("Appendable");
|
||||
ArrayList<List> appendResults = new ArrayList<List>();
|
||||
MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class));
|
||||
append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type
|
||||
MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
|
||||
MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class);
|
||||
Appendable proxy = MethodHandleProxies.asInterfaceInstance(Appendable.class, mh);
|
||||
proxy.append("one");
|
||||
proxy.append("two", 3, 4);
|
||||
proxy.append('5');
|
||||
assertEquals(Arrays.asList(Arrays.asList("one"),
|
||||
Arrays.asList("two", 3, 4),
|
||||
Arrays.asList('5')),
|
||||
appendResults);
|
||||
if (verbosity >= 3) System.out.println("appendResults="+appendResults);
|
||||
appendResults.clear();
|
||||
Formatter formatter = new Formatter(proxy);
|
||||
String fmt = "foo str=%s char='%c' num=%d";
|
||||
Object[] fmtArgs = { "str!", 'C', 42 };
|
||||
String expect = String.format(fmt, fmtArgs);
|
||||
formatter.format(fmt, fmtArgs);
|
||||
String actual = "";
|
||||
if (verbosity >= 3) System.out.println("appendResults="+appendResults);
|
||||
for (List l : appendResults) {
|
||||
Object x = l.get(0);
|
||||
switch (l.size()) {
|
||||
case 1: actual += x; continue;
|
||||
case 3: actual += ((String)x).substring((int)l.get(1), (int)l.get(2)); continue;
|
||||
}
|
||||
actual += l;
|
||||
}
|
||||
if (verbosity >= 3) System.out.println("expect="+expect);
|
||||
if (verbosity >= 3) System.out.println("actual="+actual);
|
||||
assertEquals(expect, actual);
|
||||
}
|
||||
// test case of an single name which is overloaded: Fooable.foo(...)
|
||||
{
|
||||
if (verbosity >= 2) System.out.println("Fooable");
|
||||
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable",
|
||||
MethodType.methodType(Object.class, String.class, Object[].class));
|
||||
Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh);
|
||||
for (Method m : Fooable.class.getDeclaredMethods()) {
|
||||
countTest();
|
||||
assertSame("foo", m.getName());
|
||||
if (verbosity > 3)
|
||||
System.out.println("calling "+m);
|
||||
MethodHandle invoker = lookup.unreflect(m);
|
||||
MethodType mt = invoker.type();
|
||||
Class<?>[] types = mt.parameterArray();
|
||||
types[0] = int.class; // placeholder
|
||||
Object[] args = randomArgs(types);
|
||||
args[0] = proxy;
|
||||
if (verbosity > 3)
|
||||
System.out.println("calling "+m+" on "+Arrays.asList(args));
|
||||
Object result = invoker.invokeWithArguments(args);
|
||||
if (verbosity > 4)
|
||||
System.out.println("result = "+result);
|
||||
String name = "fooForFooable/"+args[1];
|
||||
Object[] argTail = Arrays.copyOfRange(args, 2, args.length);
|
||||
assertCalled(name, argTail);
|
||||
assertEquals(result, logEntry(name, argTail));
|
||||
}
|
||||
}
|
||||
// test processing of thrown exceptions:
|
||||
for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
|
||||
new InternalError("ok"),
|
||||
new Throwable("fail"),
|
||||
@ -2285,11 +2526,12 @@ public class MethodHandlesTest {
|
||||
mh = MethodHandles.insertArguments(mh, 0, ex);
|
||||
WillThrow proxy = MethodHandleProxies.asInterfaceInstance(WillThrow.class, mh);
|
||||
try {
|
||||
countTest();
|
||||
proxy.willThrow();
|
||||
System.out.println("Failed to throw: "+ex);
|
||||
assertTrue(false);
|
||||
} catch (Throwable ex1) {
|
||||
if (verbosity > 2) {
|
||||
if (verbosity > 3) {
|
||||
System.out.println("throw "+ex);
|
||||
System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
|
||||
}
|
||||
@ -2300,23 +2542,84 @@ public class MethodHandlesTest {
|
||||
assertSame("must pass declared exception out without wrapping", ex, ex1);
|
||||
} else {
|
||||
assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
|
||||
if (!(ex1 instanceof UndeclaredThrowableException) || ex1.getCause() != ex) {
|
||||
ex1.printStackTrace();
|
||||
}
|
||||
assertSame(ex, ex1.getCause());
|
||||
UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
|
||||
assertSame(ex, utex.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Test error checking:
|
||||
for (Class<?> nonSAM : new Class[] { Object.class,
|
||||
// Test error checking on bad interfaces:
|
||||
for (Class<?> nonSMI : new Class[] { Object.class,
|
||||
String.class,
|
||||
CharSequence.class,
|
||||
java.io.Serializable.class,
|
||||
PrivateRunnable.class,
|
||||
Example.class }) {
|
||||
if (verbosity > 2) System.out.println(nonSMI.getName());
|
||||
try {
|
||||
MethodHandleProxies.asInterfaceInstance(nonSAM, varargsArray(0));
|
||||
System.out.println("Failed to throw");
|
||||
assertTrue(false);
|
||||
countTest(false);
|
||||
MethodHandleProxies.asInterfaceInstance(nonSMI, varargsArray(0));
|
||||
assertTrue("Failed to throw on "+nonSMI.getName(), false);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
if (verbosity > 2) System.out.println(nonSMI.getSimpleName()+": "+ex);
|
||||
// Object: java.lang.IllegalArgumentException:
|
||||
// not a public interface: java.lang.Object
|
||||
// String: java.lang.IllegalArgumentException:
|
||||
// not a public interface: java.lang.String
|
||||
// CharSequence: java.lang.IllegalArgumentException:
|
||||
// not a single-method interface: java.lang.CharSequence
|
||||
// Serializable: java.lang.IllegalArgumentException:
|
||||
// not a single-method interface: java.io.Serializable
|
||||
// PrivateRunnable: java.lang.IllegalArgumentException:
|
||||
// not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable
|
||||
// Example: java.lang.IllegalArgumentException:
|
||||
// not a public interface: test.java.lang.invoke.MethodHandlesTest$Example
|
||||
}
|
||||
}
|
||||
// Test error checking on interfaces with the wrong method type:
|
||||
for (Class<?> intfc : new Class[] { Runnable.class /*arity 0*/,
|
||||
Fooable.class /*arity 1 & 2*/ }) {
|
||||
int badArity = 1; // known to be incompatible
|
||||
if (verbosity > 2) System.out.println(intfc.getName());
|
||||
try {
|
||||
countTest(false);
|
||||
MethodHandleProxies.asInterfaceInstance(intfc, varargsArray(badArity));
|
||||
assertTrue("Failed to throw on "+intfc.getName(), false);
|
||||
} catch (WrongMethodTypeException ex) {
|
||||
if (verbosity > 2) System.out.println(intfc.getSimpleName()+": "+ex);
|
||||
// Runnable: java.lang.invoke.WrongMethodTypeException:
|
||||
// cannot convert MethodHandle(Object)Object[] to ()void
|
||||
// Fooable: java.lang.invoke.WrongMethodTypeException:
|
||||
// cannot convert MethodHandle(Object)Object[] to (Object,String)Object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunnableProxy() throws Throwable {
|
||||
if (CAN_SKIP_WORKING) return;
|
||||
startTest("testRunnableProxy");
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class));
|
||||
Runnable r = MethodHandleProxies.asInterfaceInstance(Runnable.class, run);
|
||||
testRunnableProxy(r);
|
||||
assertCalled("runForRunnable");
|
||||
}
|
||||
private static void testRunnableProxy(Runnable r) {
|
||||
//7058630: JSR 292 method handle proxy violates contract for Object methods
|
||||
r.run();
|
||||
Object o = r;
|
||||
r = null;
|
||||
boolean eq = (o == o);
|
||||
int hc = System.identityHashCode(o);
|
||||
String st = o.getClass().getName() + "@" + Integer.toHexString(hc);
|
||||
Object expect = Arrays.asList(st, eq, hc);
|
||||
if (verbosity >= 2) System.out.println("expect st/eq/hc = "+expect);
|
||||
Object actual = Arrays.asList(o.toString(), o.equals(o), o.hashCode());
|
||||
if (verbosity >= 2) System.out.println("actual st/eq/hc = "+actual);
|
||||
assertEquals(expect, actual);
|
||||
}
|
||||
}
|
||||
// Local abbreviated copy of sun.invoke.util.ValueConversions
|
||||
@ -2380,8 +2683,7 @@ class ValueConversions {
|
||||
public static MethodHandle varargsArray(int nargs) {
|
||||
if (nargs < ARRAYS.length)
|
||||
return ARRAYS[nargs];
|
||||
// else need to spin bytecode or do something else fancy
|
||||
throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
|
||||
return MethodHandles.identity(Object[].class).asCollector(Object[].class, nargs);
|
||||
}
|
||||
public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
|
||||
Class<?> elemType = arrayType.getComponentType();
|
||||
@ -2463,6 +2765,12 @@ class ValueConversions {
|
||||
return lists.toArray(new MethodHandle[0]);
|
||||
}
|
||||
static final MethodHandle[] LISTS = makeLists();
|
||||
static final MethodHandle AS_LIST;
|
||||
static {
|
||||
try {
|
||||
AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
|
||||
} catch (Exception ex) { throw new RuntimeException(ex); }
|
||||
}
|
||||
|
||||
/** Return a method handle that takes the indicated number of Object
|
||||
* arguments and returns List.
|
||||
@ -2470,8 +2778,7 @@ class ValueConversions {
|
||||
public static MethodHandle varargsList(int nargs) {
|
||||
if (nargs < LISTS.length)
|
||||
return LISTS[nargs];
|
||||
// else need to spin bytecode or do something else fancy
|
||||
throw new UnsupportedOperationException("NYI");
|
||||
return AS_LIST.asCollector(Object[].class, nargs);
|
||||
}
|
||||
}
|
||||
// This guy tests access from outside the same package member, but inside
|
||||
|
||||
@ -82,6 +82,7 @@ public class RicochetTest {
|
||||
testLongSpreads();
|
||||
testIntCollects();
|
||||
testReturns();
|
||||
testRecursion();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -371,6 +372,61 @@ public class RicochetTest {
|
||||
//System.out.println("faultCount="+faultCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecursion() throws Throwable {
|
||||
if (!startTest("testRecursion")) return;
|
||||
final int LIMIT = 10;
|
||||
for (int i = 0; i < LIMIT; i++) {
|
||||
RFCB rfcb = new RFCB(i);
|
||||
Object x = "x", y = "y";
|
||||
Object result = rfcb.recursiveFunction(x, y);
|
||||
verbose(1, result);
|
||||
}
|
||||
}
|
||||
/** Recursive Function Control Block */
|
||||
private static class RFCB {
|
||||
java.util.Random random;
|
||||
final MethodHandle[] fns;
|
||||
int depth;
|
||||
RFCB(int seed) throws Throwable {
|
||||
this.random = new java.util.Random(seed);
|
||||
this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)];
|
||||
java.util.Arrays.fill(fns, lookup().bind(this, "recursiveFunction", genericMethodType(2)));
|
||||
for (int i = 5; i < fns.length; i++) {
|
||||
switch (i % 4) {
|
||||
case 0: fns[i] = filterArguments(fns[i - 5], 0, insertArguments(fns[i - 4], 1, ".")); break;
|
||||
case 1: fns[i] = filterArguments(fns[i - 5], 1, insertArguments(fns[i - 3], 1, ".")); break;
|
||||
case 2: fns[i] = filterReturnValue(fns[i - 5], insertArguments(fns[i - 2], 1, ".")); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Object recursiveFunction(Object x, Object y) throws Throwable {
|
||||
depth++;
|
||||
try {
|
||||
final int ACTION_COUNT = 11;
|
||||
switch (random.nextInt(ACTION_COUNT)) {
|
||||
case 1:
|
||||
Throwable ex = new RuntimeException();
|
||||
ex.fillInStackTrace();
|
||||
if (VERBOSITY >= 2) ex.printStackTrace();
|
||||
x = "ST; " + x;
|
||||
break;
|
||||
case 2:
|
||||
System.gc();
|
||||
x = "GC; " + x;
|
||||
break;
|
||||
}
|
||||
boolean isLeaf = (depth >= MAX_DEPTH);
|
||||
if (isLeaf) {
|
||||
return Arrays.asList(x, y).toString();
|
||||
}
|
||||
return fns[random.nextInt(fns.length)].invokeExact(x, y);
|
||||
} finally {
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle sequence(MethodHandle mh1, MethodHandle... mhs) {
|
||||
MethodHandle res = mh1;
|
||||
for (MethodHandle mh2 : mhs)
|
||||
@ -536,6 +592,7 @@ public class RicochetTest {
|
||||
}
|
||||
|
||||
// stress modes:
|
||||
private static final int MAX_DEPTH = getProperty("MAX_DEPTH", 5);
|
||||
private static final int REPEAT = getProperty("REPEAT", 0);
|
||||
private static final int STRESS = getProperty("STRESS", 0);
|
||||
private static /*v*/ int STRESS_COUNT;
|
||||
|
||||
229
jdk/test/java/lang/invoke/ThrowExceptionsTest.java
Normal file
229
jdk/test/java/lang/invoke/ThrowExceptionsTest.java
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @summary unit tests for method handles which permute their arguments
|
||||
* @run junit test.java.lang.invoke.ThrowExceptionsTest
|
||||
*/
|
||||
|
||||
package test.java.lang.invoke;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import java.lang.invoke.*;
|
||||
import static java.lang.invoke.MethodHandles.*;
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class ThrowExceptionsTest {
|
||||
private static final Class CLASS = ThrowExceptionsTest.class;
|
||||
private static final Lookup LOOKUP = lookup();
|
||||
|
||||
public static void main(String argv[]) throws Throwable {
|
||||
new ThrowExceptionsTest().testAll((argv.length == 0 ? null : Arrays.asList(argv).toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWMT() throws Throwable {
|
||||
// mostly call testWMTCallee, but sometimes call its void-returning variant
|
||||
MethodHandle mh = testWMTCallee();
|
||||
MethodHandle mh1 = mh.asType(mh.type().changeReturnType(void.class));
|
||||
assert(mh1 != mh);
|
||||
testWMT(mh, mh1, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoundWMT() throws Throwable {
|
||||
// mostly call exactInvoker.bindTo(testWMTCallee), but sometimes call its void-returning variant
|
||||
MethodHandle callee = testWMTCallee();
|
||||
MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
|
||||
MethodHandle invoker = exactInvoker(callee.type());
|
||||
MethodHandle mh = invoker.bindTo(callee);
|
||||
MethodHandle mh1 = invoker.bindTo(callee1);
|
||||
testWMT(mh, mh1, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFoldWMT() throws Throwable {
|
||||
// mostly call exactInvoker.fold(constant(testWMTCallee)), but sometimes call its void-returning variant
|
||||
MethodHandle callee = testWMTCallee();
|
||||
MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
|
||||
MethodHandle invoker = exactInvoker(callee.type());
|
||||
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
|
||||
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
|
||||
testWMT(mh, mh1, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFoldCCE() throws Throwable {
|
||||
MethodHandle callee = testWMTCallee();
|
||||
MethodHandle callee1 = callee.asType(callee.type().changeParameterType(1, Number.class)).asType(callee.type());
|
||||
MethodHandle invoker = exactInvoker(callee.type());
|
||||
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
|
||||
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
|
||||
testWMT(mh, mh1, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStackOverflow() throws Throwable {
|
||||
MethodHandle callee = testWMTCallee();
|
||||
MethodHandle callee1 = makeStackOverflow().asType(callee.type());
|
||||
MethodHandle invoker = exactInvoker(callee.type());
|
||||
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
|
||||
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
|
||||
for (int i = 0; i < REPEAT; i++) {
|
||||
try {
|
||||
testWMT(mh, mh1, 1000);
|
||||
} catch (StackOverflowError ex) {
|
||||
// OK, try again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle makeStackOverflow() {
|
||||
MethodType cellType = methodType(void.class);
|
||||
MethodHandle[] cell = { null }; // recursion point
|
||||
MethodHandle getCell = insertArguments(arrayElementGetter(cell.getClass()), 0, cell, 0);
|
||||
MethodHandle invokeCell = foldArguments(exactInvoker(cellType), getCell);
|
||||
assert(invokeCell.type() == cellType);
|
||||
cell[0] = invokeCell;
|
||||
// make it conformable to any type:
|
||||
invokeCell = dropArguments(invokeCell, 0, Object[].class).asVarargsCollector(Object[].class);
|
||||
return invokeCell;
|
||||
}
|
||||
|
||||
static int testCases;
|
||||
|
||||
private void testAll(String match) throws Throwable {
|
||||
testCases = 0;
|
||||
Lookup lookup = lookup();
|
||||
for (Method m : CLASS.getDeclaredMethods()) {
|
||||
String name = m.getName();
|
||||
if (name.startsWith("test") &&
|
||||
(match == null || match.contains(name.substring("test".length()))) &&
|
||||
m.getParameterTypes().length == 0 &&
|
||||
Modifier.isPublic(m.getModifiers()) &&
|
||||
!Modifier.isStatic(m.getModifiers())) {
|
||||
System.out.println("["+name+"]");
|
||||
int tc = testCases;
|
||||
try {
|
||||
m.invoke(this);
|
||||
} catch (Throwable ex) {
|
||||
System.out.println("*** "+ex);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if (testCases == tc) testCases++;
|
||||
}
|
||||
}
|
||||
if (testCases == 0) throw new RuntimeException("no test cases found");
|
||||
System.out.println("ran a total of "+testCases+" test cases");
|
||||
}
|
||||
|
||||
private static MethodHandle findStatic(String name) {
|
||||
return findMethod(name, true);
|
||||
}
|
||||
private static MethodHandle findVirtual(String name) {
|
||||
return findMethod(name, false);
|
||||
}
|
||||
private static MethodHandle findMethod(String name, boolean isStatic) {
|
||||
MethodHandle mh = null;
|
||||
for (Method m : CLASS.getDeclaredMethods()) {
|
||||
if (m.getName().equals(name) &&
|
||||
Modifier.isStatic(m.getModifiers()) == isStatic) {
|
||||
if (mh != null)
|
||||
throw new RuntimeException("duplicate methods: "+name);
|
||||
try {
|
||||
mh = LOOKUP.unreflect(m);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mh == null)
|
||||
throw new RuntimeException("no method: "+name);
|
||||
return mh;
|
||||
}
|
||||
|
||||
int testWMTCallee;
|
||||
private int testWMTCallee(String x) {
|
||||
return testWMTCallee++;
|
||||
}
|
||||
private static MethodHandle testWMTCallee() {
|
||||
MethodHandle callee = findVirtual("testWMTCallee");
|
||||
// FIXME: should not have to retype callee
|
||||
callee = callee.asType(callee.type().changeParameterType(0, Object.class));
|
||||
return callee;
|
||||
}
|
||||
|
||||
private Exception testWMT(MethodHandle[] mhs, int reps) throws Throwable {
|
||||
testCases += 1;
|
||||
testWMTCallee = 0;
|
||||
int catches = 0;
|
||||
Exception savedEx = null;
|
||||
for (int i = 0; i < reps; i++) {
|
||||
MethodHandle mh = mhs[i % mhs.length];
|
||||
int n;
|
||||
try {
|
||||
// FIXME: should not have to retype this
|
||||
n = (int) mh.invokeExact((Object)this, "x");
|
||||
assertEquals(n, i - catches);
|
||||
// Using the exact type for this causes endless deopt due to
|
||||
// 'non_cached_result' in SystemDictionary::find_method_handle_invoke.
|
||||
// The problem is that the compiler thread needs to access a cached
|
||||
// invoke method, but invoke methods are not cached if one of the
|
||||
// component types is not on the BCP.
|
||||
} catch (Exception ex) {
|
||||
savedEx = ex;
|
||||
catches++;
|
||||
}
|
||||
}
|
||||
//VERBOSE: System.out.println("reps="+reps+" catches="+catches);
|
||||
return savedEx;
|
||||
}
|
||||
|
||||
private static final int REPEAT = Integer.getInteger(CLASS.getSimpleName()+".REPEAT", 10);
|
||||
|
||||
private Exception testWMT(MethodHandle mh, MethodHandle mh1, int reps) throws Throwable {
|
||||
//VERBOSE: System.out.println("mh="+mh+" mh1="+mh1);
|
||||
MethodHandle[] mhs = new MethodHandle[100];
|
||||
Arrays.fill(mhs, mh);
|
||||
int patch = mhs.length-1;
|
||||
Exception savedEx = null;
|
||||
for (int i = 0; i < REPEAT; i++) {
|
||||
mhs[patch] = mh;
|
||||
testWMT(mhs, 10000);
|
||||
mhs[patch] = mh1;
|
||||
savedEx = testWMT(mhs, reps);
|
||||
}
|
||||
return savedEx;
|
||||
}
|
||||
|
||||
private static void assertEquals(Object x, Object y) {
|
||||
if (x == y || x != null && x.equals(y)) return;
|
||||
throw new RuntimeException(x+" != "+y);
|
||||
}
|
||||
}
|
||||
92
jdk/test/java/text/Bidi/Bug7042148.java
Normal file
92
jdk/test/java/text/Bidi/Bug7042148.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 7042148
|
||||
* @summary verify that Bidi.baseIsLeftToRight() returns the correct value even if an incorrect position is set in the given AttributedCharacterIterator.
|
||||
*/
|
||||
import java.awt.font.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Bug7042148 {
|
||||
|
||||
private static boolean err = false;
|
||||
|
||||
public static void main(String[] args) {
|
||||
testDirection();
|
||||
|
||||
if (err) {
|
||||
throw new RuntimeException("Failed");
|
||||
} else {
|
||||
System.out.println("Passed.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testDirection() {
|
||||
Map attrLTR = new HashMap();
|
||||
attrLTR.put(TextAttribute.RUN_DIRECTION,
|
||||
TextAttribute.RUN_DIRECTION_LTR);
|
||||
Map attrRTL = new HashMap();
|
||||
attrRTL.put(TextAttribute.RUN_DIRECTION,
|
||||
TextAttribute.RUN_DIRECTION_RTL);
|
||||
|
||||
String str1 = "A\u05e0";
|
||||
String str2 = "\u05e0B";
|
||||
|
||||
test(str1, attrLTR, Bidi.DIRECTION_LEFT_TO_RIGHT);
|
||||
test(str1, attrRTL, Bidi.DIRECTION_RIGHT_TO_LEFT);
|
||||
test(str2, attrLTR, Bidi.DIRECTION_LEFT_TO_RIGHT);
|
||||
test(str2, attrRTL, Bidi.DIRECTION_RIGHT_TO_LEFT);
|
||||
}
|
||||
|
||||
private static void test(String text, Map attr, int dirFlag) {
|
||||
boolean expected = (dirFlag == Bidi.DIRECTION_LEFT_TO_RIGHT);
|
||||
|
||||
Bidi bidi = new Bidi(text, dirFlag);
|
||||
boolean got = bidi.baseIsLeftToRight();
|
||||
if (got != expected) {
|
||||
err = true;
|
||||
System.err.println("wrong Bidi(String, int).baseIsLeftToRight() value: " +
|
||||
"\n\ttext=" + text +
|
||||
"\n\tExpected=" + expected +
|
||||
"\n\tGot=" + got);
|
||||
}
|
||||
|
||||
AttributedString as = new AttributedString(text, attr);
|
||||
AttributedCharacterIterator itr = as.getIterator();
|
||||
itr.last();
|
||||
itr.next();
|
||||
bidi = new Bidi(itr);
|
||||
got = bidi.baseIsLeftToRight();
|
||||
if (got != expected) {
|
||||
err = true;
|
||||
System.err.println("Wrong Bidi(AttributedCharacterIterator).baseIsLeftToRight() value: " +
|
||||
"\n\ttext=" + text +
|
||||
"\n\tExpected=" + expected +
|
||||
"\n\tGot=" + got);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
72
jdk/test/java/text/Bidi/Bug7051769.java
Normal file
72
jdk/test/java/text/Bidi/Bug7051769.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 7051769
|
||||
* @summary verify that Bidi.toString() returns the corect result.
|
||||
*/
|
||||
import java.awt.font.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Bug7051769 {
|
||||
|
||||
private static boolean err = false;
|
||||
|
||||
public static void main(String[] args) {
|
||||
testNumericShaping();
|
||||
|
||||
if (err) {
|
||||
throw new RuntimeException("Failed");
|
||||
} else {
|
||||
System.out.println("Passed.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testNumericShaping() {
|
||||
Map attrNS = new HashMap();
|
||||
attrNS.put(TextAttribute.NUMERIC_SHAPING,
|
||||
NumericShaper.getContextualShaper(NumericShaper.ARABIC));
|
||||
attrNS.put(TextAttribute.RUN_DIRECTION,
|
||||
TextAttribute.RUN_DIRECTION_RTL);
|
||||
|
||||
String text = "\u0623\u0643\u062a\u0648\u0628\u0631 10";
|
||||
String expected = "sun.text.bidi.BidiBase[dir: 2 baselevel: 1 length: 9 runs: [1 1 1 1 1 1 1 2 2] text: [0x623 0x643 0x62a 0x648 0x628 0x631 0x20 0x661 0x660]]";
|
||||
|
||||
AttributedString as = new AttributedString(text, attrNS);
|
||||
AttributedCharacterIterator itr = as.getIterator();
|
||||
itr.last();
|
||||
itr.next();
|
||||
Bidi bidi = new Bidi(itr);
|
||||
String got = bidi.toString();
|
||||
|
||||
if (!got.equals(expected)) {
|
||||
err = true;
|
||||
System.err.println("Wrong toString() output: " +
|
||||
"\n\tExpected=" + expected +
|
||||
"\n\tGot=" + got);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user