/**
  * Helper for unzipping downloaded zips
  *
  * @param environment
  * @throws IOException
  */
 private void unzip(Environment environment, ZipFile zipFile, File targetFile, String targetPath)
     throws IOException {
   String baseDirSuffix = null;
   try {
     Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
     if (!zipEntries.hasMoreElements()) {
       logger.error("the zip archive has no entries");
     }
     ZipEntry firstEntry = zipEntries.nextElement();
     if (firstEntry.isDirectory()) {
       baseDirSuffix = firstEntry.getName();
     } else {
       zipEntries = zipFile.entries();
     }
     while (zipEntries.hasMoreElements()) {
       ZipEntry zipEntry = zipEntries.nextElement();
       if (zipEntry.isDirectory()) {
         continue;
       }
       String zipEntryName = zipEntry.getName();
       zipEntryName = zipEntryName.replace('\\', '/');
       if (baseDirSuffix != null && zipEntryName.startsWith(baseDirSuffix)) {
         zipEntryName = zipEntryName.substring(baseDirSuffix.length());
       }
       File target = new File(targetFile, zipEntryName);
       FileSystemUtils.mkdirs(target.getParentFile());
       Streams.copy(zipFile.getInputStream(zipEntry), new FileOutputStream(target));
     }
   } catch (IOException e) {
     logger.error(
         "failed to extract zip ["
             + zipFile.getName()
             + "]: "
             + ExceptionsHelper.detailedMessage(e));
     return;
   } finally {
     try {
       zipFile.close();
     } catch (IOException e) {
       // ignore
     }
   }
   File binFile = new File(targetFile, "bin");
   if (binFile.exists() && binFile.isDirectory()) {
     File toLocation = new File(new File(environment.homeFile(), "bin"), targetPath);
     logger.info("found bin, moving to " + toLocation.getAbsolutePath());
     FileSystemUtils.deleteRecursively(toLocation);
     binFile.renameTo(toLocation);
   }
   if (!new File(targetFile, "_site").exists()) {
     if (!FileSystemUtils.hasExtensions(targetFile, ".class", ".jar")) {
       logger.info("identified as a _site plugin, moving to _site structure ...");
       File site = new File(targetFile, "_site");
       File tmpLocation = new File(environment.pluginsFile(), targetPath + ".tmp");
       targetFile.renameTo(tmpLocation);
       FileSystemUtils.mkdirs(targetFile);
       tmpLocation.renameTo(site);
     }
   }
 }
 /**
  * Delete a plugin from the legacy location
  *
  * @param name the plugin name
  * @throws IOException
  */
 public void removePlugin(String name) throws IOException {
   File pluginToDelete = new File(environment.pluginsFile(), name);
   if (pluginToDelete.exists()) {
     FileSystemUtils.deleteRecursively(pluginToDelete, true);
   }
   pluginToDelete = new File(environment.pluginsFile(), name + ".zip");
   if (pluginToDelete.exists()) {
     pluginToDelete.delete();
   }
   File binLocation = new File(new File(environment.homeFile(), "bin"), name);
   if (binLocation.exists()) {
     FileSystemUtils.deleteRecursively(binLocation);
   }
 }
  @Test
  public void testLocalPluginInstallWithBinAndConfig() throws Exception {
    String pluginName = "plugin-test";
    Tuple<Settings, Environment> initialSettings =
        InternalSettingsPreparer.prepareSettings(
            ImmutableSettings.settingsBuilder().build(), false);
    Environment env = initialSettings.v2();
    Path binDir = env.homeFile().resolve("bin");
    if (!Files.exists(binDir)) {
      Files.createDirectories(binDir);
    }
    Path pluginBinDir = binDir.resolve(pluginName);
    Path configDir = env.configFile();
    if (!Files.exists(configDir)) {
      Files.createDirectories(configDir);
    }
    Path pluginConfigDir = configDir.resolve(pluginName);
    try {

      PluginManager pluginManager =
          pluginManager(getPluginUrlForResource("plugin_with_bin_and_config.zip"), initialSettings);

      pluginManager.downloadAndExtract(pluginName);

      Path[] plugins = pluginManager.getListInstalledPlugins();

      assertThat(plugins, arrayWithSize(1));
      assertDirectoryExists(pluginBinDir);
      assertDirectoryExists(pluginConfigDir);
      Path toolFile = pluginBinDir.resolve("tool");
      assertFileExists(toolFile);

      // check that the file is marked executable, without actually checking that we can execute it.
      PosixFileAttributeView view =
          Files.getFileAttributeView(toolFile, PosixFileAttributeView.class);
      // the view might be null, on e.g. windows, there is nothing to check there!
      if (view != null) {
        PosixFileAttributes attributes = view.readAttributes();
        assertTrue(
            "unexpected permissions: " + attributes.permissions(),
            attributes.permissions().contains(PosixFilePermission.OWNER_EXECUTE));
      }
    } finally {
      // we need to clean up the copied dirs
      IOUtils.rm(pluginBinDir, pluginConfigDir);
    }
  }
 // For #7152
 @Test
 public void testLocalPluginInstallWithBinOnly_7152() throws Exception {
   String pluginName = "plugin-test";
   Tuple<Settings, Environment> initialSettings =
       InternalSettingsPreparer.prepareSettings(
           ImmutableSettings.settingsBuilder().build(), false);
   Environment env = initialSettings.v2();
   Path binDir = env.homeFile().resolve("bin");
   if (!Files.exists(binDir)) {
     Files.createDirectories(binDir);
   }
   Path pluginBinDir = binDir.resolve(pluginName);
   try {
     PluginManager pluginManager =
         pluginManager(getPluginUrlForResource("plugin_with_bin_only.zip"), initialSettings);
     pluginManager.downloadAndExtract(pluginName);
     Path[] plugins = pluginManager.getListInstalledPlugins();
     assertThat(plugins.length, is(1));
     assertDirectoryExists(pluginBinDir);
   } finally {
     // we need to clean up the copied dirs
     IOUtils.rm(pluginBinDir);
   }
 }
  public InternalNode(Settings preparedSettings, boolean loadConfigSettings)
      throws ElasticsearchException {
    final Settings pSettings =
        settingsBuilder()
            .put(preparedSettings)
            .put(Client.CLIENT_TYPE_SETTING, CLIENT_TYPE)
            .build();
    Tuple<Settings, Environment> tuple =
        InternalSettingsPreparer.prepareSettings(pSettings, loadConfigSettings);
    tuple = new Tuple<>(TribeService.processSettings(tuple.v1()), tuple.v2());

    // The only place we can actually fake the version a node is running on:
    Version version = pSettings.getAsVersion("tests.mock.version", Version.CURRENT);

    ESLogger logger = Loggers.getLogger(Node.class, tuple.v1().get("name"));
    logger.info(
        "version[{}], pid[{}], build[{}/{}]",
        version,
        JvmInfo.jvmInfo().pid(),
        Build.CURRENT.hashShort(),
        Build.CURRENT.timestamp());

    logger.info("initializing ...");

    if (logger.isDebugEnabled()) {
      Environment env = tuple.v2();
      logger.debug(
          "using home [{}], config [{}], data [{}], logs [{}], work [{}], plugins [{}]",
          env.homeFile(),
          env.configFile(),
          Arrays.toString(env.dataFiles()),
          env.logsFile(),
          env.workFile(),
          env.pluginsFile());
    }

    this.pluginsService = new PluginsService(tuple.v1(), tuple.v2());
    this.settings = pluginsService.updatedSettings();
    // create the environment based on the finalized (processed) view of the settings
    this.environment = new Environment(this.settings());

    CompressorFactory.configure(settings);
    final NodeEnvironment nodeEnvironment;
    try {
      nodeEnvironment = new NodeEnvironment(this.settings, this.environment);
    } catch (IOException ex) {
      throw new ElasticsearchIllegalStateException("Failed to created node environment", ex);
    }

    boolean success = false;
    try {
      ModulesBuilder modules = new ModulesBuilder();
      modules.add(new Version.Module(version));
      modules.add(new PageCacheRecyclerModule(settings));
      modules.add(new CircuitBreakerModule(settings));
      modules.add(new BigArraysModule(settings));
      modules.add(new PluginsModule(settings, pluginsService));
      modules.add(new SettingsModule(settings));
      modules.add(new NodeModule(this));
      modules.add(new NetworkModule());
      modules.add(new ScriptModule(settings));
      modules.add(new EnvironmentModule(environment));
      modules.add(new NodeEnvironmentModule(nodeEnvironment));
      modules.add(new ClusterNameModule(settings));
      modules.add(new ThreadPoolModule(settings));
      modules.add(new DiscoveryModule(settings));
      modules.add(new ClusterModule(settings));
      modules.add(new RestModule(settings));
      modules.add(new TransportModule(settings));
      if (settings.getAsBoolean(HTTP_ENABLED, true)) {
        modules.add(new HttpServerModule(settings));
      }
      modules.add(new RiversModule(settings));
      modules.add(new IndicesModule(settings));
      modules.add(new SearchModule());
      modules.add(new ActionModule(false));
      modules.add(new MonitorModule(settings));
      modules.add(new GatewayModule(settings));
      modules.add(new NodeClientModule());
      modules.add(new ShapeModule());
      modules.add(new PercolatorModule());
      modules.add(new ResourceWatcherModule());
      modules.add(new RepositoriesModule());
      modules.add(new TribeModule());
      modules.add(new BenchmarkModule(settings));

      injector = modules.createInjector();

      client = injector.getInstance(Client.class);
      success = true;
    } finally {
      if (!success) {
        nodeEnvironment.close();
      }
    }

    logger.info("initialized");
  }