All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.core.impl.launcher.commands.ClasspathHandler Maven / Gradle / Ivy

There is a newer version: 4.5.10
Show newest version
/*
 *  Copyright (c) 2011-2015 The original author or authors
 *  ------------------------------------------------------
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *       The Eclipse Public License is available at
 *       http://www.eclipse.org/legal/epl-v10.html
 *
 *       The Apache License v2.0 is available at
 *       http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

package io.vertx.core.impl.launcher.commands;

import io.vertx.core.*;
import io.vertx.core.cli.annotations.Description;
import io.vertx.core.cli.annotations.Option;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.core.spi.launcher.DefaultCommand;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Command using the classpath option should extends this class as it manages the interaction with the
 * custom classloader.
 *
 * @author Clement Escoffier 
 */
public abstract class ClasspathHandler extends DefaultCommand {

  protected static final String PATH_SEP = System.getProperty("path.separator");

  protected final Logger log = LoggerFactory.getLogger(this.getClass());

  protected List classpath;

  protected Object manager;
  private ClassLoader classloader;

  /**
   * Sets the classpath.
   *
   * @param classpath the classpath
   */
  @Option(shortName = "cp", longName = "classpath", argName = "classpath")
  @Description("Provides an extra classpath to be used for the verticle deployment.")
  public void setClasspath(String classpath) {
    if (classpath == null || classpath.isEmpty()) {
      this.classloader = ClasspathHandler.class.getClassLoader();
      this.classpath = Collections.emptyList();
    } else {
      this.classpath = Arrays.asList(classpath.split(PATH_SEP));
      this.classloader = createClassloader();
    }
  }

  /**
   * Creates a classloader respecting the classpath option.
   *
   * @return the classloader.
   */
  protected synchronized ClassLoader createClassloader() {
    URL[] urls = classpath.stream().map(path -> {
      File file = new File(path);
      try {
        return file.toURI().toURL();
      } catch (MalformedURLException e) {
        throw new IllegalStateException(e);
      }
    }).toArray(URL[]::new);
    return new URLClassLoader(urls, this.getClass().getClassLoader());
  }

  /**
   * Creates a new instance of {@link VertxIsolatedDeployer}.
   *
   * @return the new instance.
   */
  protected synchronized Object newInstance() {
    try {
      classloader = (classpath == null || classpath.isEmpty()) ?
          ClasspathHandler.class.getClassLoader() : createClassloader();
      Class clazz = classloader.loadClass("io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer");
      return clazz.newInstance();
    } catch (Exception e) {
      log.error("Failed to load or instantiate the isolated deployer", e);
      throw new IllegalStateException(e);
    }
  }

  /**
   * Creates a new non-clustered vert.x instance.
   *
   * @param options the options
   * @return the created instance
   */
  protected synchronized Vertx create(VertxOptions options) {
    final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(classloader);
      return Vertx.vertx(options);
    } catch (Exception e) {
      log.error("Failed to create the vert.x instance", e);
    } finally {
      Thread.currentThread().setContextClassLoader(originalClassLoader);
    }
    return null;
  }

  /**
   * Creates a new clustered vert.x instance.
   *
   * @param options       the options
   * @param resultHandler the result handler
   */
  protected synchronized void create(VertxOptions options, Handler> resultHandler) {
    final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(classloader);
      Vertx.clusteredVertx(options, resultHandler);
    } catch (Exception e) {
      log.error("Failed to create the vert.x instance", e);
    } finally {
      Thread.currentThread().setContextClassLoader(originalClassLoader);
    }
  }

  /**
   * Deploys the given verticle using the given deployment options.
   *
   * @param verticle          the verticle
   * @param vertx             the vert.x instance
   * @param options           the deployment options
   * @param completionHandler the completion handler
   */
  public synchronized void deploy(String verticle, Vertx vertx, DeploymentOptions options,
                                  Handler> completionHandler) {
    if (manager == null) {
      manager = newInstance();
    }

    final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(classloader);
      Method method = manager.getClass().getMethod("deploy", String.class, Vertx.class, DeploymentOptions.class,
          Handler.class);
      method.invoke(manager, verticle, vertx, options, completionHandler);
    } catch (InvocationTargetException e) {
      log.error("Failed to deploy verticle " + verticle, e.getCause());
    } catch (Exception e) {
      log.error("Failed to deploy verticle " + verticle, e);
    } finally {
      Thread.currentThread().setContextClassLoader(originalClassLoader);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy