public BiFunction getInvoker()

in linkis-public-enhancements/linkis-datasource/linkis-datasource-manager/server/src/main/java/org/apache/linkis/metadata/query/server/loader/MetaClassLoaderManager.java [88:264]


  public BiFunction<String, Object[], Object> getInvoker(String dsType) throws ErrorException {
    boolean needToLoad = true;

    MetaServiceInstance serviceInstance = metaServiceInstances.get(dsType);
    if (Objects.nonNull(serviceInstance)) {
      Integer expireTimeInSec = INSTANCE_EXPIRE_TIME.getValue();
      // Lazy load
      needToLoad =
          Objects.nonNull(expireTimeInSec)
              && expireTimeInSec > 0
              && (serviceInstance.initTimeStamp
                      + TimeUnit.MILLISECONDS.convert(expireTimeInSec, TimeUnit.SECONDS))
                  < System.currentTimeMillis();
    }
    if (needToLoad) {
      MetaServiceInstance finalServiceInstance1 = serviceInstance;
      boolean isContains = CacheConfiguration.MYSQL_RELATIONSHIP_LIST.getValue().contains(dsType);
      String finalBaseType = isContains ? MYSQL_BASE_DIR : dsType;
      serviceInstance =
          metaServiceInstances.compute(
              dsType,
              (key, instance) -> {
                if (null != instance && !Objects.equals(finalServiceInstance1, instance)) {
                  return instance;
                }
                String lib = LIB_DIR.getValue();
                String stdLib = lib.endsWith("/") ? lib.replaceAll(".$", "") : lib;
                String componentLib = stdLib + "/" + finalBaseType;
                LOG.info(
                    "Start to load/reload meta instance of data source type: ["
                        + dsType
                        + "] from library dir:"
                        + componentLib);
                ClassLoader parentClassLoader = MetaClassLoaderManager.class.getClassLoader();
                ClassLoader metaClassLoader =
                    classLoaders.computeIfAbsent(
                        dsType,
                        (type) -> {
                          try {
                            return new URLClassLoader(
                                getJarsUrlsOfPath(componentLib).toArray(new URL[0]),
                                parentClassLoader);
                          } catch (Exception e) {
                            LOG.error(
                                "Cannot init the classloader of type: ["
                                    + dsType
                                    + "] in library path: ["
                                    + componentLib
                                    + "]",
                                e);
                            return null;
                          }
                        });
                if (Objects.isNull(metaClassLoader)) {
                  throw new MetaRuntimeException(
                      MessageFormat.format(ERROR_IN_CREATING.getErrorDesc(), dsType), null);
                }
                String expectClassName = null;
                if (dsType.length() > 0) {
                  String converDsType = dsType;
                  try {
                    if (MapUtils.isNotEmpty(databaseRelationship)
                        && databaseRelationship.containsKey(dsType)) {
                      String value = MapUtils.getString(databaseRelationship, dsType);
                      if (StringUtils.isNotBlank(value)
                          && CacheConfiguration.MYSQL_RELATIONSHIP_LIST
                              .getValue()
                              .contains(value)) {
                        converDsType = value;
                      }
                    }
                  } catch (Exception e) {
                    LOG.warn("dsType conver failed: {}", dsType);
                  }
                  String prefix =
                      converDsType.substring(0, 1).toUpperCase() + converDsType.substring(1);
                  expectClassName = String.format(META_CLASS_NAME, prefix);
                }
                Class<? extends BaseMetadataService> metaServiceClass =
                    searchForLoadMetaServiceClass(metaClassLoader, expectClassName, true);
                if (Objects.isNull(metaServiceClass)) {
                  throw new MetaRuntimeException(
                      MessageFormat.format(INIT_META_SERVICE.getErrorDesc(), dsType), null);
                }
                BaseMetadataService metadataService =
                    MetadataUtils.loadMetaService(metaServiceClass, metaClassLoader);
                if (metadataService instanceof AbstractCacheMetaService) {
                  LOG.info("Invoke the init() method in meta service for type: [" + dsType + "]");
                  ((AbstractCacheMetaService<?>) metadataService).init();
                }
                return new MetaServiceInstance(metadataService, metaClassLoader);
              });
    }
    Method[] childMethods = serviceInstance.methods;
    MetaServiceInstance finalServiceInstance = serviceInstance;
    return (String m, Object... args) -> {
      ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
      try {
        Thread.currentThread().setContextClassLoader(finalServiceInstance.metaClassLoader);
        List<Method> methodsMatched =
            Arrays.stream(childMethods)
                .filter(
                    eachMethod -> {
                      if (eachMethod.getName().equals(m)) {
                        Class<?>[] parameterType = eachMethod.getParameterTypes();
                        if (parameterType.length == args.length) {
                          for (int i = 0; i < parameterType.length; i++) {
                            if (Objects.nonNull(args[i])) {
                              boolean matches =
                                  parameterType[i].isAssignableFrom(args[i].getClass())
                                      || ((args[i].getClass().isPrimitive()
                                              || parameterType[i].isPrimitive())
                                          && MetadataUtils.getPrimitive(args[i].getClass())
                                              == MetadataUtils.getPrimitive(parameterType[i]));
                              if (!matches) {
                                return false;
                              }
                            }
                          }
                          return true;
                        }
                      }
                      return false;
                    })
                .collect(Collectors.toList());
        if (methodsMatched.isEmpty()) {
          String type = null;
          if (Objects.nonNull(args)) {
            type =
                Arrays.stream(args)
                    .map(arg -> Objects.nonNull(arg) ? arg.getClass().toString() : "null")
                    .collect(Collectors.joining(","));
          }
          String message =
              "Unknown method: [ name: "
                  + m
                  + ", type: ["
                  + type
                  + "]] for meta service instance: ["
                  + finalServiceInstance.getServiceInstance().toString()
                  + "]";
          LOG.warn(message);
          throw new MetaRuntimeException(message, null);
        } else if (methodsMatched.size() > 1) {
          LOG.warn(
              "Find multiple matched methods with name: ["
                  + m
                  + "] such as: \n"
                  + methodsMatched.stream()
                      .map(
                          method ->
                              method.getName() + ":" + Arrays.toString(method.getParameterTypes()))
                      .collect(Collectors.joining("\n"))
                  + "\n in meta service instance: ["
                  + finalServiceInstance.getServiceInstance().toString()
                  + "], will choose the first one");
        }
        return methodsMatched.get(0).invoke(finalServiceInstance.serviceInstance, args);
      } catch (Exception e) {
        Throwable t = e;
        // UnWrap the Invocation target exception
        while (t instanceof InvocationTargetException) {
          t = t.getCause();
        }
        String message =
            "Fail to invoke method: ["
                + m
                + "] in meta service instance: ["
                + finalServiceInstance.serviceInstance.toString()
                + "]";
        LOG.warn(message, t);
        throw new MetaRuntimeException(message, t);
      } finally {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
      }
    };
  }