    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}