001// Copyright 2024 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal;
016
017import static org.junit.Assert.assertNotEquals;
018
019import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
020
021public class ThrowawayClassLoader extends ClassLoader
022{
023
024    final private ClassLoader parent;
025    
026    public ThrowawayClassLoader(ClassLoader parent) 
027    {
028        super(parent);
029        this.parent = parent;
030    }
031    
032    @Override
033    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException 
034    {
035        synchronized (getClassLoadingLock(name)) 
036        
037        {
038            // First, check if the class has already been loaded
039            Class<?> c = findLoadedClass(name);
040            if (c == null) {
041                if (name.contains(".base.") || name.contains(".pages.") ||
042                        name.contains(".components.") || name.contains(".mixins."))
043                {
044                    final byte[] bytes = PlasticInternalUtils.readBytecodeForClass(parent, name, true);
045                    c = defineClass(name, bytes, 0, bytes.length);
046                    if (resolve) 
047                    {
048                        resolveClass(c);
049                    }
050                }
051                else
052                {
053                    c = parent.loadClass(name);
054                }
055            }
056            return c;
057        }    
058    }
059
060    public static void main(String[] args) throws Exception 
061    {
062        
063        final String className = "org.apache.tapestry5.corelib.components.BeanEditor";
064        
065        final ClassLoader parentClassLoader = ThrowawayClassLoader.class.getClassLoader();
066        ClassLoader classLoader1 = create(parentClassLoader);
067        ClassLoader classLoader2 = create(parentClassLoader);
068        
069        System.out.println("Parent class loader 1: " + parentClassLoader);
070        System.out.println("Class loader 1       : " + classLoader1);
071        System.out.println("Class loader 2       : " + classLoader2);
072        
073        Class class1 = classLoader1.loadClass(className);
074        Class class2 = classLoader2.loadClass(className);
075        Class class3 = parentClassLoader.loadClass(className);
076
077        System.out.println("Class 1 : " + class1.getClassLoader());
078        System.out.println("Class 2 : " + class2.getClassLoader());
079        System.out.println("Class 3 : " + class3.getClassLoader());        
080        
081        assertNotEquals(class1, class2);
082        assertNotEquals(class1, class3);
083        assertNotEquals(class2, class3);
084        
085    }
086    
087    public static Class<?> load(final String className)
088    {
089        ThrowawayClassLoader loader = new ThrowawayClassLoader(
090                ThrowawayClassLoader.class.getClassLoader());
091        try 
092        {
093            return loader.loadClass(className);
094        } catch (ClassNotFoundException e) 
095        {
096            throw new RuntimeException(e);
097        }
098    }
099
100    private static ClassLoader create(final ClassLoader parentClassLoader) {
101//        return TapestryInternalUtils.createThrowawayClassloader(parentClassLoader);
102        return new ThrowawayClassLoader(parentClassLoader);
103    }
104    
105}