/*
 * 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.openjpa.lib.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import serp.bytecode.lowlevel.ConstantPoolTable;

/**
 * ClassLoader implementation that allows classes to be temporarily
 * loaded and then thrown away. Useful for the enhancer to be able
 * to run against a class without first loading(and thus polluting)
 * the parent ClassLoader.
 *
 * @author Marc Prud'hommeaux
 */
public class TemporaryClassLoader extends ClassLoader {

    public TemporaryClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

    @Override
    protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException {
        // see if we've already loaded it
        Class c = findLoadedClass(name);
        if (c != null)
            return c;

        // bug #283. defer to system if the name is a protected name.
        // "sun." is required for JDK 1.4, which has an access check for
        // sun.reflect.GeneratedSerializationConstructorAccessor1
        if (name.startsWith("java.") || name.startsWith("javax.")
            || name.startsWith("sun.") || name.startsWith("jdk.")) {
            return Class.forName(name, resolve, getClass().getClassLoader());
        }

        String resourceName = name.replace('.', '/') + ".class";
        InputStream resource = getResourceAsStream(resourceName);
        if (resource == null) {
            throw new ClassNotFoundException(name);
        }

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        try {
            for (int n = 0; (n = resource.read(b, 0, b.length)) != -1;
                bout.write(b, 0, n))
                ;
            byte[] classBytes = bout.toByteArray();
            // To avoid classloader issues with the JVM (Sun and IBM), we
            // will not load Enums via the TemporaryClassLoader either.
            // Reference JIRA Issue OPENJPA-646 for more information.
            if (isAnnotation(classBytes) || isEnum(classBytes)) {
                try {
                    Class<?> frameworkClass = Class.forName(name, resolve,
                            getClass().getClassLoader());
                    return frameworkClass;
                } catch (ClassNotFoundException e) {
                    // OPENJPA-1121 continue, as it must be a user-defined class
                }
            }

            try {
                return defineClass(name, classBytes, 0, classBytes.length);
            } catch (SecurityException e) {
                // possible prohibited package: defer to the parent
                return super.loadClass(name, resolve);
            }
        } catch (IOException ioe) {
            // defer to the parent
            return super.loadClass(name, resolve);
        }
    }

    /**
     * Fast-parse the given class bytecode to determine if it is an
     * annotation class.
     */
    private static boolean isAnnotation(byte[] b) {
        if (JavaVersions.VERSION < 5)
            return false;
        int idx = ConstantPoolTable.getEndIndex(b);
        int access = ConstantPoolTable.readUnsignedShort(b, idx);
        return (access & 0x2000) != 0; // access constant for annotation type
    }

    /**
     * Fast-parse the given class bytecode to determine if it is an
     * enum class.
     */
    private static boolean isEnum(byte[] b) {
        if (JavaVersions.VERSION < 5)
            return false;
        int idx = ConstantPoolTable.getEndIndex(b);
        int access = ConstantPoolTable.readUnsignedShort(b, idx);
        return (access & 0x4000) != 0; // access constant for enum type
    }
}
