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    }