mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-18 22:35:12 +00:00
6397609: DOC: De-register API required for PropertyEditorManager and/or doc change
Reviewed-by: peterz, rupashka
This commit is contained in:
parent
fe4ebb456f
commit
d46ed5c358
84
jdk/src/share/classes/com/sun/beans/WeakCache.java
Normal file
84
jdk/src/share/classes/com/sun/beans/WeakCache.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package com.sun.beans;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* A hashtable-based cache with weak keys and weak values.
|
||||
* An entry in the map will be automatically removed
|
||||
* when its key is no longer in the ordinary use.
|
||||
* A value will be automatically removed as well
|
||||
* when it is no longer in the ordinary use.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @author Sergey A. Malenkov
|
||||
*/
|
||||
public final class WeakCache<K, V> {
|
||||
private final Map<K, Reference<V>> map = new WeakHashMap<K, Reference<V>>();
|
||||
|
||||
/**
|
||||
* Returns a value to which the specified {@code key} is mapped,
|
||||
* or {@code null} if this map contains no mapping for the {@code key}.
|
||||
*
|
||||
* @param key the key whose associated value is returned
|
||||
* @return a value to which the specified {@code key} is mapped
|
||||
*/
|
||||
public V get(K key) {
|
||||
Reference<V> reference = this.map.get(key);
|
||||
if (reference == null) {
|
||||
return null;
|
||||
}
|
||||
V value = reference.get();
|
||||
if (value == null) {
|
||||
this.map.remove(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified {@code value} with the specified {@code key}.
|
||||
* Removes the mapping for the specified {@code key} from this cache
|
||||
* if it is present and the specified {@code value} is {@code null}.
|
||||
* If the cache previously contained a mapping for the {@code key},
|
||||
* the old value is replaced by the specified {@code value}.
|
||||
*
|
||||
* @param key the key with which the specified value is associated
|
||||
* @param value the value to be associated with the specified key
|
||||
*/
|
||||
public void put(K key, V value) {
|
||||
if (value != null) {
|
||||
this.map.put(key, new WeakReference<V>(value));
|
||||
}
|
||||
else {
|
||||
this.map.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1996-2008 Sun Microsystems, Inc. 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,6 +25,7 @@
|
||||
|
||||
package java.beans;
|
||||
|
||||
import com.sun.beans.WeakCache;
|
||||
import sun.beans.editors.*;
|
||||
|
||||
/**
|
||||
@ -55,32 +56,30 @@ import sun.beans.editors.*;
|
||||
public class PropertyEditorManager {
|
||||
|
||||
/**
|
||||
* Register an editor class to be used to edit values of
|
||||
* a given target class.
|
||||
* Registers an editor class to edit values of the given target class.
|
||||
* If the editor class is {@code null},
|
||||
* then any existing definition will be removed.
|
||||
* Thus this method can be used to cancel the registration.
|
||||
* The registration is canceled automatically
|
||||
* if either the target or editor class is unloaded.
|
||||
* <p>
|
||||
* If there is a security manager, its {@code checkPropertiesAccess}
|
||||
* method is called. This could result in a {@linkplain SecurityException}.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkPropertiesAccess</code>
|
||||
* method is called. This could result in a SecurityException.
|
||||
* @param targetType the class object of the type to be edited
|
||||
* @param editorClass the class object of the editor class
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* its {@code checkPropertiesAccess} method
|
||||
* doesn't allow setting of system properties
|
||||
*
|
||||
* @param targetType the Class object of the type to be edited
|
||||
* @param editorClass the Class object of the editor class. If
|
||||
* this is null, then any existing definition will be removed.
|
||||
* @exception SecurityException if a security manager exists and its
|
||||
* <code>checkPropertiesAccess</code> method doesn't allow setting
|
||||
* of system properties.
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
|
||||
public static void registerEditor(Class<?> targetType, Class<?> editorClass) {
|
||||
public static synchronized void registerEditor(Class<?> targetType, Class<?> editorClass) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
initialize();
|
||||
if (editorClass == null) {
|
||||
registry.remove(targetType);
|
||||
} else {
|
||||
registry.put(targetType, editorClass);
|
||||
}
|
||||
registry.put(targetType, editorClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,10 +89,8 @@ public class PropertyEditorManager {
|
||||
* @return An editor object for the given target class.
|
||||
* The result is null if no suitable editor can be found.
|
||||
*/
|
||||
|
||||
public static synchronized PropertyEditor findEditor(Class<?> targetType) {
|
||||
initialize();
|
||||
Class editorClass = (Class)registry.get(targetType);
|
||||
Class editorClass = registry.get(targetType);
|
||||
if (editorClass != null) {
|
||||
try {
|
||||
Object o = editorClass.newInstance();
|
||||
@ -143,10 +140,7 @@ public class PropertyEditorManager {
|
||||
* e.g. Sun implementation initially sets to {"sun.beans.editors"}.
|
||||
*/
|
||||
public static synchronized String[] getEditorSearchPath() {
|
||||
// Return a copy of the searchPath.
|
||||
String result[] = new String[searchPath.length];
|
||||
System.arraycopy(searchPath, 0, result, 0, searchPath.length);
|
||||
return result;
|
||||
return searchPath.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,23 +156,22 @@ public class PropertyEditorManager {
|
||||
* of system properties.
|
||||
* @see SecurityManager#checkPropertiesAccess
|
||||
*/
|
||||
|
||||
public static synchronized void setEditorSearchPath(String path[]) {
|
||||
public static synchronized void setEditorSearchPath(String[] path) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPropertiesAccess();
|
||||
}
|
||||
if (path == null) {
|
||||
path = new String[0];
|
||||
}
|
||||
searchPath = path;
|
||||
searchPath = (path != null)
|
||||
? path.clone()
|
||||
: EMPTY;
|
||||
}
|
||||
|
||||
private static synchronized void initialize() {
|
||||
if (registry != null) {
|
||||
return;
|
||||
}
|
||||
registry = new java.util.Hashtable();
|
||||
private static String[] searchPath = { "sun.beans.editors" };
|
||||
private static final String[] EMPTY = {};
|
||||
private static final WeakCache<Class<?>, Class<?>> registry;
|
||||
|
||||
static {
|
||||
registry = new WeakCache<Class<?>, Class<?>>();
|
||||
registry.put(Byte.TYPE, ByteEditor.class);
|
||||
registry.put(Short.TYPE, ShortEditor.class);
|
||||
registry.put(Integer.TYPE, IntegerEditor.class);
|
||||
@ -187,7 +180,4 @@ public class PropertyEditorManager {
|
||||
registry.put(Float.TYPE, FloatEditor.class);
|
||||
registry.put(Double.TYPE, DoubleEditor.class);
|
||||
}
|
||||
|
||||
private static String[] searchPath = { "sun.beans.editors" };
|
||||
private static java.util.Hashtable registry;
|
||||
}
|
||||
|
||||
143
jdk/test/java/beans/PropertyEditor/MemoryClassLoader.java
Normal file
143
jdk/test/java/beans/PropertyEditor/MemoryClassLoader.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject.Kind;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
public final class MemoryClassLoader extends ClassLoader {
|
||||
private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
private final MemoryFileManager manager = new MemoryFileManager(this.compiler);
|
||||
|
||||
public Class<?> compile(String name, String content) {
|
||||
compile(new Source(name, content));
|
||||
try {
|
||||
return findClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException exception) {
|
||||
throw new Error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void compile(Source... sources) {
|
||||
List<Source> list = new ArrayList<Source>();
|
||||
if (sources != null) {
|
||||
for (Source source : sources) {
|
||||
if (source != null) {
|
||||
list.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (this.manager) {
|
||||
this.compiler.getTask(null, this.manager, null, null, null, list).call();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
synchronized (this.manager) {
|
||||
Output mc = this.manager.map.remove(name);
|
||||
if (mc != null) {
|
||||
byte[] array = mc.toByteArray();
|
||||
return defineClass(name, array, 0, array.length);
|
||||
}
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
private static final class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
|
||||
private final Map<String, Output> map = new HashMap<String, Output>();
|
||||
|
||||
MemoryFileManager(JavaCompiler compiler) {
|
||||
super(compiler.getStandardFileManager(null, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output getJavaFileForOutput(Location location, String name, Kind kind, FileObject source) {
|
||||
Output mc = this.map.get(name);
|
||||
if (mc == null) {
|
||||
mc = new Output(name);
|
||||
this.map.put(name, mc);
|
||||
}
|
||||
return mc;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MemoryFileObject extends SimpleJavaFileObject {
|
||||
MemoryFileObject(String name, Kind kind) {
|
||||
super(toURI(name, kind.extension), kind);
|
||||
}
|
||||
|
||||
private static URI toURI(String name, String extension) {
|
||||
try {
|
||||
return new URI("mfm:///" + name.replace('.', '/') + extension);
|
||||
}
|
||||
catch (URISyntaxException exception) {
|
||||
throw new Error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Output extends MemoryFileObject {
|
||||
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
Output(String name) {
|
||||
super(name, Kind.CLASS);
|
||||
}
|
||||
|
||||
byte[] toByteArray() {
|
||||
return this.baos.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayOutputStream openOutputStream() {
|
||||
this.baos.reset();
|
||||
return this.baos;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Source extends MemoryFileObject {
|
||||
private final String content;
|
||||
|
||||
Source(String name, String content) {
|
||||
super(name, Kind.SOURCE);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignore) {
|
||||
return this.content;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
jdk/test/java/beans/PropertyEditor/Test6397609.java
Normal file
59
jdk/test/java/beans/PropertyEditor/Test6397609.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6397609
|
||||
* @summary Tests autocleaning
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
|
||||
import java.beans.PropertyEditorManager;
|
||||
|
||||
public class Test6397609 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
MemoryClassLoader loader = new MemoryClassLoader();
|
||||
PropertyEditorManager.registerEditor(
|
||||
Object.class,
|
||||
loader.compile("Editor",
|
||||
"public class Editor extends java.beans.PropertyEditorSupport {}"));
|
||||
|
||||
if (!isEditorExist(Object.class)) {
|
||||
throw new Error("the editor is lost");
|
||||
}
|
||||
loader = null; // clean the reference
|
||||
if (isEditorExist(Object.class)) {
|
||||
throw new Error("unexpected editor is found");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEditorExist(Class type) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.gc(); // clean all weak references
|
||||
if (null == PropertyEditorManager.findEditor(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2008 Sun Microsystems, Inc. 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
|
||||
@ -23,18 +23,6 @@
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.beans.PropertyEditorManager;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject.Kind;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
final class TestEditor {
|
||||
private final PropertyEditor editor;
|
||||
@ -53,8 +41,7 @@ final class TestEditor {
|
||||
void testJava(Object value) {
|
||||
this.editor.setValue(value);
|
||||
|
||||
MemoryFileManager manager = new MemoryFileManager();
|
||||
Object object = manager.invoke(this.editor.getJavaInitializationString());
|
||||
Object object = execute("Executor", "execute", this.editor.getJavaInitializationString());
|
||||
|
||||
System.out.println("Property value before: " + value);
|
||||
System.out.println("Property value after: " + object);
|
||||
@ -87,98 +74,21 @@ final class TestEditor {
|
||||
: object1.equals(object2);
|
||||
}
|
||||
|
||||
private static final class MemoryFileManager extends ForwardingJavaFileManager {
|
||||
private static final String CLASS = "Executor";
|
||||
private static final String METHOD = "execute";
|
||||
private static final JavaCompiler COMPILER = ToolProvider.getSystemJavaCompiler();
|
||||
private final Map<String, MemoryClass> map = new HashMap<String, MemoryClass>();
|
||||
private final MemoryClassLoader loader = new MemoryClassLoader();
|
||||
private static Object execute(String classname, String methodname, String value) {
|
||||
String content
|
||||
= "public class " + classname + " {"
|
||||
+ " public static Object " + methodname + "() throws Exception {"
|
||||
+ " return " + value + ";"
|
||||
+ " }"
|
||||
+ "}";
|
||||
|
||||
MemoryFileManager() {
|
||||
super(COMPILER.getStandardFileManager(null, null, null));
|
||||
try {
|
||||
MemoryClassLoader loader = new MemoryClassLoader();
|
||||
Class type = loader.compile(classname, content);
|
||||
return type.getMethod(methodname).invoke(null);
|
||||
}
|
||||
|
||||
public Object invoke(String expression) {
|
||||
MemorySource file = new MemorySource(CLASS, METHOD, expression);
|
||||
if (!COMPILER.getTask(null, this, null, null, null, Arrays.asList(file)).call())
|
||||
throw new Error("compilation failed");
|
||||
|
||||
MemoryClass mc = this.map.get(CLASS);
|
||||
if (mc == null)
|
||||
throw new Error("class not found: " + CLASS);
|
||||
|
||||
Class c = this.loader.loadClass(CLASS, mc.toByteArray());
|
||||
try {
|
||||
return c.getMethod(METHOD).invoke(null);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
throw new Error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public MemoryClass getJavaFileForOutput(Location location, String name, Kind kind, FileObject source) {
|
||||
MemoryClass type = this.map.get(name);
|
||||
if (type == null) {
|
||||
type = new MemoryClass(name);
|
||||
this.map.put(name, type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MemoryClassLoader extends ClassLoader {
|
||||
public Class<?> loadClass(String name, byte[] array) {
|
||||
return defineClass(name, array, 0, array.length);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MemoryObject extends SimpleJavaFileObject {
|
||||
protected MemoryObject(String name, Kind kind) {
|
||||
super(toURI(name, kind.extension), kind);
|
||||
}
|
||||
|
||||
private static URI toURI(String name, String extension) {
|
||||
try {
|
||||
return new URI("mfm:///" + name.replace('.', '/') + extension);
|
||||
}
|
||||
catch (URISyntaxException exception) {
|
||||
throw new Error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MemoryClass extends MemoryObject {
|
||||
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
MemoryClass(String className) {
|
||||
super(className, Kind.CLASS);
|
||||
}
|
||||
|
||||
public ByteArrayOutputStream openOutputStream() {
|
||||
this.baos.reset();
|
||||
return this.baos;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return this.baos.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MemorySource extends MemoryObject {
|
||||
private final String value;
|
||||
|
||||
MemorySource(String className, String methodName, String expression) {
|
||||
super(className, Kind.SOURCE);
|
||||
this.value
|
||||
= "public class " + className + " {\n"
|
||||
+ " public static Object " + methodName + "() throws Exception {\n"
|
||||
+ " return " + expression + ";\n"
|
||||
+ " }\n"
|
||||
+ "}\n";
|
||||
}
|
||||
|
||||
public CharSequence getCharContent(boolean ignore) {
|
||||
return this.value;
|
||||
catch (Exception exception) {
|
||||
throw new Error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user