/*
 * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @test
 * @bug 4894899
 * @summary Test various cases of passing java.nio.ByteBuffers
 * to defineClass().
 *
 * @build DefineClassByteBuffer TestClass
 * @run main DefineClassByteBuffer
 */

import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class DefineClassByteBuffer {

    static void test(ClassLoader cl) throws Exception {
        Class c = Class.forName("TestClass", true, cl);
        if (!"TestClass".equals(c.getName())) {
            throw new RuntimeException("Got wrong class: " + c);
        }
    }

    public static void main(String arg[]) throws Exception {
        ClassLoader[] cls = new ClassLoader[DummyClassLoader.MAX_TYPE];
        for (int i = 0; i < cls.length; i++) {
            cls[i] = new DummyClassLoader(i);
        }

        /* Create several instances of the class using different classloaders,
           which are using different types of ByteBuffer. */
        for (int i = 0; i < cls.length; i++) {
          test(cls[i]);
        }
    }

    /** Always loads the same class, using various types of ByteBuffers */
    public static class DummyClassLoader extends ClassLoader {

        public static final String CLASS_NAME = "TestClass";

        public static final int MAPPED_BUFFER = 0;
        public static final int DIRECT_BUFFER = 1;
        public static final int ARRAY_BUFFER = 2;
        public static final int WRAPPED_BUFFER = 3;
        public static final int READ_ONLY_ARRAY_BUFFER = 4;
        public static final int READ_ONLY_DIRECT_BUFFER = 5;
        public static final int DUP_ARRAY_BUFFER = 6;
        public static final int DUP_DIRECT_BUFFER = 7;
        public static final int MAX_TYPE = 7;

        int loaderType;

        DummyClassLoader(int loaderType) {
            this.loaderType = loaderType;
        }

        static ByteBuffer[] buffers = new ByteBuffer[MAX_TYPE + 1];

        static ByteBuffer readClassFile(String name) {
            try {
                File f = new File(System.getProperty("test.classes", "."),
                                  name);
                FileInputStream fin = new FileInputStream(f);
                FileChannel fc = fin.getChannel();
                return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            } catch (FileNotFoundException e) {
                throw new RuntimeException("Can't open file: " + name, e);
            } catch (IOException e) {
                throw new RuntimeException("Can't open file: " + name, e);
            }
        }

        static {
            /* create a bunch of different ByteBuffers, starting with a mapped
               buffer from a class file, and create various duplicate and wrapped
               buffers. */
            buffers[MAPPED_BUFFER] = readClassFile(CLASS_NAME + ".class");
            byte[] array = new byte[buffers[MAPPED_BUFFER].limit()];

            buffers[DIRECT_BUFFER] = ByteBuffer.allocateDirect(array.length);
            buffers[DIRECT_BUFFER].put(array);

            buffers[ARRAY_BUFFER] = ByteBuffer.allocate(array.length);
            buffers[ARRAY_BUFFER].put(array);

            buffers[WRAPPED_BUFFER] = ByteBuffer.wrap(array);

            buffers[READ_ONLY_ARRAY_BUFFER] = buffers[ARRAY_BUFFER].asReadOnlyBuffer();

            buffers[READ_ONLY_DIRECT_BUFFER] = buffers[DIRECT_BUFFER].asReadOnlyBuffer();

            buffers[DUP_ARRAY_BUFFER] = buffers[ARRAY_BUFFER].duplicate();

            buffers[DUP_DIRECT_BUFFER] = buffers[DIRECT_BUFFER].duplicate();
        }

         public Class findClass(String name) {
             return defineClass(name, buffers[loaderType], null);
         }
    } /* DummyClassLoader */

} /* DefineClassByteBuffer */
