/*
 * Copyright (C) 2017 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_CLASS_LOADER_UTILS_H_
#define ART_RUNTIME_CLASS_LOADER_UTILS_H_

#include "art_field-inl.h"
#include "base/locks.h"
#include "handle_scope.h"
#include "jni/jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "mirror/object.h"
#include "native/dalvik_system_DexFile.h"
#include "scoped_thread_state_change-inl.h"
#include "well_known_classes.h"

namespace art {

// Returns true if the given class loader is either a PathClassLoader or a DexClassLoader.
// (they both have the same behaviour with respect to class lookup order)
inline bool IsPathOrDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
                                   Handle<mirror::ClassLoader> class_loader)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
  return
      (class_loader_class ==
          soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader)) ||
      (class_loader_class ==
          soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DexClassLoader));
}

// Returns true if the given class loader is an InMemoryDexClassLoader.
inline bool IsInMemoryDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
                                     Handle<mirror::ClassLoader> class_loader)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
  return (class_loader_class ==
      soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_InMemoryDexClassLoader));
}

inline bool IsDelegateLastClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
                                      Handle<mirror::ClassLoader> class_loader)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
  return class_loader_class ==
      soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DelegateLastClassLoader);
}

// Visit the DexPathList$Element instances in the given classloader with the given visitor.
// Constraints on the visitor:
//   * The visitor should return true to continue visiting more Elements.
//   * The last argument of the visitor is an out argument of RetType. It will be returned
//     when the visitor ends the visit (by returning false).
// This function assumes that the given classloader is a subclass of BaseDexClassLoader!
template <typename Visitor, typename RetType>
inline RetType VisitClassLoaderDexElements(ScopedObjectAccessAlreadyRunnable& soa,
                                           Handle<mirror::ClassLoader> class_loader,
                                           Visitor fn,
                                           RetType defaultReturn)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  Thread* self = soa.Self();
  ObjPtr<mirror::Object> dex_path_list =
      jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
          GetObject(class_loader.Get());
  if (dex_path_list != nullptr) {
    // DexPathList has an array dexElements of Elements[] which each contain a dex file.
    ObjPtr<mirror::Object> dex_elements_obj =
        jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
            GetObject(dex_path_list);
    // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
    // at the mCookie which is a DexFile vector.
    if (dex_elements_obj != nullptr) {
      StackHandleScope<1> hs(self);
      Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
          hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
      for (auto element : dex_elements.Iterate<mirror::Object>()) {
        if (element == nullptr) {
          // Should never happen, fail.
          break;
        }
        RetType ret_value;
        if (!fn(element, &ret_value)) {
          return ret_value;
        }
      }
    }
  }
  return defaultReturn;
}

// Visit the DexFiles in the given classloader with the given visitor.
// Constraints on the visitor:
//   * The visitor should return true to continue visiting more DexFiles.
//   * The last argument of the visitor is an out argument of RetType. It will be returned
//     when the visitor ends the visit (by returning false).
// This function assumes that the given classloader is a subclass of BaseDexClassLoader!
template <typename Visitor, typename RetType>
inline RetType VisitClassLoaderDexFiles(ScopedObjectAccessAlreadyRunnable& soa,
                                        Handle<mirror::ClassLoader> class_loader,
                                        Visitor fn,
                                        RetType defaultReturn)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ArtField* const cookie_field =
      jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
  ArtField* const dex_file_field =
      jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
  if (dex_file_field == nullptr || cookie_field == nullptr) {
    return defaultReturn;
  }
  auto visit_dex_files = [&](ObjPtr<mirror::Object> element, RetType* ret)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
    if (dex_file != nullptr) {
      ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray();
      if (long_array == nullptr) {
        // This should never happen so log a warning.
        LOG(WARNING) << "Null DexFile::mCookie";
        *ret = defaultReturn;
        return true;
      }
      int32_t long_array_size = long_array->GetLength();
      // First element is the oat file.
      for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
        const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
            long_array->GetWithoutChecks(j)));
        RetType ret_value;
        if (!fn(cp_dex_file, /* out */ &ret_value)) {
          *ret = ret_value;
          return false;
        }
      }
    }
    return true;
  };

  return VisitClassLoaderDexElements(soa, class_loader, visit_dex_files, defaultReturn);
}

// Simplified version of the above, w/o out argument.
template <typename Visitor>
inline void VisitClassLoaderDexFiles(ScopedObjectAccessAlreadyRunnable& soa,
                                     Handle<mirror::ClassLoader> class_loader,
                                     Visitor fn)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  auto helper = [&fn](const art::DexFile* dex_file, void** ret)
      REQUIRES_SHARED(Locks::mutator_lock_) {
#ifdef __clang_analyzer__
    *ret = nullptr;
#else
    UNUSED(ret);
#endif

    return fn(dex_file);
  };
  VisitClassLoaderDexFiles<decltype(helper), void*>(soa,
                                                    class_loader,
                                                    helper,
                                                    /* default= */ nullptr);
}

}  // namespace art

#endif  // ART_RUNTIME_CLASS_LOADER_UTILS_H_
