content: package org.allaymc.server.extension;
  
  import lombok.SneakyThrows;
  import lombok.extern.slf4j.Slf4j;
  import org.allaymc.api.message.I18n;
  import org.allaymc.api.message.TrKeys;
  import org.allaymc.server.Allay;
  import org.allaymc.server.utils.JSONUtils;
  
  import java.net.MalformedURLException;
  import java.nio.file.FileSystems;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.PathMatcher;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * @author daoge_cmd
   */
  @Slf4j
  public final class ExtensionManager {
  
      private static final PathMatcher PATH_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**.jar");
  
      private final Path source;
      private final List<Extension> extensionInstances = new ArrayList<>();
  
      public ExtensionManager(Path source) {
          this.source = source;
      }
  
      @SneakyThrows
      public void loadExtensions(String[] args) {
          if (!Files.exists(source)) {
              Files.createDirectory(source);
          }
  
          try (var stream = Files.walk(source)) {
              stream.filter(path -> PATH_MATCHER.matches(path) && Files.isRegularFile(path))
                      .forEach(extensionPath -> loadExtension(extensionPath, args));
          }
  
          this.extensionInstances.forEach(extension -> extension.main(args));
      }
  
      private void loadExtension(Path extensionPath, String[] args) {
          log.info(I18n.get().tr(TrKeys.ALLAY_EXTENSION_LOADING, extensionPath));
          Allay.EXTRA_RESOURCE_CLASS_LOADER.addJar(extensionPath);
  
          // Try to load the main class of the extension if it exists
          var mainClass = findMainClass(extensionPath);
          if (mainClass == null) {
              // Main class can be null
              return;
          }
  
          if (!Extension.class.isAssignableFrom(mainClass)) {
              throw new ExtensionException(I18n.get().tr(TrKeys.ALLAY_EXTENSION_MAINCLASS_TYPEINVALID, mainClass.getName()));
          }
  
          Extension extensionInstance;
          try {
              extensionInstance = (Extension) mainClass.getConstructor().newInstance();
              extensionInstance.main(args);
          } catch (Exception e) {
              throw new ExtensionException(I18n.get().tr(TrKeys.ALLAY_EXTENSION_CONSTRUCT_INSTANCE_ERROR, extensionPath, e));
          }
  
          extensionInstances.add(extensionInstance);
      }
  
      @SneakyThrows
      private Class<?> findMainClass(Path extensionPath) {
          var jarFileSystem = FileSystems.newFileSystem(extensionPath);
          try {
              var extensionDescriptorPath = jarFileSystem.getPath("extension.json");
              if (!Files.exists(extensionDescriptorPath)) {
                  return null;
              }
              var entrance = (String) JSONUtils.fromMap(Files.readString(extensionDescriptorPath)).get("entrance");
              if (entrance == null) {
                  throw new ExtensionException("Missing extrance field in extension.json!");
              }
              return Allay.EXTRA_RESOURCE_CLASS_LOADER.loadClass(entrance);
          } catch (ClassNotFoundException e1) {
              throw new ExtensionException(I18n.get().tr(TrKeys.ALLAY_EXTENSION_ENTRANCE_MISSING, extensionPath));
          } catch (MalformedURLException e2) {
              throw new ExtensionException("Invalid URL: " + extensionPath.toUri());
          }
      }
  }
  