Exemple #1
0
 /**
  *  Blocking, may take a while, up to 20 seconds
  */
 public synchronized void stop() {
     if (_log.shouldLog(Log.DEBUG))
         _log.debug("UPnP Stop");
     _shouldBeRunning = false;
     _rescanner.cancel();
     if (_isRunning)
         _upnp.terminate();
     _isRunning = false;
     _detectedAddress = null;
     if (_log.shouldLog(Log.DEBUG))
         _log.debug("UPnP Stop Done");
 }
Exemple #2
0
 /**
  *  Blocking, may take a while
  */
 public synchronized void start() {
     if (_log.shouldLog(Log.DEBUG))
         _log.debug("UPnP Start");
     _shouldBeRunning = true;
     if (!_isRunning) {
         long b = _context.clock().now();
         try {
             _isRunning = _upnp.runPlugin();
             if (_log.shouldLog(Log.INFO))
                 _log.info("UPnP runPlugin took " + (_context.clock().now() - b));
         } catch (Exception e) {
             // NPE in UPnP (ticket #728), can't let it bring us down
             if (!_errorLogged) {
                 _log.error("UPnP error, please report", e);
                 _errorLogged = true;
             }
         }
     }
     if (_isRunning) {
         _rescanner.schedule(RESCAN_LONG_DELAY);
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("UPnP Start Done");
     } else {
         _rescanner.schedule(RESCAN_SHORT_DELAY);
         // Do we have a non-loopback, non-broadcast address?
         // If not, that's why it failed (HTTPServer won't start)
         if (!Addresses.isConnected()) {
             if (!_disconLogged) {
                 _log.logAlways(Log.WARN, "UPnP start failed - no network connection?");
                 _disconLogged = true;
             }
         } else {
             _log.error("UPnP start failed - port conflict?");
         }
     }
 }
Exemple #3
0
  /**
   * @param action "start" or "stop" or "uninstall"
   * @throws just about anything if an app has a delay less than zero, caller would be wise to catch
   *     Throwable If no apps have a delay less than zero, it shouldn't throw anything
   */
  private static void runClientApps(
      RouterContext ctx, File pluginDir, List<ClientAppConfig> apps, String action)
      throws Exception {
    Log log = ctx.logManager().getLog(PluginStarter.class);

    // initialize pluginThreadGroup and _pendingPluginClients
    String pluginName = pluginDir.getName();
    if (!pluginThreadGroups.containsKey(pluginName))
      pluginThreadGroups.put(pluginName, new ThreadGroup(pluginName));
    ThreadGroup pluginThreadGroup = pluginThreadGroups.get(pluginName);
    if (action.equals("start"))
      _pendingPluginClients.put(pluginName, new ConcurrentHashSet<SimpleTimer2.TimedEvent>());

    for (ClientAppConfig app : apps) {
      // If the client is a running ClientApp that we want to stop,
      // bypass all the logic below.
      if (action.equals("stop")) {
        String[] argVal = LoadClientAppsJob.parseArgs(app.args);
        // We must do all the substitution just as when started, so the
        // argument array comparison in getClientApp() works.
        // Do this after parsing so we don't need to worry about quoting
        for (int i = 0; i < argVal.length; i++) {
          if (argVal[i].indexOf("$") >= 0) {
            argVal[i] = argVal[i].replace("$I2P", ctx.getBaseDir().getAbsolutePath());
            argVal[i] = argVal[i].replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
            argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
          }
        }
        ClientApp ca = ctx.routerAppManager().getClientApp(app.className, argVal);
        if (ca != null) {
          // even if (ca.getState() != ClientAppState.RUNNING), we do this, we don't want to fall
          // thru
          try {
            ca.shutdown(LoadClientAppsJob.parseArgs(app.stopargs));
          } catch (Throwable t) {
            throw new Exception(t);
          }
          continue;
        }
      }

      if (action.equals("start") && app.disabled) continue;
      String argVal[];
      if (action.equals("start")) {
        // start
        argVal = LoadClientAppsJob.parseArgs(app.args);
      } else {
        String args;
        if (action.equals("stop")) args = app.stopargs;
        else if (action.equals("uninstall")) args = app.uninstallargs;
        else throw new IllegalArgumentException("bad action");
        // args must be present
        if (args == null || args.length() <= 0) continue;
        argVal = LoadClientAppsJob.parseArgs(args);
      }
      // do this after parsing so we don't need to worry about quoting
      for (int i = 0; i < argVal.length; i++) {
        if (argVal[i].indexOf("$") >= 0) {
          argVal[i] = argVal[i].replace("$I2P", ctx.getBaseDir().getAbsolutePath());
          argVal[i] = argVal[i].replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
          argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
        }
      }

      ClassLoader cl = null;
      if (app.classpath != null) {
        String cp = app.classpath;
        if (cp.indexOf("$") >= 0) {
          cp = cp.replace("$I2P", ctx.getBaseDir().getAbsolutePath());
          cp = cp.replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
          cp = cp.replace("$PLUGIN", pluginDir.getAbsolutePath());
        }

        // Old way - add for the whole JVM
        // addToClasspath(cp, app.clientName, log);

        // New way - add only for this client
        // We cache the ClassLoader we start the client with, so
        // we can reuse it for stopping and uninstalling.
        // If we don't, the client won't be able to find its
        // static members.
        String clCacheKey = pluginName + app.className + app.args;
        if (!action.equals("start")) cl = _clCache.get(clCacheKey);
        if (cl == null) {
          URL[] urls = classpathToURLArray(cp, app.clientName, log);
          if (urls != null) {
            cl = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
            if (action.equals("start")) _clCache.put(clCacheKey, cl);
          }
        }
      }

      if (app.delay < 0 && action.equals("start")) {
        // this will throw exceptions
        LoadClientAppsJob.runClientInline(app.className, app.clientName, argVal, log, cl);
      } else if (app.delay == 0 || !action.equals("start")) {
        // quick check, will throw ClassNotFoundException on error
        LoadClientAppsJob.testClient(app.className, cl);
        // run this guy now
        LoadClientAppsJob.runClient(
            app.className, app.clientName, argVal, ctx, log, pluginThreadGroup, cl);
      } else {
        // If there is some delay, there may be a really good reason for it.
        // Loading a class would be one of them!
        // So we do a quick check first, If it bombs out, we delay and try again.
        // If it bombs after that, then we throw the ClassNotFoundException.
        try {
          // quick check
          LoadClientAppsJob.testClient(app.className, cl);
        } catch (ClassNotFoundException ex) {
          // Try again 1 or 2 seconds later.
          // This should be enough time. Although it is a lousy hack
          // it should work for most cases.
          // Perhaps it may be even better to delay a percentage
          // if > 1, and reduce the delay time.
          // Under normal circumstances there will be no delay at all.
          try {
            if (app.delay > 1) {
              Thread.sleep(2000);
            } else {
              Thread.sleep(1000);
            }
          } catch (InterruptedException ie) {
          }
          // quick check, will throw ClassNotFoundException on error
          LoadClientAppsJob.testClient(app.className, cl);
        }
        // wait before firing it up
        SimpleTimer2.TimedEvent evt =
            new TrackedDelayedClient(
                pluginName,
                ctx.simpleTimer2(),
                ctx,
                app.className,
                app.clientName,
                argVal,
                pluginThreadGroup,
                cl);
        evt.schedule(app.delay);
      }
    }
  }