@Override
  public void checkAccess(ThreadGroup g) {
    if (!isSecutityOn) {
      return;
    }
    Thread c = Thread.currentThread();

    if (isSafeThread(c)) {
      return;
    }
    super.checkAccess(g);

    final ThreadGroup cg = c.getThreadGroup();

    if (cg == null) {
      // What the heck is going on here?  JDK 1.3 is sending me a dead thread.
      // This crashes the entire jvm if I don't return here.
      return;
    }

    IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c);

    if (robotProxy == null) {
      throw new AccessControlException(
          "Preventing " + c.getName() + " from access to " + g.getName());
    }

    if (cg.activeCount() > 5) {
      String message = "Robots are only allowed to create up to 5 threads!";

      robotProxy.punishSecurityViolation(message);
      throw new AccessControlException(message);
    }
  }
  public PrintStream getRobotOutputStream() {
    Thread c = Thread.currentThread();

    if (isSafeThread(c)) {
      return null;
    }

    IHostedThread robotProxy = getLoadedOrLoadingRobotProxy(c);

    return (robotProxy != null) ? robotProxy.getOut() : null;
  }
  public FileOutputStream createRobotFileStream(String fileName, boolean append)
      throws IOException {
    final Thread c = Thread.currentThread();

    final IHostedThread robotProxy = getRobotProxy(c);

    if (robotProxy == null) {
      syserr.println("RobotProxy is null");
      return null;
    }
    if (!robotProxy.getStatics().isAdvancedRobot()) {
      throw new RobotException("Only advanced robots could create files");
    }

    final File dir = robotProxy.getRobotFileSystemManager().getWritableDirectory();

    if (!dir.exists()) {
      robotProxy.println("SYSTEM: Creating a data directory for you.");
      AccessController.doPrivileged(
          new PrivilegedAction<Object>() {
            public Object run() {
              outputStreamThreads.add(c);
              if (!dir.exists() && !dir.mkdirs()) {
                syserr.println("Can't create dir " + dir.toString());
              }
              return null;
            }
          });
    }

    final RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager();

    File f = new File(fileName);
    long len;

    if (f.exists()) {
      len = f.length();
    } else {
      fileSystemManager.checkQuota();
      len = 0;
    }

    if (!append) {
      fileSystemManager.adjustQuota(-len);
    }

    outputStreamThreads.add(c);
    return new RobotFileOutputStream(fileName, append, fileSystemManager);
  }
  @Override
  public void checkAccess(Thread t) {
    if (!isSecutityOn) {
      return;
    }

    Thread c = Thread.currentThread();

    if (isSafeThread(c)) {
      return;
    }
    super.checkAccess(t);

    // Threads belonging to other thread groups is not allowed to access threads belonging to other
    // thread groups
    // Bug fix [3021140] Possible for robot to kill other robot threads.
    // In the following the thread group of the current thread must be in the thread group hierarchy
    // of the
    // attacker thread; otherwise an AccessControlException must be thrown.

    boolean found = false;

    ThreadGroup cg = c.getThreadGroup();
    ThreadGroup tg = t.getThreadGroup();

    while (tg != null) {
      if (tg == cg) {
        found = true;
        break;
      }
      try {
        tg = tg.getParent();
      } catch (AccessControlException e) {
        // We expect an AccessControlException due to missing RuntimePermission modifyThreadGroup
        break;
      }
    }
    if (!found) {
      String message = "Preventing " + c.getName() + " from access to " + t.getName();
      IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c);

      if (robotProxy != null) {
        robotProxy.punishSecurityViolation(message);
      }
      throw new AccessControlException(message);
    }
  }