001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.jci; 019 020 import java.io.File; 021 022 import org.apache.commons.jci.classes.ExtendedDump; 023 import org.apache.commons.jci.classes.SimpleDump; 024 import org.apache.commons.jci.listeners.ReloadingListener; 025 import org.apache.commons.jci.monitor.FilesystemAlterationMonitor; 026 import org.apache.commons.logging.Log; 027 import org.apache.commons.logging.LogFactory; 028 029 /** 030 * 031 * @author tcurdt 032 */ 033 public final class ReloadingClassLoaderTestCase extends AbstractTestCase { 034 035 private final Log log = LogFactory.getLog(ReloadingClassLoaderTestCase.class); 036 037 private ReloadingClassLoader classloader; 038 private ReloadingListener listener; 039 private FilesystemAlterationMonitor fam; 040 041 private final byte[] clazzSimple1; 042 private final byte[] clazzSimple2; 043 private final byte[] clazzExtended; 044 045 public ReloadingClassLoaderTestCase() throws Exception { 046 clazzSimple1 = SimpleDump.dump("Simple1"); 047 clazzSimple2 = SimpleDump.dump("Simple2"); 048 clazzExtended = ExtendedDump.dump(); 049 assertTrue(clazzSimple1.length > 0); 050 assertTrue(clazzSimple2.length > 0); 051 assertTrue(clazzExtended.length > 0); 052 } 053 054 @Override 055 protected void setUp() throws Exception { 056 super.setUp(); 057 058 classloader = new ReloadingClassLoader(this.getClass().getClassLoader()); 059 listener = new ReloadingListener(); 060 061 listener.addReloadNotificationListener(classloader); 062 063 fam = new FilesystemAlterationMonitor(); 064 fam.addListener(directory, listener); 065 fam.start(); 066 } 067 068 public void testCreate() throws Exception { 069 listener.waitForFirstCheck(); 070 071 log.debug("creating class"); 072 writeFile("jci/Simple.class", clazzSimple1); 073 listener.waitForCheck(); 074 075 final Object simple = classloader.loadClass("jci.Simple").newInstance(); 076 assertEquals("Simple1", simple.toString()); 077 } 078 079 public void testChange() throws Exception { 080 listener.waitForFirstCheck(); 081 082 log.debug("creating class"); 083 writeFile("jci/Simple.class", clazzSimple1); 084 listener.waitForCheck(); 085 086 final Object simple1 = classloader.loadClass("jci.Simple").newInstance(); 087 assertEquals("Simple1", simple1.toString()); 088 089 log.debug("changing class"); 090 writeFile("jci/Simple.class", clazzSimple2); 091 listener.waitForEvent(); 092 093 final Object simple2 = classloader.loadClass("jci.Simple").newInstance(); 094 assertEquals("Simple2", simple2.toString()); 095 } 096 097 public void testDelete() throws Exception { 098 listener.waitForFirstCheck(); 099 100 log.debug("creating class"); 101 writeFile("jci/Simple.class", clazzSimple1); 102 listener.waitForCheck(); 103 104 final Object simple = classloader.loadClass("jci.Simple").newInstance(); 105 assertEquals("Simple1", simple.toString()); 106 107 log.debug("deleting class"); 108 assertTrue(new File(directory, "jci/Simple.class").delete()); 109 listener.waitForEvent(); 110 111 try { 112 classloader.loadClass("jci.Simple").newInstance(); 113 fail(); 114 } catch(final ClassNotFoundException e) { 115 assertEquals("jci.Simple", e.getMessage()); 116 } 117 } 118 119 public void testDeleteDependency() throws Exception { 120 listener.waitForFirstCheck(); 121 122 log.debug("creating classes"); 123 writeFile("jci/Simple.class", clazzSimple1); 124 writeFile("jci/Extended.class", clazzExtended); 125 listener.waitForCheck(); 126 127 final Object simple = classloader.loadClass("jci.Simple").newInstance(); 128 assertEquals("Simple1", simple.toString()); 129 130 final Object extended = classloader.loadClass("jci.Extended").newInstance(); 131 assertEquals("Extended:Simple1", extended.toString()); 132 133 log.debug("deleting class dependency"); 134 assertTrue(new File(directory, "jci/Simple.class").delete()); 135 listener.waitForEvent(); 136 137 try { 138 classloader.loadClass("jci.Extended").newInstance(); 139 fail(); 140 } catch(final NoClassDefFoundError e) { 141 assertEquals("jci/Simple", e.getMessage()); 142 } 143 } 144 145 public void testClassNotFound() { 146 try { 147 classloader.loadClass("bla"); 148 fail(); 149 } catch(final ClassNotFoundException e) { 150 } 151 } 152 153 public void testDelegation() { 154 classloader.clearAssertionStatus(); 155 classloader.setClassAssertionStatus("org.apache.commons.jci.ReloadingClassLoader", true); 156 classloader.setDefaultAssertionStatus(false); 157 classloader.setPackageAssertionStatus("org.apache.commons.jci", true); 158 // FIXME: compare with delegation 159 } 160 161 @Override 162 protected void tearDown() throws Exception { 163 fam.removeListener(listener); 164 fam.stop(); 165 super.tearDown(); 166 } 167 168 }