/*
 * 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.geode.codeAnalysis.decode;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Serializable;

import org.apache.geode.DataSerializable;
import org.apache.geode.LogWriter;
import org.apache.geode.codeAnalysis.decode.cp.Cp;
import org.apache.geode.codeAnalysis.decode.cp.CpClass;
import org.apache.geode.codeAnalysis.decode.cp.CpDouble;
import org.apache.geode.codeAnalysis.decode.cp.CpLong;
import org.apache.geode.internal.ExitCode;
import org.apache.geode.internal.logging.PureLogWriter;
import org.apache.geode.internal.serialization.DataSerializableFixedID;


/**
 * Decoder represents a jdk ClassFile header
 */

public class CompiledClass implements Comparable {
  public long magic;
  public int minor_version;
  public int major_version;
  public int constant_pool_count;
  public Cp constant_pool[];
  public int access_flags;
  public int this_class; // ptr into constant_pool
  public int super_class; // ptr into constant_pool
  public int interfaces_count;
  public int interfaces[];
  public int fields_count;
  public CompiledField fields[];
  public int methods_count;
  public CompiledMethod methods[];
  public int attributes_count;
  public CompiledAttribute attributes[];

  static LogWriter debugLog;
  static PrintStream debugStream;

  static {
    try {
      debugStream = new PrintStream("loadedClasses.log");
      debugLog = new PureLogWriter(PureLogWriter.ALL_LEVEL, debugStream);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  public static CompiledClass getInstance(File classFile) throws IOException {
    FileInputStream fstream = new FileInputStream(classFile);
    DataInputStream source = new DataInputStream(fstream);
    CompiledClass instance = new CompiledClass(source);
    fstream.close();
    return instance;
  }

  public static CompiledClass getInstance(InputStream classStream) throws IOException {
    DataInputStream source = new DataInputStream(classStream);
    CompiledClass instance = new CompiledClass(source);
    classStream.close();
    return instance;
  }

  /**
   * read a ClassFile structure from the given input source (usually a file)
   */
  public CompiledClass(DataInputStream source) throws IOException {
    int idx;

    magic = (long) source.readInt();
    minor_version = source.readUnsignedShort();
    major_version = source.readUnsignedShort();
    // the first constant-pool slot is reserved by Java and is not in the classes file
    constant_pool_count = source.readUnsignedShort();
    // read the constant pool list
    constant_pool = new Cp[constant_pool_count];
    constant_pool[0] = null;
    for (idx = 1; idx < constant_pool_count; idx++) {
      constant_pool[idx] = Cp.readCp(source);
      // from Venkatesh: workaround for Javasoft hack
      // From the Java Virtual Machine Specification,
      // all eight-byte constants take up two spots in the constant pool.
      // If this is the nth item in the constant pool, then the next
      // item will be numbered n+2.
      if ((constant_pool[idx] instanceof CpLong) || (constant_pool[idx] instanceof CpDouble))
        idx++;
    }
    access_flags = source.readUnsignedShort();
    this_class = source.readUnsignedShort();
    super_class = source.readUnsignedShort();
    interfaces_count = source.readUnsignedShort();
    // read the interfaces list (ptrs into constant_pool)
    interfaces = new int[interfaces_count];
    for (idx = 0; idx < interfaces_count; idx++) {
      interfaces[idx] = source.readUnsignedShort();
    }
    fields_count = source.readUnsignedShort();
    // read the fields list (only includes this class, not inherited variables)
    fields = new CompiledField[fields_count];
    for (idx = 0; idx < fields_count; idx++) {
      fields[idx] = new CompiledField(source, this);
    }
    methods_count = source.readUnsignedShort();
    // read the methods list
    methods = new CompiledMethod[methods_count];
    for (idx = 0; idx < methods_count; idx++) {
      methods[idx] = new CompiledMethod(source, this);
    }
    attributes_count = source.readUnsignedShort();
    // read the attributes
    attributes = new CompiledAttribute[attributes_count];
    for (idx = 0; idx < attributes_count; idx++) {
      attributes[idx] = new CompiledAttribute(source);
    }
  }

  String accessString() {
    StringBuffer result;

    result = new StringBuffer();
    if ((access_flags & 0x0001) != 0)
      result.append("public ");
    if ((access_flags & 0x0002) != 0)
      result.append("(private?) ");
    if ((access_flags & 0x0004) != 0)
      result.append("(protected?) ");
    if ((access_flags & 0x0008) != 0)
      result.append("(static?) ");
    if ((access_flags & 0x0010) != 0)
      result.append("final ");
    if ((access_flags & 0x0020) != 0)
      result.append("(??0x20??) ");
    if ((access_flags & 0x0040) != 0)
      result.append("(volatile?) ");
    if ((access_flags & 0x0080) != 0)
      result.append("(transient?) ");
    if ((access_flags & 0x0100) != 0)
      result = result.append("(??0x100??) ");
    if ((access_flags & 0x0200) != 0)
      result = result.append("interface ");
    if ((access_flags & 0x0400) != 0)
      result = result.append("abstract ");
    if ((access_flags & 0x0800) != 0)
      result = result.append("(??0x800??) ");

    return result.toString();
  }

  public boolean isInterface() {
    return (access_flags & 0x0200) != 0;
  }

  public boolean isSerializableAndNotDataSerializable() {
    // these classes throw exceptions or log ugly messages when you try to load them
    // in junit
    String name = fullyQualifiedName().replace('/', '.');
    if (name.startsWith("org.apache.geode.internal.shared.NativeCallsJNAImpl")
        || name.startsWith("org.apache.geode.internal.statistics.HostStatHelper")) {
      return false;
    }
    try {
      debugLog.info("isSerializableAndNotDataSerializable loading class " + name);
      debugStream.flush();
      Class realClass = Class.forName(name);
      return Serializable.class.isAssignableFrom(realClass)
          && !DataSerializable.class.isAssignableFrom(realClass)
          && !DataSerializableFixedID.class.isAssignableFrom(realClass);
    } catch (UnsatisfiedLinkError e) {
      System.out.println("Unable to load actual class " + name + " external JNI dependencies");
    } catch (NoClassDefFoundError e) {
      System.out.println("Unable to load actual class " + name + " not in JUnit classpath");
    } catch (Throwable e) {
      System.out.println("Unable to load actual class " + name + ": " + e);
    }
    return false;
  }

  public String fullyQualifiedName() {
    return ((CpClass) constant_pool[this_class]).className(this);
  }

  public String superClassName() {
    return ((CpClass) constant_pool[super_class]).className(this);
  }

  @Override
  public int compareTo(Object other) {
    if (!(other instanceof CompiledClass)) {
      return -1;
    }
    String otherName = ((CompiledClass) other).fullyQualifiedName();
    return this.fullyQualifiedName().compareTo(otherName);
  }

  public static void main(String argv[]) {
    File classFile;
    CompiledClass instance;
    int idx;

    classFile = null;
    try {
      classFile = new File(argv[0]);
    } catch (NullPointerException e) {
      System.err.println("You must give the name of a class file on the command line");
      System.exit(3);
    }
    if (!classFile.canRead()) {
      System.err.println("Unable to read " + argv[0]);
      System.exit(3);
    }
    try {
      instance = getInstance(classFile);
      System.out.println("Class name is " + instance.fullyQualifiedName());
      System.out.println("Class access is " + instance.accessString());
      System.out.println("Superclass name is " + instance.superClassName());
      System.out.println("Fields:");
      for (idx = 0; idx < instance.fields_count; idx++) {
        System.out.println("    " + instance.fields[idx].signature());
      }
      System.out.println("Methods:");
      for (idx = 0; idx < instance.methods_count; idx++) {
        System.out.println("    " + instance.methods[idx].signature());
        // if (idx == 0) {
        System.out.println("..method attributes");
        for (int i = 0; i < instance.methods[idx].attributes_count; i++) {
          System.out.println(".." + instance.methods[idx].attributes[i].name(instance));
        }
        // }
      }
    } catch (Throwable e) {
      System.err.println("Error reading file: " + e.getMessage());
      System.exit(3);
    }
    ExitCode.NORMAL.doSystemExit();
  }

}
