提交 03d6b6f9 编写于 作者: M malenkov

6397609: DOC: De-register API required for PropertyEditorManager and/or doc change

Reviewed-by: peterz, rupashka
上级 7f86cd1d
/*
* 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);
}
}
}
/*
* 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;
}
/*
* 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;
}
}
}
/*
* 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;
}
}
/*
* 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();
MemoryFileManager() {
super(COMPILER.getStandardFileManager(null, null, 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 Object execute(String classname, String methodname, String value) {
String content
= "public class " + classname + " {"
+ " public static Object " + methodname + "() throws Exception {"
+ " return " + value + ";"
+ " }"
+ "}";
try {
MemoryClassLoader loader = new MemoryClassLoader();
Class type = loader.compile(classname, content);
return type.getMethod(methodname).invoke(null);
}
}
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);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册