From e85a8bd11c6801f2fb5086abdaa5259c5e69a116 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Mon, 3 Sep 2012 08:35:42 +0000 Subject: [PATCH] AMQ-3797: Avoid using StringArrayEditor as property editor as it causes memory leak when undeploying app in a container such as Tomcat. git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1380168 13f79535-47bb-0310-9956-ffa450edef68 --- .../activemq/util/IntrospectionSupport.java | 23 +++++-- .../activemq/util/StringArrayConverter.java | 69 +++++++++++++++++++ .../activemq/util/StringArrayEditor.java | 60 ---------------- ...est.java => StringArrayConverterTest.java} | 43 ++++-------- 4 files changed, 101 insertions(+), 94 deletions(-) create mode 100644 activemq-core/src/main/java/org/apache/activemq/util/StringArrayConverter.java delete mode 100644 activemq-core/src/main/java/org/apache/activemq/util/StringArrayEditor.java rename activemq-core/src/test/java/org/apache/activemq/util/{StringArrayEditorTest.java => StringArrayConverterTest.java} (54%) diff --git a/activemq-core/src/main/java/org/apache/activemq/util/IntrospectionSupport.java b/activemq-core/src/main/java/org/apache/activemq/util/IntrospectionSupport.java index 8fe2bf1815..7a2eee06ab 100755 --- a/activemq-core/src/main/java/org/apache/activemq/util/IntrospectionSupport.java +++ b/activemq-core/src/main/java/org/apache/activemq/util/IntrospectionSupport.java @@ -56,7 +56,6 @@ public final class IntrospectionSupport { String[] newSearchPath = list.toArray(new String[list.size()]); try { PropertyEditorManager.setEditorSearchPath(newSearchPath); - PropertyEditorManager.registerEditor(String[].class, StringArrayEditor.class); } catch(java.security.AccessControlException ignore) { // we might be in an applet... } @@ -91,7 +90,7 @@ public final class IntrospectionSupport { try { - Object value = method.invoke(target, new Object[] {}); + Object value = method.invoke(target); if (value == null) { continue; } @@ -198,10 +197,10 @@ public final class IntrospectionSupport { // If the type is null or it matches the needed type, just use the // value directly if (value == null || value.getClass() == setter.getParameterTypes()[0]) { - setter.invoke(target, new Object[] {value}); + setter.invoke(target, value); } else { // We need to convert it - setter.invoke(target, new Object[] {convert(value, setter.getParameterTypes()[0])}); + setter.invoke(target, convert(value, setter.getParameterTypes()[0])); } return true; } catch (Throwable ignore) { @@ -210,6 +209,11 @@ public final class IntrospectionSupport { } private static Object convert(Object value, Class type) { + // special for String[] as we do not want to use a PropertyEditor for that + if (type.isAssignableFrom(String[].class)) { + return StringArrayConverter.convertToStringArray(value); + } + PropertyEditor editor = PropertyEditorManager.findEditor(type); if (editor != null) { editor.setAsText(value.toString()); @@ -219,6 +223,12 @@ public final class IntrospectionSupport { } public static String convertToString(Object value, Class type) { + // special for String[] as we do not want to use a PropertyEditor for that + if (value != null && value.getClass().isAssignableFrom(String[].class)) { + String[] array = (String[]) value; + return StringArrayConverter.convertToString(array); + } + PropertyEditor editor = PropertyEditorManager.findEditor(type); if (editor != null) { editor.setValue(value); @@ -242,6 +252,11 @@ public final class IntrospectionSupport { } private static boolean isSettableType(Class clazz) { + // special for String[] + if (clazz.isAssignableFrom(String[].class)) { + return true; + } + if (PropertyEditorManager.findEditor(clazz) != null) { return true; } diff --git a/activemq-core/src/main/java/org/apache/activemq/util/StringArrayConverter.java b/activemq-core/src/main/java/org/apache/activemq/util/StringArrayConverter.java new file mode 100644 index 0000000000..25b8a85c1c --- /dev/null +++ b/activemq-core/src/main/java/org/apache/activemq/util/StringArrayConverter.java @@ -0,0 +1,69 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Class for converting to/from String[] to be used instead of a + * {@link java.beans.PropertyEditor} which otherwise causes + * memory leaks as the JDK {@link java.beans.PropertyEditorManager} + * is a static class and has strong references to classes, causing + * problems in hot-deployment environments. + */ +public class StringArrayConverter { + + // TODO: Remove System.out + + public static String[] convertToStringArray(Object value) { + if (value == null) { + return null; + } + + String text = value.toString(); + if (text == null || text.length() == 0) { + return null; + } + + StringTokenizer stok = new StringTokenizer(text, ","); + final List list = new ArrayList(); + + while (stok.hasMoreTokens()) { + list.add(stok.nextToken()); + } + + String[] array = list.toArray(new String[list.size()]); + return array; + } + + public static String convertToString(String[] value) { + if (value == null || value.length == 0) { + return null; + } + + StringBuffer result = new StringBuffer(String.valueOf(value[0])); + for (int i = 1; i < value.length; i++) { + result.append(",").append(value[i]); + } + + return result.toString(); + } + +} + diff --git a/activemq-core/src/main/java/org/apache/activemq/util/StringArrayEditor.java b/activemq-core/src/main/java/org/apache/activemq/util/StringArrayEditor.java deleted file mode 100644 index 9ad424d508..0000000000 --- a/activemq-core/src/main/java/org/apache/activemq/util/StringArrayEditor.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.activemq.util; - -import java.beans.PropertyEditorSupport; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - - -public class StringArrayEditor extends PropertyEditorSupport { - - public void setAsText(String text) { - if (text == null || text.length() == 0) { - setValue(null); - } else { - StringTokenizer stok = new StringTokenizer(text, ","); - final List list = new ArrayList(); - - while (stok.hasMoreTokens()) { - list.add(stok.nextToken()); - } - - Object array = list.toArray(new String[list.size()]); - - setValue(array); - } - } - - public String getAsText() { - Object[] objects = (Object[]) getValue(); - if (objects == null || objects.length == 0) { - return null; - } - - StringBuffer result = new StringBuffer(String.valueOf(objects[0])); - for (int i = 1; i < objects.length; i++) { - result.append(",").append(objects[i]); - } - - return result.toString(); - - } - -} - diff --git a/activemq-core/src/test/java/org/apache/activemq/util/StringArrayEditorTest.java b/activemq-core/src/test/java/org/apache/activemq/util/StringArrayConverterTest.java similarity index 54% rename from activemq-core/src/test/java/org/apache/activemq/util/StringArrayEditorTest.java rename to activemq-core/src/test/java/org/apache/activemq/util/StringArrayConverterTest.java index 663e4a540e..3e1f966b3a 100644 --- a/activemq-core/src/test/java/org/apache/activemq/util/StringArrayEditorTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/util/StringArrayConverterTest.java @@ -21,52 +21,35 @@ import junit.framework.TestCase; /** * */ -public class StringArrayEditorTest extends TestCase { - - private StringArrayEditor editor = new StringArrayEditor(); +public class StringArrayConverterTest extends TestCase { public void testConvertToStringArray() throws Exception { - editor.setAsText(null); - assertEquals(null, editor.getValue()); - editor.setAsText(""); - assertEquals(null, editor.getValue()); + assertEquals(null, StringArrayConverter.convertToStringArray(null)); + assertEquals(null, StringArrayConverter.convertToStringArray("")); - editor.setAsText("foo"); - String[] array = (String[]) editor.getValue(); + String[] array = StringArrayConverter.convertToStringArray("foo"); assertEquals(1, array.length); assertEquals("foo", array[0]); - editor.setAsText("foo,bar"); - array = (String[]) editor.getValue(); + array = StringArrayConverter.convertToStringArray("foo,bar"); assertEquals(2, array.length); assertEquals("foo", array[0]); assertEquals("bar", array[1]); - editor.setAsText("foo,bar,baz"); - array = (String[]) editor.getValue(); + array = StringArrayConverter.convertToStringArray("foo,bar,baz"); + assertEquals(3, array.length); assertEquals("foo", array[0]); assertEquals("bar", array[1]); assertEquals("baz", array[2]); } public void testConvertToString() throws Exception { - editor.setValue(null); - assertEquals(null, editor.getAsText()); - - editor.setValue(new String[]{}); - assertEquals(null, editor.getAsText()); - - editor.setValue(new String[]{""}); - assertEquals("", editor.getAsText()); - - editor.setValue(new String[]{"foo"}); - assertEquals("foo", editor.getAsText()); - - editor.setValue(new String[]{"foo", "bar"}); - assertEquals("foo,bar", editor.getAsText()); - - editor.setValue(new String[]{"foo", "bar", "baz"}); - assertEquals("foo,bar,baz", editor.getAsText()); + assertEquals(null, StringArrayConverter.convertToString(null)); + assertEquals(null, StringArrayConverter.convertToString(new String[]{})); + assertEquals("", StringArrayConverter.convertToString(new String[]{""})); + assertEquals("foo", StringArrayConverter.convertToString(new String[]{"foo"})); + assertEquals("foo,bar", StringArrayConverter.convertToString(new String[]{"foo", "bar"})); + assertEquals("foo,bar,baz", StringArrayConverter.convertToString(new String[]{"foo", "bar", "baz"})); } }