/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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.
 */

#include "common_throws.h"

#include "base/logging.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "invoke_type.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "object_utils.h"
#include "thread.h"
#include "verifier/method_verifier.h"

#include <sstream>

namespace art {

static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  if (referrer != NULL) {
    std::string location(referrer->GetLocation());
    if (!location.empty()) {
      os << " (declaration of '" << PrettyDescriptor(referrer)
            << "' appears in " << location << ")";
    }
  }
}

static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
                           mirror::Class* referrer, const char* fmt, va_list* args = NULL)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  std::ostringstream msg;
  if (args != NULL) {
    std::string vmsg;
    StringAppendV(&vmsg, fmt, *args);
    msg << vmsg;
  } else {
    msg << fmt;
  }
  AddReferrerLocation(msg, referrer);
  Thread* self = Thread::Current();
  if (throw_location == NULL) {
    ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
    self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str());
  } else {
    self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str());
  }
}

static void ThrowWrappedException(const ThrowLocation* throw_location,
                                  const char* exception_descriptor,
                                  mirror::Class* referrer, const char* fmt, va_list* args = NULL)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  std::ostringstream msg;
  if (args != NULL) {
    std::string vmsg;
    StringAppendV(&vmsg, fmt, *args);
    msg << vmsg;
  } else {
    msg << fmt;
  }
  AddReferrerLocation(msg, referrer);
  Thread* self = Thread::Current();
  if (throw_location == NULL) {
    ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
    self->ThrowNewWrappedException(computed_throw_location, exception_descriptor, msg.str().c_str());
  } else {
    self->ThrowNewWrappedException(*throw_location, exception_descriptor, msg.str().c_str());
  }
}

// AbstractMethodError

void ThrowAbstractMethodError(mirror::ArtMethod* method) {
  ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
                 StringPrintf("abstract method \"%s\"",
                              PrettyMethod(method).c_str()).c_str());
}

// ArithmeticException

void ThrowArithmeticExceptionDivideByZero() {
  ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero");
}

// ArrayIndexOutOfBoundsException

void ThrowArrayIndexOutOfBoundsException(int index, int length) {
  ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL,
                 StringPrintf("length=%d; index=%d", length, index).c_str());
}

// ArrayStoreException

void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
  ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
                 StringPrintf("%s cannot be stored in an array of type %s",
                              PrettyDescriptor(element_class).c_str(),
                              PrettyDescriptor(array_class).c_str()).c_str());
}

// ClassCastException

void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
  ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
                 StringPrintf("%s cannot be cast to %s",
                              PrettyDescriptor(src_type).c_str(),
                              PrettyDescriptor(dest_type).c_str()).c_str());
}

void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) {
  ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg);
}

// ClassCircularityError

void ThrowClassCircularityError(mirror::Class* c) {
  std::ostringstream msg;
  msg << PrettyDescriptor(c);
  ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
}

// ClassFormatError

void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
  va_end(args);}

// IllegalAccessError

void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
  std::ostringstream msg;
  msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
      << PrettyDescriptor(accessed) << "'";
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}

void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
                                                   mirror::ArtMethod* called,
                                                   InvokeType type) {
  std::ostringstream msg;
  msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
      << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
      << " method " << PrettyMethod(called).c_str();
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}

void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
  std::ostringstream msg;
  msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
      << PrettyDescriptor(referrer) << "'";
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}

void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
  std::ostringstream msg;
  msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
      << PrettyDescriptor(referrer) << "'";
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}

void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
                                       mirror::ArtField* accessed) {
  std::ostringstream msg;
  msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
      << PrettyMethod(referrer) << "'";
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;",
                 referrer != NULL ? referrer->GetClass() : NULL,
                 msg.str().c_str());
}

void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
  va_end(args);
}

// IllegalAccessException

void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) {
  ThrowException(throw_location, "Ljava/lang/IllegalAccessException;", NULL, msg);
}

// IllegalArgumentException

void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) {
  ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg);
}


// IncompatibleClassChangeError

void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
                                       mirror::ArtMethod* method,
                                       mirror::ArtMethod* referrer) {
  std::ostringstream msg;
  msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
      << expected_type << " but instead was found to be of type " << found_type;
  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
                 referrer != NULL ? referrer->GetClass() : NULL,
                 msg.str().c_str());
}

void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
                                                                mirror::Object* this_object,
                                                                mirror::ArtMethod* referrer) {
  // Referrer is calling interface_method on this_object, however, the interface_method isn't
  // implemented by this_object.
  CHECK(this_object != NULL);
  std::ostringstream msg;
  msg << "Class '" << PrettyDescriptor(this_object->GetClass())
      << "' does not implement interface '"
      << PrettyDescriptor(interface_method->GetDeclaringClass())
      << "' in call to '" << PrettyMethod(interface_method) << "'";
  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
                 referrer != NULL ? referrer->GetClass() : NULL,
                 msg.str().c_str());
}

void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
                                            mirror::ArtMethod* referrer) {
  std::ostringstream msg;
  msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
      << (is_static ? "static" : "instance") << " field" << " rather than a "
      << (is_static ? "instance" : "static") << " field";
  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
                 msg.str().c_str());
}

void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
  va_end(args);
}

// IOException

void ThrowIOException(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
  va_end(args);
}

void ThrowWrappedIOException(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowWrappedException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
  va_end(args);
}

// LinkageError

void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
  va_end(args);
}

// NegativeArraySizeException

void ThrowNegativeArraySizeException(int size) {
  ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL,
                 StringPrintf("%d", size).c_str());
}

void ThrowNegativeArraySizeException(const char* msg) {
  ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg);
}

// NoSuchFieldError

void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
                           const StringPiece& type, const StringPiece& name)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  std::ostringstream msg;
  msg << "No " << scope << "field " << name << " of type " << type
      << " in class " << c->GetDescriptor() << " or its superclasses";
  ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
}

// NoSuchMethodError

void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
                            const Signature& signature) {
  std::ostringstream msg;
  msg << "No " << type << " method " << name << signature
      << " in class " << c->GetDescriptor() << " or its super classes";
  ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
}

void ThrowNoSuchMethodError(uint32_t method_idx) {
  Thread* self = Thread::Current();
  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
  mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
  const DexFile& dex_file = *dex_cache->GetDexFile();
  std::ostringstream msg;
  msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
  ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;",
                 throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str());
}

// NullPointerException

void ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location,
                                             mirror::ArtField* field, bool is_read) {
  std::ostringstream msg;
  msg << "Attempt to " << (is_read ? "read from" : "write to")
      << " field '" << PrettyField(field, true) << "' on a null object reference";
  ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
}

static void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location,
                                                         uint32_t method_idx,
                                                         const DexFile& dex_file,
                                                         InvokeType type)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  std::ostringstream msg;
  msg << "Attempt to invoke " << type << " method '"
      << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
  ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
}

void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
                                              uint32_t method_idx,
                                              InvokeType type) {
  mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
  const DexFile& dex_file = *dex_cache->GetDexFile();
  ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx,
                                               dex_file, type);
}

void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
                                              mirror::ArtMethod* method,
                                              InvokeType type) {
  mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
  const DexFile& dex_file = *dex_cache->GetDexFile();
  ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(),
                                               dex_file, type);
}

void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) {
  const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem();
  uint32_t throw_dex_pc = throw_location.GetDexPc();
  CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
  const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
  switch (instr->Opcode()) {
    case Instruction::INVOKE_DIRECT:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect);
      break;
    case Instruction::INVOKE_DIRECT_RANGE:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect);
      break;
    case Instruction::INVOKE_VIRTUAL:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual);
      break;
    case Instruction::INVOKE_VIRTUAL_RANGE:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual);
      break;
    case Instruction::INVOKE_INTERFACE:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface);
      break;
    case Instruction::INVOKE_INTERFACE_RANGE:
      ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface);
      break;
    case Instruction::INVOKE_VIRTUAL_QUICK:
    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
      // Since we replaced the method index, we ask the verifier to tell us which
      // method is invoked at this location.
      mirror::ArtMethod* method =
          verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(),
                                                             throw_location.GetDexPc());
      if (method != NULL) {
        // NPE with precise message.
        ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual);
      } else {
        // NPE with imprecise message.
        ThrowNullPointerException(&throw_location,
                                  "Attempt to invoke a virtual method on a null object reference");
      }
      break;
    }
    case Instruction::IGET:
    case Instruction::IGET_WIDE:
    case Instruction::IGET_OBJECT:
    case Instruction::IGET_BOOLEAN:
    case Instruction::IGET_BYTE:
    case Instruction::IGET_CHAR:
    case Instruction::IGET_SHORT: {
      mirror::ArtField* field =
          Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
                                                             throw_location.GetMethod(), false);
      ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
      break;
    }
    case Instruction::IGET_QUICK:
    case Instruction::IGET_WIDE_QUICK:
    case Instruction::IGET_OBJECT_QUICK: {
      // Since we replaced the field index, we ask the verifier to tell us which
      // field is accessed at this location.
      mirror::ArtField* field =
          verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
                                                             throw_location.GetDexPc());
      if (field != NULL) {
        // NPE with precise message.
        ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
      } else {
        // NPE with imprecise message.
        ThrowNullPointerException(&throw_location,
                                  "Attempt to read from a field on a null object reference");
      }
      break;
    }
    case Instruction::IPUT:
    case Instruction::IPUT_WIDE:
    case Instruction::IPUT_OBJECT:
    case Instruction::IPUT_BOOLEAN:
    case Instruction::IPUT_BYTE:
    case Instruction::IPUT_CHAR:
    case Instruction::IPUT_SHORT: {
      mirror::ArtField* field =
          Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
                                                             throw_location.GetMethod(), false);
      ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
      break;
    }
    case Instruction::IPUT_QUICK:
    case Instruction::IPUT_WIDE_QUICK:
    case Instruction::IPUT_OBJECT_QUICK: {
      // Since we replaced the field index, we ask the verifier to tell us which
      // field is accessed at this location.
      mirror::ArtField* field =
          verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
                                                             throw_location.GetDexPc());
      if (field != NULL) {
        // NPE with precise message.
        ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
      } else {
        // NPE with imprecise message.
        ThrowNullPointerException(&throw_location,
                                  "Attempt to write to a field on a null object reference");
      }
      break;
    }
    case Instruction::AGET:
    case Instruction::AGET_WIDE:
    case Instruction::AGET_OBJECT:
    case Instruction::AGET_BOOLEAN:
    case Instruction::AGET_BYTE:
    case Instruction::AGET_CHAR:
    case Instruction::AGET_SHORT:
      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
                     "Attempt to read from null array");
      break;
    case Instruction::APUT:
    case Instruction::APUT_WIDE:
    case Instruction::APUT_OBJECT:
    case Instruction::APUT_BOOLEAN:
    case Instruction::APUT_BYTE:
    case Instruction::APUT_CHAR:
    case Instruction::APUT_SHORT:
      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
                     "Attempt to write to null array");
      break;
    case Instruction::ARRAY_LENGTH:
      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
                     "Attempt to get length of null array");
      break;
    default: {
      // TODO: We should have covered all the cases where we expect a NPE above, this
      //       message/logging is so we can improve any cases we've missed in the future.
      const DexFile& dex_file =
          *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile();
      ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
                     StringPrintf("Null pointer exception during instruction '%s'",
                                  instr->DumpString(&dex_file).c_str()).c_str());
      break;
    }
  }
}

void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) {
  ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg);
}

// RuntimeException

void ThrowRuntimeException(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args);
  va_end(args);
}

// VerifyError

void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
  va_end(args);
}

}  // namespace art
