/*
 * Copyright (C) 2018 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.
 */

#ifndef ART_RUNTIME_PROXY_TEST_H_
#define ART_RUNTIME_PROXY_TEST_H_

#include <jni.h>
#include <vector>

#include "art_method-inl.h"
#include "class_linker-inl.h"
#include "class_root.h"
#include "mirror/class-inl.h"
#include "mirror/method.h"
#include "obj_ptr-inl.h"

namespace art {
namespace proxy_test {

// Generate a proxy class with the given name and interfaces. This is a simplification from what
// libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
// we do not declare exceptions.
ObjPtr<mirror::Class> GenerateProxyClass(ScopedObjectAccess& soa,
                                         jobject jclass_loader,
                                         ClassLinker* class_linker,
                                         const char* className,
                                         const std::vector<Handle<mirror::Class>>& interfaces)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::Class> javaLangObject = hs.NewHandle(GetClassRoot<mirror::Object>());
  CHECK(javaLangObject != nullptr);

  jclass javaLangClass = soa.AddLocalReference<jclass>(GetClassRoot<mirror::Class>());

  // Builds the interfaces array.
  jobjectArray proxyClassInterfaces =
      soa.Env()->NewObjectArray(interfaces.size(), javaLangClass, /* initialElement= */ nullptr);
  soa.Self()->AssertNoPendingException();
  for (size_t i = 0; i < interfaces.size(); ++i) {
    soa.Env()->SetObjectArrayElement(proxyClassInterfaces, i,
                                     soa.AddLocalReference<jclass>(interfaces[i].Get()));
  }

  // Builds the method array.
  jsize methods_count = 3;  // Object.equals, Object.hashCode and Object.toString.
  for (Handle<mirror::Class> interface : interfaces) {
    methods_count += interface->NumVirtualMethods();
  }
  jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
      methods_count,
      soa.AddLocalReference<jclass>(GetClassRoot<mirror::Method>()),
      /* initialElement= */ nullptr);
  soa.Self()->AssertNoPendingException();

  jsize array_index = 0;
  // Fill the method array
  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
  ArtMethod* method = javaLangObject->FindClassMethod(
      "equals", "(Ljava/lang/Object;)Z", kRuntimePointerSize);
  CHECK(method != nullptr);
  CHECK(!method->IsDirect());
  CHECK(method->GetDeclaringClass() == javaLangObject.Get());
  DCHECK(!Runtime::Current()->IsActiveTransaction());
  soa.Env()->SetObjectArrayElement(
      proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
  method = javaLangObject->FindClassMethod("hashCode", "()I", kRuntimePointerSize);
  CHECK(method != nullptr);
  CHECK(!method->IsDirect());
  CHECK(method->GetDeclaringClass() == javaLangObject.Get());
  soa.Env()->SetObjectArrayElement(
      proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
  method = javaLangObject->FindClassMethod(
      "toString", "()Ljava/lang/String;", kRuntimePointerSize);
  CHECK(method != nullptr);
  CHECK(!method->IsDirect());
  CHECK(method->GetDeclaringClass() == javaLangObject.Get());
  soa.Env()->SetObjectArrayElement(
      proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
  // Now adds all interfaces virtual methods.
  for (Handle<mirror::Class> interface : interfaces) {
    for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
      soa.Env()->SetObjectArrayElement(
          proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
              mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m)));
    }
  }
  CHECK_EQ(array_index, methods_count);

  // Builds an empty exception array.
  jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
  soa.Self()->AssertNoPendingException();

  ObjPtr<mirror::Class> proxyClass = class_linker->CreateProxyClass(
      soa,
      soa.Env()->NewStringUTF(className),
      proxyClassInterfaces,
      jclass_loader,
      proxyClassMethods,
      proxyClassThrows);
  soa.Self()->AssertNoPendingException();
  return proxyClass;
}

}  // namespace proxy_test
}  // namespace art

#endif  // ART_RUNTIME_PROXY_TEST_H_
