Merge
This commit is contained in:
commit
50abd159dd
jdk
make
data/swingbeaninfo
gensrc
lib
mapfiles
src/classes/build/tools
cldrconverter
swingbeaninfo
src
java.base/share
classes
java
lang
StringCoding.java
invoke
InfoFromMemberName.javaInvokers.javaMemberName.javaMethodHandle.javaMethodHandleImpl.javaMethodHandleNatives.javaMethodHandleStatics.javaMethodHandles.javaMethodType.javaVarForm.javaVarHandle.javaVarHandleByteArrayBase.javaVarHandleGuards.javaVarHandles.javaX-VarHandle.java.templateX-VarHandleByteArrayView.java.templatepackage-info.java
nio
Buffer.javaDirect-X-Buffer.java.templateHeap-X-Buffer.java.templateStringCharBuffer.javaX-Buffer.java.template
text
time
util
jdk/internal
module-info.javasun
misc
net
security/ssl
native
java.compact3/share/classes
java.desktop/macosx/classes
com/apple/eawt
AppEvent.javaApplication.javaApplicationAdapter.javaApplicationEvent.javaApplicationListener.javaFullScreenAdapter.javaFullScreenHandler.javaFullScreenListener.javaMacQuitResponse.javaOpenURIHandler.java_AppDockIconHandler.java_AppEventHandler.java_AppEventLegacyHandler.java_AppMenuBarHandler.java
event
sun
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2015, 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 @(BeanPackageName);
|
||||
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.awt.Image;
|
||||
|
||||
import sun.swing.BeanInfoUtils;
|
||||
|
||||
/**
|
||||
* Descriptive information about the @(BeanClassName) class for Java
|
||||
* Beans application builders. This BeanInfo class provides descriptions
|
||||
* of each property, of the bean itself, it indicates which
|
||||
* @(BeanClassName) properties are bound, and it provides other
|
||||
* information and icons useful to builders.
|
||||
*
|
||||
* @author Auto-Generated Source Code
|
||||
*/
|
||||
|
||||
public class @(BeanClassName)BeanInfo extends javax.swing.SwingBeanInfoBase {
|
||||
private static final Class<?> class@(BeanClassName) = @(BeanClassObject);
|
||||
|
||||
/**
|
||||
* @return a @(BeanClassName) BeanDescriptor
|
||||
*/
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return BeanInfoUtils.createBeanDescriptor(class@(BeanClassName),
|
||||
new Object[] {
|
||||
BeanInfoUtils.PREFERRED, Boolean.TRUE,
|
||||
@(ClassDescriptors)
|
||||
BeanInfoUtils.SHORTDESCRIPTION, "@(BeanDescription)"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a @(BeanClassName) PropertyDescriptor. This is just an internal
|
||||
* convenience method that allows one to leave the @(BeanClassName).class
|
||||
* argument out of the createPropertyDescriptor() class in the
|
||||
* getPropertyDescriptors() method below.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @param args an array java.beans.PropertyDescriptor property names and values
|
||||
* @return a @(BeanClassName) PropertyDescriptor.
|
||||
* @see BeanInfoUtils#createPropertyDescriptor
|
||||
*/
|
||||
private PropertyDescriptor createPropertyDescriptor(String name, Object[] args) {
|
||||
return BeanInfoUtils.createPropertyDescriptor(class@(BeanClassName), name, args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method returns a list of bean PropertyDescriptors, one for each public
|
||||
* property in @(BeanClassName). The first property is the "default" property.
|
||||
*
|
||||
* @return a complete list of bean PropertyDescriptors for @(BeanClassName)
|
||||
* @see SwingBeanInfo
|
||||
* @see java.beans.BeanInfo#getDefaultPropertyIndex
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
@(EnumVariables)
|
||||
return new PropertyDescriptor[] {
|
||||
@(BeanPropertyDescriptors)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return an icon of the specified kind for @(BeanClassName)
|
||||
*/
|
||||
public Image getIcon(final int kind) {
|
||||
Image i;
|
||||
switch (kind){
|
||||
case ICON_COLOR_32x32:
|
||||
i = loadStandardImage("beaninfo/images/@(BeanClassName)Color32.gif");
|
||||
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor32.gif") : i);
|
||||
case ICON_COLOR_16x16:
|
||||
i = loadStandardImage("beaninfo/images/@(BeanClassName)Color16.gif");
|
||||
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor16.gif") : i);
|
||||
case ICON_MONO_32x32:
|
||||
i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono32.gif");
|
||||
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono32.gif") : i);
|
||||
case ICON_MONO_16x16:
|
||||
i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono16.gif");
|
||||
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono16.gif") : i);
|
||||
default:
|
||||
return super.getIcon(kind);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method to help in loading standard icon images.
|
||||
*
|
||||
* @param resourceName A pathname relative to the directory holding the
|
||||
* class file of the current class
|
||||
* @return an image object. May be null if the load failed.
|
||||
* @see java.beans.SimpleBeanInfo#loadImage(String)
|
||||
*/
|
||||
private Image loadStandardImage(final String resourceName) {
|
||||
return java.security.AccessController.doPrivileged(
|
||||
(java.security.PrivilegedAction<Image>) () -> loadImage(resourceName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing;
|
||||
|
||||
import java.beans.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.awt.Image;
|
||||
|
||||
/**
|
||||
* The superclass for all Swing BeanInfo classes. It provides
|
||||
* default implementations of <code>getIcon</code> and
|
||||
* <code>getDefaultPropertyIndex</code> as well as utility
|
||||
* methods, like createPropertyDescriptor, for writing BeanInfo
|
||||
* implementations. This classes is intended to be used along
|
||||
* with <code>GenSwingBeanInfo</code> a BeanInfo class code generator.
|
||||
*
|
||||
* @see GenSwingBeanInfo
|
||||
* @author Hans Muller
|
||||
*/
|
||||
public class SwingBeanInfoBase extends SimpleBeanInfo
|
||||
{
|
||||
/**
|
||||
* The default index is always 0. In other words the first property
|
||||
* listed in the getPropertyDescriptors() method is the one
|
||||
* to show a (JFC builder) user in a situation where just a single
|
||||
* property will be shown.
|
||||
*/
|
||||
public int getDefaultPropertyIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a generic Swing icon, all icon "kinds" are supported.
|
||||
* Subclasses should defer to this method when they don't have
|
||||
* a particular beans icon kind.
|
||||
*/
|
||||
public Image getIcon(int kind) {
|
||||
// PENDING(hmuller) need generic swing icon images.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BeanInfo for the superclass of our bean, so that
|
||||
* its PropertyDescriptors will be included.
|
||||
*/
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
Class<?> superClass = getBeanDescriptor().getBeanClass().getSuperclass();
|
||||
BeanInfo superBeanInfo = null;
|
||||
try {
|
||||
superBeanInfo = Introspector.getBeanInfo(superClass);
|
||||
} catch (IntrospectionException ie) {}
|
||||
if (superBeanInfo != null) {
|
||||
BeanInfo[] ret = new BeanInfo[1];
|
||||
ret[0] = superBeanInfo;
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
Name: javax/swing/JApplet.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JButton.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JCheckBox.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JCheckBoxMenuItem.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JComboBox.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JDialog.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JEditorPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JFormattedTextField.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JInternalFrame.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JFrame.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JLabel.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JList.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JMenu.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JMenuBar.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JMenuItem.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JOptionPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JPanel.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JPasswordField.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JPopupMenu.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JProgressBar.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JRadioButton.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JRadioButtonMenuItem.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JScrollBar.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JScrollPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JSeparator.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JSlider.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JSpinner.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JSplitPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTabbedPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTextArea.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTextField.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTextPane.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JToolBar.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTree.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JTable.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JToggleButton.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: javax/swing/JWindow.class
|
||||
Java-Bean: True
|
||||
|
@ -1,293 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.swing;
|
||||
|
||||
import java.beans.*;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class BeanInfoUtils
|
||||
{
|
||||
/* The values of these createPropertyDescriptor() and
|
||||
* createBeanDescriptor() keywords are the names of the
|
||||
* properties they're used to set.
|
||||
*/
|
||||
public static final String BOUND = "bound";
|
||||
public static final String CONSTRAINED = "constrained";
|
||||
public static final String PROPERTYEDITORCLASS = "propertyEditorClass";
|
||||
public static final String READMETHOD = "readMethod";
|
||||
public static final String WRITEMETHOD = "writeMethod";
|
||||
public static final String DISPLAYNAME = "displayName";
|
||||
public static final String EXPERT = "expert";
|
||||
public static final String HIDDEN = "hidden";
|
||||
public static final String PREFERRED = "preferred";
|
||||
public static final String SHORTDESCRIPTION = "shortDescription";
|
||||
public static final String CUSTOMIZERCLASS = "customizerClass";
|
||||
|
||||
static private void initFeatureDescriptor(FeatureDescriptor fd, String key, Object value)
|
||||
{
|
||||
if (DISPLAYNAME.equals(key)) {
|
||||
fd.setDisplayName((String)value);
|
||||
}
|
||||
|
||||
if (EXPERT.equals(key)) {
|
||||
fd.setExpert(((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
if (HIDDEN.equals(key)) {
|
||||
fd.setHidden(((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
if (PREFERRED.equals(key)) {
|
||||
fd.setPreferred(((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
else if (SHORTDESCRIPTION.equals(key)) {
|
||||
fd.setShortDescription((String)value);
|
||||
}
|
||||
|
||||
/* Otherwise assume that we have an arbitrary FeatureDescriptor
|
||||
* "attribute".
|
||||
*/
|
||||
else {
|
||||
fd.setValue(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a beans PropertyDescriptor given an of keyword/value
|
||||
* arguments. The following sample call shows all of the supported
|
||||
* keywords:
|
||||
*<pre>
|
||||
* createPropertyDescriptor("contentPane", new Object[] {
|
||||
* BOUND, Boolean.TRUE,
|
||||
* CONSTRAINED, Boolean.TRUE,
|
||||
* PROPERTYEDITORCLASS, package.MyEditor.class,
|
||||
* READMETHOD, "getContentPane",
|
||||
* WRITEMETHOD, "setContentPane",
|
||||
* DISPLAYNAME, "contentPane",
|
||||
* EXPERT, Boolean.FALSE,
|
||||
* HIDDEN, Boolean.FALSE,
|
||||
* PREFERRED, Boolean.TRUE,
|
||||
* SHORTDESCRIPTION, "A top level window with a window manager border",
|
||||
* "random attribute","random object value"
|
||||
* }
|
||||
* );
|
||||
* </pre>
|
||||
* The keywords correspond to <code>java.beans.PropertyDescriptor</code> and
|
||||
* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
|
||||
* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
|
||||
* Using createPropertyDescriptor instead of the PropertyDescriptor
|
||||
* constructor and set methods is preferrable in that it regularizes
|
||||
* the code in a <code>java.beans.BeanInfo.getPropertyDescriptors()</code>
|
||||
* method implementation. One can use <code>createPropertyDescriptor</code>
|
||||
* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
|
||||
* "random object value".
|
||||
* <p>
|
||||
* All properties should provide a reasonable value for the
|
||||
* <code>SHORTDESCRIPTION</code> keyword and should set <code>BOUND</code>
|
||||
* to <code>Boolean.TRUE</code> if neccessary. The remaining keywords
|
||||
* are optional. There's no need to provide values for keywords like
|
||||
* READMETHOD if the correct value can be computed, i.e. if the properties
|
||||
* get/is method follows the standard beans pattern.
|
||||
* <p>
|
||||
* The PREFERRED keyword is not supported by the JDK1.1 java.beans package.
|
||||
* It's still worth setting it to true for properties that are most
|
||||
* likely to be interested to the average developer, e.g. AbstractButton.title
|
||||
* is a preferred property, AbstractButton.focusPainted is not.
|
||||
*
|
||||
* @see java.beans#BeanInfo
|
||||
* @see java.beans#PropertyDescriptor
|
||||
* @see java.beans#FeatureDescriptor
|
||||
*/
|
||||
public static PropertyDescriptor createPropertyDescriptor(Class<?> cls, String name, Object[] args)
|
||||
{
|
||||
PropertyDescriptor pd = null;
|
||||
try {
|
||||
pd = new PropertyDescriptor(name, cls);
|
||||
} catch (IntrospectionException e) {
|
||||
// Try creating a read-only property, in case setter isn't defined.
|
||||
try {
|
||||
pd = createReadOnlyPropertyDescriptor(name, cls);
|
||||
} catch (IntrospectionException ie) {
|
||||
throwError(ie, "Can't create PropertyDescriptor for " + name + " ");
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < args.length; i += 2) {
|
||||
String key = (String)args[i];
|
||||
Object value = args[i + 1];
|
||||
|
||||
if (BOUND.equals(key)) {
|
||||
pd.setBound(((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
else if (CONSTRAINED.equals(key)) {
|
||||
pd.setConstrained(((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
else if (PROPERTYEDITORCLASS.equals(key)) {
|
||||
pd.setPropertyEditorClass((Class)value);
|
||||
}
|
||||
|
||||
else if (READMETHOD.equals(key)) {
|
||||
String methodName = (String)value;
|
||||
Method method;
|
||||
try {
|
||||
method = cls.getMethod(methodName, new Class<?>[0]);
|
||||
pd.setReadMethod(method);
|
||||
}
|
||||
catch(Exception e) {
|
||||
throwError(e, cls + " no such method as \"" + methodName + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
else if (WRITEMETHOD.equals(key)) {
|
||||
String methodName = (String)value;
|
||||
Method method;
|
||||
try {
|
||||
Class<?> type = pd.getPropertyType();
|
||||
method = cls.getMethod(methodName, new Class<?>[]{type});
|
||||
pd.setWriteMethod(method);
|
||||
}
|
||||
catch(Exception e) {
|
||||
throwError(e, cls + " no such method as \"" + methodName + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
initFeatureDescriptor(pd, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a BeanDescriptor object given an of keyword/value
|
||||
* arguments. The following sample call shows all of the supported
|
||||
* keywords:
|
||||
*<pre>
|
||||
* createBeanDescriptor(JWindow..class, new Object[] {
|
||||
* CUSTOMIZERCLASS, package.MyCustomizer.class,
|
||||
* DISPLAYNAME, "JFrame",
|
||||
* EXPERT, Boolean.FALSE,
|
||||
* HIDDEN, Boolean.FALSE,
|
||||
* PREFERRED, Boolean.TRUE,
|
||||
* SHORTDESCRIPTION, "A top level window with a window manager border",
|
||||
* "random attribute","random object value"
|
||||
* }
|
||||
* );
|
||||
* </pre>
|
||||
* The keywords correspond to <code>java.beans.BeanDescriptor</code> and
|
||||
* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
|
||||
* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
|
||||
* Using createBeanDescriptor instead of the BeanDescriptor
|
||||
* constructor and set methods is preferrable in that it regularizes
|
||||
* the code in a <code>java.beans.BeanInfo.getBeanDescriptor()</code>
|
||||
* method implementation. One can use <code>createBeanDescriptor</code>
|
||||
* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
|
||||
* "random object value".
|
||||
*
|
||||
* @see java.beans#BeanInfo
|
||||
* @see java.beans#PropertyDescriptor
|
||||
*/
|
||||
public static BeanDescriptor createBeanDescriptor(Class<?> cls, Object[] args)
|
||||
{
|
||||
Class<?> customizerClass = null;
|
||||
|
||||
/* For reasons I don't understand, customizerClass is a
|
||||
* readOnly property. So we have to find it and pass it
|
||||
* to the constructor here.
|
||||
*/
|
||||
for(int i = 0; i < args.length; i += 2) {
|
||||
if (CUSTOMIZERCLASS.equals((String)args[i])) {
|
||||
customizerClass = (Class)args[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);
|
||||
|
||||
for(int i = 0; i < args.length; i += 2) {
|
||||
String key = (String)args[i];
|
||||
Object value = args[i + 1];
|
||||
initFeatureDescriptor(bd, key, value);
|
||||
}
|
||||
|
||||
return bd;
|
||||
}
|
||||
|
||||
static private PropertyDescriptor createReadOnlyPropertyDescriptor(
|
||||
String name, Class<?> cls) throws IntrospectionException {
|
||||
|
||||
Method readMethod = null;
|
||||
String base = capitalize(name);
|
||||
Class<?>[] parameters = new Class<?>[0];
|
||||
|
||||
// Is it a boolean?
|
||||
try {
|
||||
readMethod = cls.getMethod("is" + base, parameters);
|
||||
} catch (Exception ex) {}
|
||||
if (readMethod == null) {
|
||||
try {
|
||||
// Try normal accessor pattern.
|
||||
readMethod = cls.getMethod("get" + base, parameters);
|
||||
} catch (Exception ex2) {}
|
||||
}
|
||||
if (readMethod != null) {
|
||||
return new PropertyDescriptor(name, readMethod, null);
|
||||
}
|
||||
|
||||
try {
|
||||
// Try indexed accessor pattern.
|
||||
parameters = new Class<?>[1];
|
||||
parameters[0] = int.class;
|
||||
readMethod = cls.getMethod("get" + base, parameters);
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new IntrospectionException(
|
||||
"cannot find accessor method for " + name + " property.");
|
||||
}
|
||||
return new IndexedPropertyDescriptor(name, null, null, readMethod, null);
|
||||
}
|
||||
|
||||
// Modified methods from java.beans.Introspector
|
||||
private static String capitalize(String s) {
|
||||
if (s.length() == 0) {
|
||||
return s;
|
||||
}
|
||||
char chars[] = s.toCharArray();
|
||||
chars[0] = Character.toUpperCase(chars[0]);
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fatal errors are handled by calling this method.
|
||||
*/
|
||||
public static void throwError(Exception e, String s) {
|
||||
throw new Error(e.toString() + " " + s);
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ include GensrcCharsetMapping.gmk
|
||||
include GensrcCharsetCoder.gmk
|
||||
include GensrcBuffer.gmk
|
||||
include GensrcExceptions.gmk
|
||||
include GensrcVarHandles.gmk
|
||||
include GensrcModuleLoaderMap.gmk
|
||||
|
||||
################################################################################
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2016, 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
|
||||
@ -62,7 +62,9 @@ endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/classes/sun/awt/windows
|
||||
else
|
||||
endif
|
||||
|
||||
ifeq ($(filter $(OPENJDK_TARGET_OS), windows macosx), )
|
||||
PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources
|
||||
endif
|
||||
|
||||
|
162
jdk/make/gensrc/GensrcVarHandles.gmk
Normal file
162
jdk/make/gensrc/GensrcVarHandles.gmk
Normal file
@ -0,0 +1,162 @@
|
||||
#
|
||||
# Copyright (c) 2015, 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.
|
||||
#
|
||||
|
||||
GENSRC_VARHANDLES :=
|
||||
|
||||
VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
|
||||
VARHANDLES_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/invoke
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandle java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
define GenerateVarHandle
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Object Int Long), )
|
||||
$1_ARGS += -KCAS
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Int Long), )
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
|
||||
ifeq ($$($1_Type), Object)
|
||||
$$(eval $1_type := $$($1_Type))
|
||||
else
|
||||
$$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
|
||||
endif
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
|
||||
$$($1_ARGS) < $$< > $$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandleByteArray java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
define GenerateVarHandleByteArray
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
$1_type := short
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
$1_type := char
|
||||
$1_BoxType := Character
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
$1_type := int
|
||||
$1_BoxType := Integer
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Long)
|
||||
$1_type := long
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Float)
|
||||
$1_type := float
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := int
|
||||
$1_RawType := Int
|
||||
$1_RawBoxType := Integer
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Double)
|
||||
$1_type := double
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := long
|
||||
$1_RawType := Long
|
||||
$1_RawBoxType := Long
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(TOOL_SPP) -nel -K$$($1_type) \
|
||||
-Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
|
||||
-DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
|
||||
$$($1_ARGS) < $$< > $$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Object
|
||||
$(foreach t, $(VARHANDLES_TYPES), \
|
||||
$(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
|
||||
$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
|
||||
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
||||
|
||||
GENSRC_JAVA_BASE += $(GENSRC_VARHANDLES)
|
@ -204,6 +204,7 @@ endif
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
|
||||
$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
|
||||
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \
|
||||
# Why does libawt need java.base headers?
|
||||
LIBAWT_CFLAGS += -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
|
||||
-I$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
|
||||
@ -311,6 +312,10 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
|
||||
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
|
||||
#
|
||||
|
||||
ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
|
||||
LIBAWT_XAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
|
||||
endif
|
||||
|
||||
LIBAWT_XAWT_EXCLUDES := medialib
|
||||
|
||||
LIBAWT_XAWT_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBAWT_XAWT_DIRS) -type d)) \
|
||||
@ -883,6 +888,13 @@ ifndef BUILD_HEADLESS_ONLY
|
||||
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/macosx/native/libsplashscreen
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
|
||||
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
|
||||
endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/native/common/awt/systemscale
|
||||
endif
|
||||
LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 \
|
||||
$(addprefix -I, $(LIBSPLASHSCREEN_DIRS)) \
|
||||
$(LIBJAVA_HEADER_FLAGS) \
|
||||
@ -923,7 +935,7 @@ ifndef BUILD_HEADLESS_ONLY
|
||||
-framework JavaNativeFoundation
|
||||
else ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
LIBSPLASHSCREEN_LDFLAGS := -delayload:user32.dll
|
||||
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib
|
||||
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib
|
||||
else
|
||||
LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread
|
||||
endif
|
||||
|
53
jdk/make/lib/Lib-java.rmi.gmk
Normal file
53
jdk/make/lib/Lib-java.rmi.gmk
Normal file
@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (c) 2016, 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.
|
||||
#
|
||||
|
||||
include LibCommon.gmk
|
||||
|
||||
################################################################################
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBRMI, \
|
||||
LIBRARY := rmi, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(JDK_TOPDIR)/src/java.rmi/share/native/librmi, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.rmi, \
|
||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/librmi/mapfile-vers, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LIBS_unix := -ljvm, \
|
||||
LIBS_windows := jvm.lib, \
|
||||
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
|
||||
RC_FLAGS := $(RC_FLAGS) \
|
||||
-D "JDK_FNAME=rmi.dll" \
|
||||
-D "JDK_INTERNAL_NAME=rmi" \
|
||||
-D "JDK_FTYPE=0x2L", \
|
||||
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/librmi, \
|
||||
))
|
||||
|
||||
$(BUILD_LIBRMI): $(call FindLib, java.base, java)
|
||||
|
||||
TARGETS += $(BUILD_LIBRMI)
|
||||
|
||||
################################################################################
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2016, 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
|
||||
@ -150,6 +150,12 @@ SUNWprivate_1.1 {
|
||||
Java_sun_awt_X11_XlibWrapper_XdbeEndIdiom;
|
||||
Java_sun_awt_X11_XDesktopPeer_init;
|
||||
Java_sun_awt_X11_XDesktopPeer_gnome_1url_1show;
|
||||
Java_sun_awt_X11_XTaskbarPeer_init;
|
||||
Java_sun_awt_X11_XTaskbarPeer_runloop;
|
||||
Java_sun_awt_X11_XTaskbarPeer_setBadge;
|
||||
Java_sun_awt_X11_XTaskbarPeer_setUrgent;
|
||||
Java_sun_awt_X11_XTaskbarPeer_updateProgress;
|
||||
Java_sun_awt_X11_XTaskbarPeer_setNativeMenu;
|
||||
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_keyPressImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_keyReleaseImpl;
|
||||
|
@ -259,7 +259,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_io_Console_istty;
|
||||
Java_java_io_Console_encoding;
|
||||
Java_java_io_Console_echo;
|
||||
Java_sun_misc_GC_maxObjectInspectionAge;
|
||||
Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
|
||||
Java_sun_reflect_NativeMethodAccessorImpl_invoke0;
|
||||
Java_sun_reflect_Reflection_getCallerClass__;
|
||||
@ -283,8 +282,8 @@ SUNWprivate_1.1 {
|
||||
Java_jdk_internal_loader_BootLoader_getSystemPackageNames;
|
||||
Java_jdk_internal_loader_BootLoader_setBootLoaderUnnamedModule0;
|
||||
|
||||
Java_sun_misc_VMSupport_initAgentProperties;
|
||||
Java_sun_misc_VMSupport_getVMTemporaryDirectory;
|
||||
Java_jdk_internal_vm_VMSupport_initAgentProperties;
|
||||
Java_jdk_internal_vm_VMSupport_getVMTemporaryDirectory;
|
||||
|
||||
# ZipFile.c needs this one
|
||||
throwFileNotFoundException;
|
||||
|
31
jdk/make/mapfiles/librmi/mapfile-vers
Normal file
31
jdk/make/mapfiles/librmi/mapfile-vers
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (c) 2016, 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.
|
||||
#
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
Java_sun_rmi_transport_GC_maxObjectInspectionAge;
|
||||
local:
|
||||
*;
|
||||
};
|
@ -42,6 +42,8 @@ SUNWprivate_1.1 {
|
||||
SplashInit;
|
||||
SplashClose;
|
||||
SplashSetFileJarName;
|
||||
SplashSetScaleFactor;
|
||||
SplashGetScaledImageName;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -786,10 +786,10 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
private String getTarget(String qName, String path, String calType, String context, String width) {
|
||||
// qName
|
||||
private String getTarget(String path, String calType, String context, String width) {
|
||||
// Target qName
|
||||
int lastSlash = path.lastIndexOf('/');
|
||||
qName = path.substring(lastSlash+1);
|
||||
String qName = path.substring(lastSlash+1);
|
||||
int bracket = qName.indexOf('[');
|
||||
if (bracket != -1) {
|
||||
qName = qName.substring(0, bracket);
|
||||
@ -885,7 +885,7 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
|
||||
String[] tmp = keyName.split(",", 3);
|
||||
String calType = currentCalendarType.lname();
|
||||
String src = calType+"."+tmp[0];
|
||||
String target = getTarget(containerqName,
|
||||
String target = getTarget(
|
||||
entry.getKey(),
|
||||
calType,
|
||||
tmp[1].length()>0 ? tmp[1] : currentContext,
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package build.tools.swingbeaninfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Class that holds information for populating a FeatureDescriptor. For the class,
|
||||
* This information represents the BeanDescriptor, for a property, it represents
|
||||
* a PropertyDescriptor.
|
||||
*/
|
||||
public class DocBeanInfo {
|
||||
|
||||
// Values of the BeanFlags
|
||||
public static final int BOUND = 1;
|
||||
public static final int EXPERT = 2;
|
||||
public static final int CONSTRAINED = 4;
|
||||
public static final int HIDDEN = 8;
|
||||
public static final int PREFERRED = 16 ;
|
||||
|
||||
public String name;
|
||||
public int beanflags;
|
||||
public String desc;
|
||||
public String displayname;
|
||||
public String propertyeditorclass;
|
||||
public String customizerclass;
|
||||
|
||||
public HashMap attribs;
|
||||
public HashMap enums;
|
||||
|
||||
public DocBeanInfo(){}
|
||||
|
||||
public DocBeanInfo(String p, int flags, String d,
|
||||
String displayname, String pec, String cc,
|
||||
HashMap attribs, HashMap enums) {
|
||||
this.name = p;
|
||||
this.beanflags = flags;
|
||||
this.desc = d;
|
||||
this.displayname = displayname;
|
||||
this.propertyeditorclass = pec;
|
||||
this.customizerclass = cc;
|
||||
|
||||
this.attribs = attribs;
|
||||
this.enums = enums;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer("*****");
|
||||
buffer.append("\nProperty: " + name);
|
||||
buffer.append("\tDescription: " + desc);
|
||||
buffer.append("\nDisplayname: " + displayname);
|
||||
buffer.append("\nPropertyEditorClass: " + propertyeditorclass);
|
||||
buffer.append("\nCustomizerClass: " + customizerclass);
|
||||
|
||||
if ((beanflags & BOUND) != 0)
|
||||
buffer.append("\nBound: true");
|
||||
|
||||
if ((beanflags & EXPERT) != 0)
|
||||
buffer.append("\nExpert: true");
|
||||
|
||||
if ((beanflags & CONSTRAINED) != 0)
|
||||
buffer.append("\nConstrained: true");
|
||||
|
||||
if ((beanflags & HIDDEN) !=0)
|
||||
buffer.append("\nHidden: true");
|
||||
|
||||
if ((beanflags & PREFERRED) !=0)
|
||||
|
||||
if (attribs != null)
|
||||
buffer.append(attribs.toString());
|
||||
|
||||
if (enums != null)
|
||||
buffer.append(enums.toString());
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,447 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package build.tools.swingbeaninfo;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.MethodDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
import com.sun.javadoc.Tag;
|
||||
|
||||
import java.beans.Introspector;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Properties supported and tag syntax:
|
||||
*
|
||||
* @beaninfo
|
||||
* bound: flag
|
||||
* constrained: flag
|
||||
* expert: flag
|
||||
* hidden: flag
|
||||
* preferred: flag
|
||||
* description: string
|
||||
* displayname: string
|
||||
* propertyeditorclass: string (with dots: foo.bar.MyPropertyEditor
|
||||
* customizerclass: string (w/dots: foo.bar.MyCustomizer)
|
||||
* attribute: key1 value1
|
||||
* attribute: key2 value2
|
||||
*
|
||||
* TODO: getValue and genDocletInfo needs some cleaning.
|
||||
*
|
||||
* @author Hans Muller
|
||||
* @author Rich Schiavi
|
||||
* @author Mark Davidson
|
||||
*/
|
||||
public class GenDocletBeanInfo {
|
||||
|
||||
static String[] ATTRIBUTE_NAMES = { "bound",
|
||||
"constrained",
|
||||
"expert",
|
||||
"hidden",
|
||||
"preferred",
|
||||
"displayname",
|
||||
"propertyeditorclass",
|
||||
"customizerclass",
|
||||
"displayname",
|
||||
"description",
|
||||
"enum",
|
||||
"attribute" };
|
||||
private static boolean DEBUG = false;
|
||||
|
||||
private static String fileDir = "";
|
||||
private static String templateDir = "";
|
||||
|
||||
public static final String TRUE = "true";
|
||||
public static final String FALSE = "false";
|
||||
|
||||
/**
|
||||
* Method called from the javadoc environment to determint the options length.
|
||||
* Doclet options:
|
||||
* -t template location
|
||||
* -d outputdir
|
||||
* -x true Enable debug output.
|
||||
*/
|
||||
public static int optionLength(String option) {
|
||||
// remind: this needs to be cleaned up
|
||||
if (option.equals("-t"))
|
||||
return 2;
|
||||
if (option.equals("-d"))
|
||||
return 2;
|
||||
if (option.equals("-x"))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @beaninfo
|
||||
* bound:true
|
||||
* constrained:false
|
||||
* expert:true
|
||||
* hidden:true
|
||||
* preferred:false
|
||||
* description: the description of this method can
|
||||
* do all sorts of funky things. if it \n
|
||||
* is indented like this, we have to remove
|
||||
* all char spaces greater than 2 and also any hard-coded \n
|
||||
* newline characters and all newlines
|
||||
* displayname: theString
|
||||
* propertyeditorclass: foo.bar.MyPropertyEditorClass
|
||||
* customizerclass: foo.bar.MyCustomizerClass
|
||||
* attribute:key1 value1
|
||||
* attribute: key2 value2
|
||||
*
|
||||
*/
|
||||
public static boolean start(RootDoc doc) {
|
||||
readOptions(doc.options());
|
||||
|
||||
if (templateDir.length() == 0) {
|
||||
System.err.println("-t option not specified");
|
||||
return false;
|
||||
}
|
||||
if (fileDir.length() == 0) {
|
||||
System.err.println("-d option not specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
GenSwingBeanInfo generator = new GenSwingBeanInfo(fileDir, templateDir, DEBUG);
|
||||
Hashtable dochash = new Hashtable();
|
||||
DocBeanInfo dbi;
|
||||
|
||||
/* "javadoc Foo.java Bar.java" will return:
|
||||
* "Foo Foo.I1 Foo.I2 Bar Bar.I1 Bar.I2"
|
||||
* i.e., with all the innerclasses of classes specified in the command
|
||||
* line. We don't want to generate BeanInfo for any of these inner
|
||||
* classes, so we ignore these by remembering what the last outer
|
||||
* class was. A hack, I admit, but makes the build faster.
|
||||
*/
|
||||
String previousClass = null;
|
||||
|
||||
ClassDoc[] classes = doc.classes();
|
||||
|
||||
for (int cnt = 0; cnt < classes.length; cnt++) {
|
||||
String className = classes[cnt].qualifiedName();
|
||||
if (previousClass != null &&
|
||||
className.startsWith(previousClass) &&
|
||||
className.charAt(previousClass.length()) == '.') {
|
||||
continue;
|
||||
}
|
||||
previousClass = className;
|
||||
|
||||
// XXX - debug
|
||||
System.out.println("\n>>> Generating beaninfo for " + className + "...");
|
||||
|
||||
// Examine the javadoc tags and look for the the @beaninfo tag
|
||||
// This first block looks at the javadoc for the class
|
||||
Tag[] tags = classes[cnt].tags();
|
||||
for (int i = 0; i < tags.length; i++) {
|
||||
if (tags[i].kind().equalsIgnoreCase("@beaninfo")) {
|
||||
if (DEBUG)
|
||||
System.out.println("GenDocletBeanInfo: found @beaninfo tagged Class: " + tags[i].text());
|
||||
dbi = genDocletInfo(tags[i].text(), classes[cnt].name());
|
||||
dochash.put(dbi.name, dbi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This block looks at the javadoc for the class methods.
|
||||
int startPos = -1;
|
||||
MethodDoc[] methods = classes[cnt].methods();
|
||||
for (int j = 0; j < methods.length; j++) {
|
||||
// actually don't "introspect" - look for all
|
||||
// methods with a @beaninfo tag
|
||||
tags = methods[j].tags();
|
||||
for (int x = 0; x < tags.length; x++){
|
||||
if (tags[x].kind().equalsIgnoreCase("@beaninfo")){
|
||||
if ((methods[j].name().startsWith("get")) ||
|
||||
(methods[j].name().startsWith("set")))
|
||||
startPos = 3;
|
||||
else if (methods[j].name().startsWith("is"))
|
||||
startPos = 2;
|
||||
else
|
||||
startPos = 0;
|
||||
String propDesc =
|
||||
Introspector.decapitalize((methods[j].name()).substring(startPos));
|
||||
if (DEBUG)
|
||||
System.out.println("GenDocletBeanInfo: found @beaninfo tagged Method: " + tags[x].text());
|
||||
dbi = genDocletInfo(tags[x].text(), propDesc);
|
||||
dochash.put(dbi.name, dbi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
// dump our classes doc beaninfo
|
||||
System.out.println(">>>>DocletBeanInfo for class: " + classes[cnt].name());
|
||||
Enumeration e = dochash.elements();
|
||||
while (e.hasMoreElements()) {
|
||||
DocBeanInfo db = (DocBeanInfo)e.nextElement();
|
||||
System.out.println(db.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Use the generator to create the beaninfo code for the class.
|
||||
generator.genBeanInfo(classes[cnt].containingPackage().name(),
|
||||
classes[cnt].name(), dochash);
|
||||
// reset the values!
|
||||
dochash.clear();
|
||||
} // end for loop
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the command line options.
|
||||
* Side Effect, sets class variables templateDir, fileDir and DEBUG
|
||||
*/
|
||||
private static void readOptions(String[][] options) {
|
||||
// Parse the command line args
|
||||
for (int i = 0; i < options.length; i++){
|
||||
if (options[i][0].equals("-t")) {
|
||||
templateDir = options[i][1];
|
||||
} else if (options[i][0].equals("-d")) {
|
||||
fileDir = options[i][1];
|
||||
} else if (options[i][0].equals("-x")){
|
||||
if (options[i][1].equals("true"))
|
||||
DEBUG=true;
|
||||
else
|
||||
DEBUG=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "BeanInfo" data structure from the tag. This is a data structure
|
||||
* which contains all beaninfo data for a method or a class.
|
||||
*
|
||||
* @param text All the text after the @beaninfo tag.
|
||||
* @param name Name of the property i.e., mnemonic for setMnemonic
|
||||
*/
|
||||
private static DocBeanInfo genDocletInfo(String text, String name) {
|
||||
int beanflags = 0;
|
||||
String desc = "null";
|
||||
String displayname = "null";
|
||||
String propertyeditorclass = "null";
|
||||
String customizerclass = "null";
|
||||
String value = "null";
|
||||
HashMap attribs = null;
|
||||
HashMap enums = null;
|
||||
|
||||
int index;
|
||||
|
||||
for (int j = 0; j < ATTRIBUTE_NAMES.length; j++){
|
||||
index = 0;
|
||||
if ((index = text.indexOf(ATTRIBUTE_NAMES[j])) != -1){
|
||||
value = getValue((text).substring(index),ATTRIBUTE_NAMES[j]);
|
||||
|
||||
if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("attribute")) {
|
||||
attribs = getAttributeMap(value, " ");
|
||||
}
|
||||
if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("enum")) {
|
||||
enums = getAttributeMap(value, " \n");
|
||||
}
|
||||
else if (ATTRIBUTE_NAMES[j].equals("displayname")){
|
||||
displayname = value;
|
||||
}
|
||||
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("propertyeditorclass")) {
|
||||
propertyeditorclass = value;
|
||||
}
|
||||
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("customizerclass")){
|
||||
customizerclass = value;
|
||||
}
|
||||
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("bound"))
|
||||
&& (value.equalsIgnoreCase(TRUE)))
|
||||
beanflags = beanflags | DocBeanInfo.BOUND;
|
||||
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("expert"))
|
||||
&& (value.equalsIgnoreCase(TRUE)))
|
||||
beanflags = beanflags | DocBeanInfo.EXPERT;
|
||||
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("constrained"))
|
||||
&& (value.equalsIgnoreCase(TRUE)))
|
||||
beanflags = beanflags | DocBeanInfo.CONSTRAINED;
|
||||
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("hidden"))
|
||||
&& (value.equalsIgnoreCase(TRUE)))
|
||||
beanflags = beanflags | DocBeanInfo.HIDDEN;
|
||||
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("preferred"))
|
||||
&& (value.equalsIgnoreCase(TRUE)))
|
||||
beanflags = beanflags | DocBeanInfo.PREFERRED;
|
||||
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("description")){
|
||||
desc = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** here we create our doclet-beaninfo data structure, which we read in
|
||||
* later if it has anything worthwhile
|
||||
*/
|
||||
|
||||
// Construct a new Descriptor class
|
||||
return new DocBeanInfo(name, beanflags, desc,displayname,
|
||||
propertyeditorclass, customizerclass,
|
||||
attribs, enums);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the substring and returns the cleaned up value for the attribute.
|
||||
* @param substring Full String of the attrib tag.
|
||||
* i.e., "attribute: visualUpdate true" will return "visualUpdate true";
|
||||
*/
|
||||
private static String getValue(String substring, String prop) {
|
||||
StringTokenizer t;
|
||||
String value = "null";
|
||||
|
||||
try {
|
||||
/** if the ATTRIBUTE_NAMES is NOT the description, then we
|
||||
* parse until newline
|
||||
* if it is the description we read until the next token
|
||||
* and then look for a match in the last MAXMATCH index
|
||||
* and truncate the description
|
||||
* if it is the attribute we wead until no more
|
||||
*/
|
||||
if (prop.equalsIgnoreCase("attribute")){
|
||||
StringBuffer tmp = new StringBuffer();
|
||||
try {
|
||||
t = new StringTokenizer(substring, " :\n");
|
||||
t.nextToken().trim();//the prop
|
||||
// we want to return : key1 value1 key2 value2
|
||||
while (t.hasMoreTokens()){
|
||||
tmp.append(t.nextToken().trim()).append(" ");
|
||||
tmp.append(t.nextToken().trim()).append(" ");
|
||||
String test = t.nextToken().trim();
|
||||
if (!(test.equalsIgnoreCase("attribute")))
|
||||
break;
|
||||
}
|
||||
} catch (Exception e){
|
||||
}
|
||||
value = tmp.toString();
|
||||
}
|
||||
else if (prop.equalsIgnoreCase("enum")){
|
||||
t = new StringTokenizer(substring, ":");
|
||||
t.nextToken().trim(); // the prop we already know
|
||||
StringBuffer tmp = new StringBuffer(t.nextToken().trim());
|
||||
for (int i = 0; i < ATTRIBUTE_NAMES.length; i++){
|
||||
if (tmp.toString().endsWith(ATTRIBUTE_NAMES[i])){
|
||||
int len = ATTRIBUTE_NAMES[i].length();
|
||||
// trim off that
|
||||
tmp.setLength(tmp.length() - len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
value = tmp.toString();
|
||||
}
|
||||
else if (prop.equalsIgnoreCase("description")){
|
||||
t = new StringTokenizer(substring, ":");
|
||||
t.nextToken().trim(); // the prop we already know
|
||||
StringBuffer tmp = new StringBuffer(t.nextToken().trim());
|
||||
for (int i = 0; i < ATTRIBUTE_NAMES.length; i++){
|
||||
if (tmp.toString().endsWith(ATTRIBUTE_NAMES[i])){
|
||||
int len = ATTRIBUTE_NAMES[i].length();
|
||||
// trim off that
|
||||
tmp.setLength(tmp.length() - len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
value = hansalizeIt(tmp.toString());
|
||||
}
|
||||
else {
|
||||
// Single value properties like bound: true
|
||||
t = new StringTokenizer(substring, ":\n");
|
||||
t.nextToken().trim(); // the prop we already know
|
||||
value = t.nextToken().trim();
|
||||
}
|
||||
|
||||
// now we need to look for a match of any of the
|
||||
// property
|
||||
|
||||
return value;
|
||||
}
|
||||
catch (Exception e){
|
||||
return "invalidValue";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HashMap containing the key value pair for the parsed values
|
||||
* of the "attributes" and "enum" tags.
|
||||
* ie. For attribute value: visualUpdate true
|
||||
* The HashMap will have key: visualUpdate, value: true
|
||||
*/
|
||||
private static HashMap getAttributeMap(String str, String delim) {
|
||||
StringTokenizer t = new StringTokenizer(str, delim);
|
||||
HashMap map = null;
|
||||
String key;
|
||||
String value;
|
||||
|
||||
int num = t.countTokens()/2;
|
||||
if (num > 0) {
|
||||
map = new HashMap();
|
||||
for (int i = 0; i < num; i++) {
|
||||
key = t.nextToken().trim();
|
||||
value = t.nextToken().trim();
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// looks for extra spaces, \n hard-coded and invisible,etc
|
||||
private static String hansalizeIt(String from){
|
||||
char [] chars = from.toCharArray();
|
||||
int len = chars.length;
|
||||
int toss = 0;
|
||||
|
||||
// remove double spaces
|
||||
for (int i = 0; i < len; i++){
|
||||
if ((chars[i] == ' ')) {
|
||||
if (i+1 < len) {
|
||||
if ((chars[i+1] == ' ' ) || (chars[i+1] == '\n'))
|
||||
{
|
||||
--len;
|
||||
System.arraycopy(chars,i+1,chars,i,len-i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chars[i] == '\n'){
|
||||
chars[i] = ' ';
|
||||
i -= 2;
|
||||
}
|
||||
|
||||
if (chars[i] == '\\') {
|
||||
if (i+1 < len) {
|
||||
if (chars[i+1] == 'n'){
|
||||
chars[i+1] = ' ';
|
||||
--len;
|
||||
System.arraycopy(chars,i+1, chars,i, len-i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new String(chars,0,len);
|
||||
}
|
||||
|
||||
}
|
@ -1,532 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package build.tools.swingbeaninfo;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A utlity for generating a BeanInfo source file from a template and a
|
||||
* Hashtable with hints that were generated from a doclet.
|
||||
* it's neccessary to write things like the per property descriptions
|
||||
* by hand. To run the application:
|
||||
* <pre>
|
||||
* java GenSwingBeanInfo <class name>
|
||||
* </pre>
|
||||
* Code for a bean info class is written to out. If the class is
|
||||
* swing package, you don't need to fully specify its name.
|
||||
*
|
||||
* @author Hans Muller
|
||||
* @author Rich Schiavi
|
||||
* @author Mark Davidson
|
||||
*/
|
||||
public class GenSwingBeanInfo {
|
||||
private final static String BEANINFO_SUFFIX = "BeanInfo.java";
|
||||
|
||||
// Tokens in @(...)
|
||||
private final static String TOK_BEANPACKAGE = "BeanPackageName";
|
||||
private final static String TOK_BEANCLASS = "BeanClassName";
|
||||
private final static String TOK_BEANOBJECT = "BeanClassObject";
|
||||
private final static String TOK_CLASSDESC = "ClassDescriptors";
|
||||
private final static String TOK_BEANDESC = "BeanDescription";
|
||||
private final static String TOK_PROPDESC = "BeanPropertyDescriptors";
|
||||
private final static String TOK_ENUMVARS = "EnumVariables";
|
||||
|
||||
private String enumcode; // Generated code for enumerated properties.
|
||||
|
||||
private boolean DEBUG = false;
|
||||
|
||||
private String fileDir;
|
||||
private String templateFilename;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
* @param fileDir Location to put the generated source files.
|
||||
* @param templateFilename Location of the BeanInfo template
|
||||
* @param debug Flag to turn on debugging
|
||||
*/
|
||||
public GenSwingBeanInfo(String fileDir, String templateFilename, boolean debug) {
|
||||
this.fileDir = fileDir;
|
||||
this.templateFilename = templateFilename;
|
||||
this.DEBUG = debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a BeanInfo PrintStream for the class.
|
||||
*/
|
||||
private PrintStream initOutputFile(String classname) {
|
||||
try {
|
||||
OutputStream out = new FileOutputStream(fileDir + File.separator + classname + BEANINFO_SUFFIX);
|
||||
BufferedOutputStream bout = new BufferedOutputStream(out);
|
||||
return new PrintStream(out);
|
||||
} catch (IOException e){
|
||||
// System.err.println("GenSwingBeanInfo: " + e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void messageAndExit(String msg) {
|
||||
System.err.println("\n" + msg);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load the contents of the BeanInfo template into a string and
|
||||
* return the string.
|
||||
*/
|
||||
private String loadTemplate() {
|
||||
String template = "<no template>";
|
||||
|
||||
try {
|
||||
File file = new File(templateFilename);
|
||||
DataInputStream stream = new DataInputStream(new FileInputStream(file));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
int c;
|
||||
while((c = reader.read()) != -1) {
|
||||
buffer.append((char)c);
|
||||
}
|
||||
|
||||
template = buffer.toString();
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
messageAndExit("GenSwingBeanInfo: Couldn't load template: " + templateFilename + e);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a string for the BeanDescriptor
|
||||
*/
|
||||
private String genBeanDescriptor(DocBeanInfo dbi) {
|
||||
String code = "";
|
||||
int beanflags = dbi.beanflags;
|
||||
|
||||
// we support export, hidden, preferred
|
||||
if ((beanflags & DocBeanInfo.EXPERT) != 0)
|
||||
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
|
||||
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
|
||||
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
|
||||
/* 1.2 only - make sure build flag build using 1.2 */
|
||||
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
|
||||
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
|
||||
if (!(dbi.customizerclass.equals("null")))
|
||||
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
|
||||
|
||||
if (dbi.attribs != null) {
|
||||
code += genAttributes(dbi.attribs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code for the attributes table.
|
||||
*/
|
||||
private String genAttributes(HashMap attribs) {
|
||||
StringBuffer code = new StringBuffer();
|
||||
String key;
|
||||
String value;
|
||||
|
||||
Iterator iterator = attribs.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
key = (String)iterator.next();
|
||||
value = (String)attribs.get(key);
|
||||
|
||||
if (value.equals("true") || value.equals("false")) {
|
||||
// Substitute the "true" and "false" for codegen Boolean values.
|
||||
if(value.equals("true"))
|
||||
value = "Boolean.TRUE";
|
||||
else
|
||||
value = "Boolean.FALSE";
|
||||
|
||||
code.append(" \"").append(key).append("\", ").append(value).append(",\n");
|
||||
} else {
|
||||
code.append(" \"").append(key).append("\", \"").append(value).append("\",\n");
|
||||
}
|
||||
}
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code for the enumeration.
|
||||
* XXX - side effect: Modifies the enumcode field variable.
|
||||
*/
|
||||
private String genEnumeration(String propName, HashMap enums) {
|
||||
String objectName = propName + "Enumeration";
|
||||
String key;
|
||||
String value;
|
||||
|
||||
StringBuffer code = new StringBuffer("\n\t\tObject[] ");
|
||||
code.append(objectName).append(" = new Object[] { \n");
|
||||
|
||||
Iterator iterator = enums.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
key = (String)iterator.next();
|
||||
value = (String)enums.get(key);
|
||||
|
||||
code.append("\t\t\t\"").append(key).append("\" , new Integer(");
|
||||
code.append(value).append("), \"").append(value).append("\",\n");
|
||||
}
|
||||
// Close the statically initialized Object[]
|
||||
code.replace(code.length() - 2, code.length(), "\n\t\t};\n");
|
||||
|
||||
// Add this string to the enumeration code.
|
||||
enumcode += code.toString();
|
||||
|
||||
// Return the PropertyDescriptor init string;
|
||||
return " \"enumerationValues\", " + objectName + ",\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the createPropertyDescriptor() calls, one per property.
|
||||
* A fully specified createPropertyDescriptor() call looks like this:
|
||||
* <pre>
|
||||
* createPropertyDescriptor("contentPane", new Object[] {
|
||||
* BOUND, Boolean.TRUE,
|
||||
* CONSTRAINED, Boolean.TRUE,
|
||||
* PROPERTYEDITORCLASS, package.MyEditor.cl
|
||||
* WRITEMETHOD, "setContentPane",
|
||||
* DISPLAYNAME, "contentPane",
|
||||
* EXPERT, Boolean.FALSE,
|
||||
* HIDDEN, Boolean.FALSE,
|
||||
* PREFERRED, Boolean.TRUE,
|
||||
* SHORTDESCRIPTION, "A top level window with a window manager border",
|
||||
* "random attribute","random value"
|
||||
* }
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* @param info The actual BeanInfo class generated from from the Intospector.
|
||||
* @param dochash Set of DocBeanInfo pairs for each property. This information
|
||||
* is used to suplement the instrospected properties.
|
||||
* @return A snippet of source code which would construct all the PropertyDescriptors.
|
||||
*/
|
||||
private String genPropertyDescriptors(BeanInfo info, Hashtable dochash) {
|
||||
String code = "";
|
||||
enumcode = " "; // code for enumerated properties.
|
||||
PropertyDescriptor[] pds = info.getPropertyDescriptors();
|
||||
boolean hash_match = false;
|
||||
DocBeanInfo dbi = null;
|
||||
|
||||
for(int i = 0; i < pds.length; i++) {
|
||||
if (pds[i].getReadMethod() != null) {
|
||||
code += "\ncreatePropertyDescriptor(\"" + pds[i].getName() + "\", new Object[] {\n";
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Introspected propertyDescriptor: " + pds[i].getName());
|
||||
|
||||
if (dochash.size() > 0 && dochash.containsKey(pds[i].getName())) {
|
||||
dbi = (DocBeanInfo)dochash.remove(pds[i].getName());
|
||||
// override/set properties on this *introspected*
|
||||
// BeanInfo pds using our DocBeanInfo class values
|
||||
setDocInfoProps(dbi, pds[i]);
|
||||
hash_match = true;
|
||||
if (DEBUG)
|
||||
System.out.println("DocBeanInfo class exists for propertyDescriptor: " + pds[i].getName() + "\n");
|
||||
} else {
|
||||
hash_match = false;
|
||||
}
|
||||
|
||||
// Do I need to do anything with this property descriptor
|
||||
if (hash_match) {
|
||||
if ((dbi.beanflags & DocBeanInfo.BOUND) != 0) {
|
||||
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.TRUE,\n";
|
||||
} else {
|
||||
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.FALSE,\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (pds[i].isConstrained()) {
|
||||
code += " sun.swing.BeanInfoUtils.CONSTRAINED, Boolean.TRUE,\n";
|
||||
}
|
||||
|
||||
if (pds[i].getPropertyEditorClass() != null) {
|
||||
String className = pds[i].getPropertyEditorClass().getName();
|
||||
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + className + ".class,\n";
|
||||
} else if ((hash_match) && (!(dbi.propertyeditorclass.equals("null")))) {
|
||||
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + dbi.propertyeditorclass + ".class,\n";
|
||||
}
|
||||
|
||||
if ((hash_match) && (!(dbi.customizerclass.equals("null")))) {
|
||||
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
|
||||
}
|
||||
|
||||
if ((hash_match) && (dbi.enums != null)) {
|
||||
code += genEnumeration(pds[i].getName(), dbi.enums);
|
||||
}
|
||||
|
||||
if (!pds[i].getDisplayName().equals(pds[i].getName())) {
|
||||
code += " sun.swing.BeanInfoUtils.DISPLAYNAME, \"" + pds[i].getDisplayName() + "\",\n";
|
||||
}
|
||||
|
||||
if (pds[i].isExpert()) {
|
||||
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
|
||||
}
|
||||
|
||||
if (pds[i].isHidden()) {
|
||||
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
|
||||
}
|
||||
|
||||
if (pds[i].isPreferred()) {
|
||||
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
|
||||
}
|
||||
|
||||
// user attributes
|
||||
if (hash_match) {
|
||||
if (dbi.attribs != null) {
|
||||
code += genAttributes(dbi.attribs);
|
||||
}
|
||||
}
|
||||
code += " sun.swing.BeanInfoUtils.SHORTDESCRIPTION, \"" + pds[i].getShortDescription() + "\",\n";
|
||||
|
||||
// Print the closing brackets. If this is the last array initializer,
|
||||
// don't print the trailing comma.
|
||||
if (i == (pds.length - 1)) {
|
||||
code += " }\n)\n";
|
||||
} else {
|
||||
code += " }\n),\n";
|
||||
}
|
||||
|
||||
} // end if ( readMethod != null )
|
||||
} // end for
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets properties from the BeanInfo supplement on the
|
||||
* introspected PropertyDescriptor
|
||||
*/
|
||||
private void setDocInfoProps(DocBeanInfo dbi, PropertyDescriptor pds) {
|
||||
int beanflags = dbi.beanflags;
|
||||
|
||||
if ((beanflags & DocBeanInfo.BOUND) != 0)
|
||||
pds.setBound(true);
|
||||
if ((beanflags & DocBeanInfo.EXPERT) != 0)
|
||||
pds.setExpert(true);
|
||||
if ((beanflags & DocBeanInfo.CONSTRAINED) != 0)
|
||||
pds.setConstrained(true);
|
||||
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
|
||||
pds.setHidden(true);
|
||||
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
|
||||
pds.setPreferred(true);
|
||||
|
||||
if (!(dbi.desc.equals("null"))){
|
||||
pds.setShortDescription(dbi.desc);
|
||||
}
|
||||
if (!(dbi.displayname.equals("null"))){
|
||||
pds.setDisplayName(dbi.displayname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the BeanInfo source file using instrospection and a
|
||||
* Hashtable full of hints. This the only public method in this class.
|
||||
*
|
||||
* @param classname Root name of the class. i.e., JButton
|
||||
* @param dochash A hashtable containing the DocBeanInfo.
|
||||
*/
|
||||
public void genBeanInfo(String packageName, String classname, Hashtable dochash) {
|
||||
// The following initial values are just examples. All of these
|
||||
// fields are initialized below.
|
||||
String beanClassName = "JInternalFrame";
|
||||
String beanClassObject = "javax.swing.JInternalFrame.class";
|
||||
String beanDescription = "<A description of this component>.";
|
||||
String beanPropertyDescriptors = "<createSwingPropertyDescriptor code>";
|
||||
String classPropertyDescriptors = "<createSwingClassPropertyDescriptor code>";
|
||||
|
||||
Class cls = getClass(packageName, classname);
|
||||
if (cls == null){
|
||||
messageAndExit("Can't find class: " + classname);
|
||||
}
|
||||
|
||||
// Get the output stream.
|
||||
PrintStream out = initOutputFile(classname);
|
||||
|
||||
// Run the Introspector and initialize the variables
|
||||
|
||||
BeanInfo beanInfo = null;
|
||||
BeanDescriptor beanDescriptor = null;
|
||||
|
||||
try {
|
||||
if (cls == javax.swing.JComponent.class) {
|
||||
// Go all the way up the heirarchy for JComponent
|
||||
beanInfo = Introspector.getBeanInfo(cls);
|
||||
} else {
|
||||
beanInfo = Introspector.getBeanInfo(cls, cls.getSuperclass());
|
||||
}
|
||||
beanDescriptor = beanInfo.getBeanDescriptor();
|
||||
beanDescription = beanDescriptor.getShortDescription();
|
||||
} catch (IntrospectionException e) {
|
||||
messageAndExit("Introspection failed for " + cls.getName() + " " + e);
|
||||
}
|
||||
|
||||
beanClassName = beanDescriptor.getName();
|
||||
beanClassObject = cls.getName() + ".class";
|
||||
|
||||
if (DEBUG){
|
||||
System.out.println(">>>>GenSwingBeanInfo class: " + beanClassName);
|
||||
}
|
||||
// Generate the Class BeanDescriptor information first
|
||||
if (dochash.size() > 0) {
|
||||
if (dochash.containsKey(beanClassName)) {
|
||||
DocBeanInfo dbi = (DocBeanInfo)dochash.remove(beanClassName);
|
||||
classPropertyDescriptors = genBeanDescriptor(dbi);
|
||||
if (DEBUG)
|
||||
System.out.println("ClassPropertyDescriptors: " + classPropertyDescriptors);
|
||||
if (!(dbi.desc.equals("null")))
|
||||
beanDescription = dbi.desc;
|
||||
} else
|
||||
beanDescription = beanDescriptor.getShortDescription();
|
||||
} else
|
||||
beanDescription = beanDescriptor.getShortDescription();
|
||||
|
||||
// Generate the Property descriptors
|
||||
beanPropertyDescriptors = genPropertyDescriptors(beanInfo,dochash);
|
||||
|
||||
// Dump the template to out, substituting values for
|
||||
// @(token) tokens as they're encountered.
|
||||
|
||||
int currentIndex = 0;
|
||||
// not loading this to get around build issue for now
|
||||
String template = loadTemplate();
|
||||
|
||||
// This loop substitutes the "@(...)" tags in the template with the ones for the
|
||||
// current class.
|
||||
while (currentIndex < template.length()) {
|
||||
// Find the Token
|
||||
int tokenStart = template.indexOf("@(", currentIndex);
|
||||
if (tokenStart != -1) {
|
||||
out.print(template.substring(currentIndex, tokenStart));
|
||||
|
||||
int tokenEnd = template.indexOf(")", tokenStart);
|
||||
if (tokenEnd == -1) {
|
||||
messageAndExit("Bad @(<token>) beginning at " + tokenStart);
|
||||
}
|
||||
String token = template.substring(tokenStart+2, tokenEnd);
|
||||
|
||||
if (token.equals(TOK_BEANCLASS)) {
|
||||
out.print(beanClassName);
|
||||
} else if (token.equals(TOK_CLASSDESC)) {
|
||||
if (!(classPropertyDescriptors.equals("<createSwingClassPropertyDescriptor code>"))) {
|
||||
printDescriptors(out, classPropertyDescriptors, template, tokenStart);
|
||||
}
|
||||
} else if (token.equals(TOK_BEANPACKAGE)){
|
||||
out.print(packageName);
|
||||
} else if (token.equals(TOK_BEANOBJECT)) {
|
||||
out.print(beanClassObject);
|
||||
} else if (token.equals(TOK_BEANDESC)) {
|
||||
out.print(beanDescription);
|
||||
} else if (token.equals(TOK_ENUMVARS)){
|
||||
out.print(enumcode);
|
||||
} else if (token.equals(TOK_PROPDESC)) {
|
||||
printDescriptors(out, beanPropertyDescriptors, template, tokenStart);
|
||||
} else if (token.equals("#")) {
|
||||
// Ignore the @(#) Version Control tag if it exists.
|
||||
} else {
|
||||
messageAndExit("Unrecognized token @(" + token + ")");
|
||||
}
|
||||
currentIndex = tokenEnd + 1;
|
||||
} else {
|
||||
// tokenStart == -1 - We are finsihed.
|
||||
out.print(template.substring(currentIndex, template.length()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class from the package name and the class root name.
|
||||
*
|
||||
* @param packageName The name of the package of the containing class.
|
||||
* @param rootname The root name of the class. i.e, JButton
|
||||
* @return The class instance or null.
|
||||
*/
|
||||
private Class getClass(String packageName, String rootname) {
|
||||
Class cls = null;
|
||||
String classname = rootname;
|
||||
|
||||
if (packageName != null || !packageName.equals("")) {
|
||||
classname = packageName + "." + rootname;
|
||||
}
|
||||
|
||||
try {
|
||||
cls = Class.forName(classname);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Fail silently.
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the formated descriptors to the PrintStream
|
||||
* @param out Open PrintStream
|
||||
* @param s String descriptor
|
||||
* @param template Template
|
||||
* @param tokenStart Index into the template
|
||||
*/
|
||||
private void printDescriptors(PrintStream out, String s,
|
||||
String template, int tokenStart) {
|
||||
String indent = "";
|
||||
|
||||
// Find the newline that preceeds @(BeanPropertyDescriptors) to
|
||||
// calculate the indent.
|
||||
for (int i = tokenStart; i >= 0; i--) {
|
||||
if (template.charAt(i) == '\n') {
|
||||
char[] chars = new char[tokenStart - i];
|
||||
for (int j = 0; j < chars.length; j++) {
|
||||
chars[j] = ' ';
|
||||
}
|
||||
indent = new String(chars);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while(i < s.length()) {
|
||||
int nlIndex = s.indexOf('\n', i);
|
||||
out.print(s.substring(i, nlIndex+1));
|
||||
out.print(indent);
|
||||
i = nlIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -146,7 +146,7 @@ class StringCoding {
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static boolean hasNegatives(byte[] ba, int off, int len) {
|
||||
public static boolean hasNegatives(byte[] ba, int off, int len) {
|
||||
for (int i = off; i < off + len; i++) {
|
||||
if (ba[i] < 0) {
|
||||
return true;
|
||||
|
@ -41,7 +41,7 @@ class InfoFromMemberName implements MethodHandleInfo {
|
||||
private final int referenceKind;
|
||||
|
||||
InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
|
||||
assert(member.isResolved() || member.isMethodHandleInvoke());
|
||||
assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());
|
||||
assert(member.referenceKindIsConsistentWith(referenceKind));
|
||||
this.member = member;
|
||||
this.referenceKind = referenceKind;
|
||||
@ -79,7 +79,8 @@ class InfoFromMemberName implements MethodHandleInfo {
|
||||
|
||||
@Override
|
||||
public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
|
||||
if (member.isMethodHandleInvoke() && !member.isVarargs()) {
|
||||
if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())
|
||||
&& !member.isVarargs()) {
|
||||
// This member is an instance of a signature-polymorphic method, which cannot be reflected
|
||||
// A method handle invoker can come in either of two forms:
|
||||
// A generic placeholder (present in the source code, and varargs)
|
||||
|
@ -93,6 +93,16 @@ class Invokers {
|
||||
return setCachedInvoker(INV_BASIC, invoker);
|
||||
}
|
||||
|
||||
/*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
|
||||
// TODO cache invoker
|
||||
return makeVarHandleMethodInvoker(ak);
|
||||
}
|
||||
|
||||
/*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
|
||||
// TODO cache invoker
|
||||
return makeVarHandleMethodExactInvoker(ak);
|
||||
}
|
||||
|
||||
private MethodHandle cachedInvoker(int idx) {
|
||||
return invokers[idx];
|
||||
}
|
||||
@ -117,6 +127,36 @@ class Invokers {
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
|
||||
MethodType mtype = targetType;
|
||||
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
|
||||
|
||||
LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.name(), mtype);
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
|
||||
|
||||
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
|
||||
assert(checkVarHandleInvoker(invoker));
|
||||
|
||||
maybeCompileToBytecode(invoker);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
|
||||
MethodType mtype = targetType;
|
||||
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
|
||||
|
||||
LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.name(), mtype);
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
|
||||
|
||||
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
|
||||
assert(checkVarHandleInvoker(invoker));
|
||||
|
||||
maybeCompileToBytecode(invoker);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
|
||||
private void maybeCompileToBytecode(MethodHandle invoker) {
|
||||
final int EAGER_COMPILE_ARITY_LIMIT = 10;
|
||||
@ -146,6 +186,16 @@ class Invokers {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkVarHandleInvoker(MethodHandle invoker) {
|
||||
MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class);
|
||||
assert(invokerType.equals(invoker.type()))
|
||||
: java.util.Arrays.asList(targetType, invokerType, invoker);
|
||||
assert(invoker.internalMemberName() == null ||
|
||||
invoker.internalMemberName().getMethodType().equals(targetType));
|
||||
assert(!invoker.isVarargsCollector());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create an invoker which passes unchanged a given number of arguments
|
||||
* and spreads the rest from a trailing array argument.
|
||||
@ -193,9 +243,9 @@ class Invokers {
|
||||
Object[] appendixResult) {
|
||||
int which;
|
||||
switch (name) {
|
||||
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
|
||||
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
|
||||
default: throw new InternalError("not invoker: "+name);
|
||||
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
|
||||
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
|
||||
default: throw new InternalError("not invoker: "+name);
|
||||
}
|
||||
LambdaForm lform;
|
||||
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
|
||||
@ -296,6 +346,199 @@ class Invokers {
|
||||
return lform;
|
||||
}
|
||||
|
||||
|
||||
static MemberName varHandleInvokeLinkerMethod(String name,
|
||||
MethodType mtype) {
|
||||
LambdaForm lform;
|
||||
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
|
||||
lform = varHandleMethodGenericLinkerHandleForm(name, mtype);
|
||||
} else {
|
||||
// TODO
|
||||
throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
|
||||
}
|
||||
return lform.vmentry;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodGenericLinkerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_VH = 0;
|
||||
final int ARG_BASE = THIS_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[THIS_VH], names[VAD_ARG]);
|
||||
|
||||
Object[] outArgs = new Object[ARG_LIMIT + 1];
|
||||
outArgs[0] = names[CHECK_TYPE];
|
||||
for (int i = 0; i < ARG_LIMIT; i++) {
|
||||
outArgs[i + 1] = names[i];
|
||||
}
|
||||
|
||||
if (CHECK_CUSTOM != -1) {
|
||||
names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
|
||||
}
|
||||
|
||||
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType();
|
||||
names[LINKER_CALL] = new Name(outCallType, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT + 1, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_MH = 0;
|
||||
final int CALL_VH = THIS_MH + 1;
|
||||
final int ARG_BASE = CALL_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int GET_MEMBER = nameCursor++;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType()
|
||||
.appendParameterTypes(MemberName.class);
|
||||
|
||||
MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
|
||||
try {
|
||||
linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
|
||||
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
|
||||
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
|
||||
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
|
||||
|
||||
NamedFunction getter = speciesData.getterFunction(0);
|
||||
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
|
||||
|
||||
Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
|
||||
|
||||
names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
|
||||
outArgs[outArgs.length - 1] = names[GET_MEMBER];
|
||||
|
||||
names[LINKER_CALL] = new Name(linker, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_MH = 0;
|
||||
final int CALL_VH = THIS_MH + 1;
|
||||
final int ARG_BASE = CALL_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
|
||||
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
|
||||
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
|
||||
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
|
||||
|
||||
NamedFunction getter = speciesData.getterFunction(0);
|
||||
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
|
||||
|
||||
Object[] outArgs = new Object[ARG_LIMIT];
|
||||
outArgs[0] = names[CHECK_TYPE];
|
||||
for (int i = 1; i < ARG_LIMIT; i++) {
|
||||
outArgs[i] = names[i];
|
||||
}
|
||||
|
||||
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType();
|
||||
names[LINKER_CALL] = new Name(outCallType, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null)
|
||||
throw vh.unsupported();
|
||||
// TODO the following MH is not constant, cache in stable field array
|
||||
// on VarForm?
|
||||
MethodHandle mh = DirectMethodHandle.make(mn);
|
||||
if (actual == expected) {
|
||||
return mh;
|
||||
}
|
||||
else {
|
||||
// Adapt to the actual (which should never fail since mh's method
|
||||
// type is in the basic form), then to the expected (which my fail
|
||||
// if the symbolic type descriptor does not match)
|
||||
// TODO optimize for the case of actual.erased() == expected.erased()
|
||||
return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
|
||||
asType(expected.insertParameterTypes(0, VarHandle.class));
|
||||
}
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
if (actual != expected)
|
||||
throw newWrongMethodTypeException(expected, actual);
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null) {
|
||||
throw vh.unsupported();
|
||||
}
|
||||
return mn;
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
|
||||
// FIXME: merge with JVM logic for throwing WMTE
|
||||
@ -415,7 +658,10 @@ class Invokers {
|
||||
NF_checkExactType,
|
||||
NF_checkGenericType,
|
||||
NF_getCallSiteTarget,
|
||||
NF_checkCustomized;
|
||||
NF_checkCustomized,
|
||||
NF_checkVarHandleGenericType,
|
||||
NF_checkVarHandleExactType,
|
||||
NF_getVarHandleMemberName;
|
||||
static {
|
||||
try {
|
||||
NamedFunction nfs[] = {
|
||||
@ -426,7 +672,13 @@ class Invokers {
|
||||
NF_getCallSiteTarget = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("getCallSiteTarget", CallSite.class)),
|
||||
NF_checkCustomized = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkCustomized", MethodHandle.class))
|
||||
.getDeclaredMethod("checkCustomized", MethodHandle.class)),
|
||||
NF_checkVarHandleGenericType = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
|
||||
NF_checkVarHandleExactType = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
|
||||
NF_getVarHandleMemberName = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
|
||||
};
|
||||
// Each nf must be statically invocable or we get tied up in our bootstraps.
|
||||
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
|
||||
|
@ -363,6 +363,23 @@ import java.util.Objects;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean isVarHandleMethodInvoke() {
|
||||
final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
|
||||
final int negs = Modifier.STATIC;
|
||||
if (testFlags(bits | negs, bits) &&
|
||||
clazz == VarHandle.class) {
|
||||
return isVarHandleMethodInvokeName(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean isVarHandleMethodInvokeName(String name) {
|
||||
try {
|
||||
VarHandle.AccessMode.valueOf(name);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
|
||||
|
||||
/** Utility method to query the modifier flags of this member. */
|
||||
@ -538,6 +555,17 @@ import java.util.Objects;
|
||||
if (isMethodHandleInvoke())
|
||||
return;
|
||||
}
|
||||
if (m.getDeclaringClass() == VarHandle.class &&
|
||||
isVarHandleMethodInvokeName(m.getName())) {
|
||||
// The JVM did not reify this signature-polymorphic instance.
|
||||
// Need a special case here.
|
||||
// See comments on MethodHandleNatives.linkMethod.
|
||||
MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
|
||||
int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
|
||||
init(VarHandle.class, m.getName(), type, flags);
|
||||
if (isVarHandleMethodInvoke())
|
||||
return;
|
||||
}
|
||||
throw new LinkageError(m.toString());
|
||||
}
|
||||
assert(isResolved() && this.clazz != null);
|
||||
@ -666,6 +694,16 @@ import java.util.Objects;
|
||||
return mem;
|
||||
}
|
||||
|
||||
static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
|
||||
return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
|
||||
}
|
||||
static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
|
||||
MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
|
||||
mem.flags |= mods; // it's not resolved, but add these modifiers anyway
|
||||
assert(mem.isVarHandleMethodInvoke()) : mem;
|
||||
return mem;
|
||||
}
|
||||
|
||||
// bare-bones constructor; the JVM will fill it in
|
||||
MemberName() { }
|
||||
|
||||
|
@ -26,9 +26,11 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
|
||||
/**
|
||||
@ -92,14 +94,16 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* and {@code invoke} compile to an {@code invokevirtual} instruction.
|
||||
* More unusually, the compiler must record the actual argument types,
|
||||
* and may not perform method invocation conversions on the arguments.
|
||||
* Instead, it must push them on the stack according to their own unconverted types.
|
||||
* The method handle object itself is pushed on the stack before the arguments.
|
||||
* The compiler then calls the method handle with a symbolic type descriptor which
|
||||
* describes the argument and return types.
|
||||
* Instead, it must generate instructions that push them on the stack according
|
||||
* to their own unconverted types. The method handle object itself is pushed on
|
||||
* the stack before the arguments.
|
||||
* The compiler then generates an {@code invokevirtual} instruction that invokes
|
||||
* the method handle with a symbolic type descriptor which describes the argument
|
||||
* and return types.
|
||||
* <p>
|
||||
* To issue a complete symbolic type descriptor, the compiler must also determine
|
||||
* the return type. This is based on a cast on the method invocation expression,
|
||||
* if there is one, or else {@code Object} if the invocation is an expression
|
||||
* if there is one, or else {@code Object} if the invocation is an expression,
|
||||
* or else {@code void} if the invocation is a statement.
|
||||
* The cast may be to a primitive type (but not {@code void}).
|
||||
* <p>
|
||||
@ -109,12 +113,12 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* {@code Void} except the null reference.
|
||||
*
|
||||
* <h1>Method handle invocation</h1>
|
||||
* The first time a {@code invokevirtual} instruction is executed
|
||||
* it is linked, by symbolically resolving the names in the instruction
|
||||
* The first time an {@code invokevirtual} instruction is executed
|
||||
* it is linked by symbolically resolving the names in the instruction
|
||||
* and verifying that the method call is statically legal.
|
||||
* This is true of calls to {@code invokeExact} and {@code invoke}.
|
||||
* This also holds for calls to {@code invokeExact} and {@code invoke}.
|
||||
* In this case, the symbolic type descriptor emitted by the compiler is checked for
|
||||
* correct syntax and names it contains are resolved.
|
||||
* correct syntax, and names it contains are resolved.
|
||||
* Thus, an {@code invokevirtual} instruction which invokes
|
||||
* a method handle will always link, as long
|
||||
* as the symbolic type descriptor is syntactically well-formed
|
||||
@ -163,7 +167,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* in a program which uses method handles.
|
||||
* <p>
|
||||
* Because method types contain "live" {@code Class} objects,
|
||||
* method type matching takes into account both types names and class loaders.
|
||||
* method type matching takes into account both type names and class loaders.
|
||||
* Thus, even if a method handle {@code M} is created in one
|
||||
* class loader {@code L1} and used in another {@code L2},
|
||||
* method handle calls are type-safe, because the caller's symbolic type
|
||||
@ -174,7 +178,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* and its type is assigned, while the resolution in {@code L2} happens
|
||||
* when the {@code invokevirtual} instruction is linked.
|
||||
* <p>
|
||||
* Apart from the checking of type descriptors,
|
||||
* Apart from type descriptor checks,
|
||||
* a method handle's capability to call its underlying method is unrestricted.
|
||||
* If a method handle is formed on a non-public method by a class
|
||||
* that has access to that method, the resulting handle can be used
|
||||
@ -196,7 +200,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* Java code can create a method handle that directly accesses
|
||||
* any method, constructor, or field that is accessible to that code.
|
||||
* This is done via a reflective, capability-based API called
|
||||
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
|
||||
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}.
|
||||
* For example, a static method handle can be obtained
|
||||
* from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
|
||||
* There are also conversion methods from Core Reflection API objects,
|
||||
|
@ -1060,6 +1060,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
|
||||
return mh;
|
||||
}
|
||||
static MethodHandle fakeVarHandleInvoke(MemberName method) {
|
||||
// TODO caching, is it necessary?
|
||||
MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
|
||||
VarHandle.class, Object[].class);
|
||||
MethodHandle mh = throwException(type);
|
||||
mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
|
||||
if (!method.getInvocationType().equals(mh.type()))
|
||||
throw new InternalError(method.toString());
|
||||
mh = mh.withInternalMemberName(method, false);
|
||||
mh = mh.asVarargsCollector(Object[].class);
|
||||
assert(method.isVarargs());
|
||||
return mh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an alias for the method handle which, when called,
|
||||
|
@ -25,12 +25,15 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
|
||||
/**
|
||||
* The JVM interface for the method handles package is all here.
|
||||
@ -367,8 +370,14 @@ class MethodHandleNatives {
|
||||
Class<?> defc, String name, Object type,
|
||||
Object[] appendixResult) {
|
||||
try {
|
||||
if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
|
||||
return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
|
||||
if (refKind == REF_invokeVirtual) {
|
||||
if (defc == MethodHandle.class) {
|
||||
return Invokers.methodHandleInvokeLinkerMethod(
|
||||
name, fixMethodType(callerClass, type), appendixResult);
|
||||
} else if (defc == VarHandle.class) {
|
||||
return varHandleOperationLinkerMethod(
|
||||
name, fixMethodType(callerClass, type), appendixResult);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
if (ex instanceof LinkageError)
|
||||
@ -400,6 +409,80 @@ class MethodHandleNatives {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the method to link to the VarHandle operation.
|
||||
* This method is located here and not in Invokers to avoid
|
||||
* intializing that and other classes early on in VM bootup.
|
||||
*/
|
||||
private static MemberName varHandleOperationLinkerMethod(String name,
|
||||
MethodType mtype,
|
||||
Object[] appendixResult) {
|
||||
// Get the signature method type
|
||||
MethodType sigType = mtype.basicType();
|
||||
|
||||
// Get the access kind from the method name
|
||||
VarHandle.AccessMode ak;
|
||||
try {
|
||||
ak = VarHandle.AccessMode.valueOf(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw MethodHandleStatics.newInternalError(e);
|
||||
}
|
||||
|
||||
// If not polymorphic in the return type, such as the compareAndSet
|
||||
// methods that return boolean
|
||||
if (ak.isPolyMorphicInReturnType) {
|
||||
if (ak.returnType != mtype.returnType()) {
|
||||
// The caller contains a different return type than that
|
||||
// defined by the method
|
||||
throw newNoSuchMethodErrorOnVarHandle(name, mtype);
|
||||
}
|
||||
// Adjust the return type of the signature method type
|
||||
sigType = sigType.changeReturnType(ak.returnType);
|
||||
}
|
||||
|
||||
// Get the guard method type for linking
|
||||
MethodType guardType = sigType
|
||||
// VarHandle at start
|
||||
.insertParameterTypes(0, VarHandle.class)
|
||||
// Access descriptor at end
|
||||
.appendParameterTypes(VarHandle.AccessDescriptor.class);
|
||||
|
||||
// Create the appendix descriptor constant
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
appendixResult[0] = ad;
|
||||
|
||||
if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
|
||||
MemberName linker = new MemberName(
|
||||
VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
|
||||
guardType, REF_invokeStatic);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
}
|
||||
}
|
||||
return Invokers.varHandleInvokeLinkerMethod(name, mtype);
|
||||
}
|
||||
static String getVarHandleMethodSignature(MethodType mt) {
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
|
||||
|
||||
for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
Class<?> pt = mt.parameterType(i);
|
||||
sb.append(getCharType(pt));
|
||||
}
|
||||
|
||||
sb.append('_').append(getCharType(mt.returnType()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
static char getCharType(Class<?> pt) {
|
||||
return Wrapper.forBasicType(pt).basicTypeChar();
|
||||
}
|
||||
static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
|
||||
return new NoSuchMethodError("VarHandle." + name + mtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
|
||||
|
@ -50,9 +50,10 @@ import jdk.internal.misc.Unsafe;
|
||||
static final int PROFILE_LEVEL;
|
||||
static final boolean PROFILE_GWT;
|
||||
static final int CUSTOMIZE_THRESHOLD;
|
||||
static final boolean VAR_HANDLE_GUARDS;
|
||||
|
||||
static {
|
||||
final Object[] values = new Object[9];
|
||||
final Object[] values = new Object[10];
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public Void run() {
|
||||
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
|
||||
@ -64,6 +65,7 @@ import jdk.internal.misc.Unsafe;
|
||||
values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
|
||||
values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
|
||||
values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
|
||||
values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -76,6 +78,7 @@ import jdk.internal.misc.Unsafe;
|
||||
PROFILE_LEVEL = (Integer) values[6];
|
||||
PROFILE_GWT = (Boolean) values[7];
|
||||
CUSTOMIZE_THRESHOLD = (Integer) values[8];
|
||||
VAR_HANDLE_GUARDS = (Boolean) values[9];
|
||||
|
||||
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
|
||||
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
|
||||
|
@ -53,6 +53,10 @@ import java.util.stream.Stream;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that operate on or return
|
||||
* method handles. They fall into several categories:
|
||||
@ -873,7 +877,14 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
|
||||
* {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
|
||||
* {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
|
||||
* with the same {@code type} argument.
|
||||
*
|
||||
* <p>
|
||||
* If the class is {@code VarHandle} and the name string corresponds to
|
||||
* the name of a signature-polymorphic access mode method, the resulting
|
||||
* method handle is equivalent to one produced by
|
||||
* {@link java.lang.invoke.MethodHandles#varHandleInvoker} with
|
||||
* the access mode corresponding to the name string and with the same
|
||||
* {@code type} arguments.
|
||||
* <p>
|
||||
* <b>Example:</b>
|
||||
* <blockquote><pre>{@code
|
||||
import static java.lang.invoke.MethodHandles.*;
|
||||
@ -920,6 +931,9 @@ assertEquals("", (String) MH_newString.invokeExact());
|
||||
if (refc == MethodHandle.class) {
|
||||
MethodHandle mh = findVirtualForMH(name, type);
|
||||
if (mh != null) return mh;
|
||||
} else if (refc == VarHandle.class) {
|
||||
MethodHandle mh = findVirtualForVH(name, type);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
|
||||
MemberName method = resolveOrFail(refKind, refc, name, type);
|
||||
@ -936,6 +950,13 @@ assertEquals("", (String) MH_newString.invokeExact());
|
||||
assert(!MemberName.isMethodHandleInvokeName(name));
|
||||
return null;
|
||||
}
|
||||
private MethodHandle findVirtualForVH(String name, MethodType type) {
|
||||
try {
|
||||
return varHandleInvoker(VarHandle.AccessMode.valueOf(name), type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle which creates an object and initializes it, using
|
||||
@ -1135,6 +1156,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @see #findVarHandle(Class, String, Class)
|
||||
*/
|
||||
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName field = resolveOrFail(REF_getField, refc, name, type);
|
||||
@ -1157,12 +1179,60 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @see #findVarHandle(Class, String, Class)
|
||||
*/
|
||||
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName field = resolveOrFail(REF_putField, refc, name, type);
|
||||
return getDirectField(REF_putField, refc, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to non-static fields of type
|
||||
* {@code T} declared by a receiver class of type {@code R}, supporting
|
||||
* shape {@code (R : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param recv the receiver class, of type {@code R}, that declares the
|
||||
* non-static field
|
||||
* @param name the field's name
|
||||
* @param type the field's type, of type {@code T}
|
||||
* @return a VarHandle giving access to non-static fields.
|
||||
* @throws NoSuchFieldException if the field does not exist
|
||||
* @throws IllegalAccessException if access checking fails, or if the field is {@code static}
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName getField = resolveOrFail(REF_getField, recv, name, type);
|
||||
MemberName putField = resolveOrFail(REF_putField, recv, name, type);
|
||||
return getFieldVarHandle(REF_getField, REF_putField, recv, getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle giving read access to a static field.
|
||||
* The type of the method handle will have a return type of the field's
|
||||
@ -1211,6 +1281,55 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
return getDirectField(REF_putStatic, refc, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to a static field of type
|
||||
* {@code T} declared by a given declaring class, supporting shape
|
||||
* {@code ((empty) : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class.
|
||||
* <p>
|
||||
* If the returned VarHandle is operated on, the declaring class will be
|
||||
* initialized, if it has not already been initialized.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param decl the class that declares the static field
|
||||
* @param name the field's name
|
||||
* @param type the field's type, of type {@code T}
|
||||
* @return a VarHandle giving access to a static field
|
||||
* @throws NoSuchFieldException if the field does not exist
|
||||
* @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName getField = resolveOrFail(REF_getStatic, decl, name, type);
|
||||
MemberName putField = resolveOrFail(REF_putStatic, decl, name, type);
|
||||
return getFieldVarHandle(REF_getStatic, REF_putStatic, decl, getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces an early-bound method handle for a non-static method.
|
||||
* The receiver must have a supertype {@code defc} in which a method
|
||||
@ -1297,6 +1416,10 @@ return mh1;
|
||||
MethodHandle mh = unreflectForMH(m);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
if (m.getDeclaringClass() == VarHandle.class) {
|
||||
MethodHandle mh = unreflectForVH(m);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
MemberName method = new MemberName(m);
|
||||
byte refKind = method.getReferenceKind();
|
||||
if (refKind == REF_invokeSpecial)
|
||||
@ -1311,6 +1434,12 @@ return mh1;
|
||||
return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
|
||||
return null;
|
||||
}
|
||||
private MethodHandle unreflectForVH(Method m) {
|
||||
// these names require special lookups because they throw UnsupportedOperationException
|
||||
if (MemberName.isVarHandleMethodInvokeName(m.getName()))
|
||||
return MethodHandleImpl.fakeVarHandleInvoke(new MemberName(m));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle for a reflected method.
|
||||
@ -1434,6 +1563,57 @@ return mh1;
|
||||
return unreflectField(f, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle that accesses fields of type {@code T} declared
|
||||
* by a class of type {@code R}, as described by the given reflected
|
||||
* field.
|
||||
* If the field is non-static the VarHandle supports a shape of
|
||||
* {@code (R : T)}, otherwise supports a shape of {@code ((empty) : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class, regardless of the value of the field's {@code accessible}
|
||||
* flag.
|
||||
* <p>
|
||||
* If the field is static, and if the returned VarHandle is operated
|
||||
* on, the field's declaring class will be initialized, if it has not
|
||||
* already been initialized.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param f the reflected field, with a field of type {@code T}, and
|
||||
* a declaring class of type {@code R}
|
||||
* @return a VarHandle giving access to non-static fields or a static
|
||||
* field
|
||||
* @throws IllegalAccessException if access checking fails
|
||||
* @throws NullPointerException if the argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
|
||||
MemberName getField = new MemberName(f, false);
|
||||
MemberName putField = new MemberName(f, true);
|
||||
return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(),
|
||||
f.getDeclaringClass(), getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
|
||||
* created by this lookup object or a similar one.
|
||||
@ -1454,7 +1634,9 @@ return mh1;
|
||||
*/
|
||||
public MethodHandleInfo revealDirect(MethodHandle target) {
|
||||
MemberName member = target.internalMemberName();
|
||||
if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
|
||||
if (member == null || (!member.isResolved() &&
|
||||
!member.isMethodHandleInvoke() &&
|
||||
!member.isVarHandleMethodInvoke()))
|
||||
throw newIllegalArgumentException("not a direct method handle");
|
||||
Class<?> defc = member.getDeclaringClass();
|
||||
byte refKind = member.getReferenceKind();
|
||||
@ -1829,6 +2011,52 @@ return mh1;
|
||||
return restrictReceiver(field, dmh, lookupClass());
|
||||
return dmh;
|
||||
}
|
||||
private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField)
|
||||
throws IllegalAccessException {
|
||||
final boolean checkSecurity = true;
|
||||
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
|
||||
}
|
||||
private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField)
|
||||
throws IllegalAccessException {
|
||||
final boolean checkSecurity = false;
|
||||
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
|
||||
}
|
||||
private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField,
|
||||
boolean checkSecurity) throws IllegalAccessException {
|
||||
assert getField.isStatic() == putField.isStatic();
|
||||
assert getField.isGetter() && putField.isSetter();
|
||||
assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind);
|
||||
assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind);
|
||||
|
||||
checkField(getRefKind, refc, getField);
|
||||
if (checkSecurity)
|
||||
checkSecurityManager(refc, getField);
|
||||
|
||||
if (!putField.isFinal()) {
|
||||
// A VarHandle does not support updates to final fields, any
|
||||
// such VarHandle to a final field will be read-only and
|
||||
// therefore the following write-based accessibility checks are
|
||||
// only required for non-final fields
|
||||
checkField(putRefKind, refc, putField);
|
||||
if (checkSecurity)
|
||||
checkSecurityManager(refc, putField);
|
||||
}
|
||||
|
||||
boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
|
||||
restrictProtectedReceiver(getField));
|
||||
if (doRestrict) {
|
||||
assert !getField.isStatic();
|
||||
// receiver type of VarHandle is too wide; narrow to caller
|
||||
if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
|
||||
throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
|
||||
}
|
||||
refc = lookupClass();
|
||||
}
|
||||
return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);
|
||||
}
|
||||
/** Check access and get the requested constructor. */
|
||||
private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
|
||||
final boolean checkSecurity = true;
|
||||
@ -2018,6 +2246,205 @@ return mh1;
|
||||
return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Produces a VarHandle giving access to elements of an array type
|
||||
* {@code T[]}, supporting shape {@code (T[], int : T)}.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the component type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the component type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* @param arrayClass the class of an array, of type {@code T[]}
|
||||
* @return a VarHandle giving access to elements of an array
|
||||
* @throws NullPointerException if the arrayClass is null
|
||||
* @throws IllegalArgumentException if arrayClass is not an array type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
|
||||
return VarHandles.makeArrayElementHandle(arrayClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to elements of a {@code byte[]} array
|
||||
* viewed as if it were a different primitive array type, such as
|
||||
* {@code int[]} or {@code long[]}. The shape of the resulting VarHandle is
|
||||
* {@code (byte[], int : T)}, where the {@code int} coordinate type
|
||||
* corresponds to an argument that is an index in a {@code byte[]} array,
|
||||
* and {@code T} is the component type of the given view array class. The
|
||||
* returned VarHandle accesses bytes at an index in a {@code byte[]} array,
|
||||
* composing bytes to or from a value of {@code T} according to the given
|
||||
* endianness.
|
||||
* <p>
|
||||
* The supported component types (variables types) are {@code short},
|
||||
* {@code char}, {@code int}, {@code long}, {@code float} and
|
||||
* {@code double}.
|
||||
* <p>
|
||||
* Access of bytes at a given index will result in an
|
||||
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
|
||||
* or greater than the {@code byte[]} array length minus the size (in bytes)
|
||||
* of {@code T}.
|
||||
* <p>
|
||||
* Access of bytes at an index may be aligned or misaligned for {@code T},
|
||||
* with respect to the underlying memory address, {@code A} say, associated
|
||||
* with the array and index.
|
||||
* If access is misaligned then access for anything other than the
|
||||
* {@code get} and {@code set} access modes will result in an
|
||||
* {@code IllegalStateException}. In such cases atomic access is only
|
||||
* guaranteed with respect to the largest power of two that divides the GCD
|
||||
* of {@code A} and the size (in bytes) of {@code T}.
|
||||
* If access is aligned then following access modes are supported and are
|
||||
* guaranteed to support atomic access:
|
||||
* <ul>
|
||||
* <li>read write access modes for all {@code T};
|
||||
* <li>atomic update access modes for {@code int}, {@code long},
|
||||
* {@code float} or {@code double}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* types for certain currently unsupported access modes.)
|
||||
* <li>numeric atomic update access modes for {@code int} and {@code long}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* numeric types for certain currently unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* Misaligned access, and therefore atomicity guarantees, may be determined
|
||||
* for {@code byte[]} arrays without operating on a specific array. Given
|
||||
* an {@code index}, {@code T} and it's corresponding boxed type,
|
||||
* {@code T_BOX}, misalignment may be determined as follows:
|
||||
* <pre>{@code
|
||||
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
|
||||
* int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
|
||||
* alignmentOffset(0, sizeOfT);
|
||||
* int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
|
||||
* boolean isMisaligned = misalignedAtIndex != 0;
|
||||
* }</pre>
|
||||
*
|
||||
* @implNote
|
||||
* The variable types {@code float} and {@code double} are supported as if
|
||||
* by transformation to and access with the variable types {@code int} and
|
||||
* {@code long} respectively. For example, the transformation of a
|
||||
* {@code double} value to a long value is performed as if using
|
||||
* {@link Double#doubleToRawLongBits(double)}, and the reverse
|
||||
* transformation is performed as if using
|
||||
* {@link Double#longBitsToDouble(long)}.
|
||||
*
|
||||
* @param viewArrayClass the view array class, with a component type of
|
||||
* type {@code T}
|
||||
* @param bigEndian true if the endianness of the view array elements, as
|
||||
* stored in the underlying {@code byte} array, is big endian, otherwise
|
||||
* little endian
|
||||
* @return a VarHandle giving access to elements of a {@code byte[]} array
|
||||
* viewed as if elements corresponding to the components type of the view
|
||||
* array class
|
||||
* @throws NullPointerException if viewArrayClass is null
|
||||
* @throws IllegalArgumentException if viewArrayClass is not an array type
|
||||
* @throws UnsupportedOperationException if the component type of
|
||||
* viewArrayClass is not supported as a variable type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
|
||||
boolean bigEndian) throws IllegalArgumentException {
|
||||
return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to elements of a {@code ByteBuffer}
|
||||
* viewed as if it were an array of elements of a different primitive
|
||||
* component type to that of {@code byte}, such as {@code int[]} or
|
||||
* {@code long[]}. The shape of the resulting VarHandle is
|
||||
* {@code (ByteBuffer, int : T)}, where the {@code int} coordinate type
|
||||
* corresponds to an argument that is an index in a {@code ByteBuffer}, and
|
||||
* {@code T} is the component type of the given view array class. The
|
||||
* returned VarHandle accesses bytes at an index in a {@code ByteBuffer},
|
||||
* composing bytes to or from a value of {@code T} according to the given
|
||||
* endianness.
|
||||
* <p>
|
||||
* The supported component types (variables types) are {@code short},
|
||||
* {@code char}, {@code int}, {@code long}, {@code float} and
|
||||
* {@code double}.
|
||||
* <p>
|
||||
* Access will result in a {@code ReadOnlyBufferException} for anything
|
||||
* other than the read access modes if the {@code ByteBuffer} is read-only.
|
||||
* <p>
|
||||
* Access of bytes at a given index will result in an
|
||||
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
|
||||
* or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
|
||||
* {@code T}.
|
||||
* <p>
|
||||
* Access of bytes at an index may be aligned or misaligned for {@code T},
|
||||
* with respect to the underlying memory address, {@code A} say, associated
|
||||
* with the {@code ByteBuffer} and index.
|
||||
* If access is misaligned then access for anything other than the
|
||||
* {@code get} and {@code set} access modes will result in an
|
||||
* {@code IllegalStateException}. In such cases atomic access is only
|
||||
* guaranteed with respect to the largest power of two that divides the GCD
|
||||
* of {@code A} and the size (in bytes) of {@code T}.
|
||||
* If access is aligned then following access modes are supported and are
|
||||
* guaranteed to support atomic access:
|
||||
* <ul>
|
||||
* <li>read write access modes for all {@code T};
|
||||
* <li>atomic update access modes for {@code int}, {@code long},
|
||||
* {@code float} or {@code double}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* types for certain currently unsupported access modes.)
|
||||
* <li>numeric atomic update access modes for {@code int} and {@code long}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* numeric types for certain currently unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* Misaligned access, and therefore atomicity guarantees, may be determined
|
||||
* for a {@code ByteBuffer}, {@code bb} (direct or otherwise), an
|
||||
* {@code index}, {@code T} and it's corresponding boxed type,
|
||||
* {@code T_BOX}, as follows:
|
||||
* <pre>{@code
|
||||
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
|
||||
* ByteBuffer bb = ...
|
||||
* int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
|
||||
* boolean isMisaligned = misalignedAtIndex != 0;
|
||||
* }</pre>
|
||||
*
|
||||
* @implNote
|
||||
* The variable types {@code float} and {@code double} are supported as if
|
||||
* by transformation to and access with the variable types {@code int} and
|
||||
* {@code long} respectively. For example, the transformation of a
|
||||
* {@code double} value to a long value is performed as if using
|
||||
* {@link Double#doubleToRawLongBits(double)}, and the reverse
|
||||
* transformation is performed as if using
|
||||
* {@link Double#longBitsToDouble(long)}.
|
||||
*
|
||||
* @param viewArrayClass the view array class, with a component type of
|
||||
* type {@code T}
|
||||
* @param bigEndian true if the endianness of the view array elements, as
|
||||
* stored in the underlying {@code ByteBuffer}, is big endian, otherwise
|
||||
* little endian (Note this overrides the endianness of a
|
||||
* {@code ByteBuffer})
|
||||
* @return a VarHandle giving access to elements of a {@code ByteBuffer}
|
||||
* viewed as if elements corresponding to the components type of the view
|
||||
* array class
|
||||
* @throws NullPointerException if viewArrayClass is null
|
||||
* @throws IllegalArgumentException if viewArrayClass is not an array type
|
||||
* @throws UnsupportedOperationException if the component type of
|
||||
* viewArrayClass is not supported as a variable type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
|
||||
boolean bigEndian) throws IllegalArgumentException {
|
||||
return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
|
||||
}
|
||||
|
||||
|
||||
/// method handle invocation (reflective style)
|
||||
|
||||
/**
|
||||
@ -2153,6 +2580,54 @@ return invoker;
|
||||
return type.invokers().genericInvoker();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a special <em>invoker method handle</em> which can be used to
|
||||
* invoke a signature-polymorphic access mode method on any VarHandle whose
|
||||
* associated access mode type is compatible with the given type.
|
||||
* The resulting invoker will have a type which is exactly equal to the
|
||||
* desired given type, except that it will accept an additional leading
|
||||
* argument of type {@code VarHandle}.
|
||||
*
|
||||
* @param accessMode the VarHandle access mode
|
||||
* @param type the desired target type
|
||||
* @return a method handle suitable for invoking an access mode method of
|
||||
* any VarHandle whose access mode type is of the given type.
|
||||
* @since 9
|
||||
*/
|
||||
static public
|
||||
MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
|
||||
return type.invokers().varHandleMethodExactInvoker(accessMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a special <em>invoker method handle</em> which can be used to
|
||||
* invoke a signature-polymorphic access mode method on any VarHandle whose
|
||||
* associated access mode type is compatible with the given type.
|
||||
* The resulting invoker will have a type which is exactly equal to the
|
||||
* desired given type, except that it will accept an additional leading
|
||||
* argument of type {@code VarHandle}.
|
||||
* <p>
|
||||
* Before invoking its target, if the access mode type differs from the
|
||||
* desired given type, the invoker will apply reference casts as necessary
|
||||
* and box, unbox, or widen primitive values, as if by
|
||||
* {@link MethodHandle#asType asType}. Similarly, the return value will be
|
||||
* converted as necessary.
|
||||
* <p>
|
||||
* This method is equivalent to the following code (though it may be more
|
||||
* efficient): {@code publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)}
|
||||
*
|
||||
* @param accessMode the VarHandle access mode
|
||||
* @param type the desired target type
|
||||
* @return a method handle suitable for invoking an access mode method of
|
||||
* any VarHandle whose access mode type is convertible to the given
|
||||
* type.
|
||||
* @since 9
|
||||
*/
|
||||
static public
|
||||
MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
|
||||
return type.invokers().varHandleMethodInvoker(accessMode);
|
||||
}
|
||||
|
||||
static /*non-public*/
|
||||
MethodHandle basicInvoker(MethodType type) {
|
||||
return type.invokers().basicInvoker();
|
||||
|
@ -95,7 +95,7 @@ class MethodType implements java.io.Serializable {
|
||||
|
||||
// The rtype and ptypes fields define the structural identity of the method type:
|
||||
private final Class<?> rtype;
|
||||
private final Class<?>[] ptypes;
|
||||
private final @Stable Class<?>[] ptypes;
|
||||
|
||||
// The remaining fields are caches of various sorts:
|
||||
private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
|
||||
|
164
jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java
Normal file
164
jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, 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 java.lang.invoke.VarHandle.AccessMode;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||
|
||||
/**
|
||||
* A var handle form containing a set of member name, one for each operation.
|
||||
* Each member characterizes a static method.
|
||||
*/
|
||||
class VarForm {
|
||||
|
||||
// Holds VarForm for VarHandle implementation classes
|
||||
private static final ClassValue<VarForm> VFORMS
|
||||
= new ClassValue<VarForm>() {
|
||||
@Override
|
||||
protected VarForm computeValue(Class<?> impl) {
|
||||
return new VarForm(link(staticMethodLinker(impl)));
|
||||
}
|
||||
};
|
||||
|
||||
final MemberName mbGet;
|
||||
final MemberName mbSet;
|
||||
final MemberName mbGetVolatile;
|
||||
final MemberName mbSetVolatile;
|
||||
final MemberName mbGetAcquire;
|
||||
final MemberName mbSetRelease;
|
||||
final MemberName mbCompareAndSet;
|
||||
final MemberName mbCompareAndExchangeVolatile;
|
||||
final MemberName mbCompareAndExchangeAcquire;
|
||||
final MemberName mbCompareAndExchangeRelease;
|
||||
final MemberName mbWeakCompareAndSet;
|
||||
final MemberName mbWeakCompareAndSetAcquire;
|
||||
final MemberName mbWeakCompareAndSetRelease;
|
||||
final MemberName mbGetAndSet;
|
||||
final MemberName mbGetAndAdd;
|
||||
final MemberName mbAddAndGet;
|
||||
final MemberName mbGetOpaque;
|
||||
final MemberName mbSetOpaque;
|
||||
|
||||
VarForm(Map<AccessMode, MemberName> linkMap) {
|
||||
mbGet = linkMap.get(AccessMode.get);
|
||||
mbSet = linkMap.get(AccessMode.set);
|
||||
mbGetVolatile = linkMap.get(AccessMode.getVolatile);
|
||||
mbSetVolatile = linkMap.get(AccessMode.setVolatile);
|
||||
mbGetOpaque = linkMap.get(AccessMode.getOpaque);
|
||||
mbSetOpaque = linkMap.get(AccessMode.setOpaque);
|
||||
mbGetAcquire = linkMap.get(AccessMode.getAcquire);
|
||||
mbSetRelease = linkMap.get(AccessMode.setRelease);
|
||||
mbCompareAndSet = linkMap.get(AccessMode.compareAndSet);
|
||||
mbCompareAndExchangeVolatile = linkMap.get(AccessMode.compareAndExchangeVolatile);
|
||||
mbCompareAndExchangeAcquire = linkMap.get(AccessMode.compareAndExchangeAcquire);
|
||||
mbCompareAndExchangeRelease = linkMap.get(AccessMode.compareAndExchangeRelease);
|
||||
mbWeakCompareAndSet = linkMap.get(AccessMode.weakCompareAndSet);
|
||||
mbWeakCompareAndSetAcquire = linkMap.get(AccessMode.weakCompareAndSetAcquire);
|
||||
mbWeakCompareAndSetRelease = linkMap.get(AccessMode.weakCompareAndSetRelease);
|
||||
mbGetAndSet = linkMap.get(AccessMode.getAndSet);
|
||||
mbGetAndAdd = linkMap.get(AccessMode.getAndAdd);
|
||||
mbAddAndGet = linkMap.get(AccessMode.addAndGet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a var form given an VarHandle implementation class.
|
||||
* Each signature polymorphic method is linked to a static method of the
|
||||
* same name on the implementation class or a super class.
|
||||
*/
|
||||
static VarForm createFromStatic(Class<? extends VarHandle> impl) {
|
||||
return VFORMS.get(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link all signature polymorphic methods.
|
||||
*/
|
||||
private static Map<AccessMode, MemberName> link(Function<AccessMode, MemberName> linker) {
|
||||
Map<AccessMode, MemberName> links = new HashMap<>();
|
||||
for (AccessMode ak : AccessMode.values()) {
|
||||
links.put(ak, linker.apply(ak));
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a function that associates an AccessMode with a MemberName that
|
||||
* is a static concrete method implementation for the access operation of
|
||||
* the implementing class.
|
||||
*/
|
||||
private static Function<AccessMode, MemberName> staticMethodLinker(Class<?> implClass) {
|
||||
// Find all declared static methods on the implementation class and
|
||||
// all super classes up to but not including VarHandle
|
||||
List<Method> staticMethods = new ArrayList<>(AccessMode.values().length);
|
||||
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
staticMethods.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This needs to be an anonymous inner class and not a lambda expression
|
||||
// The latter will cause the intialization of classes in java.lang.invoke
|
||||
// resulting in circular dependencies if VarHandles are utilized early
|
||||
// in the start up process. For example, if ConcurrentHashMap
|
||||
// is modified to use VarHandles.
|
||||
return new Function<>() {
|
||||
@Override
|
||||
public MemberName apply(AccessMode ak) {
|
||||
Method m = null;
|
||||
for (Method to_m : staticMethods) {
|
||||
if (to_m.getName().equals(ak.name()) &&
|
||||
Modifier.isStatic(to_m.getModifiers())) {
|
||||
assert m == null : String.format(
|
||||
"Two or more static methods named %s are present on " +
|
||||
"class %s or a super class", ak.name(), implClass.getName());
|
||||
m = to_m;
|
||||
}
|
||||
}
|
||||
|
||||
if (m == null)
|
||||
return null;
|
||||
|
||||
MemberName linkedMethod = new MemberName(m);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linkedMethod, m.getDeclaringClass(), NoSuchMethodException.class);
|
||||
}
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
1416
jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
Normal file
1416
jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
/**
|
||||
* The base class for generated byte array and byte buffer view
|
||||
* implementations
|
||||
*/
|
||||
abstract class VarHandleByteArrayBase {
|
||||
// Buffer.address
|
||||
static final long BUFFER_ADDRESS;
|
||||
// Buffer.limit
|
||||
static final long BUFFER_LIMIT;
|
||||
// ByteBuffer.hb
|
||||
static final long BYTE_BUFFER_HB;
|
||||
// ByteBuffer.isReadOnly
|
||||
static final long BYTE_BUFFER_IS_READ_ONLY;
|
||||
|
||||
static {
|
||||
try {
|
||||
BUFFER_ADDRESS = UNSAFE.objectFieldOffset(
|
||||
Buffer.class.getDeclaredField("address"));
|
||||
|
||||
BUFFER_LIMIT = UNSAFE.objectFieldOffset(
|
||||
Buffer.class.getDeclaredField("limit"));
|
||||
|
||||
BYTE_BUFFER_HB = UNSAFE.objectFieldOffset(
|
||||
ByteBuffer.class.getDeclaredField("hb"));
|
||||
|
||||
BYTE_BUFFER_IS_READ_ONLY = UNSAFE.objectFieldOffset(
|
||||
ByteBuffer.class.getDeclaredField("isReadOnly"));
|
||||
}
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static final boolean BE = UNSAFE.isBigEndian();
|
||||
|
||||
static IllegalStateException newIllegalStateExceptionForMisalignedAccess(int index) {
|
||||
return new IllegalStateException("Misaligned access at index: " + index);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
533
jdk/src/java.base/share/classes/java/lang/invoke/VarHandles.java
Normal file
533
jdk/src/java.base/share/classes/java/lang/invoke/VarHandles.java
Normal file
@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, 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.UNSAFE;
|
||||
|
||||
final class VarHandles {
|
||||
|
||||
static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
|
||||
if (!f.isStatic()) {
|
||||
long foffset = MethodHandleNatives.objectFieldOffset(f);
|
||||
if (!type.isPrimitive()) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
|
||||
: new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type);
|
||||
}
|
||||
else if (type == boolean.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == byte.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == short.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == char.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == int.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == long.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == float.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == double.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO This is not lazy on first invocation
|
||||
// and might cause some circular initialization issues
|
||||
|
||||
// Replace with something similar to direct method handles
|
||||
// where a barrier is used then elided after use
|
||||
|
||||
if (UNSAFE.shouldBeInitialized(refc))
|
||||
UNSAFE.ensureClassInitialized(refc);
|
||||
|
||||
Object base = MethodHandleNatives.staticFieldBase(f);
|
||||
long foffset = MethodHandleNatives.staticFieldOffset(f);
|
||||
if (!type.isPrimitive()) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
|
||||
: new VarHandleObjects.FieldStaticReadWrite(base, foffset, type);
|
||||
}
|
||||
else if (type == boolean.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == byte.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleBytes.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == short.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleShorts.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == char.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleChars.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleChars.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == int.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleInts.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleInts.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == long.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleLongs.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == float.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleFloats.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == double.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
|
||||
if (!arrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + arrayClass);
|
||||
|
||||
Class<?> componentType = arrayClass.getComponentType();
|
||||
|
||||
int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
|
||||
int ascale = UNSAFE.arrayIndexScale(arrayClass);
|
||||
int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
|
||||
|
||||
if (!componentType.isPrimitive()) {
|
||||
return new VarHandleObjects.Array(aoffset, ashift, arrayClass);
|
||||
}
|
||||
else if (componentType == boolean.class) {
|
||||
return new VarHandleBooleans.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == byte.class) {
|
||||
return new VarHandleBytes.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == short.class) {
|
||||
return new VarHandleShorts.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == char.class) {
|
||||
return new VarHandleChars.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == int.class) {
|
||||
return new VarHandleInts.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == long.class) {
|
||||
return new VarHandleLongs.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == float.class) {
|
||||
return new VarHandleFloats.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == double.class) {
|
||||
return new VarHandleDoubles.Array(aoffset, ashift);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
|
||||
boolean be) {
|
||||
if (!viewArrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + viewArrayClass);
|
||||
|
||||
Class<?> viewComponentType = viewArrayClass.getComponentType();
|
||||
|
||||
if (viewComponentType == long.class) {
|
||||
return new VarHandleByteArrayAsLongs.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == int.class) {
|
||||
return new VarHandleByteArrayAsInts.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == short.class) {
|
||||
return new VarHandleByteArrayAsShorts.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == char.class) {
|
||||
return new VarHandleByteArrayAsChars.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == double.class) {
|
||||
return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == float.class) {
|
||||
return new VarHandleByteArrayAsFloats.ArrayHandle(be);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
|
||||
boolean be) {
|
||||
if (!viewArrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + viewArrayClass);
|
||||
|
||||
Class<?> viewComponentType = viewArrayClass.getComponentType();
|
||||
|
||||
if (viewComponentType == long.class) {
|
||||
return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == int.class) {
|
||||
return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == short.class) {
|
||||
return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == char.class) {
|
||||
return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == double.class) {
|
||||
return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == float.class) {
|
||||
return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * A helper program to generate the VarHandleGuards class with a set of
|
||||
// * static guard methods each of which corresponds to a particular shape and
|
||||
// * performs a type check of the symbolic type descriptor with the VarHandle
|
||||
// * type descriptor before linking/invoking to the underlying operation as
|
||||
// * characterized by the operation member name on the VarForm of the
|
||||
// * VarHandle.
|
||||
// * <p>
|
||||
// * The generated class essentially encapsulates pre-compiled LambdaForms,
|
||||
// * one for each method, for the most set of common method signatures.
|
||||
// * This reduces static initialization costs, footprint costs, and circular
|
||||
// * dependencies that may arise if a class is generated per LambdaForm.
|
||||
// * <p>
|
||||
// * A maximum of L*T*S methods will be generated where L is the number of
|
||||
// * access modes kinds (or unique operation signatures) and T is the number
|
||||
// * of variable types and S is the number of shapes (such as instance field,
|
||||
// * static field, or array access).
|
||||
// * If there are 4 unique operation signatures, 5 basic types (Object, int,
|
||||
// * long, float, double), and 3 shapes then a maximum of 60 methods will be
|
||||
// * generated. However, the number is likely to be less since there
|
||||
// * be duplicate signatures.
|
||||
// * <p>
|
||||
// * Each method is annotated with @LambdaForm.Compiled to inform the runtime
|
||||
// * that such methods should be treated as if a method of a class that is the
|
||||
// * result of compiling a LambdaForm. Annotation of such methods is
|
||||
// * important for correct evaluation of certain assertions and method return
|
||||
// * type profiling in HotSpot.
|
||||
// */
|
||||
// public static class GuardMethodGenerator {
|
||||
//
|
||||
// static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
|
||||
//
|
||||
// static final String GUARD_METHOD_TEMPLATE =
|
||||
// "@ForceInline\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
|
||||
// " MethodType symbolic = ad.symbolicMethodType;\n" +
|
||||
// " if (target == symbolic) {\n" +
|
||||
// " <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (target.erase() == symbolic.erase()) {\n" +
|
||||
// " <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
|
||||
// " <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// "}";
|
||||
//
|
||||
// static final String GET_MEMBER_NAME_METHOD =
|
||||
// "@ForceInline\n" +
|
||||
// "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
|
||||
// " MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
|
||||
// " if (mn == null) {\n" +
|
||||
// " throw handle.unsupported();\n" +
|
||||
// " }\n" +
|
||||
// " return mn;\n" +
|
||||
// "}";
|
||||
//
|
||||
// // A template for deriving the operations
|
||||
// // could be supported by annotating VarHandle directly with the
|
||||
// // operation kind and shape
|
||||
// interface VarHandleTemplate {
|
||||
// Object get();
|
||||
//
|
||||
// void set(Object value);
|
||||
//
|
||||
// boolean compareAndSwap(Object actualValue, Object expectedValue);
|
||||
//
|
||||
// Object compareAndExchange(Object actualValue, Object expectedValue);
|
||||
//
|
||||
// Object getAndUpdate(Object value);
|
||||
// }
|
||||
//
|
||||
// static class HandleType {
|
||||
// final Class<?> receiver;
|
||||
// final Class<?>[] intermediates;
|
||||
// final Class<?> value;
|
||||
//
|
||||
// HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
// this.receiver = receiver;
|
||||
// this.intermediates = intermediates;
|
||||
// this.value = value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param args parameters
|
||||
// */
|
||||
// public static void main(String[] args) {
|
||||
// System.out.println("package java.lang.invoke;");
|
||||
// System.out.println();
|
||||
// System.out.println("import jdk.internal.vm.annotation.ForceInline;");
|
||||
// System.out.println();
|
||||
// System.out.println("// This class is auto-generated by " +
|
||||
// GuardMethodGenerator.class.getName() +
|
||||
// ". Do not edit.");
|
||||
// System.out.println("final class VarHandleGuards {");
|
||||
//
|
||||
// System.out.println();
|
||||
// System.out.println(GET_MEMBER_NAME_METHOD);
|
||||
// System.out.println();
|
||||
//
|
||||
// // Declare the stream of shapes
|
||||
// Stream<HandleType> hts = Stream.of(
|
||||
// // Object->Object
|
||||
// new HandleType(Object.class, Object.class),
|
||||
// // Object->int
|
||||
// new HandleType(Object.class, int.class),
|
||||
// // Object->long
|
||||
// new HandleType(Object.class, long.class),
|
||||
// // Object->float
|
||||
// new HandleType(Object.class, float.class),
|
||||
// // Object->double
|
||||
// new HandleType(Object.class, double.class),
|
||||
//
|
||||
// // <static>->Object
|
||||
// new HandleType(null, Object.class),
|
||||
// // <static>->int
|
||||
// new HandleType(null, int.class),
|
||||
// // <static>->long
|
||||
// new HandleType(null, long.class),
|
||||
// // <static>->float
|
||||
// new HandleType(null, float.class),
|
||||
// // <static>->double
|
||||
// new HandleType(null, double.class),
|
||||
//
|
||||
// // Array[int]->Object
|
||||
// new HandleType(Object.class, Object.class, int.class),
|
||||
// // Array[int]->int
|
||||
// new HandleType(Object.class, int.class, int.class),
|
||||
// // Array[int]->long
|
||||
// new HandleType(Object.class, long.class, int.class),
|
||||
// // Array[int]->float
|
||||
// new HandleType(Object.class, float.class, int.class),
|
||||
// // Array[int]->double
|
||||
// new HandleType(Object.class, double.class, int.class),
|
||||
//
|
||||
// // Array[long]->int
|
||||
// new HandleType(Object.class, int.class, long.class),
|
||||
// // Array[long]->long
|
||||
// new HandleType(Object.class, long.class, long.class)
|
||||
// );
|
||||
//
|
||||
// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
|
||||
// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
|
||||
// distinct().
|
||||
// map(mt -> generateMethod(mt)).
|
||||
// forEach(s -> {
|
||||
// System.out.println(s);
|
||||
// System.out.println();
|
||||
// });
|
||||
//
|
||||
// System.out.println("}");
|
||||
// }
|
||||
//
|
||||
// static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
// Class<?> returnType = m.getReturnType() == Object.class
|
||||
// ? value : m.getReturnType();
|
||||
//
|
||||
// List<Class<?>> params = new ArrayList<>();
|
||||
// if (receiver != null)
|
||||
// params.add(receiver);
|
||||
// for (int i = 0; i < intermediates.length; i++) {
|
||||
// params.add(intermediates[i]);
|
||||
// }
|
||||
// for (Parameter p : m.getParameters()) {
|
||||
// params.add(value);
|
||||
// }
|
||||
// return MethodType.methodType(returnType, params);
|
||||
// }
|
||||
//
|
||||
// static String generateMethod(MethodType mt) {
|
||||
// Class<?> returnType = mt.returnType();
|
||||
//
|
||||
// LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
|
||||
// params.put("handle", VarHandle.class);
|
||||
// for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
// params.put("arg" + i, mt.parameterType(i));
|
||||
// }
|
||||
// params.put("ad", VarHandle.AccessDescriptor.class);
|
||||
//
|
||||
// // Generate method signature line
|
||||
// String RETURN = className(returnType);
|
||||
// String NAME = "guard";
|
||||
// String SIGNATURE = getSignature(mt);
|
||||
// String PARAMS = params.entrySet().stream().
|
||||
// map(e -> className(e.getValue()) + " " + e.getKey()).
|
||||
// collect(joining(", "));
|
||||
// String METHOD = GUARD_METHOD_SIG_TEMPLATE.
|
||||
// replace("<RETURN>", RETURN).
|
||||
// replace("<NAME>", NAME).
|
||||
// replace("<SIGNATURE>", SIGNATURE).
|
||||
// replace("<PARAMS>", PARAMS);
|
||||
//
|
||||
// // Generate method
|
||||
// params.remove("ad");
|
||||
//
|
||||
// List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
|
||||
//
|
||||
// List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
//
|
||||
// RETURN = returnType == void.class
|
||||
// ? ""
|
||||
// : returnType == Object.class
|
||||
// ? "return "
|
||||
// : "return (" + returnType.getName() + ") ";
|
||||
//
|
||||
// String RESULT_ERASED = returnType == void.class
|
||||
// ? ""
|
||||
// : returnType != Object.class
|
||||
// ? "return (" + returnType.getName() + ") "
|
||||
// : "Object r = ";
|
||||
//
|
||||
// String RETURN_ERASED = returnType != Object.class
|
||||
// ? ""
|
||||
// : " return symbolic.returnType().cast(r);";
|
||||
//
|
||||
// return GUARD_METHOD_TEMPLATE.
|
||||
// replace("<METHOD>", METHOD).
|
||||
// replace("<NAME>", NAME).
|
||||
// replaceAll("<RETURN>", RETURN).
|
||||
// replace("<RESULT_ERASED>", RESULT_ERASED).
|
||||
// replace("<RETURN_ERASED>", RETURN_ERASED).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
|
||||
// collect(joining(", "))).
|
||||
// replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
|
||||
// collect(joining(", ")))
|
||||
// ;
|
||||
// }
|
||||
//
|
||||
// static String className(Class<?> c) {
|
||||
// String n = c.getName();
|
||||
// if (n.startsWith("java.lang.")) {
|
||||
// n = n.replace("java.lang.", "");
|
||||
// if (n.startsWith("invoke.")) {
|
||||
// n = n.replace("invoke.", "");
|
||||
// }
|
||||
// }
|
||||
// return n.replace('$', '.');
|
||||
// }
|
||||
//
|
||||
// static String getSignature(MethodType m) {
|
||||
// StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
|
||||
//
|
||||
// for (int i = 0; i < m.parameterCount(); i++) {
|
||||
// Class<?> pt = m.parameterType(i);
|
||||
// sb.append(getCharType(pt));
|
||||
// }
|
||||
//
|
||||
// sb.append('_').append(getCharType(m.returnType()));
|
||||
//
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
// static char getCharType(Class<?> pt) {
|
||||
// if (pt == void.class) {
|
||||
// return 'V';
|
||||
// }
|
||||
// else if (!pt.isPrimitive()) {
|
||||
// return 'L';
|
||||
// }
|
||||
// else if (pt == boolean.class) {
|
||||
// return 'Z';
|
||||
// }
|
||||
// else if (pt == int.class) {
|
||||
// return 'I';
|
||||
// }
|
||||
// else if (pt == long.class) {
|
||||
// return 'J';
|
||||
// }
|
||||
// else if (pt == float.class) {
|
||||
// return 'F';
|
||||
// }
|
||||
// else if (pt == double.class) {
|
||||
// return 'D';
|
||||
// }
|
||||
// else {
|
||||
// throw new IllegalStateException(pt.getName());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
@ -0,0 +1,602 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, 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 java.util.Objects;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
#warn
|
||||
|
||||
final class VarHandle$Type$s {
|
||||
|
||||
static class FieldInstanceReadOnly extends VarHandle {
|
||||
final long fieldOffset;
|
||||
final Class<?> receiverType;
|
||||
#if[Object]
|
||||
final Class<?> fieldType;
|
||||
#end[Object]
|
||||
|
||||
FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
|
||||
}
|
||||
|
||||
protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldInstanceReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
this.fieldOffset = fieldOffset;
|
||||
this.receiverType = receiverType;
|
||||
#if[Object]
|
||||
this.fieldType = fieldType;
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
|
||||
FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndSet$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static class FieldStaticReadOnly extends VarHandle {
|
||||
final Object base;
|
||||
final long fieldOffset;
|
||||
#if[Object]
|
||||
final Class<?> fieldType;
|
||||
#end[Object]
|
||||
|
||||
FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
|
||||
}
|
||||
|
||||
protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldStaticReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
|
||||
this.base = base;
|
||||
this.fieldOffset = fieldOffset;
|
||||
#if[Object]
|
||||
this.fieldType = fieldType;
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Volatile(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Opaque(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Acquire(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
static class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
|
||||
FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Volatile(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Opaque(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndSwap$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndSet$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static final class Array extends VarHandle {
|
||||
final int abase;
|
||||
final int ashift;
|
||||
#if[Object]
|
||||
final Class<{#if[Object]??:$type$[]}> arrayType;
|
||||
final Class<?> componentType;
|
||||
#end[Object]
|
||||
|
||||
Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
|
||||
super(VarForm.createFromStatic(Array.class),
|
||||
{#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
this.abase = abase;
|
||||
this.ashift = ashift;
|
||||
#if[Object]
|
||||
this.arrayType = {#if[Object]?arrayType:$type$[].class};
|
||||
this.componentType = arrayType.getComponentType();
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
array[index] = {#if[Object]?handle.componentType.cast(value):value};
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Opaque(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Opaque(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndSwap$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndSet$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndAdd$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndAdd$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
497
jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
Normal file
497
jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, 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 jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
#warn
|
||||
|
||||
final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
|
||||
static final int ALIGN = $BoxType$.BYTES - 1;
|
||||
|
||||
#if[floatingPoint]
|
||||
@ForceInline
|
||||
static $rawType$ convEndian(boolean big, $type$ v) {
|
||||
$rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
|
||||
return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ convEndian(boolean big, $rawType$ rv) {
|
||||
rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
|
||||
return $Type$.$rawType$BitsTo$Type$(rv);
|
||||
}
|
||||
#else[floatingPoint]
|
||||
@ForceInline
|
||||
static $type$ convEndian(boolean big, $type$ n) {
|
||||
return big == BE ? n : $BoxType$.reverseBytes(n);
|
||||
}
|
||||
#end[floatingPoint]
|
||||
|
||||
|
||||
private static class ByteArrayViewVarHandle extends VarHandle {
|
||||
final boolean be;
|
||||
|
||||
ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
|
||||
Class<?> arrayType, Class<?> component, boolean be) {
|
||||
super(VarForm.createFromStatic(implSubType),
|
||||
arrayType, component, int.class);
|
||||
this.be = be;
|
||||
}
|
||||
}
|
||||
|
||||
static final class ArrayHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ArrayHandle(boolean be) {
|
||||
super(ArrayHandle.class, byte[].class, $type$.class, be);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int index(byte[] ba, int index) {
|
||||
return Objects.checkIndex(index, ba.length - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long address(byte[] ba, int index) {
|
||||
long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
if ((address & ALIGN) != 0)
|
||||
throw newIllegalStateExceptionForMisalignedAccess(index);
|
||||
return address;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
return UNSAFE.get$Type$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
#if[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
value,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Opaque(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Opaque(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.compareAndSwap$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndSet$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static final class ByteBufferHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ByteBufferHandle(boolean be) {
|
||||
super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int index(ByteBuffer bb, int index) {
|
||||
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int indexRO(ByteBuffer bb, int index) {
|
||||
if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
|
||||
throw new ReadOnlyBufferException();
|
||||
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long address(ByteBuffer bb, int index) {
|
||||
long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
|
||||
if ((address & ALIGN) != 0)
|
||||
throw newIllegalStateExceptionForMisalignedAccess(index);
|
||||
return address;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
return UNSAFE.get$Type$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
#if[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
UNSAFE.put$Type$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
value,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Opaque(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Opaque(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.compareAndSwap$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndSet$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -32,7 +32,8 @@
|
||||
* certain types in this package have special relations to dynamic
|
||||
* language support in the virtual machine:
|
||||
* <ul>
|
||||
* <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
|
||||
* <li>The classes {@link java.lang.invoke.MethodHandle MethodHandle}
|
||||
* {@link java.lang.invoke.VarHandle VarHandle} contain
|
||||
* <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
|
||||
* which can be linked regardless of their type descriptor.
|
||||
* Normally, method linkage requires exact matching of type descriptors.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -25,9 +25,10 @@
|
||||
|
||||
package java.nio;
|
||||
|
||||
import java.util.Spliterator;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import java.util.Spliterator;
|
||||
|
||||
/**
|
||||
* A container for data of a specific primitive type.
|
||||
*
|
||||
@ -188,7 +189,15 @@ public abstract class Buffer {
|
||||
private int limit;
|
||||
private int capacity;
|
||||
|
||||
// Used only by direct buffers
|
||||
// Used by heap byte buffers or direct buffers with Unsafe access
|
||||
// For heap byte buffers this field will be the address relative to the
|
||||
// array base address and offset into that array. The address might
|
||||
// not align on a word boundary for slices, nor align at a long word
|
||||
// (8 byte) boundary for byte[] allocations on 32-bit systems.
|
||||
// For direct buffers it is the start address of the memory region. The
|
||||
// address might not align on a word boundary for slices, nor when created
|
||||
// using JNI, see NewDirectByteBuffer(void*, long).
|
||||
// Should ideally be declared final
|
||||
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
|
||||
long address;
|
||||
|
||||
|
@ -140,6 +140,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = null;
|
||||
#else[rw]
|
||||
super(cap);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -180,6 +181,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = null;
|
||||
#else[rw]
|
||||
super(cap, addr, fd, unmapper);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -200,6 +202,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = db;
|
||||
#else[rw]
|
||||
super(db, mark, pos, lim, cap, off);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -213,6 +216,15 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
|
||||
}
|
||||
|
||||
#if[byte]
|
||||
public $Type$Buffer slice(int pos, int lim) {
|
||||
assert (pos >= 0);
|
||||
assert (pos <= lim);
|
||||
int rem = lim - pos;
|
||||
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
public $Type$Buffer duplicate() {
|
||||
return new Direct$Type$Buffer$RW$$BO$(this,
|
||||
this.markValue(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -74,6 +74,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(cap, lim);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
|
||||
@ -87,6 +90,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(buf, off, len);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
protected Heap$Type$Buffer$RW$($type$[] buf,
|
||||
@ -103,6 +109,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(buf, mark, pos, lim, cap, off);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset + off;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
public $Type$Buffer slice() {
|
||||
@ -114,6 +123,20 @@ class Heap$Type$Buffer$RW$
|
||||
this.position() + offset);
|
||||
}
|
||||
|
||||
#if[byte]
|
||||
$Type$Buffer slice(int pos, int lim) {
|
||||
assert (pos >= 0);
|
||||
assert (pos <= lim);
|
||||
int rem = lim - pos;
|
||||
return new Heap$Type$Buffer$RW$(hb,
|
||||
-1,
|
||||
0,
|
||||
rem,
|
||||
rem,
|
||||
pos + offset);
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
public $Type$Buffer duplicate() {
|
||||
return new Heap$Type$Buffer$RW$(hb,
|
||||
this.markValue(),
|
||||
@ -144,7 +167,7 @@ class Heap$Type$Buffer$RW$
|
||||
|
||||
#if[byte]
|
||||
private long byteOffset(long i) {
|
||||
return arrayBaseOffset + i + offset;
|
||||
return address + i;
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -39,6 +39,7 @@ class StringCharBuffer // package-private
|
||||
if ((start < 0) || (start > n) || (end < start) || (end > n))
|
||||
throw new IndexOutOfBoundsException();
|
||||
str = s;
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
|
||||
public CharBuffer slice() {
|
||||
@ -58,6 +59,7 @@ class StringCharBuffer // package-private
|
||||
int offset) {
|
||||
super(mark, pos, limit, cap, null, offset);
|
||||
str = s;
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
|
||||
public CharBuffer duplicate() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -269,7 +269,7 @@ public abstract class $Type$Buffer
|
||||
//
|
||||
final $type$[] hb; // Non-null only for heap buffers
|
||||
final int offset;
|
||||
boolean isReadOnly; // Valid only for heap buffers
|
||||
boolean isReadOnly;
|
||||
|
||||
// Creates a new buffer with the given mark, position, limit, capacity,
|
||||
// backing array, and array offset
|
||||
@ -530,6 +530,10 @@ public abstract class $Type$Buffer
|
||||
* it will be read-only if, and only if, this buffer is read-only. </p>
|
||||
*
|
||||
* @return The new $type$ buffer
|
||||
#if[byte]
|
||||
*
|
||||
* @see #alignedSlice(int)
|
||||
#end[byte]
|
||||
*/
|
||||
public abstract $Type$Buffer slice();
|
||||
|
||||
@ -1611,6 +1615,143 @@ public abstract class $Type$Buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the memory address, pointing to the byte at the given index,
|
||||
* modulus the given unit size.
|
||||
*
|
||||
* <p> A return value greater than zero indicates the address of the byte at
|
||||
* the index is misaligned for the unit size, and the value's quantity
|
||||
* indicates how much the index should be rounded up or down to locate a
|
||||
* byte at an aligned address. Otherwise, a value of {@code 0} indicates
|
||||
* that the address of the byte at the index is aligned for the unit size.
|
||||
*
|
||||
* @apiNote
|
||||
* This method may be utilized to determine if unit size bytes from an
|
||||
* index can be accessed atomically, if supported by the native platform.
|
||||
*
|
||||
* @implNote
|
||||
* This implementation throws {@code UnsupportedOperationException} for
|
||||
* non-direct buffers when the given unit size is greater then {@code 8}.
|
||||
*
|
||||
* @param index
|
||||
* The index to query for alignment offset, must be non-negative, no
|
||||
* upper bounds check is performed
|
||||
*
|
||||
* @param unitSize
|
||||
* The unit size in bytes, must be a power of {@code 2}
|
||||
*
|
||||
* @return The indexed byte's memory address modulus the unit size
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the index is negative or the unit size is not a power of
|
||||
* {@code 2}
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the native platform does not guarantee stable alignment offset
|
||||
* values for the given unit size when managing the memory regions
|
||||
* of buffers of the same kind as this buffer (direct or
|
||||
* non-direct). For example, if garbage collection would result
|
||||
* in the moving of a memory region covered by a non-direct buffer
|
||||
* from one location to another and both locations have different
|
||||
* alignment characteristics.
|
||||
*
|
||||
* @see #alignedSlice(int)
|
||||
* @since 9
|
||||
*/
|
||||
public final int alignmentOffset(int index, int unitSize) {
|
||||
if (index < 0)
|
||||
throw new IllegalArgumentException("Index less than zero: " + index);
|
||||
if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
|
||||
throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
|
||||
if (unitSize > 8 && !isDirect())
|
||||
throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
|
||||
|
||||
return (int) ((address + index) % unitSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new byte buffer whose content is a shared and aligned
|
||||
* subsequence of this buffer's content.
|
||||
*
|
||||
* <p> The content of the new buffer will start at this buffer's current
|
||||
* position rounded up to the index of the nearest aligned byte for the
|
||||
* given unit size, and end at this buffer's limit rounded down to the index
|
||||
* of the nearest aligned byte for the given unit size.
|
||||
* If rounding results in out-of-bound values then the new buffer's capacity
|
||||
* and limit will be zero. If rounding is within bounds the following
|
||||
* expressions will be true for a new buffer {@code nb} and unit size
|
||||
* {@code unitSize}:
|
||||
* <pre>{@code
|
||||
* nb.alignmentOffset(0, unitSize) == 0
|
||||
* nb.alignmentOffset(nb.limit(), unitSize) == 0
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Changes to this buffer's content will be visible in the new
|
||||
* buffer, and vice versa; the two buffers' position, limit, and mark
|
||||
* values will be independent.
|
||||
*
|
||||
* <p> The new buffer's position will be zero, its capacity and its limit
|
||||
* will be the number of bytes remaining in this buffer or fewer subject to
|
||||
* alignment, its mark will be undefined, and its byte order will be
|
||||
* {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
|
||||
*
|
||||
* The new buffer will be direct if, and only if, this buffer is direct, and
|
||||
* it will be read-only if, and only if, this buffer is read-only. </p>
|
||||
*
|
||||
* @apiNote
|
||||
* This method may be utilized to create a new buffer where unit size bytes
|
||||
* from index, that is a multiple of the unit size, may be accessed
|
||||
* atomically, if supported by the native platform.
|
||||
*
|
||||
* @implNote
|
||||
* This implementation throws {@code UnsupportedOperationException} for
|
||||
* non-direct buffers when the given unit size is greater then {@code 8}.
|
||||
*
|
||||
* @param unitSize
|
||||
* The unit size in bytes, must be a power of {@code 2}
|
||||
*
|
||||
* @return The new byte buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the unit size not a power of {@code 2}
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the native platform does not guarantee stable aligned slices
|
||||
* for the given unit size when managing the memory regions
|
||||
* of buffers of the same kind as this buffer (direct or
|
||||
* non-direct). For example, if garbage collection would result
|
||||
* in the moving of a memory region covered by a non-direct buffer
|
||||
* from one location to another and both locations have different
|
||||
* alignment characteristics.
|
||||
*
|
||||
* @see #alignmentOffset(int, int)
|
||||
* @see #slice()
|
||||
* @since 9
|
||||
*/
|
||||
public final ByteBuffer alignedSlice(int unitSize) {
|
||||
int pos = position();
|
||||
int lim = limit();
|
||||
|
||||
int pos_mod = alignmentOffset(pos, unitSize);
|
||||
int lim_mod = alignmentOffset(lim, unitSize);
|
||||
|
||||
// Round up the position to align with unit size
|
||||
int aligned_pos = (pos_mod > 0)
|
||||
? pos + (unitSize - pos_mod)
|
||||
: pos;
|
||||
|
||||
// Round down the limit to align with unit size
|
||||
int aligned_lim = lim - lim_mod;
|
||||
|
||||
if (aligned_pos > lim || aligned_lim < pos) {
|
||||
aligned_pos = aligned_lim = pos;
|
||||
}
|
||||
|
||||
return slice(aligned_pos, aligned_lim);
|
||||
}
|
||||
|
||||
abstract ByteBuffer slice(int pos, int lim);
|
||||
|
||||
// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
|
||||
//
|
||||
abstract byte _get(int i); // package-private
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, 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
|
||||
@ -47,7 +47,6 @@ import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
@ -146,6 +145,12 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
initializeData(locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized DateFormatSymbols.
|
||||
*/
|
||||
private DateFormatSymbols(boolean flag) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Era strings. For example: "AD" and "BC". An array of 2 strings,
|
||||
* indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
|
||||
@ -679,54 +684,80 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
*/
|
||||
transient volatile int cachedHashCode;
|
||||
|
||||
private void initializeData(Locale desiredLocale) {
|
||||
locale = desiredLocale;
|
||||
|
||||
// Copy values of a cached instance if any.
|
||||
/**
|
||||
* Initializes this DateFormatSymbols with the locale data. This method uses
|
||||
* a cached DateFormatSymbols instance for the given locale if available. If
|
||||
* there's no cached one, this method creates an uninitialized instance and
|
||||
* populates its fields from the resource bundle for the locale, and caches
|
||||
* the instance. Note: zoneStrings isn't initialized in this method.
|
||||
*/
|
||||
private void initializeData(Locale locale) {
|
||||
SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
|
||||
DateFormatSymbols dfs;
|
||||
if (ref != null && (dfs = ref.get()) != null) {
|
||||
copyMembers(dfs, this);
|
||||
return;
|
||||
}
|
||||
if (ref == null || (dfs = ref.get()) == null) {
|
||||
if (ref != null) {
|
||||
// Remove the empty SoftReference
|
||||
cachedInstances.remove(locale, ref);
|
||||
}
|
||||
dfs = new DateFormatSymbols(false);
|
||||
|
||||
// Initialize the fields from the ResourceBundle for locale.
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
|
||||
// Avoid any potential recursions
|
||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
}
|
||||
ResourceBundle resource = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
|
||||
// Initialize the fields from the ResourceBundle for locale.
|
||||
LocaleProviderAdapter adapter
|
||||
= LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
|
||||
// Avoid any potential recursions
|
||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
}
|
||||
ResourceBundle resource
|
||||
= ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
|
||||
|
||||
// JRE and CLDR use different keys
|
||||
// JRE: Eras, short.Eras and narrow.Eras
|
||||
// CLDR: long.Eras, Eras and narrow.Eras
|
||||
if (resource.containsKey("Eras")) {
|
||||
eras = resource.getStringArray("Eras");
|
||||
} else if (resource.containsKey("long.Eras")) {
|
||||
eras = resource.getStringArray("long.Eras");
|
||||
} else if (resource.containsKey("short.Eras")) {
|
||||
eras = resource.getStringArray("short.Eras");
|
||||
}
|
||||
months = resource.getStringArray("MonthNames");
|
||||
shortMonths = resource.getStringArray("MonthAbbreviations");
|
||||
ampms = resource.getStringArray("AmPmMarkers");
|
||||
localPatternChars = resource.getString("DateTimePatternChars");
|
||||
dfs.locale = locale;
|
||||
// JRE and CLDR use different keys
|
||||
// JRE: Eras, short.Eras and narrow.Eras
|
||||
// CLDR: long.Eras, Eras and narrow.Eras
|
||||
if (resource.containsKey("Eras")) {
|
||||
dfs.eras = resource.getStringArray("Eras");
|
||||
} else if (resource.containsKey("long.Eras")) {
|
||||
dfs.eras = resource.getStringArray("long.Eras");
|
||||
} else if (resource.containsKey("short.Eras")) {
|
||||
dfs.eras = resource.getStringArray("short.Eras");
|
||||
}
|
||||
dfs.months = resource.getStringArray("MonthNames");
|
||||
dfs.shortMonths = resource.getStringArray("MonthAbbreviations");
|
||||
dfs.ampms = resource.getStringArray("AmPmMarkers");
|
||||
dfs.localPatternChars = resource.getString("DateTimePatternChars");
|
||||
|
||||
// Day of week names are stored in a 1-based array.
|
||||
weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
|
||||
shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
|
||||
// Day of week names are stored in a 1-based array.
|
||||
dfs.weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
|
||||
dfs.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
|
||||
|
||||
// Put a clone in the cache
|
||||
ref = new SoftReference<>((DateFormatSymbols)this.clone());
|
||||
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
|
||||
if (x != null) {
|
||||
DateFormatSymbols y = x.get();
|
||||
if (y == null) {
|
||||
// Replace the empty SoftReference with ref.
|
||||
cachedInstances.put(locale, ref);
|
||||
// Put dfs in the cache
|
||||
ref = new SoftReference<>(dfs);
|
||||
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
|
||||
if (x != null) {
|
||||
DateFormatSymbols y = x.get();
|
||||
if (y == null) {
|
||||
// Replace the empty SoftReference with ref.
|
||||
cachedInstances.replace(locale, x, ref);
|
||||
} else {
|
||||
ref = x;
|
||||
dfs = y;
|
||||
}
|
||||
}
|
||||
// If the bundle's locale isn't the target locale, put another cache
|
||||
// entry for the bundle's locale.
|
||||
Locale bundleLocale = resource.getLocale();
|
||||
if (!bundleLocale.equals(locale)) {
|
||||
SoftReference<DateFormatSymbols> z
|
||||
= cachedInstances.putIfAbsent(bundleLocale, ref);
|
||||
if (z != null && z.get() == null) {
|
||||
cachedInstances.replace(bundleLocale, z, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the field values from dfs to this instance.
|
||||
copyMembers(dfs, this);
|
||||
}
|
||||
|
||||
private static String[] toOneBasedArray(String[] src) {
|
||||
@ -808,12 +839,14 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
|
||||
/**
|
||||
* Clones all the data members from the source DateFormatSymbols to
|
||||
* the target DateFormatSymbols. This is only for subclasses.
|
||||
* the target DateFormatSymbols.
|
||||
*
|
||||
* @param src the source DateFormatSymbols.
|
||||
* @param dst the target DateFormatSymbols.
|
||||
*/
|
||||
private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
|
||||
{
|
||||
dst.locale = src.locale;
|
||||
dst.eras = Arrays.copyOf(src.eras, src.eras.length);
|
||||
dst.months = Arrays.copyOf(src.months, src.months.length);
|
||||
dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -61,12 +61,17 @@
|
||||
*/
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
|
||||
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.ResolverStyle;
|
||||
import java.time.format.TextStyle;
|
||||
@ -712,6 +717,59 @@ public interface Chronology extends Comparable<Chronology> {
|
||||
return new ChronoPeriodImpl(this, years, months, days);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
|
||||
* <p>
|
||||
* The number of seconds is calculated using the proleptic-year,
|
||||
* month, day-of-month, hour, minute, second, and zoneOffset.
|
||||
*
|
||||
* @param prolepticYear the chronology proleptic-year
|
||||
* @param month the chronology month-of-year
|
||||
* @param dayOfMonth the chronology day-of-month
|
||||
* @param hour the hour-of-day, from 0 to 23
|
||||
* @param minute the minute-of-hour, from 0 to 59
|
||||
* @param second the second-of-minute, from 0 to 59
|
||||
* @param zoneOffset the zone offset, not null
|
||||
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
|
||||
* @throws DateTimeException if any of the values are out of range
|
||||
* @since 9
|
||||
*/
|
||||
public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
|
||||
int hour, int minute, int second, ZoneOffset zoneOffset) {
|
||||
Objects.requireNonNull(zoneOffset, "zoneOffset");
|
||||
HOUR_OF_DAY.checkValidValue(hour);
|
||||
MINUTE_OF_HOUR.checkValidValue(minute);
|
||||
SECOND_OF_MINUTE.checkValidValue(second);
|
||||
long daysInSec = Math.multiplyExact(date(prolepticYear, month, dayOfMonth).toEpochDay(), 86400);
|
||||
long timeinSec = (hour * 60 + minute) * 60 + second;
|
||||
return Math.addExact(daysInSec, timeinSec - zoneOffset.getTotalSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
|
||||
* <p>
|
||||
* The number of seconds is calculated using the era, year-of-era,
|
||||
* month, day-of-month, hour, minute, second, and zoneOffset.
|
||||
*
|
||||
* @param era the era of the correct type for the chronology, not null
|
||||
* @param yearOfEra the chronology year-of-era
|
||||
* @param month the chronology month-of-year
|
||||
* @param dayOfMonth the chronology day-of-month
|
||||
* @param hour the hour-of-day, from 0 to 23
|
||||
* @param minute the minute-of-hour, from 0 to 59
|
||||
* @param second the second-of-minute, from 0 to 59
|
||||
* @param zoneOffset the zone offset, not null
|
||||
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
|
||||
* @throws DateTimeException if any of the values are out of range
|
||||
* @since 9
|
||||
*/
|
||||
public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
|
||||
int hour, int minute, int second, ZoneOffset zoneOffset) {
|
||||
Objects.requireNonNull(era, "era");
|
||||
return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Compares this chronology to another chronology.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -61,14 +61,17 @@
|
||||
*/
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
|
||||
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
import static java.time.temporal.ChronoField.YEAR_OF_ERA;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
@ -79,8 +82,9 @@ import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.Period;
|
||||
import java.time.Year;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.ResolverStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
@ -132,6 +136,8 @@ public final class IsoChronology extends AbstractChronology implements Serializa
|
||||
*/
|
||||
private static final long serialVersionUID = -1440403870442975015L;
|
||||
|
||||
private static final long DAYS_0000_TO_1970 = (146097 * 5L) - (30L * 365L + 7L); // taken from LocalDate
|
||||
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
@ -263,6 +269,94 @@ public final class IsoChronology extends AbstractChronology implements Serializa
|
||||
return LocalDate.from(temporal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
|
||||
* <p>
|
||||
* The number of seconds is calculated using the year,
|
||||
* month, day-of-month, hour, minute, second, and zoneOffset.
|
||||
*
|
||||
* @param prolepticYear the year, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the day-of-month, from 1 to 31
|
||||
* @param hour the hour-of-day, from 0 to 23
|
||||
* @param minute the minute-of-hour, from 0 to 59
|
||||
* @param second the second-of-minute, from 0 to 59
|
||||
* @param zoneOffset the zone offset, not null
|
||||
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
|
||||
* @throws DateTimeException if the value of any argument is out of range,
|
||||
* or if the day-of-month is invalid for the month-of-year
|
||||
* @since 9
|
||||
*/
|
||||
@Override
|
||||
public long epochSecond(int prolepticYear, int month, int dayOfMonth,
|
||||
int hour, int minute, int second, ZoneOffset zoneOffset) {
|
||||
YEAR.checkValidValue(prolepticYear);
|
||||
MONTH_OF_YEAR.checkValidValue(month);
|
||||
DAY_OF_MONTH.checkValidValue(dayOfMonth);
|
||||
HOUR_OF_DAY.checkValidValue(hour);
|
||||
MINUTE_OF_HOUR.checkValidValue(minute);
|
||||
SECOND_OF_MINUTE.checkValidValue(second);
|
||||
Objects.requireNonNull(zoneOffset, "zoneOffset");
|
||||
if (dayOfMonth > 28) {
|
||||
int dom = numberOfDaysOfMonth(prolepticYear, month);
|
||||
if (dayOfMonth > dom) {
|
||||
if (dayOfMonth == 29) {
|
||||
throw new DateTimeException("Invalid date 'February 29' as '" + prolepticYear + "' is not a leap year");
|
||||
} else {
|
||||
throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long totalDays = 0;
|
||||
int timeinSec = 0;
|
||||
totalDays += 365L * prolepticYear;
|
||||
if (prolepticYear >= 0) {
|
||||
totalDays += (prolepticYear + 3L) / 4 - (prolepticYear + 99L) / 100 + (prolepticYear + 399L) / 400;
|
||||
} else {
|
||||
totalDays -= prolepticYear / -4 - prolepticYear / -100 + prolepticYear / -400;
|
||||
}
|
||||
totalDays += (367 * month - 362) / 12;
|
||||
totalDays += dayOfMonth - 1;
|
||||
if (month > 2) {
|
||||
totalDays--;
|
||||
if (IsoChronology.INSTANCE.isLeapYear(prolepticYear) == false) {
|
||||
totalDays--;
|
||||
}
|
||||
}
|
||||
totalDays -= DAYS_0000_TO_1970;
|
||||
timeinSec = (hour * 60 + minute ) * 60 + second;
|
||||
return Math.addExact(Math.multiplyExact(totalDays, 86400L), timeinSec - zoneOffset.getTotalSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of days for the given month in the given year.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year to represent, from 1 to 12
|
||||
* @return the number of days for the given month in the given year
|
||||
*/
|
||||
private int numberOfDaysOfMonth(int year, int month) {
|
||||
int dom;
|
||||
switch (month) {
|
||||
case 2:
|
||||
dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
dom = 30;
|
||||
break;
|
||||
default:
|
||||
dom = 31;
|
||||
break;
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains an ISO local date-time from another date-time object.
|
||||
* <p>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -270,6 +270,8 @@ public enum ChronoField implements TemporalField {
|
||||
* In lenient mode the value is not validated. It is combined with
|
||||
* {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
|
||||
* the {AMPM_OF_DAY} value by 12.
|
||||
* <p>
|
||||
* See {@link #CLOCK_HOUR_OF_AMPM} for the related field that counts hours from 1 to 12.
|
||||
*/
|
||||
HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
|
||||
/**
|
||||
@ -284,6 +286,8 @@ public enum ChronoField implements TemporalField {
|
||||
* 0 to 12 in smart mode. In lenient mode the value is not validated.
|
||||
* The field is converted to an {@code HOUR_OF_AMPM} with the same value,
|
||||
* unless the value is 12, in which case it is converted to 0.
|
||||
* <p>
|
||||
* See {@link #HOUR_OF_AMPM} for the related field that counts hours from 0 to 11.
|
||||
*/
|
||||
CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
|
||||
/**
|
||||
@ -299,12 +303,14 @@ public enum ChronoField implements TemporalField {
|
||||
* {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
|
||||
* In lenient mode, any excess days are added to the parsed date, or
|
||||
* made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
|
||||
* <p>
|
||||
* See {@link #CLOCK_HOUR_OF_DAY} for the related field that counts hours from 1 to 24.
|
||||
*/
|
||||
HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
|
||||
/**
|
||||
* The clock-hour-of-day.
|
||||
* <p>
|
||||
* This counts the hour within the AM/PM, from 1 to 24.
|
||||
* This counts the hour within the day, from 1 to 24.
|
||||
* This is the hour that would be observed on a 24-hour analog wall clock.
|
||||
* This field has the same meaning for all calendar systems.
|
||||
* <p>
|
||||
@ -313,6 +319,8 @@ public enum ChronoField implements TemporalField {
|
||||
* 0 to 24 in smart mode. In lenient mode the value is not validated.
|
||||
* The field is converted to an {@code HOUR_OF_DAY} with the same value,
|
||||
* unless the value is 24, in which case it is converted to 0.
|
||||
* <p>
|
||||
* See {@link #HOUR_OF_DAY} for the related field that counts hours from 0 to 23.
|
||||
*/
|
||||
CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
|
||||
/**
|
||||
|
@ -174,7 +174,7 @@ package java.util;
|
||||
* that do allow null elements are strongly encouraged <i>not</i> to
|
||||
* take advantage of the ability to insert nulls. This is so because
|
||||
* {@code null} is used as a special return value by various methods
|
||||
* to indicated that the deque is empty.
|
||||
* to indicate that the deque is empty.
|
||||
*
|
||||
* <p>{@code Deque} implementations generally do not define
|
||||
* element-based versions of the {@code equals} and {@code hashCode}
|
||||
|
@ -480,7 +480,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
}
|
||||
|
||||
static void lazySetNext(Completion c, Completion next) {
|
||||
U.putOrderedObject(c, NEXT, next);
|
||||
U.putObjectRelease(c, NEXT, next);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -583,9 +583,9 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
*/
|
||||
final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
|
||||
if (a != null && a.stack != null) {
|
||||
if (mode < 0 || a.result == null)
|
||||
if (a.result == null)
|
||||
a.cleanStack();
|
||||
else
|
||||
else if (mode >= 0)
|
||||
a.postComplete();
|
||||
}
|
||||
if (result != null && stack != null) {
|
||||
@ -1107,9 +1107,9 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
final CompletableFuture<T> postFire(CompletableFuture<?> a,
|
||||
CompletableFuture<?> b, int mode) {
|
||||
if (b != null && b.stack != null) { // clean second source
|
||||
if (mode < 0 || b.result == null)
|
||||
if (b.result == null)
|
||||
b.cleanStack();
|
||||
else
|
||||
else if (mode >= 0)
|
||||
b.postComplete();
|
||||
}
|
||||
return postFire(a, mode);
|
||||
|
@ -628,10 +628,14 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
volatile V val;
|
||||
volatile Node<K,V> next;
|
||||
|
||||
Node(int hash, K key, V val, Node<K,V> next) {
|
||||
Node(int hash, K key, V val) {
|
||||
this.hash = hash;
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
Node(int hash, K key, V val, Node<K,V> next) {
|
||||
this(hash, key, val);
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@ -1024,8 +1028,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
if (tab == null || (n = tab.length) == 0)
|
||||
tab = initTable();
|
||||
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
|
||||
if (casTabAt(tab, i, null,
|
||||
new Node<K,V>(hash, key, value, null)))
|
||||
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
|
||||
break; // no lock when adding to empty bin
|
||||
}
|
||||
else if ((fh = f.hash) == MOVED)
|
||||
@ -1048,8 +1051,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
Node<K,V> pred = e;
|
||||
if ((e = e.next) == null) {
|
||||
pred.next = new Node<K,V>(hash, key,
|
||||
value, null);
|
||||
pred.next = new Node<K,V>(hash, key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1709,7 +1711,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
Node<K,V> node = null;
|
||||
try {
|
||||
if ((val = mappingFunction.apply(key)) != null)
|
||||
node = new Node<K,V>(h, key, val, null);
|
||||
node = new Node<K,V>(h, key, val);
|
||||
} finally {
|
||||
setTabAt(tab, i, node);
|
||||
}
|
||||
@ -1740,7 +1742,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
if (pred.next != null)
|
||||
throw new IllegalStateException("Recursive update");
|
||||
added = true;
|
||||
pred.next = new Node<K,V>(h, key, val, null);
|
||||
pred.next = new Node<K,V>(h, key, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1909,7 +1911,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
try {
|
||||
if ((val = remappingFunction.apply(key, null)) != null) {
|
||||
delta = 1;
|
||||
node = new Node<K,V>(h, key, val, null);
|
||||
node = new Node<K,V>(h, key, val);
|
||||
}
|
||||
} finally {
|
||||
setTabAt(tab, i, node);
|
||||
@ -1951,8 +1953,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
if (pred.next != null)
|
||||
throw new IllegalStateException("Recursive update");
|
||||
delta = 1;
|
||||
pred.next =
|
||||
new Node<K,V>(h, key, val, null);
|
||||
pred.next = new Node<K,V>(h, key, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2030,7 +2031,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
if (tab == null || (n = tab.length) == 0)
|
||||
tab = initTable();
|
||||
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
|
||||
if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
|
||||
if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
|
||||
delta = 1;
|
||||
val = value;
|
||||
break;
|
||||
@ -2065,8 +2066,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
if ((e = e.next) == null) {
|
||||
delta = 1;
|
||||
val = value;
|
||||
pred.next =
|
||||
new Node<K,V>(h, key, val, null);
|
||||
pred.next = new Node<K,V>(h, key, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2227,7 +2227,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
static final class ForwardingNode<K,V> extends Node<K,V> {
|
||||
final Node<K,V>[] nextTable;
|
||||
ForwardingNode(Node<K,V>[] tab) {
|
||||
super(MOVED, null, null, null);
|
||||
super(MOVED, null, null);
|
||||
this.nextTable = tab;
|
||||
}
|
||||
|
||||
@ -2263,7 +2263,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
*/
|
||||
static final class ReservationNode<K,V> extends Node<K,V> {
|
||||
ReservationNode() {
|
||||
super(RESERVED, null, null, null);
|
||||
super(RESERVED, null, null);
|
||||
}
|
||||
|
||||
Node<K,V> find(int h, Object k) {
|
||||
@ -2690,12 +2690,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list on non-TreeNodes replacing those in given list.
|
||||
* Returns a list of non-TreeNodes replacing those in given list.
|
||||
*/
|
||||
static <K,V> Node<K,V> untreeify(Node<K,V> b) {
|
||||
Node<K,V> hd = null, tl = null;
|
||||
for (Node<K,V> q = b; q != null; q = q.next) {
|
||||
Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
|
||||
Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
|
||||
if (tl == null)
|
||||
hd = p;
|
||||
else
|
||||
@ -2801,7 +2801,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
* Creates bin with initial set of nodes headed by b.
|
||||
*/
|
||||
TreeBin(TreeNode<K,V> b) {
|
||||
super(TREEBIN, null, null, null);
|
||||
super(TREEBIN, null, null);
|
||||
this.first = b;
|
||||
TreeNode<K,V> r = null;
|
||||
for (TreeNode<K,V> x = b, next; x != null; x = next) {
|
||||
|
@ -309,7 +309,7 @@ public class ConcurrentLinkedDeque<E>
|
||||
}
|
||||
|
||||
void lazySetNext(Node<E> val) {
|
||||
U.putOrderedObject(this, NEXT, val);
|
||||
U.putObjectRelease(this, NEXT, val);
|
||||
}
|
||||
|
||||
boolean casNext(Node<E> cmp, Node<E> val) {
|
||||
@ -317,7 +317,7 @@ public class ConcurrentLinkedDeque<E>
|
||||
}
|
||||
|
||||
void lazySetPrev(Node<E> val) {
|
||||
U.putOrderedObject(this, PREV, val);
|
||||
U.putObjectRelease(this, PREV, val);
|
||||
}
|
||||
|
||||
boolean casPrev(Node<E> cmp, Node<E> val) {
|
||||
|
@ -198,7 +198,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
static <E> void lazySetNext(Node<E> node, Node<E> val) {
|
||||
U.putOrderedObject(node, NEXT, val);
|
||||
U.putObjectRelease(node, NEXT, val);
|
||||
}
|
||||
|
||||
static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
|
||||
|
@ -239,7 +239,7 @@ public class Exchanger<V> {
|
||||
* not to be as readily inlined by dynamic compilers when they are
|
||||
* hidden behind other methods that would more nicely name and
|
||||
* encapsulate the intended effects). This includes the use of
|
||||
* putOrderedX to clear fields of the per-thread Nodes between
|
||||
* putXRelease to clear fields of the per-thread Nodes between
|
||||
* uses. Note that field Node.item is not declared as volatile
|
||||
* even though it is read by releasing threads, because they only
|
||||
* do so after CAS operations that must precede access, and all
|
||||
@ -376,7 +376,7 @@ public class Exchanger<V> {
|
||||
for (int h = p.hash, spins = SPINS;;) {
|
||||
Object v = p.match;
|
||||
if (v != null) {
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
U.putObjectRelease(p, MATCH, null);
|
||||
p.item = null; // clear for next use
|
||||
p.hash = h;
|
||||
return v;
|
||||
@ -507,7 +507,7 @@ public class Exchanger<V> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
U.putObjectRelease(p, MATCH, null);
|
||||
p.item = null;
|
||||
p.hash = h;
|
||||
return v;
|
||||
|
@ -289,7 +289,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* on to try or create other queues -- they block only when
|
||||
* creating and registering new queues. Because it is used only as
|
||||
* a spinlock, unlocking requires only a "releasing" store (using
|
||||
* putOrderedInt). The qlock is also used during termination
|
||||
* putIntRelease). The qlock is also used during termination
|
||||
* detection, in which case it is forced to a negative
|
||||
* non-lockable value.
|
||||
*
|
||||
@ -1071,7 +1071,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
popped = true;
|
||||
top = s;
|
||||
}
|
||||
U.putOrderedInt(this, QLOCK, 0);
|
||||
U.putIntRelease(this, QLOCK, 0);
|
||||
}
|
||||
}
|
||||
return popped;
|
||||
@ -1261,7 +1261,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
popped = true;
|
||||
top = s - 1;
|
||||
}
|
||||
U.putOrderedInt(this, QLOCK, 0);
|
||||
U.putIntRelease(this, QLOCK, 0);
|
||||
if (popped)
|
||||
return t;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public class ForkJoinWorkerThread extends Thread {
|
||||
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
|
||||
AccessControlContext acc) {
|
||||
super(threadGroup, null, "aForkJoinWorkerThread");
|
||||
U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
|
||||
U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
|
||||
eraseThreadLocals(); // clear before registering
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
|
@ -174,7 +174,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
if (t != null)
|
||||
t.interrupt();
|
||||
} finally { // final state
|
||||
U.putOrderedInt(this, STATE, INTERRUPTED);
|
||||
U.putIntRelease(this, STATE, INTERRUPTED);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@ -230,7 +230,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
protected void set(V v) {
|
||||
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
|
||||
outcome = v;
|
||||
U.putOrderedInt(this, STATE, NORMAL); // final state
|
||||
U.putIntRelease(this, STATE, NORMAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
@ -248,7 +248,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
protected void setException(Throwable t) {
|
||||
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
|
||||
outcome = t;
|
||||
U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
|
||||
U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
|
@ -1496,7 +1496,7 @@ public class SubmissionPublisher<T> implements Flow.Publisher<T>,
|
||||
else if (((c & CONSUME) != 0 ||
|
||||
U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
|
||||
U.compareAndSwapObject(a, i, x, null)) {
|
||||
U.putOrderedInt(this, HEAD, ++h);
|
||||
U.putIntRelease(this, HEAD, ++h);
|
||||
U.getAndAddLong(this, DEMAND, -1L);
|
||||
if ((w = waiter) != null)
|
||||
signalWaiter(w);
|
||||
|
@ -136,7 +136,7 @@ public class AtomicBoolean implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(boolean newValue) {
|
||||
U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
|
||||
U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +108,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int newValue) {
|
||||
U.putOrderedInt(this, VALUE, newValue);
|
||||
U.putIntRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,7 +136,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, int newValue) {
|
||||
U.putOrderedInt(array, checkedByteOffset(i), newValue);
|
||||
U.putIntRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -475,7 +475,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
|
||||
|
||||
public final void lazySet(T obj, int newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedInt(obj, offset, newValue);
|
||||
U.putIntRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final int get(T obj) {
|
||||
|
@ -124,7 +124,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(long newValue) {
|
||||
U.putOrderedLong(this, VALUE, newValue);
|
||||
U.putLongRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +135,7 @@ public class AtomicLongArray implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, long newValue) {
|
||||
U.putOrderedLong(array, checkedByteOffset(i), newValue);
|
||||
U.putLongRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,7 +457,7 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
|
||||
public final void lazySet(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedLong(obj, offset, newValue);
|
||||
U.putLongRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final long get(T obj) {
|
||||
|
@ -103,7 +103,7 @@ public class AtomicReference<V> implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(V newValue) {
|
||||
U.putOrderedObject(this, VALUE, newValue);
|
||||
U.putObjectRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +147,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, E newValue) {
|
||||
U.putOrderedObject(array, checkedByteOffset(i), newValue);
|
||||
U.putObjectRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -426,7 +426,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
|
||||
public final void lazySet(T obj, V newValue) {
|
||||
accessCheck(obj);
|
||||
valueCheck(newValue);
|
||||
U.putOrderedObject(obj, offset, newValue);
|
||||
U.putObjectRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -42,107 +42,95 @@ import java.util.List;
|
||||
* to the jimage file provided by the shipped JDK by tools running on JDK 8.
|
||||
*/
|
||||
public class CompressIndexes {
|
||||
private static final int INTEGER_SIZE = 4;
|
||||
private static final int COMPRESSED_FLAG = 1 << (Byte.SIZE - 1);
|
||||
private static final int HEADER_WIDTH = 3;
|
||||
private static final int HEADER_SHIFT = Byte.SIZE - HEADER_WIDTH;
|
||||
|
||||
public static List<Integer> decompressFlow(byte[] values) {
|
||||
List<Integer> lst = new ArrayList<>();
|
||||
for (int i = 0; i < values.length;) {
|
||||
byte b = values[i];
|
||||
int length = isCompressed(b) ? getLength(b) : INTEGER_SIZE;
|
||||
|
||||
for (int i = 0; i < values.length; i += getHeaderLength(values[i])) {
|
||||
int decompressed = decompress(values, i);
|
||||
lst.add(decompressed);
|
||||
i += length;
|
||||
}
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
public static int readInt(DataInputStream cr) throws IOException {
|
||||
byte[] b = new byte[1];
|
||||
cr.readFully(b);
|
||||
byte firstByte = b[0];
|
||||
boolean compressed = CompressIndexes.isCompressed(firstByte);
|
||||
int toRead = 4;
|
||||
if(compressed) {
|
||||
toRead = CompressIndexes.getLength(firstByte);
|
||||
// Get header byte.
|
||||
byte header = cr.readByte();
|
||||
// Determine size.
|
||||
int size = getHeaderLength(header);
|
||||
// Prepare result.
|
||||
int result = getHeaderValue(header);
|
||||
|
||||
// For each value byte
|
||||
for (int i = 1; i < size; i++) {
|
||||
// Merge byte value.
|
||||
result <<= Byte.SIZE;
|
||||
result |= cr.readByte() & 0xFF;
|
||||
}
|
||||
byte[] content = new byte[toRead-1];
|
||||
cr.readFully(content);
|
||||
ByteBuffer bb = ByteBuffer.allocate(content.length+1);
|
||||
bb.put(firstByte);
|
||||
bb.put(content);
|
||||
int index = CompressIndexes.decompress(bb.array(), 0);
|
||||
return index;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getLength(byte b) {
|
||||
return ((byte) (b & 0x60) >> 5);
|
||||
private static boolean isCompressed(byte b) {
|
||||
return (b & COMPRESSED_FLAG) != 0;
|
||||
}
|
||||
|
||||
public static boolean isCompressed(byte b) {
|
||||
return b < 0;
|
||||
private static int getHeaderLength(byte b) {
|
||||
return isCompressed(b) ? (b >> HEADER_SHIFT) & 3 : Integer.BYTES;
|
||||
}
|
||||
|
||||
private static int getHeaderValue(byte b) {
|
||||
return isCompressed(b) ? b & (1 << HEADER_SHIFT) - 1 : b;
|
||||
}
|
||||
|
||||
public static int decompress(byte[] value, int offset) {
|
||||
byte b1 = value[offset];
|
||||
ByteBuffer buffer = ByteBuffer.allocate(INTEGER_SIZE);
|
||||
if (isCompressed(b1)) { // compressed
|
||||
int length = getLength(b1);
|
||||
byte clearedValue = (byte) (b1 & 0x1F);
|
||||
// Get header byte.
|
||||
byte header = value[offset];
|
||||
// Determine size.
|
||||
int size = getHeaderLength(header);
|
||||
// Prepare result.
|
||||
int result = getHeaderValue(header);
|
||||
|
||||
int start = INTEGER_SIZE - length;
|
||||
buffer.put(start, clearedValue);
|
||||
for (int i = offset + 1; i < offset + length; i++) {
|
||||
buffer.put(++start, value[i]);
|
||||
}
|
||||
} else {
|
||||
buffer.put(value, offset, INTEGER_SIZE);
|
||||
// For each value byte
|
||||
for (int i = 1; i < size; i++) {
|
||||
// Merge byte value.
|
||||
result <<= Byte.SIZE;
|
||||
result |= value[offset + i] & 0xFF;
|
||||
}
|
||||
return buffer.getInt(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] compress(int val) {
|
||||
ByteBuffer result = ByteBuffer.allocate(4).putInt(val);
|
||||
byte[] array = result.array();
|
||||
|
||||
if ((val & 0xFF000000) == 0) { // nothing on 4th
|
||||
if ((val & 0x00FF0000) == 0) { // nothing on 3rd
|
||||
if ((val & 0x0000FF00) == 0) { // nothing on 2nd
|
||||
if ((val & 0x000000E0) == 0) { // only in 1st, encode length in the byte.
|
||||
//sign bit and size 1 ==> 101X
|
||||
result = ByteBuffer.allocate(1);
|
||||
result.put((byte) (0xA0 | array[3]));
|
||||
} else { // add a byte for size
|
||||
//sign bit and size 2 ==> 110X
|
||||
result = ByteBuffer.allocate(2);
|
||||
result.put((byte) 0xC0);
|
||||
result.put(array[3]);
|
||||
}
|
||||
} else { // content in 2nd
|
||||
if ((val & 0x0000E000) == 0) {// encode length in the byte.
|
||||
//sign bit and size 2 ==> 110X
|
||||
result = ByteBuffer.allocate(2);
|
||||
result.put((byte) (0xC0 | array[2]));
|
||||
result.put(array[3]);
|
||||
} else { // add a byte for size
|
||||
//sign bit and size 3 ==> 111X
|
||||
result = ByteBuffer.allocate(3);
|
||||
result.put((byte) 0xE0);
|
||||
result.put(array[2]);
|
||||
result.put(array[3]);
|
||||
}
|
||||
}
|
||||
} else {// content in 3rd
|
||||
if ((val & 0x00E00000) == 0) {// encode length in the byte.
|
||||
//sign bit and size 3 ==> 111X
|
||||
result = ByteBuffer.allocate(3);
|
||||
result.put((byte) (0xE0 | array[1]));
|
||||
result.put(array[2]);
|
||||
result.put(array[3]);
|
||||
} else { // add a byte, useless
|
||||
//
|
||||
}
|
||||
}
|
||||
public static byte[] compress(int value) {
|
||||
// Only positive values are supported.
|
||||
if (value < 0) {
|
||||
throw new IllegalArgumentException("value < 0");
|
||||
}
|
||||
return result.array();
|
||||
|
||||
// Determine number of significant digits.
|
||||
int width = 32 - Integer.numberOfLeadingZeros(value);
|
||||
// Determine number of byte to represent. Allow for header if
|
||||
// compressed.
|
||||
int size = Math.min(((width + HEADER_WIDTH - 1) >> 3) + 1, Integer.BYTES);
|
||||
|
||||
// Allocate result buffer.
|
||||
byte[] result = new byte[size];
|
||||
|
||||
// Insert significant bytes in result.
|
||||
for (int i = 0; i < size; i++) {
|
||||
result[i] = (byte)(value >> ((size - i - 1) * Byte.SIZE));
|
||||
}
|
||||
|
||||
// If compressed, mark and insert size.
|
||||
if (size < Integer.BYTES) {
|
||||
result[0] |= (byte)(COMPRESSED_FLAG | (size << HEADER_SHIFT));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ public final class InnocuousThread extends Thread {
|
||||
|
||||
private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
|
||||
super(group, target, name, 0L, false);
|
||||
UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
|
||||
UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);
|
||||
UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
|
||||
UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1457,25 +1457,7 @@ public final class Unsafe {
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putDoubleVolatile(Object o, long offset, double x);
|
||||
|
||||
/**
|
||||
* Version of {@link #putObjectVolatile(Object, long, Object)}
|
||||
* that does not guarantee immediate visibility of the store to
|
||||
* other threads. This method is generally only useful if the
|
||||
* underlying field is a Java volatile (or if an array cell, one
|
||||
* that is otherwise only accessed using volatile accesses).
|
||||
*
|
||||
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedObject(Object o, long offset, Object x);
|
||||
|
||||
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedInt(Object o, long offset, int x);
|
||||
|
||||
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedLong(Object o, long offset, long x);
|
||||
|
||||
/** Acquire version of {@link #getObjectVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
@ -1531,6 +1513,16 @@ public final class Unsafe {
|
||||
return getDoubleVolatile(o, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Versions of {@link #putObjectVolatile(Object, long, Object)}
|
||||
* that do not guarantee immediate visibility of the store to
|
||||
* other threads. This method is generally only useful if the
|
||||
* underlying field is a Java volatile (or if an array cell, one
|
||||
* that is otherwise only accessed using volatile accesses).
|
||||
*
|
||||
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
|
||||
*/
|
||||
|
||||
/** Release version of {@link #putObjectVolatile(Object, long, Object)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putObjectRelease(Object o, long offset, Object x) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.misc;
|
||||
package jdk.internal.vm;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
@ -182,6 +182,9 @@ module java.base {
|
||||
java.desktop;
|
||||
exports jdk.internal.util.jar to
|
||||
jdk.jartool;
|
||||
exports jdk.internal.vm to
|
||||
java.management,
|
||||
jdk.jvmstat;
|
||||
exports sun.net to
|
||||
java.httpclient;
|
||||
exports sun.net.dns to
|
||||
|
@ -1068,19 +1068,19 @@ public final class Unsafe {
|
||||
*/
|
||||
@ForceInline
|
||||
public void putOrderedObject(Object o, long offset, Object x) {
|
||||
theInternalUnsafe.putOrderedObject(o, offset, x);
|
||||
theInternalUnsafe.putObjectRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@ForceInline
|
||||
public void putOrderedInt(Object o, long offset, int x) {
|
||||
theInternalUnsafe.putOrderedInt(o, offset, x);
|
||||
theInternalUnsafe.putIntRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@ForceInline
|
||||
public void putOrderedLong(Object o, long offset, long x) {
|
||||
theInternalUnsafe.putOrderedLong(o, offset, x);
|
||||
theInternalUnsafe.putLongRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +83,7 @@ public class TransferProtocolClient extends NetworkClient {
|
||||
code = Integer.parseInt(response, 0, 3, 10);
|
||||
} catch (NumberFormatException e) {
|
||||
code = -1;
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
/* this line doesn't contain a response code, so
|
||||
we just completely ignore it */
|
||||
continue;
|
||||
|
@ -440,7 +440,7 @@ public class FtpClient extends sun.net.ftp.FtpClient {
|
||||
code = Integer.parseInt(response, 0, 3, 10);
|
||||
} catch (NumberFormatException e) {
|
||||
code = -1;
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
/* this line doesn't contain a response code, so
|
||||
we just completely ignore it */
|
||||
continue;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2016, 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
|
||||
@ -299,6 +299,13 @@ public class FtpURLConnection extends URLConnection {
|
||||
// Just keep throwing for now.
|
||||
throw e;
|
||||
} catch (FtpProtocolException fe) {
|
||||
if (ftp != null) {
|
||||
try {
|
||||
ftp.close();
|
||||
} catch (IOException ioe) {
|
||||
fe.addSuppressed(ioe);
|
||||
}
|
||||
}
|
||||
throw new IOException(fe);
|
||||
}
|
||||
try {
|
||||
@ -481,11 +488,34 @@ public class FtpURLConnection extends URLConnection {
|
||||
msgh.add("content-type", "text/plain");
|
||||
msgh.add("access-type", "directory");
|
||||
} catch (IOException ex) {
|
||||
throw new FileNotFoundException(fullpath);
|
||||
FileNotFoundException fnfe = new FileNotFoundException(fullpath);
|
||||
if (ftp != null) {
|
||||
try {
|
||||
ftp.close();
|
||||
} catch (IOException ioe) {
|
||||
fnfe.addSuppressed(ioe);
|
||||
}
|
||||
}
|
||||
throw fnfe;
|
||||
} catch (FtpProtocolException ex2) {
|
||||
throw new FileNotFoundException(fullpath);
|
||||
FileNotFoundException fnfe = new FileNotFoundException(fullpath);
|
||||
if (ftp != null) {
|
||||
try {
|
||||
ftp.close();
|
||||
} catch (IOException ioe) {
|
||||
fnfe.addSuppressed(ioe);
|
||||
}
|
||||
}
|
||||
throw fnfe;
|
||||
}
|
||||
} catch (FtpProtocolException ftpe) {
|
||||
if (ftp != null) {
|
||||
try {
|
||||
ftp.close();
|
||||
} catch (IOException ioe) {
|
||||
ftpe.addSuppressed(ioe);
|
||||
}
|
||||
}
|
||||
throw new IOException(ftpe);
|
||||
}
|
||||
setProperties(msgh);
|
||||
|
@ -1198,8 +1198,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
if (!localSupportedSignAlgs.contains(
|
||||
preferableSignatureAlgorithm)) {
|
||||
throw new SSLHandshakeException(
|
||||
"Unsupported SignatureAndHashAlgorithm in " +
|
||||
"ServerKeyExchange message");
|
||||
"Unsupported SignatureAndHashAlgorithm in " +
|
||||
"ServerKeyExchange message: " +
|
||||
preferableSignatureAlgorithm);
|
||||
}
|
||||
} else {
|
||||
this.preferableSignatureAlgorithm = null;
|
||||
@ -1232,7 +1233,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
sig = RSASignature.getInstance();
|
||||
break;
|
||||
default:
|
||||
throw new SSLKeyException("neither an RSA or a DSA key");
|
||||
throw new SSLKeyException(
|
||||
"neither an RSA or a DSA key: " + algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1482,7 +1484,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
||||
preferableSignatureAlgorithm)) {
|
||||
throw new SSLHandshakeException(
|
||||
"Unsupported SignatureAndHashAlgorithm in " +
|
||||
"ServerKeyExchange message");
|
||||
"ServerKeyExchange message: " +
|
||||
preferableSignatureAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1522,7 +1525,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
||||
case "RSA":
|
||||
return RSASignature.getInstance();
|
||||
default:
|
||||
throw new NoSuchAlgorithmException("neither an RSA or a EC key");
|
||||
throw new NoSuchAlgorithmException(
|
||||
"neither an RSA or a EC key : " + keyAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1729,7 +1733,8 @@ class CertificateRequest extends HandshakeMessage
|
||||
algorithmsLen = input.getInt16();
|
||||
if (algorithmsLen < 2) {
|
||||
throw new SSLProtocolException(
|
||||
"Invalid supported_signature_algorithms field");
|
||||
"Invalid supported_signature_algorithms field: " +
|
||||
algorithmsLen);
|
||||
}
|
||||
|
||||
algorithms = new ArrayList<SignatureAndHashAlgorithm>();
|
||||
@ -1748,7 +1753,8 @@ class CertificateRequest extends HandshakeMessage
|
||||
|
||||
if (remains != 0) {
|
||||
throw new SSLProtocolException(
|
||||
"Invalid supported_signature_algorithms field");
|
||||
"Invalid supported_signature_algorithms field. remains: " +
|
||||
remains);
|
||||
}
|
||||
} else {
|
||||
algorithms = new ArrayList<SignatureAndHashAlgorithm>();
|
||||
@ -1765,7 +1771,8 @@ class CertificateRequest extends HandshakeMessage
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
throw new SSLProtocolException("Bad CertificateRequest DN length");
|
||||
throw new SSLProtocolException(
|
||||
"Bad CertificateRequest DN length: " + len);
|
||||
}
|
||||
|
||||
authorities = v.toArray(new DistinguishedName[v.size()]);
|
||||
@ -1995,8 +2002,8 @@ static final class CertificateVerify extends HandshakeMessage {
|
||||
if (!localSupportedSignAlgs.contains(
|
||||
preferableSignatureAlgorithm)) {
|
||||
throw new SSLHandshakeException(
|
||||
"Unsupported SignatureAndHashAlgorithm in " +
|
||||
"CertificateVerify message");
|
||||
"Unsupported SignatureAndHashAlgorithm in " +
|
||||
"CertificateVerify message: " + preferableSignatureAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2364,7 +2371,8 @@ static final class Finished extends HandshakeMessage {
|
||||
SecretKey prfKey = kg.generateKey();
|
||||
if ("RAW".equals(prfKey.getFormat()) == false) {
|
||||
throw new ProviderException(
|
||||
"Invalid PRF output, format must be RAW");
|
||||
"Invalid PRF output, format must be RAW. " +
|
||||
"Format received: " + prfKey.getFormat());
|
||||
}
|
||||
byte[] finished = prfKey.getEncoded();
|
||||
return finished;
|
||||
|
@ -68,7 +68,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
ProtocolVersion maxVersion,
|
||||
SecureRandom generator, PublicKey publicKey) throws IOException {
|
||||
if (publicKey.getAlgorithm().equals("RSA") == false) {
|
||||
throw new SSLKeyException("Public key not of type RSA");
|
||||
throw new SSLKeyException("Public key not of type RSA: " +
|
||||
publicKey.getAlgorithm());
|
||||
}
|
||||
this.protocolVersion = protocolVersion;
|
||||
|
||||
@ -100,7 +101,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
int messageSize, PrivateKey privateKey) throws IOException {
|
||||
|
||||
if (privateKey.getAlgorithm().equals("RSA") == false) {
|
||||
throw new SSLKeyException("Private key not of type RSA");
|
||||
throw new SSLKeyException("Private key not of type RSA: " +
|
||||
privateKey.getAlgorithm());
|
||||
}
|
||||
|
||||
if (currentVersion.useTLS10PlusSpec()) {
|
||||
@ -161,8 +163,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
}
|
||||
} catch (InvalidKeyException ibk) {
|
||||
// the message is too big to process with RSA
|
||||
throw new SSLProtocolException(
|
||||
"Unable to process PreMasterSecret, may be too big");
|
||||
throw new SSLException(
|
||||
"Unable to process PreMasterSecret", ibk);
|
||||
} catch (Exception e) {
|
||||
// unlikely to happen, otherwise, must be a provider exception
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
|
@ -27,36 +27,17 @@
|
||||
#include "jni_util.h"
|
||||
#include "jlong.h"
|
||||
#include "jvm.h"
|
||||
#include "jdk_util.h"
|
||||
|
||||
#include "sun_misc_VMSupport.h"
|
||||
|
||||
typedef jobject (JNICALL *INIT_AGENT_PROPERTIES_FN)(JNIEnv *, jobject);
|
||||
|
||||
static INIT_AGENT_PROPERTIES_FN InitAgentProperties_fp = NULL;
|
||||
#include "jdk_internal_vm_VMSupport.h"
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_sun_misc_VMSupport_initAgentProperties(JNIEnv *env, jclass cls, jobject props)
|
||||
Java_jdk_internal_vm_VMSupport_initAgentProperties(JNIEnv *env, jclass cls, jobject props)
|
||||
{
|
||||
if (InitAgentProperties_fp == NULL) {
|
||||
if (!JDK_InitJvmHandle()) {
|
||||
JNU_ThrowInternalError(env,
|
||||
"Handle for JVM not found for symbol lookup");
|
||||
return NULL;
|
||||
}
|
||||
InitAgentProperties_fp = (INIT_AGENT_PROPERTIES_FN)
|
||||
JDK_FindJvmEntry("JVM_InitAgentProperties");
|
||||
if (InitAgentProperties_fp == NULL) {
|
||||
JNU_ThrowInternalError(env,
|
||||
"Mismatched VM version: JVM_InitAgentProperties not found");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (*InitAgentProperties_fp)(env, props);
|
||||
return JVM_InitAgentProperties(env, props);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_sun_misc_VMSupport_getVMTemporaryDirectory(JNIEnv *env, jclass cls)
|
||||
Java_jdk_internal_vm_VMSupport_getVMTemporaryDirectory(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return JVM_GetTemporaryDirectory(env);
|
||||
}
|
||||
|
@ -2003,16 +2003,21 @@ ShowSplashScreen()
|
||||
void *image_data = NULL;
|
||||
float scale_factor = 1;
|
||||
char *scaled_splash_name = NULL;
|
||||
|
||||
jboolean isImageScaled = JNI_FALSE;
|
||||
size_t maxScaledImgNameLength = 0;
|
||||
if (file_name == NULL){
|
||||
return;
|
||||
}
|
||||
maxScaledImgNameLength = DoSplashGetScaledImgNameMaxPstfixLen(file_name);
|
||||
|
||||
scaled_splash_name = DoSplashGetScaledImageName(
|
||||
jar_name, file_name, &scale_factor);
|
||||
scaled_splash_name = JLI_MemAlloc(
|
||||
maxScaledImgNameLength * sizeof(char));
|
||||
isImageScaled = DoSplashGetScaledImageName(jar_name, file_name,
|
||||
&scale_factor,
|
||||
scaled_splash_name, maxScaledImgNameLength);
|
||||
if (jar_name) {
|
||||
|
||||
if (scaled_splash_name) {
|
||||
if (isImageScaled) {
|
||||
image_data = JLI_JarUnpackFile(
|
||||
jar_name, scaled_splash_name, &data_size);
|
||||
}
|
||||
@ -2030,17 +2035,14 @@ ShowSplashScreen()
|
||||
}
|
||||
} else {
|
||||
DoSplashInit();
|
||||
if (scaled_splash_name) {
|
||||
if (isImageScaled) {
|
||||
DoSplashSetScaleFactor(scale_factor);
|
||||
DoSplashLoadFile(scaled_splash_name);
|
||||
} else {
|
||||
DoSplashLoadFile(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (scaled_splash_name) {
|
||||
JLI_MemFree(scaled_splash_name);
|
||||
}
|
||||
JLI_MemFree(scaled_splash_name);
|
||||
|
||||
DoSplashSetFileJarName(file_name, jar_name);
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
int DoSplashLoadMemory(void* pdata, int size); /* requires preloading the file */
|
||||
int DoSplashLoadFile(const char* filename);
|
||||
@ -30,5 +30,6 @@ void DoSplashInit(void);
|
||||
void DoSplashClose(void);
|
||||
void DoSplashSetFileJarName(const char* fileName, const char* jarName);
|
||||
void DoSplashSetScaleFactor(float scaleFactor);
|
||||
char* DoSplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
float* scaleFactor);
|
||||
jboolean DoSplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
float* scaleFactor, char *scaleImageName, const size_t scaleImageNameLength);
|
||||
int DoSplashGetScaledImgNameMaxPstfixLen(const char *fileName);
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "splashscreen.h"
|
||||
|
||||
#include "jni.h"
|
||||
extern void* SplashProcAddress(const char* name); /* in java_md.c */
|
||||
|
||||
/*
|
||||
@ -38,8 +38,10 @@ typedef void (*SplashClose_t)(void);
|
||||
typedef void (*SplashSetFileJarName_t)(const char* fileName,
|
||||
const char* jarName);
|
||||
typedef void (*SplashSetScaleFactor_t)(float scaleFactor);
|
||||
typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
|
||||
const char* jarName, float* scaleFactor);
|
||||
typedef jboolean (*SplashGetScaledImageName_t)(const char* fileName,
|
||||
const char* jarName, float* scaleFactor,
|
||||
char *scaleImageName, const size_t scaleImageNameLength);
|
||||
typedef int (*SplashGetScaledImgNameMaxPstfixLen_t)(const char* filename);
|
||||
|
||||
/*
|
||||
* This macro invokes a function from the shared lib.
|
||||
@ -60,6 +62,7 @@ typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
|
||||
#define INVOKE(name,def) _INVOKE(name,def,return)
|
||||
#define INVOKEV(name) _INVOKE(name, ,;)
|
||||
|
||||
|
||||
int DoSplashLoadMemory(void* pdata, int size) {
|
||||
INVOKE(SplashLoadMemory, 0)(pdata, size);
|
||||
}
|
||||
@ -84,7 +87,13 @@ void DoSplashSetScaleFactor(float scaleFactor) {
|
||||
INVOKEV(SplashSetScaleFactor)(scaleFactor);
|
||||
}
|
||||
|
||||
char* DoSplashGetScaledImageName(const char* fileName, const char* jarName,
|
||||
float* scaleFactor) {
|
||||
INVOKE(SplashGetScaledImageName, NULL)(fileName, jarName, scaleFactor);
|
||||
jboolean DoSplashGetScaledImageName(const char* fileName, const char* jarName,
|
||||
float* scaleFactor, char *scaledImageName, const size_t scaledImageNameLength) {
|
||||
INVOKE(SplashGetScaledImageName, 0)(fileName, jarName, scaleFactor,
|
||||
scaledImageName, scaledImageNameLength);
|
||||
}
|
||||
|
||||
int DoSplashGetScaledImgNameMaxPstfixLen(const char *fileName) {
|
||||
INVOKE(SplashGetScaledImgNameMaxPstfixLen, 0)(fileName);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
module java.compact3 {
|
||||
requires public java.compact2;
|
||||
requires public java.compiler;
|
||||
requires public java.httpclient;
|
||||
requires public java.instrument;
|
||||
requires public java.management;
|
||||
requires public java.naming;
|
||||
|
@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.awt.Window;
|
||||
|
||||
/**
|
||||
* AppEvents are sent to listeners and handlers installed on the {@link Application}.
|
||||
*
|
||||
* @since Java for Mac OS X 10.6 Update 3
|
||||
* @since Java for Mac OS X 10.5 Update 8
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public abstract class AppEvent extends EventObject {
|
||||
AppEvent() {
|
||||
super(Application.getApplication());
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains a list of files.
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public abstract static class FilesEvent extends AppEvent {
|
||||
final List<File> files;
|
||||
|
||||
FilesEvent(final List<File> files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of files
|
||||
*/
|
||||
public List<File> getFiles() {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event sent when the app is asked to open a list of files.
|
||||
*
|
||||
* @see OpenFilesHandler#openFiles(OpenFilesEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class OpenFilesEvent extends FilesEvent {
|
||||
final String searchTerm;
|
||||
|
||||
OpenFilesEvent(final List<File> files, final String searchTerm) {
|
||||
super(files);
|
||||
this.searchTerm = searchTerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the files were opened using the Spotlight search menu or a Finder search window, this method obtains the search term used to find the files.
|
||||
* This is useful for highlighting the search term in the documents when they are opened.
|
||||
* @return the search term used to find the files
|
||||
*/
|
||||
public String getSearchTerm() {
|
||||
return searchTerm;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event sent when the app is asked to print a list of files.
|
||||
*
|
||||
* @see PrintFilesHandler#printFiles(PrintFilesEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class PrintFilesEvent extends FilesEvent {
|
||||
PrintFilesEvent(final List<File> files) {
|
||||
super(files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event sent when the app is asked to open a URI.
|
||||
*
|
||||
* @see OpenURIHandler#openURI(OpenURIEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class OpenURIEvent extends AppEvent {
|
||||
final URI uri;
|
||||
|
||||
OpenURIEvent(final URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the URI the app was asked to open
|
||||
*/
|
||||
public URI getURI() {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event sent when the application is asked to open it's about window.
|
||||
*
|
||||
* @see AboutHandler#handleAbout()
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class AboutEvent extends AppEvent { AboutEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the application is asked to open it's preferences window.
|
||||
*
|
||||
* @see PreferencesHandler#handlePreferences()
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class PreferencesEvent extends AppEvent { PreferencesEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the application is asked to quit.
|
||||
*
|
||||
* @see QuitHandler#handleQuitRequestWith(QuitEvent, QuitResponse)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class QuitEvent extends AppEvent { QuitEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the application is asked to re-open itself.
|
||||
*
|
||||
* @see AppReOpenedListener#appReOpened(AppReOpenedEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class AppReOpenedEvent extends AppEvent { AppReOpenedEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the application has become the foreground app, and when it has resigned being the foreground app.
|
||||
*
|
||||
* @see AppForegroundListener#appRaisedToForeground(AppForegroundEvent)
|
||||
* @see AppForegroundListener#appMovedToBackground(AppForegroundEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class AppForegroundEvent extends AppEvent { AppForegroundEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the application has been hidden or shown.
|
||||
*
|
||||
* @see AppHiddenListener#appHidden(AppHiddenEvent)
|
||||
* @see AppHiddenListener#appUnhidden(AppHiddenEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class AppHiddenEvent extends AppEvent { AppHiddenEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the user session has been changed via Fast User Switching.
|
||||
*
|
||||
* @see UserSessionListener#userSessionActivated(UserSessionEvent)
|
||||
* @see UserSessionListener#userSessionDeactivated(UserSessionEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class UserSessionEvent extends AppEvent { UserSessionEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the displays attached to the system enter and exit power save sleep.
|
||||
*
|
||||
* @see ScreenSleepListener#screenAboutToSleep(ScreenSleepEvent)
|
||||
* @see ScreenSleepListener#screenAwoke(ScreenSleepEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class ScreenSleepEvent extends AppEvent { ScreenSleepEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when the system enters and exits power save sleep.
|
||||
*
|
||||
* @see SystemSleepListener#systemAboutToSleep(SystemSleepEvent)
|
||||
* @see SystemSleepListener#systemAwoke(SystemSleepEvent)
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class SystemSleepEvent extends AppEvent { SystemSleepEvent() { } }
|
||||
|
||||
/**
|
||||
* Event sent when a window is entering/exiting or has entered/exited full screen state.
|
||||
*
|
||||
* @see FullScreenUtilities
|
||||
*
|
||||
* @since Java for Mac OS X 10.7 Update 1
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public static class FullScreenEvent extends AppEvent {
|
||||
final Window window;
|
||||
|
||||
FullScreenEvent(final Window window) {
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return window transitioning between full screen states
|
||||
*/
|
||||
public Window getWindow() {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,10 +26,10 @@
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.desktop.*;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.JMenuBar;
|
||||
@ -104,38 +104,38 @@ public class Application {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds sub-types of {@link AppEventListener} to listen for notifications from the native Mac OS X system.
|
||||
* Adds sub-types of {@link SystemEventListener} to listen for notifications from the native Mac OS X system.
|
||||
*
|
||||
* @see AppForegroundListener
|
||||
* @see AppHiddenListener
|
||||
* @see AppReOpenedListener
|
||||
* @see ScreenSleepListener
|
||||
* @see SystemSleepListener
|
||||
* @see UserSessionListener
|
||||
* @see AppScreenSleepListener
|
||||
* @see AppSystemSleepListener
|
||||
* @see AppUserSessionListener
|
||||
*
|
||||
* @param listener
|
||||
* @since Java for Mac OS X 10.6 Update 3
|
||||
* @since Java for Mac OS X 10.5 Update 8
|
||||
*/
|
||||
public void addAppEventListener(final AppEventListener listener) {
|
||||
public void addAppEventListener(final SystemEventListener listener) {
|
||||
eventHandler.addListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes sub-types of {@link AppEventListener} from listening for notifications from the native Mac OS X system.
|
||||
* Removes sub-types of {@link SystemEventListener} from listening for notifications from the native Mac OS X system.
|
||||
*
|
||||
* @see AppForegroundListener
|
||||
* @see AppHiddenListener
|
||||
* @see AppReOpenedListener
|
||||
* @see ScreenSleepListener
|
||||
* @see SystemSleepListener
|
||||
* @see UserSessionListener
|
||||
* @see AppScreenSleepListener
|
||||
* @see AppSystemSleepListener
|
||||
* @see AppUserSessionListener
|
||||
*
|
||||
* @param listener
|
||||
* @since Java for Mac OS X 10.6 Update 3
|
||||
* @since Java for Mac OS X 10.5 Update 8
|
||||
*/
|
||||
public void removeAppEventListener(final AppEventListener listener) {
|
||||
public void removeAppEventListener(final SystemEventListener listener) {
|
||||
eventHandler.removeListener(listener);
|
||||
}
|
||||
|
||||
@ -367,6 +367,17 @@ public class Application {
|
||||
iconHandler.setDockIconBadge(badge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a progress bar to this application's Dock icon.
|
||||
* Acceptable values are from 0 to 100, any other disables progress indication.
|
||||
*
|
||||
* @param value progress value
|
||||
* @since 1.9
|
||||
*/
|
||||
public void setDockIconProgress(final int value) {
|
||||
iconHandler.setDockIconProgress(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default menu bar to use when there are no active frames.
|
||||
* Only used when the system property "apple.laf.useScreenMenuBar" is "true", and
|
||||
@ -397,168 +408,4 @@ public class Application {
|
||||
((CPlatformWindow)platformWindow).toggleFullScreen();
|
||||
}
|
||||
|
||||
|
||||
// -- DEPRECATED API --
|
||||
|
||||
/**
|
||||
* Adds the specified ApplicationListener as a receiver of callbacks from this class.
|
||||
* This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
|
||||
*
|
||||
* @param listener an implementation of ApplicationListener that handles ApplicationEvents
|
||||
*
|
||||
* @deprecated register individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
|
||||
* @since 1.4
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public void addApplicationListener(final ApplicationListener listener) {
|
||||
eventHandler.legacyHandler.addLegacyAppListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified ApplicationListener from being a receiver of callbacks from this class.
|
||||
* This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
|
||||
*
|
||||
* @param listener an implementation of ApplicationListener that had previously been registered to handle ApplicationEvents
|
||||
*
|
||||
* @deprecated unregister individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
|
||||
* @since 1.4
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public void removeApplicationListener(final ApplicationListener listener) {
|
||||
eventHandler.legacyHandler.removeLegacyAppListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the Preferences item in the application menu. The ApplicationListener receives a callback for
|
||||
* selection of the Preferences item in the application menu only if this is set to {@code true}.
|
||||
*
|
||||
* If a Preferences item isn't present, this method adds and enables it.
|
||||
*
|
||||
* @param enable specifies whether the Preferences item in the application menu should be enabled ({@code true}) or not ({@code false})
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void setEnabledPreferencesMenu(final boolean enable) {
|
||||
menuBarHandler.setPreferencesMenuItemVisible(true);
|
||||
menuBarHandler.setPreferencesMenuItemEnabled(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the About item in the application menu. The ApplicationListener receives a callback for
|
||||
* selection of the About item in the application menu only if this is set to {@code true}. Because AWT supplies
|
||||
* a standard About window when an application may not, by default this is set to {@code true}.
|
||||
*
|
||||
* If the About item isn't present, this method adds and enables it.
|
||||
*
|
||||
* @param enable specifies whether the About item in the application menu should be enabled ({@code true}) or not ({@code false})
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void setEnabledAboutMenu(final boolean enable) {
|
||||
menuBarHandler.setAboutMenuItemEnabled(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Preferences item of the application menu is enabled.
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getEnabledPreferencesMenu() {
|
||||
return menuBarHandler.isPreferencesMenuItemEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the About item of the application menu is enabled.
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getEnabledAboutMenu() {
|
||||
return menuBarHandler.isAboutMenuItemEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the About item of the application menu is present.
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isAboutMenuItemPresent() {
|
||||
return menuBarHandler.isAboutMenuItemVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the About item to the application menu if the item is not already present.
|
||||
*
|
||||
* @deprecated use {@link #setAboutHandler(AboutHandler)} with a non-null {@link AboutHandler} parameter
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void addAboutMenuItem() {
|
||||
menuBarHandler.setAboutMenuItemVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the About item from the application menu if the item is present.
|
||||
*
|
||||
* @deprecated use {@link #setAboutHandler(AboutHandler)} with a null parameter
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void removeAboutMenuItem() {
|
||||
menuBarHandler.setAboutMenuItemVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the About Preferences of the application menu is present. By default there is no Preferences menu item.
|
||||
*
|
||||
* @deprecated no replacement
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isPreferencesMenuItemPresent() {
|
||||
return menuBarHandler.isPreferencesMenuItemVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Preferences item to the application menu if the item is not already present.
|
||||
*
|
||||
* @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a non-null {@link PreferencesHandler} parameter
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void addPreferencesMenuItem() {
|
||||
menuBarHandler.setPreferencesMenuItemVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Preferences item from the application menu if that item is present.
|
||||
*
|
||||
* @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a null parameter
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public void removePreferencesMenuItem() {
|
||||
menuBarHandler.setPreferencesMenuItemVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@code java.awt.MouseInfo.getPointerInfo().getLocation()}.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
public static Point getMouseLocationOnScreen() {
|
||||
return java.awt.MouseInfo.getPointerInfo().getLocation();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -46,7 +46,7 @@ package com.apple.eawt;
|
||||
* @see ScreenSleepListener
|
||||
* @see SystemSleepListener
|
||||
*
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}.
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}.
|
||||
* @since 1.4
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -30,7 +30,7 @@ import java.util.EventObject;
|
||||
/**
|
||||
* The class of events sent to the deprecated ApplicationListener callbacks.
|
||||
*
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}
|
||||
* @since 1.4
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -47,7 +47,7 @@ import java.util.EventListener;
|
||||
* @see SystemSleepListener
|
||||
*
|
||||
* @since 1.4
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}
|
||||
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@ -134,7 +134,7 @@ public interface ApplicationListener extends EventListener {
|
||||
* {@code event}. To reject the quit, set {@code isHandled(false)}.
|
||||
*
|
||||
* @param event a Quit Application event
|
||||
* @deprecated use {@link QuitHandler} and {@link QuitResponse}
|
||||
* @deprecated use {@link QuitHandler} and {@link MacQuitResponse}
|
||||
*/
|
||||
@Deprecated
|
||||
public void handleQuit(ApplicationEvent event);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import com.apple.eawt.AppEvent.FullScreenEvent;
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
|
||||
/**
|
||||
* Abstract adapter class for receiving fullscreen events. This class is provided
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.RootPaneContainer;
|
||||
|
||||
import com.apple.eawt.AppEvent.FullScreenEvent;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -25,9 +25,9 @@
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
import java.util.EventListener;
|
||||
|
||||
import com.apple.eawt.AppEvent.FullScreenEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -25,9 +25,11 @@
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.awt.desktop.QuitResponse;
|
||||
|
||||
/**
|
||||
* Used to respond to a request to quit the application.
|
||||
* The QuitResponse may be used after the {@link QuitHandler#handleQuitRequestWith(AppEvent.QuitEvent, QuitResponse)} method has returned, and may be used from any thread.
|
||||
* The QuitResponse may be used after the {@link QuitHandler#handleQuitRequestWith(AppEvent.QuitEvent, MacQuitResponse)} method has returned, and may be used from any thread.
|
||||
*
|
||||
* @see Application#setQuitHandler(QuitHandler)
|
||||
* @see QuitHandler
|
||||
@ -36,16 +38,17 @@ package com.apple.eawt;
|
||||
* @since Java for Mac OS X 10.6 Update 3
|
||||
* @since Java for Mac OS X 10.5 Update 8
|
||||
*/
|
||||
public class QuitResponse {
|
||||
public class MacQuitResponse implements QuitResponse {
|
||||
final _AppEventHandler appEventHandler;
|
||||
|
||||
QuitResponse(final _AppEventHandler appEventHandler) {
|
||||
MacQuitResponse(final _AppEventHandler appEventHandler) {
|
||||
this.appEventHandler = appEventHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the external quit requester that the quit will proceed, and performs the default {@link QuitStrategy}.
|
||||
*/
|
||||
@Override
|
||||
public void performQuit() {
|
||||
if (appEventHandler.currentQuitResponse != this) return;
|
||||
appEventHandler.performQuit();
|
||||
@ -55,6 +58,7 @@ public class QuitResponse {
|
||||
* Notifies the external quit requester that the user has explicitly canceled the pending quit, and leaves the application running.
|
||||
* <b>Note: this will cancel a pending log-out, restart, or shutdown.</b>
|
||||
*/
|
||||
@Override
|
||||
public void cancelQuit() {
|
||||
if (appEventHandler.currentQuitResponse != this) return;
|
||||
appEventHandler.cancelQuit();
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 com.apple.eawt;
|
||||
|
||||
import com.apple.eawt.AppEvent.OpenURIEvent;
|
||||
|
||||
/**
|
||||
* An implementor is notified when the application is asked to open a URI.
|
||||
* The application only sends {@link com.apple.eawt.EAWTEvent.OpenURIEvent}s when it has been launched as a bundled Mac application, and it's Info.plist claims URL schemes in it's {@code CFBundleURLTypes} entry.
|
||||
* See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a {@code CFBundleURLTypes} key to your app's Info.plist.
|
||||
*
|
||||
* @see Application#setOpenURIHandler(OpenURIHandler)
|
||||
*
|
||||
* @since Java for Mac OS X 10.6 Update 3
|
||||
* @since Java for Mac OS X 10.5 Update 8
|
||||
*/
|
||||
public interface OpenURIHandler {
|
||||
/**
|
||||
* Called when the application is asked to open a URI
|
||||
* @param e the request to open a URI
|
||||
*/
|
||||
public void openURI(final OpenURIEvent e);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -35,6 +35,7 @@ import sun.lwawt.macosx.CImage.Creator;
|
||||
class _AppDockIconHandler {
|
||||
private static native void nativeSetDockMenu(final long cmenu);
|
||||
private static native void nativeSetDockIconImage(final long image);
|
||||
private static native void nativeSetDockIconProgress(final int value);
|
||||
private static native long nativeGetDockIconImage();
|
||||
private static native void nativeSetDockIconBadge(final String badge);
|
||||
|
||||
@ -93,6 +94,10 @@ class _AppDockIconHandler {
|
||||
nativeSetDockIconBadge(badge);
|
||||
}
|
||||
|
||||
void setDockIconProgress(int value) {
|
||||
nativeSetDockIconProgress(value);
|
||||
}
|
||||
|
||||
static Creator getCImageCreator() {
|
||||
try {
|
||||
final Method getCreatorMethod = CImage.class.getDeclaredMethod("getCreator", new Class<?>[] {});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -25,17 +25,47 @@
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Frame;
|
||||
import java.awt.desktop.AboutEvent;
|
||||
import java.awt.desktop.AboutHandler;
|
||||
import java.awt.desktop.AppForegroundEvent;
|
||||
import java.awt.desktop.AppForegroundListener;
|
||||
import java.awt.desktop.AppHiddenEvent;
|
||||
import java.awt.desktop.AppHiddenListener;
|
||||
import java.awt.desktop.AppReopenedEvent;
|
||||
import java.awt.desktop.AppReopenedListener;
|
||||
import java.awt.desktop.OpenFilesEvent;
|
||||
import java.awt.desktop.OpenFilesHandler;
|
||||
import java.awt.desktop.OpenURIEvent;
|
||||
import java.awt.desktop.OpenURIHandler;
|
||||
import java.awt.desktop.PreferencesEvent;
|
||||
import java.awt.desktop.PreferencesHandler;
|
||||
import java.awt.desktop.PrintFilesEvent;
|
||||
import java.awt.desktop.PrintFilesHandler;
|
||||
import java.awt.desktop.QuitEvent;
|
||||
import java.awt.desktop.QuitHandler;
|
||||
import java.awt.desktop.QuitStrategy;
|
||||
import java.awt.desktop.ScreenSleepEvent;
|
||||
import java.awt.desktop.ScreenSleepListener;
|
||||
import java.awt.desktop.SystemEventListener;
|
||||
import java.awt.desktop.SystemSleepEvent;
|
||||
import java.awt.desktop.SystemSleepListener;
|
||||
import java.awt.desktop.UserSessionEvent;
|
||||
import java.awt.desktop.UserSessionEvent.Reason;
|
||||
import java.awt.desktop.UserSessionListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import com.apple.eawt.AppEvent.*;
|
||||
|
||||
class _AppEventHandler {
|
||||
private static final int NOTIFY_ABOUT = 1;
|
||||
private static final int NOTIFY_PREFS = 2;
|
||||
@ -84,9 +114,7 @@ class _AppEventHandler {
|
||||
final _ScreenSleepDispatcher screenSleepDispatcher = new _ScreenSleepDispatcher();
|
||||
final _SystemSleepDispatcher systemSleepDispatcher = new _SystemSleepDispatcher();
|
||||
|
||||
final _AppEventLegacyHandler legacyHandler = new _AppEventLegacyHandler(this);
|
||||
|
||||
QuitStrategy defaultQuitAction = QuitStrategy.SYSTEM_EXIT_0;
|
||||
QuitStrategy defaultQuitAction = QuitStrategy.NORMAL_EXIT;
|
||||
|
||||
_AppEventHandler() {
|
||||
final String strategyProp = System.getProperty("apple.eawt.quitStrategy");
|
||||
@ -94,15 +122,16 @@ class _AppEventHandler {
|
||||
|
||||
if ("CLOSE_ALL_WINDOWS".equals(strategyProp)) {
|
||||
setDefaultQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
|
||||
} else if ("SYSTEM_EXIT_O".equals(strategyProp)) {
|
||||
setDefaultQuitStrategy(QuitStrategy.SYSTEM_EXIT_0);
|
||||
} else if ("SYSTEM_EXIT_O".equals(strategyProp)
|
||||
|| "NORMAL_EXIT".equals(strategyProp)) {
|
||||
setDefaultQuitStrategy(QuitStrategy.NORMAL_EXIT);
|
||||
} else {
|
||||
System.err.println("unrecognized apple.eawt.quitStrategy: " + strategyProp);
|
||||
}
|
||||
}
|
||||
|
||||
void addListener(final AppEventListener listener) {
|
||||
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.addListener((AppReOpenedListener)listener);
|
||||
void addListener(final SystemEventListener listener) {
|
||||
if (listener instanceof AppReopenedListener) reOpenAppDispatcher.addListener((AppReopenedListener)listener);
|
||||
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.addListener((AppForegroundListener)listener);
|
||||
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.addListener((AppHiddenListener)listener);
|
||||
if (listener instanceof UserSessionListener) userSessionDispatcher.addListener((UserSessionListener)listener);
|
||||
@ -110,8 +139,8 @@ class _AppEventHandler {
|
||||
if (listener instanceof SystemSleepListener) systemSleepDispatcher.addListener((SystemSleepListener)listener);
|
||||
}
|
||||
|
||||
void removeListener(final AppEventListener listener) {
|
||||
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.removeListener((AppReOpenedListener)listener);
|
||||
void removeListener(final SystemEventListener listener) {
|
||||
if (listener instanceof AppReopenedListener) reOpenAppDispatcher.removeListener((AppReopenedListener)listener);
|
||||
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.removeListener((AppForegroundListener)listener);
|
||||
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.removeListener((AppHiddenListener)listener);
|
||||
if (listener instanceof UserSessionListener) userSessionDispatcher.removeListener((UserSessionListener)listener);
|
||||
@ -127,10 +156,10 @@ class _AppEventHandler {
|
||||
this.defaultQuitAction = defaultQuitAction;
|
||||
}
|
||||
|
||||
QuitResponse currentQuitResponse;
|
||||
synchronized QuitResponse obtainQuitResponse() {
|
||||
MacQuitResponse currentQuitResponse;
|
||||
synchronized MacQuitResponse obtainQuitResponse() {
|
||||
if (currentQuitResponse != null) return currentQuitResponse;
|
||||
return currentQuitResponse = new QuitResponse(this);
|
||||
return currentQuitResponse = new MacQuitResponse(this);
|
||||
}
|
||||
|
||||
synchronized void cancelQuit() {
|
||||
@ -142,7 +171,7 @@ class _AppEventHandler {
|
||||
currentQuitResponse = null;
|
||||
|
||||
try {
|
||||
if (defaultQuitAction == QuitStrategy.SYSTEM_EXIT_0) System.exit(0);
|
||||
if (defaultQuitAction == QuitStrategy.NORMAL_EXIT) System.exit(0);
|
||||
|
||||
if (defaultQuitAction != QuitStrategy.CLOSE_ALL_WINDOWS) {
|
||||
throw new RuntimeException("Unknown quit action");
|
||||
@ -270,10 +299,10 @@ class _AppEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
|
||||
void performOnListener(AppReOpenedListener listener, final _NativeEvent event) {
|
||||
final AppReOpenedEvent e = new AppReOpenedEvent();
|
||||
listener.appReOpened(e);
|
||||
class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReopenedListener> {
|
||||
void performOnListener(AppReopenedListener listener, final _NativeEvent event) {
|
||||
final AppReopenedEvent e = new AppReopenedEvent();
|
||||
listener.appReopened(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +331,9 @@ class _AppEventHandler {
|
||||
}
|
||||
|
||||
class _UserSessionDispatcher extends _BooleanAppEventMultiplexor<UserSessionListener, UserSessionEvent> {
|
||||
UserSessionEvent createEvent(final boolean isTrue) { return new UserSessionEvent(); }
|
||||
UserSessionEvent createEvent(final boolean isTrue) {
|
||||
return new UserSessionEvent(Reason.UNSPECIFIED);
|
||||
}
|
||||
|
||||
void performFalseEventOn(final UserSessionListener listener, final UserSessionEvent e) {
|
||||
listener.userSessionDeactivated(e);
|
||||
@ -391,7 +422,7 @@ class _AppEventHandler {
|
||||
}
|
||||
|
||||
void performUsing(final QuitHandler handler, final _NativeEvent event) {
|
||||
final QuitResponse response = obtainQuitResponse(); // obtains the "current" quit response
|
||||
final MacQuitResponse response = obtainQuitResponse(); // obtains the "current" quit response
|
||||
handler.handleQuitRequestWith(new QuitEvent(), response);
|
||||
}
|
||||
}
|
||||
@ -524,9 +555,6 @@ class _AppEventHandler {
|
||||
|
||||
setHandlerContext(AppContext.getAppContext());
|
||||
|
||||
// if a new handler is installed, block addition of legacy ApplicationListeners
|
||||
if (handler == legacyHandler) return;
|
||||
legacyHandler.blockLegacyAPI();
|
||||
}
|
||||
|
||||
void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
|
||||
@ -574,10 +602,6 @@ class _AppEventHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if a new handler is installed, block addition of legacy ApplicationListeners
|
||||
if (handler == legacyHandler) return;
|
||||
legacyHandler.blockLegacyAPI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import com.apple.eawt.AppEvent.*;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
class _AppEventLegacyHandler implements AboutHandler, PreferencesHandler, _OpenAppHandler, AppReOpenedListener, OpenFilesHandler, PrintFilesHandler, QuitHandler {
|
||||
final _AppEventHandler parent;
|
||||
final Vector<ApplicationListener> legacyAppListeners = new Vector<ApplicationListener>();
|
||||
boolean blockLegacyAPI;
|
||||
boolean initializedParentDispatchers;
|
||||
|
||||
_AppEventLegacyHandler(final _AppEventHandler parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
void blockLegacyAPI() {
|
||||
blockLegacyAPI = true;
|
||||
}
|
||||
|
||||
void checkIfLegacyAPIBlocked() {
|
||||
if (!blockLegacyAPI) return;
|
||||
throw new IllegalStateException("Cannot add com.apple.eawt.ApplicationListener after installing an app event handler");
|
||||
}
|
||||
|
||||
void addLegacyAppListener(final ApplicationListener listener) {
|
||||
checkIfLegacyAPIBlocked();
|
||||
|
||||
if (!initializedParentDispatchers) {
|
||||
final _AppMenuBarHandler menuBarHandler = Application.getApplication().menuBarHandler;
|
||||
final boolean prefsMenuAlreadyExplicitlySet = menuBarHandler.prefsMenuItemExplicitlySet;
|
||||
|
||||
parent.aboutDispatcher.setHandler(this);
|
||||
parent.preferencesDispatcher.setHandler(this);
|
||||
if (!prefsMenuAlreadyExplicitlySet) {
|
||||
menuBarHandler.setPreferencesMenuItemVisible(false); // default behavior is not to have a preferences item
|
||||
}
|
||||
parent.openAppDispatcher.setHandler(this);
|
||||
parent.reOpenAppDispatcher.addListener(this);
|
||||
parent.openFilesDispatcher.setHandler(this);
|
||||
parent.printFilesDispatcher.setHandler(this);
|
||||
parent.quitDispatcher.setHandler(this);
|
||||
|
||||
initializedParentDispatchers = true;
|
||||
}
|
||||
|
||||
synchronized (legacyAppListeners) {
|
||||
legacyAppListeners.addElement(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLegacyAppListener(final ApplicationListener listener) {
|
||||
checkIfLegacyAPIBlocked();
|
||||
|
||||
synchronized (legacyAppListeners) {
|
||||
legacyAppListeners.removeElement(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAbout(final AboutEvent e) {
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handleAbout(ae);
|
||||
}
|
||||
});
|
||||
|
||||
if (ae.isHandled()) return;
|
||||
parent.openCocoaAboutWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePreferences(final PreferencesEvent e) {
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handlePreferences(ae);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOpenApp() {
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handleOpenApplication(ae);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appReOpened(final AppReOpenedEvent e) {
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handleReOpenApplication(ae);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openFiles(final OpenFilesEvent e) {
|
||||
final List<File> files = e.getFiles();
|
||||
for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handleOpenFile(ae);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printFiles(PrintFilesEvent e) {
|
||||
final List<File> files = e.getFiles();
|
||||
for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handlePrintFile(ae);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleQuitRequestWith(final QuitEvent e, final QuitResponse response) {
|
||||
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
|
||||
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
|
||||
public void dispatchEvent(final ApplicationListener listener) {
|
||||
listener.handleQuit(ae);
|
||||
}
|
||||
});
|
||||
|
||||
if (ae.isHandled()) {
|
||||
parent.performQuit();
|
||||
} else {
|
||||
parent.cancelQuit();
|
||||
}
|
||||
}
|
||||
|
||||
interface EventDispatcher {
|
||||
void dispatchEvent(final ApplicationListener listener);
|
||||
}
|
||||
|
||||
// helper that cycles through the loop and aborts if the event is handled, or there are no listeners
|
||||
void sendEventToEachListenerUntilHandled(final ApplicationEvent event, final EventDispatcher dispatcher) {
|
||||
synchronized (legacyAppListeners) {
|
||||
if (legacyAppListeners.size() == 0) return;
|
||||
|
||||
final Enumeration<ApplicationListener> e = legacyAppListeners.elements();
|
||||
while (e.hasMoreElements() && !event.isHandled()) {
|
||||
dispatcher.dispatchEvent(e.nextElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
package com.apple.eawt;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.peer.MenuComponentPeer;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.MenuBarUI;
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 com.apple.eawt.event;
|
||||
|
||||
import com.apple.eawt.Application;
|
||||
import java.awt.Window;
|
||||
import java.util.EventObject;
|
||||
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public class FullScreenEvent extends EventObject {
|
||||
|
||||
final Window window;
|
||||
|
||||
/**
|
||||
* @param window window
|
||||
*/
|
||||
public FullScreenEvent(final Window window) {
|
||||
super(Application.getApplication());
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return window transitioning between full screen states
|
||||
*/
|
||||
public Window getWindow() {
|
||||
return window;
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ import java.awt.GraphicsDevice;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
import java.util.Objects;
|
||||
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.opengl.CGLGraphicsConfig;
|
||||
|
||||
public final class CGraphicsDevice extends GraphicsDevice
|
||||
@ -140,7 +140,7 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
public void displayChanged() {
|
||||
xResolution = nativeGetXResolution(displayID);
|
||||
yResolution = nativeGetYResolution(displayID);
|
||||
scale = (int) nativeGetScaleFactor(displayID);
|
||||
initScaleFactor();
|
||||
//TODO configs/fullscreenWindow/modes?
|
||||
}
|
||||
|
||||
@ -249,6 +249,17 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
return nativeGetDisplayModes(displayID);
|
||||
}
|
||||
|
||||
private void initScaleFactor() {
|
||||
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
|
||||
double debugScale = SunGraphicsEnvironment.getDebugScale();
|
||||
scale = (int) (debugScale >= 1
|
||||
? Math.round(debugScale)
|
||||
: nativeGetScaleFactor(displayID));
|
||||
} else {
|
||||
scale = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static native double nativeGetScaleFactor(int displayID);
|
||||
|
||||
private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);
|
||||
|
@ -142,94 +142,6 @@ public final class CFontManager extends SunFontManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font2D createFont2D(File fontFile, int fontFormat, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException {
|
||||
|
||||
String fontFilePath = fontFile.getPath();
|
||||
Font2D font2D = null;
|
||||
final File fFile = fontFile;
|
||||
final CreatedFontTracker _tracker = tracker;
|
||||
try {
|
||||
switch (fontFormat) {
|
||||
case Font.TRUETYPE_FONT:
|
||||
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
|
||||
break;
|
||||
case Font.TYPE1_FONT:
|
||||
font2D = new Type1Font(fontFilePath, null, isCopy);
|
||||
break;
|
||||
default:
|
||||
throw new FontFormatException("Unrecognised Font Format");
|
||||
}
|
||||
} catch (FontFormatException e) {
|
||||
if (isCopy) {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
if (_tracker != null) {
|
||||
_tracker.subBytes((int)fFile.length());
|
||||
}
|
||||
fFile.delete();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
throw(e);
|
||||
}
|
||||
if (isCopy) {
|
||||
FileFont.setFileToRemove(font2D, fontFile, tracker);
|
||||
synchronized (FontManager.class) {
|
||||
|
||||
if (tmpFontFiles == null) {
|
||||
tmpFontFiles = new Vector<File>();
|
||||
}
|
||||
tmpFontFiles.add(fontFile);
|
||||
|
||||
if (fileCloser == null) {
|
||||
final Runnable fileCloserRunnable = new Runnable() {
|
||||
public void run() {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
|
||||
for (int i=0;i<CHANNELPOOLSIZE;i++) {
|
||||
if (fontFileCache[i] != null) {
|
||||
try {
|
||||
fontFileCache[i].close();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
if (tmpFontFiles != null) {
|
||||
File[] files = new File[tmpFontFiles.size()];
|
||||
files = tmpFontFiles.toArray(files);
|
||||
for (int f=0; f<files.length;f++) {
|
||||
try {
|
||||
files[f].delete();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
/* The thread must be a member of a thread group
|
||||
* which will not get GCed before VM exit.
|
||||
* Make its parent the top-level thread group.
|
||||
*/
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
fileCloser = new ManagedLocalsThread(rootTG, fileCloserRunnable);
|
||||
fileCloser.setContextClassLoader(null);
|
||||
Runtime.getRuntime().addShutdownHook(fileCloser);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return font2D;
|
||||
}
|
||||
|
||||
protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
|
||||
loadNativeDirFonts(dirName);
|
||||
super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);
|
||||
|
@ -478,13 +478,9 @@ public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements Raster
|
||||
// <rdar://problem/4488745> For the Sun2D renderer we should rely on the implementation of the super class.
|
||||
// BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class.
|
||||
|
||||
int offsetX = 0;
|
||||
int offsetY = 0;
|
||||
if (sg2d.transformState == SunGraphics2D.TRANSFORM_ANY_TRANSLATE ||
|
||||
sg2d.transformState == SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
offsetX = (int) sg2d.transform.getTranslateX();
|
||||
offsetY = (int) sg2d.transform.getTranslateY();
|
||||
} else if (sg2d.transformState != SunGraphics2D.TRANSFORM_ISIDENT) { return false; }
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// reset the clip (this is how it works on windows)
|
||||
// we actually can handle a case with any clips but windows ignores the light clip
|
||||
@ -498,18 +494,23 @@ public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements Raster
|
||||
return true;
|
||||
}
|
||||
|
||||
// the rectangle returned from clipCopyArea() is in the coordinate space of the surface (image)
|
||||
// we need to substract the offsetX and offsetY to move it to the coordinate space of the graphics2d.
|
||||
// sg2d.drawImage expects the destination rect to be in the coord space of the graphics2d. <rdar://3746194>
|
||||
// (vm)
|
||||
x = clippedCopyAreaRect.x - offsetX;
|
||||
y = clippedCopyAreaRect.y - offsetY;
|
||||
// the rectangle returned from clipCopyArea() is in the coordinate space
|
||||
// of the surface (image)
|
||||
x = clippedCopyAreaRect.x;
|
||||
y = clippedCopyAreaRect.y;
|
||||
w = clippedCopyAreaRect.width;
|
||||
h = clippedCopyAreaRect.height;
|
||||
|
||||
// copy (dst coordinates are in the coord space of the graphics2d, and src coordinates are
|
||||
// in the coordinate space of the image)
|
||||
sg2d.drawImage(this.bim, x + dx, y + dy, x + dx + w, y + dy + h, x + offsetX, y + offsetY, x + w + offsetX, y + h + offsetY, null);
|
||||
// copy (dst coordinates are in the coord space of the graphics2d, and
|
||||
// src coordinates are in the coordinate space of the image)
|
||||
// sg2d.drawImage expects the destination rect to be in the coord space
|
||||
// of the graphics2d. <rdar://3746194> (vm)
|
||||
// we need to substract the transX and transY to move it
|
||||
// to the coordinate space of the graphics2d.
|
||||
int dstX = x + dx - sg2d.transX;
|
||||
int dstY = y + dy - sg2d.transY;
|
||||
sg2d.drawImage(this.bim, dstX, dstY, dstX + w, dstY + h,
|
||||
x, y, x + w, y + h, null);
|
||||
|
||||
// restore the clip
|
||||
sg2d.setClip(clip);
|
||||
|
@ -1094,19 +1094,13 @@ public abstract class OSXSurfaceData extends BufImgSurfaceData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clips the copy area to the heavywieght bounds and returns the cliped rectangle. The tricky part here is the
|
||||
* passed arguments x, y are in the coordinate space of the sg2d/lightweight comp. In order to do the clipping we
|
||||
* translate them to the coordinate space of the surface, and the returned clipped rectangle is in the coordinate
|
||||
* space of the surface.
|
||||
* Clips the copy area to the heavyweight bounds and returns the clipped rectangle.
|
||||
* The returned clipped rectangle is in the coordinate space of the surface.
|
||||
*/
|
||||
protected Rectangle clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
|
||||
// we need to clip against the heavyweight bounds
|
||||
copyAreaBounds.setBounds(sg2d.devClip.getLoX(), sg2d.devClip.getLoY(), sg2d.devClip.getWidth(), sg2d.devClip.getHeight());
|
||||
|
||||
// put src rect into surface coordinate space
|
||||
x += sg2d.transX;
|
||||
y += sg2d.transY;
|
||||
|
||||
// clip src rect
|
||||
srcCopyAreaRect.setBounds(x, y, w, h);
|
||||
intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);
|
||||
|
@ -175,31 +175,6 @@ public abstract class CGLSurfaceData extends OGLSurfaceData {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
|
||||
int dx, int dy) {
|
||||
final int state = sg2d.transformState;
|
||||
if (state > SunGraphics2D.TRANSFORM_TRANSLATESCALE
|
||||
|| sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
|
||||
return false;
|
||||
}
|
||||
if (state <= SunGraphics2D.TRANSFORM_ANY_TRANSLATE) {
|
||||
x += sg2d.transX;
|
||||
y += sg2d.transY;
|
||||
} else if (state == SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
final double[] coords = {x, y, x + w, y + h, x + dx, y + dy};
|
||||
sg2d.transform.transform(coords, 0, coords, 0, 3);
|
||||
x = (int) Math.ceil(coords[0] - 0.5);
|
||||
y = (int) Math.ceil(coords[1] - 0.5);
|
||||
w = ((int) Math.ceil(coords[2] - 0.5)) - x;
|
||||
h = ((int) Math.ceil(coords[3] - 0.5)) - y;
|
||||
dx = ((int) Math.ceil(coords[4] - 0.5)) - x;
|
||||
dy = ((int) Math.ceil(coords[5] - 0.5)) - y;
|
||||
}
|
||||
oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected native void clearWindow();
|
||||
|
||||
public static class CGLWindowSurfaceData extends CGLSurfaceData {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user