You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by tc...@apache.org on 2007/05/16 23:57:59 UTC
svn commit: r538753 - in /jakarta/commons/proper/jci/trunk/core/src:
main/java/org/apache/commons/jci/ main/java/org/apache/commons/jci/utils/
test/java/org/apache/commons/jci/
Author: tcurdt
Date: Wed May 16 14:57:58 2007
New Revision: 538753
URL: http://svn.apache.org/viewvc?view=rev&rev=538753
Log:
https://issues.apache.org/jira/browse/JCI-45
Added:
jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java (with props)
Modified:
jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/ReloadingClassLoader.java
jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/utils/ConversionUtils.java
Modified: jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/ReloadingClassLoader.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/ReloadingClassLoader.java?view=diff&rev=538753&r1=538752&r2=538753
==============================================================================
--- jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/ReloadingClassLoader.java (original)
+++ jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/ReloadingClassLoader.java Wed May 16 14:57:58 2007
@@ -71,7 +71,7 @@
// FIXME: this should be improved with a Map
// find the pStore and index position with var i
- while ( ( i <= n ) && ( stores[i] != pStore ) ) {
+ while ( ( i < n ) && ( stores[i] != pStore ) ) {
i++;
}
@@ -81,17 +81,16 @@
}
// if stores length > 1 then array copy old values, else create new empty store
- if (n > 1) {
- final ResourceStore[] newStores = new ResourceStore[n - 1];
-
- System.arraycopy(stores, 0, newStores, 0, i-1);
- System.arraycopy(stores, i, newStores, i, newStores.length - 1);
-
- stores = newStores;
- delegate = new ResourceStoreClassLoader(parent, stores);
- } else {
- stores = new ResourceStore[0];
+ final ResourceStore[] newStores = new ResourceStore[n - 1];
+ if (i > 0) {
+ System.arraycopy(stores, 0, newStores, 0, i);
}
+ if (i < n - 1) {
+ System.arraycopy(stores, i + 1, newStores, i, (n - i - 1));
+ }
+
+ stores = newStores;
+ delegate = new ResourceStoreClassLoader(parent, stores);
return true;
}
Modified: jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/utils/ConversionUtils.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/utils/ConversionUtils.java?view=diff&rev=538753&r1=538752&r2=538753
==============================================================================
--- jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/utils/ConversionUtils.java (original)
+++ jakarta/commons/proper/jci/trunk/core/src/main/java/org/apache/commons/jci/utils/ConversionUtils.java Wed May 16 14:57:58 2007
@@ -21,6 +21,7 @@
/**
* Mainly common path manipultation helper methods
+ * NOT FOR USE OUTSIDE OF JCI
*
* @author tcurdt
*/
@@ -61,6 +62,7 @@
return new String(name);
}
+/*
public static String clazzName( final File base, final File file ) {
final int rootLength = base.getAbsolutePath().length();
final String absFileName = file.getAbsolutePath();
@@ -69,7 +71,7 @@
final String clazzName = relFileName.replace(File.separatorChar, '.');
return clazzName;
}
-
+*/
public static String relative( final File base, final File file ) {
final int rootLength = base.getAbsolutePath().length();
final String absFileName = file.getAbsolutePath();
Added: jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java?view=auto&rev=538753
==============================================================================
--- jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java (added)
+++ jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java Wed May 16 14:57:58 2007
@@ -0,0 +1,262 @@
+/*
+ * 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.commons.jci;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.commons.jci.classes.SimpleDump;
+import org.apache.commons.jci.stores.ResourceStore;
+import org.apache.commons.jci.stores.MemoryResourceStore;
+
+/**
+ * Test ReloadingClassLoader's <code>removeResourceStore({@link ResourceStore})</code>
+ * method.
+ */
+public class ReloadingClassLoaderRemoveTestCase extends TestCase {
+
+ private final Log log = LogFactory.getLog(ReloadingClassLoaderRemoveTestCase.class);
+
+ private final byte[] clazzSimpleA;
+ private MemoryResourceStore store1 = new MemoryResourceStore();
+ private MemoryResourceStore store2 = new MemoryResourceStore();
+ private MemoryResourceStore store3 = new MemoryResourceStore();
+ private MemoryResourceStore store4 = new MemoryResourceStore();
+
+ public ReloadingClassLoaderRemoveTestCase() throws Exception {
+ clazzSimpleA = SimpleDump.dump("SimpleA");
+ assertTrue(clazzSimpleA.length > 0);
+ }
+
+ protected void setUp() throws Exception {
+ System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
+ }
+
+ protected void tearDown() throws Exception {
+ }
+
+ /**
+ * Test trying to remove a ResourceStore from the ReloadingClassLoader
+ * which can't be found - when the ClassLoader contains NO other ResourceStore.
+ *
+ * Bug: The While loop in the removeResourceStore() throws an ArrayOutOfBoundsException
+ */
+ public void testRemoveStoreNotFoundClassLoaderNoStores() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ checkRemoveResourceStore("No ResourceStore", loader, store1, false);
+ }
+
+ /**
+ * Test trying to remove a ResourceStore from the ReloadingClassLoader
+ * which can't be found - when the ClassLoader DOES contain other ResourceStore.
+ *
+ * Bug: The While loop in the removeResourceStore() throws an ArrayOutOfBoundsException
+ */
+ public void testRemoveStoreNotFoundClassLoaderHasStores() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ loader.addResourceStore(store1);
+ loader.addResourceStore(store2);
+ checkRemoveResourceStore("Has ResourceStore", loader, store3, false);
+ }
+
+ /**
+ * Test trying to remove the first ResourceStore added
+ *
+ * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
+ * first one added (last in array) causes the second System.arraycopy() statement to throw a
+ * ArrayIndexOutOfBoundsException because the destination array position in the new smaller
+ * array is too large.
+ */
+ public void testRemoveStoresOne() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ loader.addResourceStore(store1);
+ loader.addResourceStore(store2);
+ loader.addResourceStore(store3);
+ loader.addResourceStore(store4);
+
+ checkRemoveResourceStore("One: Remove Store 1", loader, store1, true);
+ checkRemoveResourceStore("One: Store 1 Not Found", loader, store1, false);
+
+ checkRemoveResourceStore("One: Remove Store 2", loader, store2, true);
+ checkRemoveResourceStore("One: Store 2 Not Found", loader, store2, false);
+
+ checkRemoveResourceStore("One: Remove Store 3", loader, store3, true);
+ checkRemoveResourceStore("One: Store 3 Not Found", loader, store3, false);
+
+ checkRemoveResourceStore("One: Remove Store 4", loader, store4, true);
+ checkRemoveResourceStore("One: Store 4 Not Found", loader, store4, false);
+ }
+
+ /**
+ * Test trying to remove the second ResourceStore added
+ *
+ * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
+ * first one added (last in array) causes the second System.arraycopy() statement to throw a
+ * ArrayIndexOutOfBoundsException (??not sure why??)
+ */
+ public void testRemoveStoresTwo() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ loader.addResourceStore(store1);
+ loader.addResourceStore(store2);
+ loader.addResourceStore(store3);
+ loader.addResourceStore(store4);
+
+ checkRemoveResourceStore("Two: Remove Store 2", loader, store2, true);
+ checkRemoveResourceStore("Two: Store 2 Not Found", loader, store2, false);
+
+ checkRemoveResourceStore("Two: Remove Store 4", loader, store4, true);
+ checkRemoveResourceStore("Two: Store 4 Not Found", loader, store4, false);
+
+ checkRemoveResourceStore("Two: Remove Store 3", loader, store3, true);
+ checkRemoveResourceStore("Two: Store 3 Not Found", loader, store3, false);
+
+ checkRemoveResourceStore("Two: Remove Store 1", loader, store1, true);
+ checkRemoveResourceStore("Two: Store 1 Not Found", loader, store1, false);
+ }
+
+ /**
+ * Test trying to remove the third ResourceStore added
+ *
+ * Bug: In this scenario the two System.arraycopy() statements don't copy the correct
+ * ResourceStore - it creates a new array where the first resource store is null
+ * and copies store3 and store2 to their same positions
+ */
+ public void testRemoveStoresThree() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ loader.addResourceStore(store1);
+ loader.addResourceStore(store2);
+ loader.addResourceStore(store3);
+ loader.addResourceStore(store4);
+
+ checkRemoveResourceStore("Three: Remove Store 3", loader, store3, true);
+ checkRemoveResourceStore("Three: Store 3 Not Found", loader, store3, false);
+
+ checkRemoveResourceStore("Three: Remove Store 1", loader, store1, true);
+ checkRemoveResourceStore("Three: Store 1 Not Found", loader, store1, false);
+
+ checkRemoveResourceStore("Three: Remove Store 4", loader, store4, true);
+ checkRemoveResourceStore("Three: Store 4 Not Found", loader, store4, false);
+
+ checkRemoveResourceStore("Three: Remove Store 2", loader, store2, true);
+ checkRemoveResourceStore("Three: Store 2 Not Found", loader, store2, false);
+ }
+
+ /**
+ * Test trying to remove the fourth ResourceStore added
+ *
+ * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
+ * last one added (first in array) causes the first System.arraycopy() statement to throw a
+ * ArrayIndexOutOfBoundsException because the length to copy is -1
+ */
+ public void testRemoveStoresFour() {
+ ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
+ loader.addResourceStore(store1);
+ loader.addResourceStore(store2);
+ loader.addResourceStore(store3);
+ loader.addResourceStore(store4);
+
+ checkRemoveResourceStore("Four: Remove Store 4", loader, store4, true);
+ checkRemoveResourceStore("Four: Store 4 Not Found", loader, store4, false);
+
+ checkRemoveResourceStore("Four: Remove Store 3", loader, store3, true);
+ checkRemoveResourceStore("Four: Store 3 Not Found", loader, store3, false);
+
+ checkRemoveResourceStore("Four: Remove Store 2", loader, store2, true);
+ checkRemoveResourceStore("Four: Store 2 Not Found", loader, store2, false);
+
+ checkRemoveResourceStore("Four: Remove Store 1", loader, store1, true);
+ checkRemoveResourceStore("Four: Store 1 Not Found", loader, store1, false);
+ }
+
+
+ /**
+ * Test that a class can't be loaded after the ResourceStore containing
+ * it has been removed.
+ *
+ * Bug: When theres a single ResourceStore in the ClassLoader and its removed
+ * a new "delegate" ClassLoader with the new ResourceStore array isn't being
+ * created - which means that calling loadClass() still returns the classes
+ * from the removed ResourceStore rather than throwing a ClassNotFoundException
+ */
+ public void testLoadClassAfterResourceStoreRemoved() {
+
+ // Create a class loader & add resource store
+ ReloadingClassLoader loader = new ReloadingClassLoader(this.getClass().getClassLoader());
+ MemoryResourceStore store = new MemoryResourceStore();
+ loader.addResourceStore(store);
+
+ // Check "jci.Simple" class can't be loaded
+ try {
+ Object simple1 = loader.loadClass("jci.Simple").newInstance();
+ fail("Success loadClass[1]");
+ } catch(ClassNotFoundException e) {
+ // expected not found
+ } catch(Exception e) {
+ log.error(e);
+ fail("Error loadClass[1]: " + e);
+ }
+
+ // Add "jci.Simple" class to the resource store
+ String toStringValue = "FooBar";
+ try {
+ byte[] classBytes = SimpleDump.dump(toStringValue);
+ store.write("jci/Simple.class", classBytes);
+ } catch(Exception e) {
+ log.error(e);
+ fail("Error adding class to store: " + e);
+ }
+
+ // Check "jci.Simple" class can now be loaded
+ try {
+ Object simple2 = loader.loadClass("jci.Simple").newInstance();
+ assertNotNull("Found loadClass[2]", simple2);
+ assertEquals("toString loadClass[2]", toStringValue, simple2.toString());
+ } catch(Exception e) {
+ log.error(e);
+ fail("Error loadClass[2]: " + e);
+ }
+
+ // Remove the resource store from the class loader
+ checkRemoveResourceStore("Remove Resource Store", loader, store, true);
+
+ // Test "jci.Simple" class can't be loaded after ResourceStore removed
+ try {
+ Object simple3 = loader.loadClass("jci.Simple").newInstance();
+ fail("Success loadClass[3]");
+ } catch(ClassNotFoundException e) {
+ // expected not found
+ } catch(Exception e) {
+ log.error(e);
+ fail("Error loadClass[3]: " + e);
+ }
+
+ }
+
+ /**
+ * Check removing a ResourceStore from ReloadingClassLoader
+ */
+ private void checkRemoveResourceStore(String label, ReloadingClassLoader loader, ResourceStore store, boolean expected) {
+ try {
+ assertEquals(label, expected, loader.removeResourceStore(store));
+ } catch(Exception e) {
+ log.error(label, e);
+ fail(label + " failed: " + e);
+ }
+ }
+}
Propchange: jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java
------------------------------------------------------------------------------
svn:keywords = Date Revision Author HeadURL Id
Propchange: jakarta/commons/proper/jci/trunk/core/src/test/java/org/apache/commons/jci/ReloadingClassLoaderRemoveTestCase.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org