public synchronized void uninstallModule(String moduleName) {
   log.info("Uninstalling module " + moduleName + " from directory " + modRoot);
   File modDir = new File(modRoot, moduleName);
   if (!modDir.exists()) {
     log.error("Cannot find module to uninstall");
   } else {
     try {
       vertx.fileSystem().deleteSync(modDir.getAbsolutePath(), true);
       log.info("Module " + moduleName + " successfully uninstalled");
     } catch (Exception e) {
       log.error("Failed to delete directory: " + e.getMessage());
     }
   }
 }
 private boolean checkModDirs() {
   if (!modRoot.exists()) {
     if (!modRoot.mkdir()) {
       log.error("Failed to create mods dir " + modRoot);
       return false;
     }
   }
   if (!systemModRoot.exists()) {
     if (!systemModRoot.mkdir()) {
       log.error("Failed to create sys mods dir " + modRoot);
       return false;
     }
   }
   return true;
 }
  private boolean basicAuth(HttpServerRequest request, String encodedAuth) {
    byte[] authBytes = Base64.decodeBase64(encodedAuth);
    String decodedString = new String(authBytes);
    String[] splitAuth = StringUtils.split(StringUtils.trim(decodedString), ":"); // $NON-NLS-1$

    if (splitAuth.length != 2) return false;

    if (fileBasicAuthData.containsKey(splitAuth[0])) {
      String storedHash = new String(Base64.decodeBase64(fileBasicAuthData.get(splitAuth[0])));

      MessageDigest digest;
      try {
        digest = MessageDigest.getInstance("SHA-256"); // $NON-NLS-1$
        digest.update(splitAuth[1].getBytes());

        String receivedHash = new String(digest.digest());

        if (storedHash.equals(receivedHash)) {
          return true;
        }
      } catch (NoSuchAlgorithmException e) {
        logger.error(e.getMessage(), e.getCause());
      }
    }

    request
        .response()
        .headers()
        .add(
            "WWW-Authenticate",
            "Basic realm=\"" + config.getRealm() + "\""); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

    return false;
  }
Exemple #4
0
 private void sendMessage(JsonObject msg) {
   EventLog.addEvent("Sending message: " + msg.encode());
   try {
     vertx.eventBus().publish(TestBase.EVENTS_ADDRESS, msg);
   } catch (Exception e) {
     log.error("Failed to send message", e);
   }
 }
Exemple #5
0
 public void reportException(Throwable t) {
   if (deploymentContext != null) {
     deploymentContext.reportException(t);
   } else {
     t.printStackTrace();
     log.error("context Unhandled exception", t);
   }
 }
Exemple #6
0
 public void reportException(Throwable t) {
   Context ctx = getContext();
   if (ctx != null) {
     ctx.reportException(t);
   } else {
     log.error(" default vertx Unhandled exception ", t);
   }
 }
 void handleException(Exception e) {
   checkThread();
   if (exceptionHandler != null) {
     exceptionHandler.handle(e);
   } else {
     log.error("Unhandled exception", e);
   }
 }
Exemple #8
0
 protected String escapeForJavaScript(String str) {
   try {
     str = StringEscapeUtils.escapeJavaScript(str);
   } catch (Exception e) {
     log.error("Failed to escape", e);
     str = null;
   }
   return str;
 }
 private boolean doPullInDependencies(File modRoot, ModuleIdentifier modID) {
   File modDir = new File(modRoot, modID.toString());
   if (!modDir.exists()) {
     log.error("Cannot find module to uninstall");
   }
   JsonObject conf = loadModuleConfig(modID, modDir);
   if (conf == null) {
     log.error("Module " + modID + " does not contain a mod.json");
   }
   ModuleFields fields = new ModuleFields(conf);
   List<String> mods = new ArrayList<>();
   String includes = fields.getIncludes();
   if (includes != null) {
     mods.addAll(Arrays.asList(parseIncludeString(includes)));
   }
   String deploys = fields.getDeploys();
   if (deploys != null) {
     mods.addAll(Arrays.asList(parseIncludeString(deploys)));
   }
   if (!mods.isEmpty()) {
     File internalModsDir = new File(modDir, "mods");
     if (!internalModsDir.exists()) {
       internalModsDir.mkdir();
     }
     for (String modName : mods) {
       File internalModDir = new File(internalModsDir, modName);
       if (!internalModDir.exists()) {
         ModuleIdentifier theModID = new ModuleIdentifier(modName);
         ModuleZipInfo zipInfo = getModule(theModID);
         if (zipInfo.filename != null) {
           internalModDir.mkdir();
           if (!unzipModuleData(internalModDir, zipInfo, true)) {
             return false;
           } else {
             log.info("Module " + modName + " successfully installed in mods dir of " + modName);
             // Now recurse so we bring in all of the deps
             doPullInDependencies(internalModsDir, theModID);
           }
         }
       }
     }
   }
   return true;
 }
 private ModuleZipInfo getModule(ModuleIdentifier modID) {
   String fileName = generateTmpFileName() + ".zip";
   for (RepoResolver resolver : repos) {
     if (resolver.getModule(fileName, modID)) {
       return new ModuleZipInfo(resolver.isOldStyle(), fileName);
     }
   }
   log.error("Module " + modID + " not found in any repositories");
   return null;
 }
 public boolean pullInDependencies(String moduleName) {
   log.info("Attempting to pull in dependencies for module: " + moduleName);
   ModuleIdentifier modID = new ModuleIdentifier(moduleName);
   try {
     return doPullInDependencies(modRoot, modID);
   } catch (Exception e) {
     log.error("Failed to pull in dependencies", e);
     return false;
   }
 }
 private String getMD5String(final String str) {
   try {
     MessageDigest md = MessageDigest.getInstance("MD5");
     byte[] bytes = md.digest(str.getBytes("UTF-8"));
     StringBuilder sb = new StringBuilder();
     for (byte b : bytes) {
       sb.append(Integer.toHexString(b + 127));
     }
     return sb.toString();
   } catch (Exception e) {
     log.error("Failed to generate MD5 for iframe, If-None-Match headers will be ignored");
     return null;
   }
 }
 private String[] parseIncludeString(String sincludes) {
   sincludes = sincludes.trim();
   if ("".equals(sincludes)) {
     log.error("Empty include string");
     return null;
   }
   String[] arr = sincludes.split(",");
   if (arr != null) {
     for (int i = 0; i < arr.length; i++) {
       arr[i] = arr[i].trim();
     }
   }
   return arr;
 }
 private boolean doInstallMod(final ModuleIdentifier modID) {
   checkWorkerContext();
   if (repos.isEmpty()) {
     log.warn("No repositories configured!");
     return false;
   }
   if (locateModule(null, modID) != null) {
     log.error("Module is already installed");
     return false;
   }
   ModuleZipInfo info = getModule(modID);
   if (info != null) {
     return unzipModule(modID, info, true);
   }
   return false;
 }
  private boolean unzipModule(
      final ModuleIdentifier modID, final ModuleZipInfo zipInfo, boolean deleteZip) {
    // We synchronize to prevent a race whereby it tries to unzip the same module at the
    // same time (e.g. deployModule for the same module name has been called in parallel)
    String modName = modID.toString();
    synchronized (modName.intern()) {
      if (!checkModDirs()) {
        return false;
      }

      File fdest = new File(modRoot, modName);
      File sdest = new File(systemModRoot, modName);
      if (fdest.exists() || sdest.exists()) {
        // This can happen if the same module is requested to be installed
        // at around the same time
        // It's ok if this happens
        log.warn("Module " + modID + " is already installed");
        return true;
      }

      // Unzip into temp dir first
      File tdest = unzipIntoTmpDir(zipInfo, deleteZip);
      if (tdest == null) {
        return false;
      }

      // Check if it's a system module
      JsonObject conf = loadModuleConfig(modID, tdest);
      ModuleFields fields = new ModuleFields(conf);

      boolean system = fields.isSystem();

      // Now copy it to the proper directory
      String moveFrom = tdest.getAbsolutePath();
      try {
        vertx
            .fileSystem()
            .moveSync(moveFrom, system ? sdest.getAbsolutePath() : fdest.getAbsolutePath());
      } catch (Exception e) {
        log.error("Failed to move module", e);
        return false;
      }

      log.info("Module " + modID + " successfully installed");
      return true;
    }
  }
 void handleResponse(HttpClientResponse resp) {
   try {
     if (resp.statusCode == 100) {
       if (continueHandler != null) {
         continueHandler.handle(null);
       }
     } else {
       respHandler.handle(resp);
     }
   } catch (Throwable t) {
     if (t instanceof Exception) {
       handleException((Exception) t);
     } else {
       log.error("Unhandled exception", t);
     }
   }
 }
  @Override
  protected void prepareUser(User user, String userId, JsonObject data) {
    user.setUser(data.getString(principalAttributeName));
    user.setAttributes(new HashMap<String, String>());

    try {
      if (data.getString("lastName") != null && data.getString("firstName") != null) {
        user.getAttributes().put("nom", data.getString("lastName"));
        user.getAttributes().put("prenom", data.getString("firstName"));
      }

      if (data.getString("birthDate") != null) {
        user.getAttributes()
            .put(
                "dateNaissance",
                data.getString("birthDate").replaceAll("([0-9]+)-([0-9]+)-([0-9]+)", "$3/$2/$1"));
      }
      if (data.getString("postalCode") != null) {
        user.getAttributes().put("codePostal", data.getString("postalCode"));
      }

      String category = null;
      JsonArray types = data.getArray("type");
      for (Object type : types.toList()) {
        switch (type.toString()) {
          case "Student":
            category = checkProfile(category, "National_1");
            break;
          case "Teacher":
            category = checkProfile(category, "National_3");
            break;
          case "Relative":
            category = checkProfile(category, "National_2");
            break;
          case "Personnel":
            category = checkProfile(category, "National_4");
            break;
        }
      }
      if (category != null) {
        user.getAttributes().put("categories", category);
      }
    } catch (Exception e) {
      log.error("Failed to transform User for Pronote");
    }
  }
 private void loadRepos() {
   try (InputStream is = getClass().getClassLoader().getResourceAsStream(REPOS_FILE_NAME)) {
     if (is != null) {
       BufferedReader rdr = new BufferedReader(new InputStreamReader(is));
       String line;
       while ((line = rdr.readLine()) != null) {
         line = line.trim();
         if (line.isEmpty() || line.startsWith("#")) {
           // blank line or comment
           continue;
         }
         int colonPos = line.indexOf(':');
         if (colonPos == -1 || colonPos == line.length() - 1) {
           throw new IllegalArgumentException("Invalid repo: " + line);
         }
         String type = line.substring(0, colonPos);
         String repoID = line.substring(colonPos + 1);
         RepoResolver resolver;
         switch (type) {
           case "mavenLocal":
             resolver = new MavenLocalRepoResolver(repoID);
             type = "maven";
             break;
           case "maven":
             resolver = new MavenRepoResolver(vertx, repoID);
             break;
           case "bintray":
             resolver = new BintrayRepoResolver(vertx, repoID);
             break;
           case "old":
             resolver = new OldRepoResolver(vertx, repoID);
             break;
           default:
             throw new IllegalArgumentException("Unknown repo type: " + type);
         }
         repos.add(resolver);
       }
     }
   } catch (IOException e) {
     log.error("Failed to load " + LANG_PROPS_FILE_NAME + " " + e.getMessage());
   }
 }
 private List<URL> getModuleClasspath(File modDir) {
   List<URL> urls = new ArrayList<>();
   // Add the urls for this module
   try {
     urls.add(modDir.toURI().toURL());
     File libDir = new File(modDir, "lib");
     if (libDir.exists()) {
       File[] jars = libDir.listFiles();
       for (File jar : jars) {
         URL jarURL = jar.toURI().toURL();
         urls.add(jarURL);
       }
     }
     return urls;
   } catch (MalformedURLException e) {
     // Won't happen
     log.error("malformed url", e);
     return null;
   }
 }
 private boolean unzipModuleData(
     final File directory, final ModuleZipInfo zipinfo, boolean deleteZip) {
   try (InputStream is = new BufferedInputStream(new FileInputStream(zipinfo.filename));
       ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is))) {
     ZipEntry entry;
     while ((entry = zis.getNextEntry()) != null) {
       String entryName = zipinfo.oldStyle ? removeTopDir(entry.getName()) : entry.getName();
       if (!entryName.isEmpty()) {
         if (entry.isDirectory()) {
           new File(directory, entryName).mkdir();
         } else {
           int count;
           byte[] buff = new byte[BUFFER_SIZE];
           BufferedOutputStream dest = null;
           try {
             OutputStream fos = new FileOutputStream(new File(directory, entryName));
             dest = new BufferedOutputStream(fos, BUFFER_SIZE);
             while ((count = zis.read(buff, 0, BUFFER_SIZE)) != -1) {
               dest.write(buff, 0, count);
             }
             dest.flush();
           } finally {
             if (dest != null) {
               dest.close();
             }
           }
         }
       }
     }
   } catch (Exception e) {
     log.error("Failed to unzip module", e);
     return false;
   } finally {
     directory.delete();
     if (deleteZip) {
       new File(zipinfo.filename).delete();
     }
   }
   return true;
 }
Exemple #21
0
  /*
  If you don't specify a trust store, and you haven't set system properties, the system will try to use either a file
  called jsssecacerts or cacerts in the JDK/JRE security directory.
  You can override this by specifying the javax.echo.ssl.trustStore system property

  If you don't specify a key store, and don't specify a system property no key store will be used
  You can override this by specifying the javax.echo.ssl.keyStore system property
   */
  public SSLContext createContext(
      final String ksPath,
      final String ksPassword,
      final String tsPath,
      final String tsPassword,
      final boolean trustAll) {
    try {
      SSLContext context = SSLContext.getInstance("TLS");
      KeyManager[] keyMgrs = ksPath == null ? null : getKeyMgrs(ksPath, ksPassword);
      TrustManager[] trustMgrs;
      if (trustAll) {
        trustMgrs = new TrustManager[] {createTrustAllTrustManager()};
      } else {
        trustMgrs = tsPath == null ? null : getTrustMgrs(tsPath, tsPassword);
      }
      context.init(keyMgrs, trustMgrs, new SecureRandom());
      return context;
    } catch (Exception e) {
      // TODO better logging
      log.error("Failed to create conext", e);
      throw new RuntimeException(e.getMessage());
    }
  }
  public void installModule(final String moduleName) {
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicReference<Exception> result = new AtomicReference<>();
    final ModuleIdentifier modID = new ModuleIdentifier(moduleName);
    AsyncResultHandler<Void> handler =
        new AsyncResultHandler<Void>() {
          public void handle(AsyncResult<Void> res) {
            result.set(res.exception);
            latch.countDown();
          }
        };

    BlockingAction<Void> installModuleAction =
        new BlockingAction<Void>(vertx, handler) {
          @Override
          public Void action() throws Exception {
            doInstallMod(modID);
            return null;
          }
        };

    installModuleAction.run();

    while (true) {
      try {
        if (!latch.await(300, TimeUnit.SECONDS)) {
          throw new IllegalStateException("Timed out waiting to install module");
        }
        break;
      } catch (InterruptedException ignore) {
      }
    }
    Exception e = result.get();
    if (e != null) {
      log.error("Failed to install module", e);
    }
  }
  private void loadLanguageMappings() {
    // The only language that Vert.x understands out of the box is Java, so we add the default
    // runtime and
    // extension mapping for that. This can be overridden in langs.properties
    languageImpls.put(
        "java",
        new LanguageImplInfo(null, "org.vertx.java.platform.impl.java.JavaVerticleFactory"));
    extensionMappings.put("java", "java");
    extensionMappings.put("class", "java");
    defaultLanguageImplName = "java";

    // First try loading mappings from the LANG_PROPS_FILE_NAMEs file
    // This file is structured as follows:
    //   It should contain one line for every language implementation that is to be used with Vert.x
    //     That line should be structured as follows:
    //       <lang_impl_name>=[module_name:]<factory_name>
    //     Where:
    //       <lang_impl_name> is the name you want to give to the language implementation, e.g.
    // 'jython'
    //       module_name is the (optional) name of a module that contains the language
    // implementation
    //         if ommitted it will be assumed the language implementation is included as part of the
    // Vert.x installation
    //         - this is only true for the Java implementation
    //         if included the module_name should be followed by a colon
    //       factory_name is the FQCN of a VerticleFactory for the language implementation
    //     Examples:
    //       rhino=vertx.lang-rhino-v1.0.0:org.vertx.java.platform.impl.rhino.RhinoVerticleFactory
    //       java=org.vertx.java.platform.impl.java.JavaVerticleFactory
    //   The file should also contain one line for every extension mapping - this maps a file
    // extension to
    //   a <lang_impl_name> as specified above
    //     Examples:
    //       .js=rhino
    //       .rb=jruby
    //   The file can also contain a line representing the default language runtime to be used when
    // no extension or
    //   prefix maps, e.g.
    //     .=java

    try (InputStream is = getClass().getClassLoader().getResourceAsStream(LANG_PROPS_FILE_NAME)) {
      if (is != null) {
        Properties props = new Properties();
        props.load(new BufferedInputStream(is));
        loadLanguageMappings(props);
      }
    } catch (IOException e) {
      log.error("Failed to load " + LANG_PROPS_FILE_NAME + " " + e.getMessage());
    }

    // Then override any with system properties
    Properties sysProps = new Properties();
    Set<String> propertyNames = System.getProperties().stringPropertyNames();
    for (String propertyName : propertyNames) {
      if (propertyName.startsWith(LANG_IMPLS_SYS_PROP_ROOT)) {
        String lang = propertyName.substring(LANG_IMPLS_SYS_PROP_ROOT.length());
        String value = System.getProperty(propertyName);
        sysProps.put(lang, value);
      }
    }
    loadLanguageMappings(sysProps);
  }
  private void doDeployMod(
      final boolean redeploy,
      final String depName,
      final ModuleIdentifier modID,
      final JsonObject config,
      final int instances,
      final File currentModDir,
      final Handler<String> doneHandler) {
    checkWorkerContext();
    File modDir = locateModule(currentModDir, modID);
    if (modDir != null) {
      JsonObject conf = loadModuleConfig(modID, modDir);
      ModuleFields fields = new ModuleFields(conf);
      String main = fields.getMain();
      if (main == null) {
        log.error("Runnable module " + modID + " mod.json must contain a \"main\" field");
        callDoneHandler(doneHandler, null);
        return;
      }
      boolean worker = fields.isWorker();
      boolean multiThreaded = fields.isMultiThreaded();
      if (multiThreaded && !worker) {
        throw new IllegalArgumentException("Multi-threaded modules must be workers");
      }
      boolean preserveCwd = fields.isPreserveCurrentWorkingDirectory();

      // If preserveCwd then use the current module directory instead, or the cwd if not in a module
      File modDirToUse = preserveCwd ? currentModDir : modDir;

      List<URL> urls = getModuleClasspath(modDir);
      if (urls == null) {
        callDoneHandler(doneHandler, null);
        return;
      }

      ModuleReference mr = moduleRefs.get(modID.toString());
      if (mr == null) {
        boolean res = fields.isResident();
        mr =
            new ModuleReference(
                this,
                modID.toString(),
                new ModuleClassLoader(platformClassLoader, urls.toArray(new URL[urls.size()])),
                res);
        ModuleReference prev = moduleRefs.putIfAbsent(modID.toString(), mr);
        if (prev != null) {
          mr = prev;
        }
      }
      ModuleIdentifier enclosingModID = getEnclosingModID();
      if (enclosingModID != null) {
        // If enclosed in another module then the enclosing module classloader becomes a parent of
        // this one
        ModuleReference parentRef = moduleRefs.get(enclosingModID.toString());
        mr.mcl.addParent(parentRef);
        parentRef.incRef();
      }

      // Now load any included moduleRefs
      String includes = fields.getIncludes();
      if (includes != null) {
        if (!loadIncludedModules(modDir, mr, includes)) {
          callDoneHandler(doneHandler, null);
          return;
        }
      }

      final boolean autoRedeploy = fields.isAutoRedeploy();

      doDeploy(
          depName,
          autoRedeploy,
          worker,
          multiThreaded,
          main,
          modID,
          config,
          urls.toArray(new URL[urls.size()]),
          instances,
          modDirToUse,
          mr,
          new Handler<String>() {
            @Override
            public void handle(String deploymentID) {
              if (deploymentID != null && !redeploy && autoRedeploy) {
                redeployer.moduleDeployed(deployments.get(deploymentID));
              }
              callDoneHandler(doneHandler, deploymentID);
            }
          });
    } else {
      if (doInstallMod(modID)) {
        doDeployMod(redeploy, depName, modID, config, instances, currentModDir, doneHandler);
      } else {
        callDoneHandler(doneHandler, null);
      }
    }
  }
Exemple #25
0
  public NetServer listen(int port, String host) {
    if (connectHandler == null) {
      throw new IllegalStateException("Set connect handler first");
    }
    if (listening) {
      throw new IllegalStateException("Listen already called");
    }
    listening = true;

    synchronized (vertx.sharedNetServers()) {
      id = new ServerID(port, host);
      DefaultNetServer shared = vertx.sharedNetServers().get(id);
      if (shared == null) {
        serverChannelGroup = new DefaultChannelGroup("vertx-acceptor-channels");

        ChannelFactory factory =
            new NioServerSocketChannelFactory(vertx.getAcceptorPool(), availableWorkers);
        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        tcpHelper.checkSSL();

        bootstrap.setPipelineFactory(
            new ChannelPipelineFactory() {
              public ChannelPipeline getPipeline() {
                ChannelPipeline pipeline = Channels.pipeline();
                if (tcpHelper.isSSL()) {
                  SSLEngine engine = tcpHelper.getSSLContext().createSSLEngine();
                  engine.setUseClientMode(false);
                  switch (tcpHelper.getClientAuth()) {
                    case REQUEST:
                      {
                        engine.setWantClientAuth(true);
                        break;
                      }
                    case REQUIRED:
                      {
                        engine.setNeedClientAuth(true);
                        break;
                      }
                    case NONE:
                      {
                        engine.setNeedClientAuth(false);
                        break;
                      }
                  }
                  pipeline.addLast("ssl", new SslHandler(engine));
                }
                pipeline.addLast(
                    "chunkedWriter",
                    new ChunkedWriteHandler()); // For large file / sendfile support
                pipeline.addLast("handler", new ServerHandler());
                return pipeline;
              }
            });

        bootstrap.setOptions(tcpHelper.generateConnectionOptions(true));

        try {
          // TODO - currently bootstrap.bind is blocking - need to make it non blocking by not using
          // bootstrap directly
          Channel serverChannel =
              bootstrap.bind(new InetSocketAddress(InetAddress.getByName(host), port));
          serverChannelGroup.add(serverChannel);
          log.trace("Net server listening on " + host + ":" + port);
        } catch (UnknownHostException e) {
          log.error("Failed to bind", e);
        }
        vertx.sharedNetServers().put(id, this);
        actualServer = this;
      } else {
        // Server already exists with that host/port - we will use that
        checkConfigs(actualServer, this);
        actualServer = shared;
      }
      actualServer.handlerManager.addHandler(connectHandler, ctx);
    }
    return this;
  }
  private void doDeploy(
      final String depName,
      boolean autoRedeploy,
      boolean worker,
      boolean multiThreaded,
      String theMain,
      final ModuleIdentifier modID,
      final JsonObject config,
      final URL[] urls,
      int instances,
      final File modDir,
      final ModuleReference mr,
      final Handler<String> doneHandler) {
    checkWorkerContext();

    final String deploymentName = depName != null ? depName : genDepName();

    log.debug(
        "Deploying name : " + deploymentName + " main: " + theMain + " instances: " + instances);

    // How we determine which language implementation to use:
    // 1. Look for a prefix on the main, e.g. 'groovy:org.foo.myproject.MyGroovyMain' would force
    // the groovy
    //    language impl to be used
    // 2. If there is no prefix, then look at the extension, if any. If there is an extension
    // mapping for that
    //    extension, use that.
    // 3. No prefix and no extension mapping - use the default runtime

    LanguageImplInfo langImplInfo = null;

    final String main;
    // Look for a prefix
    int prefixMarker = theMain.indexOf(COLON);
    if (prefixMarker != -1) {
      String prefix = theMain.substring(0, prefixMarker);
      langImplInfo = languageImpls.get(prefix);
      if (langImplInfo == null) {
        throw new IllegalStateException("No language implementation known for prefix " + prefix);
      }
      main = theMain.substring(prefixMarker + 1);
    } else {
      main = theMain;
    }
    if (langImplInfo == null) {
      // No prefix - now look at the extension
      int extensionMarker = main.lastIndexOf('.');
      if (extensionMarker != -1) {
        String extension = main.substring(extensionMarker + 1);
        String langImplName = extensionMappings.get(extension);
        if (langImplName != null) {
          langImplInfo = languageImpls.get(langImplName);
          if (langImplInfo == null) {
            throw new IllegalStateException(
                "Extension mapping for "
                    + extension
                    + " specified as "
                    + langImplName
                    + ", but no language implementation known for that name");
          }
        }
      }
    }
    if (langImplInfo == null) {
      // Use the default
      langImplInfo = languageImpls.get(defaultLanguageImplName);
      if (langImplInfo == null) {
        throw new IllegalStateException(
            "Default language implementation is "
                + defaultLanguageImplName
                + " but no language implementation known for that name");
      }
    }

    // Include the language impl module as a parent of the classloader
    if (langImplInfo.moduleName != null) {
      if (!loadIncludedModules(modDir, mr, langImplInfo.moduleName)) {
        log.error("Failed to load module: " + langImplInfo.moduleName);
        doneHandler.handle(null);
        return;
      }
    }

    final VerticleFactory verticleFactory;

    final Container container = new DefaultContainer(this);

    try {
      // TODO not one verticle factory per module ref, but one per language per module ref
      verticleFactory = mr.getVerticleFactory(langImplInfo.factoryName, vertx, container);
    } catch (Exception e) {
      log.error("Failed to instantiate verticle factory", e);
      doneHandler.handle(null);
      return;
    }

    final int instCount = instances;

    class AggHandler {
      AtomicInteger count = new AtomicInteger(0);
      boolean failed;

      void done(boolean res) {
        if (!res) {
          failed = true;
        }
        if (count.incrementAndGet() == instCount) {
          String deploymentID = failed ? null : deploymentName;
          callDoneHandler(doneHandler, deploymentID);
        }
      }
    }

    final AggHandler aggHandler = new AggHandler();

    String parentDeploymentName = getDeploymentName();
    final Deployment deployment =
        new Deployment(
            deploymentName,
            main,
            modID,
            instances,
            config == null ? new JsonObject() : config.copy(),
            urls,
            modDir,
            parentDeploymentName,
            mr,
            autoRedeploy);
    mr.incRef();
    deployments.put(deploymentName, deployment);

    if (parentDeploymentName != null) {
      Deployment parentDeployment = deployments.get(parentDeploymentName);
      parentDeployment.childDeployments.add(deploymentName);
    }

    ClassLoader oldTCCL = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(mr.mcl);
    try {

      for (int i = 0; i < instances; i++) {

        // Launch the verticle instance

        Runnable runner =
            new Runnable() {
              public void run() {

                Verticle verticle = null;
                boolean error = true;

                try {
                  verticle = verticleFactory.createVerticle(main);
                  error = false;
                } catch (ClassNotFoundException e) {
                  log.error(
                      "Cannot find verticle "
                          + main
                          + " in "
                          + verticleFactory.getClass().getName(),
                      e);
                } catch (Throwable t) {
                  log.error(
                      "Failed to create verticle "
                          + main
                          + " in "
                          + verticleFactory.getClass().getName(),
                      t);
                }

                if (error) {
                  doUndeploy(
                      deploymentName,
                      new SimpleHandler() {
                        public void handle() {
                          aggHandler.done(false);
                        }
                      });
                  return;
                }
                verticle.setContainer(container);
                verticle.setVertx(vertx);

                try {
                  addVerticle(deployment, verticle, verticleFactory);
                  if (modDir != null) {
                    setPathAdjustment(modDir);
                  }
                  VoidResult vr = new VoidResult();
                  verticle.start(vr);
                  vr.setHandler(
                      new AsyncResultHandler<Void>() {
                        @Override
                        public void handle(AsyncResult<Void> ar) {
                          if (ar.succeeded()) {
                            aggHandler.done(true);
                          } else {
                            log.error(
                                "Failed to deploy verticle "
                                    + main
                                    + " in "
                                    + verticleFactory.getClass().getName(),
                                ar.exception);
                            aggHandler.done(false);
                          }
                        }
                      });
                } catch (Throwable t) {
                  t.printStackTrace();
                  vertx.reportException(t);
                  doUndeploy(
                      deploymentName,
                      new SimpleHandler() {
                        public void handle() {
                          aggHandler.done(false);
                        }
                      });
                }
              }
            };

        if (worker) {
          vertx.startInBackground(runner, multiThreaded);
        } else {
          vertx.startOnEventLoop(runner);
        }
      }
    } finally {
      Thread.currentThread().setContextClassLoader(oldTCCL);
    }
  }