Пример #1
0
  public static final void loadLevelTree(int resource, Context context) {
    if (mLoaded) return;

    XmlResourceParser parser = context.getResources().getXml(resource);

    levels.clear();

    Level currentLevel = null;

    try {
      int eventType = parser.getEventType();
      while (eventType != XmlPullParser.END_DOCUMENT) {
        if (eventType == XmlPullParser.START_TAG) {
          if (parser.getName().equals("level")) {
            String titleString = null;
            Long index = null;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
              if (parser.getAttributeName(i).equals("index")) {
                index = Long.getLong(parser.getAttributeValue(i));
              }
              if (parser.getAttributeName(i).equals("title")) {
                titleString = parser.getAttributeValue(i);
              }
            }
            currentLevel = new Level(index, titleString);
            levels.add(currentLevel);
          }

          if (parser.getName().equals("enemy") && currentLevel != null) {
            Integer type = null;
            Integer quantity = null;
            Long spawnDelay = null;
            Long minInterval = null;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
              if (parser.getAttributeName(i).equals("type")) {
                type = Integer.getInteger(parser.getAttributeValue(i));
              }
              if (parser.getAttributeName(i).equals("quantity")) {
                quantity = Integer.getInteger(parser.getAttributeValue(i));
              }
              if (parser.getAttributeName(i).equals("spawnDelay")) {
                spawnDelay = Long.getLong(parser.getAttributeValue(i));
              }
              if (parser.getAttributeName(i).equals("minInterval")) {
                minInterval = Long.getLong(parser.getAttributeValue(i));
              }
            }
            EnemyEntry enemyEntry = new EnemyEntry(type, quantity, spawnDelay, minInterval);
            currentLevel.enemyEntries.add(enemyEntry);
          }
        }
        eventType = parser.next();
      }
    } catch (Exception e) {
      DebugLog.e("LevelTree", e.getStackTrace().toString());
    } finally {
      parser.close();
    }
    mLoaded = true;
  }
  @Override
  public Object createEntry(String data) {

    ContentValues values = new ContentValues();

    int endTitle = data.indexOf(";");
    int endUser = data.indexOf(";", endTitle + 1);
    int endStartTime = data.indexOf(";", endUser + 1);
    int endEndTime = data.indexOf(";", endStartTime + 1);
    int endDescription = data.indexOf(";", endEndTime + 1);

    String title = data.substring(0, endTitle);
    String user = data.substring(endTitle + 1, endUser);
    Long starttime = Long.getLong(data.substring(endUser + 1, endStartTime));
    Long endtime = Long.getLong(data.substring(endStartTime + 1, endEndTime));
    String description = (data.substring(endEndTime + 1, endDescription));
    String profilePicURI = (data.substring(endDescription + 1, data.length()));

    // TODO start and endtime check
    starttime = System.currentTimeMillis();
    endtime = System.currentTimeMillis();
    if (";".equals(profilePicURI)) profilePicURI = "";

    values.put(MySQLiteHelper.COLUMN_TIMESTAMP, System.currentTimeMillis());
    values.put(MySQLiteHelper.COLUMN_TITLE, title);
    values.put(MySQLiteHelper.COLUMN_USERNAME, user);
    values.put(MySQLiteHelper.COLUMN_STARTTIME, starttime);
    values.put(MySQLiteHelper.COLUMN_ENDTIME, endtime);
    values.put(MySQLiteHelper.COLUMN_DESCRIPTION, description);
    values.put(MySQLiteHelper.COLUMN_PICPROFILEURI, profilePicURI);

    long insertId = database.insert(MySQLiteHelper.TABLE_EVENTS, null, values);

    String[] allColumnNames = dbHelper.getAllColumnNames(MySQLiteHelper.TABLE_EVENTS);
    Cursor cursor =
        database.query(
            MySQLiteHelper.TABLE_EVENTS,
            allColumnNames,
            MySQLiteHelper.COLUMN_ID + " = " + insertId,
            null,
            null,
            null,
            null);

    Event event = null;
    if (cursor.moveToFirst()) event = cursorToEvent(cursor);
    cursor.close();
    return event;
  }
Пример #3
0
  /**
   * Method to configure the factory (and validation layer) from the environment properties, before
   * any Catalog instance is created
   */
  private void configure() {

    lenientFields =
        Boolean.parseBoolean(
            System.getProperty(
                "org.apache.oodt.cas.filemgr.catalog.datasource.lenientFields", "false"));
    if (!lenientFields) {
      String validationLayerFactoryClass =
          System.getProperty(
              "filemgr.validationLayer.factory",
              "org.apache.oodt.cas.filemgr.validation.DataSourceValidationLayerFactory");
      validationLayer =
          GenericFileManagerObjectFactory.getValidationLayerFromFactory(
              validationLayerFactoryClass);
    }

    fieldIdStr = Boolean.getBoolean("org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields");

    pageSize = Integer.getInteger("org.apache.oodt.cas.filemgr.catalog.datasource.pageSize", VAL);
    cacheUpdateMinutes =
        Long.getLong("org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes", VAL1);

    productIdString =
        Boolean.parseBoolean(
            System.getProperty(
                "org.apache.oodt.cas.filemgr.catalog.datasource.productId.string", "false"));

    orderedValues =
        Boolean.parseBoolean(
            System.getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues"));
  }
 @Override
 public long getItemId(int position) {
   try {
     return Long.getLong(reviewItems.get(position).getId());
   } catch (Exception e) {
     return 0;
   }
   // return 0;
 }
/**
 * This class is a "stoppable" cover for {@link CountDownLatch}.
 *
 * @author jpenney
 */
public class StoppableCountDownLatch {

  /** This is how often waiters will wake up to check for cancellation */
  static final long RETRY_TIME = Long.getLong("gemfire.stoppable-retry-interval", 2000).longValue();

  /** The underlying latch */
  private final CountDownLatch latch;

  /** The cancellation criterion */
  private final CancelCriterion stopper;

  /**
   * @param count the number of times {@link #countDown} must be invoked before threads can pass
   *     through {@link #await()}
   * @throws IllegalArgumentException if {@code count} is negative
   */
  public StoppableCountDownLatch(CancelCriterion stopper, int count) {
    Assert.assertTrue(stopper != null);
    this.latch = new CountDownLatch(count);
    this.stopper = stopper;
  }

  /** @throws InterruptedException */
  public void await() throws InterruptedException {
    for (; ; ) {
      stopper.checkCancelInProgress(null);
      if (latch.await(RETRY_TIME, TimeUnit.MILLISECONDS)) {
        break;
      }
    }
  }

  /**
   * @param msTimeout how long to wait in milliseconds
   * @return true if it was unlatched
   * @throws InterruptedException
   */
  public boolean await(long msTimeout) throws InterruptedException {
    stopper.checkCancelInProgress(null);
    return latch.await(msTimeout, TimeUnit.MILLISECONDS);
  }

  public synchronized void countDown() {
    latch.countDown();
  }

  /** @return the current count */
  public long getCount() {
    return latch.getCount();
  }

  /** @return a string identifying this latch, as well as its state */
  @Override
  public String toString() {
    return "(Stoppable) " + latch.toString();
  }
}
/**
 * Default convenience implementation of {@link RetentionStrategy} for slaves provisioned from
 * {@link Cloud}.
 *
 * <p>If a slave is idle for 10 mins, this retention strategy will remove the slave. This can be
 * used as-is for a {@link Node} provisioned by cloud to implement the auto-scaling semantics, it
 * can be subtyped to tweak the behavior, or it can be used as an example.
 *
 * <p>TODO {@link CloudRetentionStrategy} seems to be a better implementation.
 *
 * @author Kohsuke Kawaguchi
 * @since 1.510
 */
public class CloudSlaveRetentionStrategy<T extends Computer> extends RetentionStrategy<T> {

  @Override
  @GuardedBy("hudson.model.Queue.lock")
  public long check(T c) {
    if (!c.isConnecting() && c.isAcceptingTasks()) {
      if (isIdleForTooLong(c)) {
        try {
          Node n = c.getNode();
          if (n
              != null) // rare, but n==null if the node is deleted and being checked roughly at the
            // same time
            kill(n);
        } catch (IOException e) {
          LOGGER.log(Level.WARNING, "Failed to remove " + c.getDisplayName(), e);
        }
      }
    }
    return checkCycle();
  }

  /**
   * Remove the node.
   *
   * <p>To actually deallocate the resource tied to this {@link Node}, implement {@link
   * Computer#onRemoved()}.
   */
  protected void kill(Node n) throws IOException {
    Jenkins.getInstance().removeNode(n);
  }

  /** When do we check again next time? */
  protected long checkCycle() {
    return getIdleMaxTime() / 10;
  }

  /** Has this computer been idle for too long? */
  protected boolean isIdleForTooLong(T c) {
    return System.currentTimeMillis() - c.getIdleStartMilliseconds() > getIdleMaxTime();
  }

  /** If the computer has been idle longer than this time, we'll kill the slave. */
  protected long getIdleMaxTime() {
    return TIMEOUT;
  }

  // for debugging, it's convenient to be able to reduce this time
  public static long TIMEOUT =
      Long.getLong(
          CloudSlaveRetentionStrategy.class.getName() + ".timeout", TimeUnit2.MINUTES.toMillis(10));

  private static final Logger LOGGER =
      Logger.getLogger(CloudSlaveRetentionStrategy.class.getName());
}
Пример #7
0
  public KubernetesIaas(IaasProvider iaasProvider) {
    super(iaasProvider);
    partitionValidator = new KubernetesPartitionValidator();
    payload = new ArrayList<NameValuePair>();

    podActivationTimeout = Long.getLong("stratos.pod.activation.timeout");
    if (podActivationTimeout == null) {
      podActivationTimeout = DEFAULT_POD_ACTIVATION_TIMEOUT;
      if (log.isInfoEnabled()) {
        log.info("Pod activation timeout was set: " + podActivationTimeout);
      }
    }
  }
 private void runTerminalChangeTask(Map<String, Object> map) {
   // 5.2調用存儲過程,進行數據統計
   logger.info("Exec proc_terminalChangeTask use param:{}", map);
   try {
     manager = new TerminalChangeTaskManagerImpl();
     manager.update("proc_terminalChangeTask", map);
   } catch (SQLException e) {
     logger.error(
         "{}\n MASSAGE : {} \n CAUSE :{} \n CLASS : {}\n",
         new Object[] {"執行終端升級任務定制功能--存儲過程时,报错:", e.getMessage(), e.getCause(), e.getClass()});
     updateTaskStatus(Long.getLong(String.valueOf(map.get("nmTerminalChangeIdTaskId"))), 5);
     manager = null;
     System.exit(1);
   } finally {
     manager = null;
   }
 }
  public static Long getListeningPort(Context context) {
    String listeningPort =
        LocalPreferences.getString(
            context, LocalPreferences.PREF_PORT, LocalPreferences.PREF_PORT_DEFAULT);
    Long port = null;

    try {
      port = Long.getLong(listeningPort, 2222);
    } catch (NumberFormatException e) {
      port = 2222L;
    }

    if (port < LocalPreferences.PORT_MIN || port > LocalPreferences.PORT_MAX) {
      port = 2222L;
    }

    return port;
  }
Пример #10
0
  /** @throws AuthenticationException */
  @SuppressWarnings("unused")
  @Override
  public void authenticate() throws AuthenticationException {
    Usuario user;
    Map<Integer, Integer> recursosOperacoes = new HashMap<Integer, Integer>();

    try {
      user = usuarioDAO.findById(Long.getLong(identity.getId()));

      if (user != null) {

        List<UsuarioRecurso> recursosUsuario = usuarioRecursoDAO.findByUsuario(user.getId());

        if (recursosUsuario != null) {

          Iterator<UsuarioRecurso> it = recursosUsuario.iterator();

          while (it.hasNext()) {
            UsuarioRecurso usuarioRecurso = it.next();
            recursosOperacoes.put(
                usuarioRecurso.getUsuarioRecursosPK().getRecursos(), usuarioRecurso.getOperacao());
          }
        } else {
          throw new AuthenticationException(
              rb.getString("login.usuario.nao.existe"), new Exception());
        }
      } else {
        throw new AuthenticationException(
            rb.getString("login.usuario.nao.existe"), new Exception());
      }

    } catch (Exception ex) {
      throw new AuthenticationException(rb.getString("login.usuario.nao.existe"), ex);
    }

    if (!user.getAminesia().isEmpty()
        && user.getSenha().equals(user.getAminesia().substring(21, 27))) {
      throw new AuthenticationException(rb.getString("login.alteracao.por.email"));
    }

    this.identity.setAttribute("Nome", user.getNome());
    this.identity.setAttribute("Papel", Roles.getRole(user.getPapel()).get(0));
    this.identity.setAttribute("Recurso", recursosOperacoes);
  }
Пример #11
0
public class RandomPolicyAdapter implements PolicyAdapter {
  public static final Long ADAPT_SEED = Long.getLong("starnet.adapt.seed", System.nanoTime());
  public static Random _numberGenerator = new Random();
  RoutingPolicy[] _policies;
  RoutingPolicy _current;

  RandomPolicyAdapter(RoutingPolicy[] policies) {
    _policies = policies;
    adaptPolicy();
  }

  public RoutingPolicy adaptPolicy() {
    _current = _policies[_numberGenerator.nextInt(_policies.length)];
    return _current;
  }

  public RoutingPolicy getCurrentPolicy() {
    return _current;
  }
}
  /**
   * Convenience - getLocalHome().findByTransportOrderIdAndSortNumberGT(id, sortNumber) with
   * exception mapping.
   */
  public static java.util.Collection findByTransportOrderIdAndSortNumberGT(long id, long sortNumber)
      throws net.metaship.generic.LocalException {
    if ("findByPrimaryKey".equals("findByTransportOrderIdAndSortNumberGT")) {
      java.util.Collection r = null;

      int maxRetry = Integer.getInteger("ims.orderload.retry", 10);
      long delay = Long.getLong("ims.orderload.delayms", 100);

      String logCode =
          "findByTransportOrderIdAndSortNumberGT(id, sortNumber)-" + System.currentTimeMillis();
      for (int i = 1; i <= maxRetry; i++) {
        try {
          r = getLocalHome().findByTransportOrderIdAndSortNumberGT(id, sortNumber);
          if (i > 1) {
            log.warn(logCode + " loading succeeded on attempt #" + i);
          }
          return r;
        } catch (javax.ejb.FinderException fx) {
          if (i >= maxRetry) {
            log.error(logCode + " loading failed after " + i + " attempts!");
            throw new net.metaship.generic.LocalException(fx);
          }
          try {
            Thread.sleep(delay);
          } catch (InterruptedException ie) {
          }
        } catch (javax.naming.NamingException nx) {
          throw new net.metaship.generic.LocalException(nx);
        }
      }
    }
    try {
      return getLocalHome().findByTransportOrderIdAndSortNumberGT(id, sortNumber);
    } catch (javax.naming.NamingException nx) {
      throw new net.metaship.generic.LocalException(nx);
    } catch (javax.ejb.FinderException fx) {
      throw new net.metaship.generic.LocalException(fx);
    }
  }
  /** Convenience - getLocalHome().findByPrimaryKey(pk) with exception mapping. */
  public static net.metaship.intermodal.depot.ejb.ServiceAreaLocal findByPrimaryKey(
      net.metaship.intermodal.depot.ejb.ServiceAreaPK pk)
      throws net.metaship.generic.LocalException {
    if ("findByPrimaryKey".equals("findByPrimaryKey")) {
      net.metaship.intermodal.depot.ejb.ServiceAreaLocal r = null;

      int maxRetry = Integer.getInteger("ims.orderload.retry", 10);
      long delay = Long.getLong("ims.orderload.delayms", 100);

      String logCode = "findByPrimaryKey(pk)-" + System.currentTimeMillis();
      for (int i = 1; i <= maxRetry; i++) {
        try {
          r = getLocalHome().findByPrimaryKey(pk);
          if (i > 1) {
            log.warn(logCode + " loading succeeded on attempt #" + i);
          }
          return r;
        } catch (javax.ejb.FinderException fx) {
          if (i >= maxRetry) {
            log.error(logCode + " loading failed after " + i + " attempts!");
            throw new net.metaship.generic.LocalException(fx);
          }
          try {
            Thread.sleep(delay);
          } catch (InterruptedException ie) {
          }
        } catch (javax.naming.NamingException nx) {
          throw new net.metaship.generic.LocalException(nx);
        }
      }
    }
    try {
      return getLocalHome().findByPrimaryKey(pk);
    } catch (javax.naming.NamingException nx) {
      throw new net.metaship.generic.LocalException(nx);
    } catch (javax.ejb.FinderException fx) {
      throw new net.metaship.generic.LocalException(fx);
    }
  }
Пример #14
0
/** Helper functions to run tests. */
public class Helpers implements play.mvc.Http.Status, play.mvc.Http.HeaderNames {

  public static String GET = "GET";
  public static String POST = "POST";
  public static String PUT = "PUT";
  public static String DELETE = "DELETE";
  public static String HEAD = "HEAD";

  // --

  public static Class<? extends WebDriver> HTMLUNIT = HtmlUnitDriver.class;
  public static Class<? extends WebDriver> FIREFOX = FirefoxDriver.class;

  // --
  @SuppressWarnings(value = "unchecked")
  private static Result invokeHandler(
      play.api.mvc.Handler handler, FakeRequest fakeRequest, long timeout) {
    if (handler instanceof play.core.j.JavaAction) {
      play.api.mvc.Action action = (play.api.mvc.Action) handler;
      return wrapScalaResult(action.apply(fakeRequest.getWrappedRequest()), timeout);
    } else {
      throw new RuntimeException("This is not a JavaAction and can't be invoked this way.");
    }
  }

  /**
   * Default Timeout (milliseconds) for fake requests issued by these Helpers. This value is
   * determined from System property <b>test.timeout</b>. The default value is <b>30000</b> (30
   * seconds).
   */
  public static final long DEFAULT_TIMEOUT = Long.getLong("test.timeout", 30000L);

  private static Result wrapScalaResult(
      scala.concurrent.Future<play.api.mvc.Result> result, long timeout) {
    if (result == null) {
      return null;
    } else {
      final play.api.mvc.Result scalaResult = Promise.wrap(result).get(timeout);
      return new Result() {
        public play.api.mvc.Result toScala() {
          return scalaResult;
        }
      };
    }
  }

  // --

  /** Call an action method while decorating it with the right @With interceptors. */
  public static Result callAction(HandlerRef actionReference) {
    return callAction(actionReference, DEFAULT_TIMEOUT);
  }

  public static Result callAction(HandlerRef actionReference, long timeout) {
    return callAction(actionReference, fakeRequest(), timeout);
  }

  /** Call an action method while decorating it with the right @With interceptors. */
  public static Result callAction(HandlerRef actionReference, FakeRequest fakeRequest) {
    return callAction(actionReference, fakeRequest, DEFAULT_TIMEOUT);
  }

  public static Result callAction(
      HandlerRef actionReference, FakeRequest fakeRequest, long timeout) {
    play.api.mvc.HandlerRef handlerRef = (play.api.mvc.HandlerRef) actionReference;
    return invokeHandler(handlerRef.handler(), fakeRequest, timeout);
  }

  /** Build a new GET / fake request. */
  public static FakeRequest fakeRequest() {
    return new FakeRequest();
  }

  /** Build a new fake request. */
  public static FakeRequest fakeRequest(String method, String uri) {
    return new FakeRequest(method, uri);
  }

  /** Build a new fake request corresponding to a given route call */
  public static FakeRequest fakeRequest(Call call) {
    return fakeRequest(call.method(), call.url());
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication() {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        new HashMap<String, Object>(),
        new ArrayList<String>(),
        null);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        new HashMap<String, Object>(),
        new ArrayList<String>(),
        global);
  }

  /** A fake Global */
  public static GlobalSettings fakeGlobal() {
    return new GlobalSettings();
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase() {
    return inMemoryDatabase("default");
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase(String name) {
    return inMemoryDatabase(name, Collections.<String, String>emptyMap());
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase(String name, Map<String, String> options) {
    return Scala.asJava(play.api.test.Helpers.inMemoryDatabase(name, Scala.asScala(options)));
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        new ArrayList<String>(),
        null);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration, GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        new ArrayList<String>(),
        global);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration, List<String> additionalPlugin) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        additionalPlugin,
        null);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration,
      List<String> additionalPlugin,
      GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        additionalPlugin,
        global);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration,
      List<String> additionalPlugins,
      List<String> withoutPlugins) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        additionalPlugins,
        withoutPlugins,
        null);
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration,
      List<String> additionalPlugins,
      List<String> withoutPlugins,
      GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        additionalConfiguration,
        additionalPlugins,
        withoutPlugins,
        global);
  }

  /** Extracts the Status code of this Result value. */
  public static int status(Result result) {
    return result.toScala().header().status();
  }

  /** Extracts the Location header of this Result value if this Result is a Redirect. */
  public static String redirectLocation(Result result) {
    return header(LOCATION, result);
  }

  /** Extracts the Flash values of this Result value. */
  public static Flash flash(Result result) {
    return JavaResultExtractor.getFlash(result);
  }

  /** Extracts the Session of this Result value. */
  public static Session session(Result result) {
    return JavaResultExtractor.getSession(result);
  }

  /** Extracts a Cookie value from this Result value */
  public static Cookie cookie(String name, Result result) {
    return JavaResultExtractor.getCookies(result).get(name);
  }

  /** Extracts the Cookies (an iterator) from this result value. */
  public static Cookies cookies(Result result) {
    return play.core.j.JavaResultExtractor.getCookies(result);
  }

  /** Extracts an Header value of this Result value. */
  public static String header(String header, Result result) {
    return JavaResultExtractor.getHeaders(result).get(header);
  }

  /** Extracts all Headers of this Result value. */
  public static Map<String, String> headers(Result result) {
    return JavaResultExtractor.getHeaders(result);
  }

  /** Extracts the Content-Type of this Content value. */
  public static String contentType(Content content) {
    return content.contentType();
  }

  /** Extracts the Content-Type of this Result value. */
  public static String contentType(Result result) {
    String h = header(CONTENT_TYPE, result);
    if (h == null) return null;
    if (h.contains(";")) {
      return h.substring(0, h.indexOf(";")).trim();
    } else {
      return h.trim();
    }
  }

  /** Extracts the Charset of this Result value. */
  public static String charset(Result result) {
    String h = header(CONTENT_TYPE, result);
    if (h == null) return null;
    if (h.contains("; charset=")) {
      return h.substring(h.indexOf("; charset=") + 10, h.length()).trim();
    } else {
      return null;
    }
  }

  /** Extracts the content as bytes. */
  public static byte[] contentAsBytes(Result result) {
    return contentAsBytes(result, DEFAULT_TIMEOUT);
  }

  public static byte[] contentAsBytes(Result result, long timeout) {
    return JavaResultExtractor.getBody(result, timeout);
  }

  /** Extracts the content as bytes. */
  public static byte[] contentAsBytes(Content content) {
    return content.body().getBytes();
  }

  /** Extracts the content as String. */
  public static String contentAsString(Content content) {
    return content.body();
  }

  /** Extracts the content as String. */
  public static String contentAsString(Result result) {
    return contentAsString(result, DEFAULT_TIMEOUT);
  }

  public static String contentAsString(Result result, long timeout) {
    try {
      String charset = charset(result);
      if (charset == null) {
        charset = "utf-8";
      }
      return new String(contentAsBytes(result, timeout), charset);
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  @SuppressWarnings(value = "unchecked")
  public static Result routeAndCall(FakeRequest fakeRequest, long timeout) {
    try {
      return routeAndCall(
          (Class<? extends Routes>) FakeRequest.class.getClassLoader().loadClass("Routes"),
          fakeRequest,
          timeout);
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  public static Result routeAndCall(
      Class<? extends Routes> router, FakeRequest fakeRequest, long timeout) {
    try {
      Routes routes =
          (Routes)
              router
                  .getClassLoader()
                  .loadClass(router.getName() + "$")
                  .getDeclaredField("MODULE$")
                  .get(null);
      if (routes.routes().isDefinedAt(fakeRequest.getWrappedRequest())) {
        return invokeHandler(
            routes.routes().apply(fakeRequest.getWrappedRequest()), fakeRequest, timeout);
      } else {
        return null;
      }
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  public static Result route(FakeRequest fakeRequest) {
    return route(fakeRequest, DEFAULT_TIMEOUT);
  }

  public static Result route(FakeRequest fakeRequest, long timeout) {
    return route(play.Play.application(), fakeRequest, timeout);
  }

  public static Result route(Application app, FakeRequest fakeRequest) {
    return route(app, fakeRequest, DEFAULT_TIMEOUT);
  }

  public static Result route(Application app, FakeRequest fakeRequest, long timeout) {
    final scala.Option<scala.concurrent.Future<play.api.mvc.Result>> opt =
        play.api.test.Helpers.jRoute(app.getWrappedApplication(), fakeRequest.fake);
    return wrapScalaResult(Scala.orNull(opt), timeout);
  }

  public static Result route(Application app, FakeRequest fakeRequest, byte[] body) {
    return route(app, fakeRequest, body, DEFAULT_TIMEOUT);
  }

  public static Result route(Application app, FakeRequest fakeRequest, byte[] body, long timeout) {
    return wrapScalaResult(
        Scala.orNull(
            play.api.test.Helpers.jRoute(
                app.getWrappedApplication(), fakeRequest.getWrappedRequest(), body)),
        timeout);
  }

  public static Result route(FakeRequest fakeRequest, byte[] body) {
    return route(fakeRequest, body, DEFAULT_TIMEOUT);
  }

  public static Result route(FakeRequest fakeRequest, byte[] body, long timeout) {
    return route(play.Play.application(), fakeRequest, body, timeout);
  }

  /** Starts a new application. */
  public static void start(FakeApplication fakeApplication) {

    play.api.Play.start(fakeApplication.getWrappedApplication());
  }

  /** Stops an application. */
  public static void stop(FakeApplication fakeApplication) {
    play.api.Play.stop();
  }

  /** Executes a block of code in a running application. */
  public static void running(FakeApplication fakeApplication, final Runnable block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      try {
        start(fakeApplication);
        block.run();
      } finally {
        stop(fakeApplication);
      }
    }
  }

  /**
   * Creates a new Test server listening on port defined by configuration setting "testserver.port"
   * (defaults to 19001).
   */
  public static TestServer testServer() {
    return testServer(play.api.test.Helpers.testServerPort());
  }

  /**
   * Creates a new Test server listening on port defined by configuration setting "testserver.port"
   * (defaults to 19001) and using the given FakeApplication.
   */
  public static TestServer testServer(FakeApplication app) {
    return testServer(play.api.test.Helpers.testServerPort(), app);
  }

  /** Creates a new Test server. */
  public static TestServer testServer(int port) {
    return new TestServer(port, fakeApplication());
  }

  /** Creates a new Test server. */
  public static TestServer testServer(int port, FakeApplication app) {
    return new TestServer(port, app);
  }

  /** Starts a Test server. */
  public static void start(TestServer server) {
    server.start();
  }

  /** Stops a Test server. */
  public static void stop(TestServer server) {
    server.stop();
  }

  /** Executes a block of code in a running server. */
  public static void running(TestServer server, final Runnable block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      try {
        start(server);
        block.run();
      } finally {
        stop(server);
      }
    }
  }

  /** Executes a block of code in a running server, with a test browser. */
  public static void running(
      TestServer server, Class<? extends WebDriver> webDriver, final Callback<TestBrowser> block) {
    running(server, play.api.test.WebDriverFactory.apply(webDriver), block);
  }

  /** Executes a block of code in a running server, with a test browser. */
  public static void running(
      TestServer server, WebDriver webDriver, final Callback<TestBrowser> block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      TestBrowser browser = null;
      TestServer startedServer = null;
      try {
        start(server);
        startedServer = server;
        browser = testBrowser(webDriver);
        block.invoke(browser);
      } catch (Error e) {
        throw e;
      } catch (RuntimeException re) {
        throw re;
      } catch (Throwable t) {
        throw new RuntimeException(t);
      } finally {
        if (browser != null) {
          browser.quit();
        }
        if (startedServer != null) {
          stop(startedServer);
        }
      }
    }
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser() {
    return testBrowser(HTMLUNIT);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(int port) {
    return testBrowser(HTMLUNIT, port);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(Class<? extends WebDriver> webDriver) {
    return testBrowser(webDriver, Helpers$.MODULE$.testServerPort());
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(Class<? extends WebDriver> webDriver, int port) {
    try {
      return new TestBrowser(webDriver, "http://localhost:" + port);
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(WebDriver of, int port) {
    return new TestBrowser(of, "http://localhost:" + port);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(WebDriver of) {
    return testBrowser(of, Helpers$.MODULE$.testServerPort());
  }
}
Пример #15
0
 /**
  * Determines the <code>Long</code> value of the system property whose name was specified in the
  * constructor.
  *
  * <p>If there is no property of the specified name, or if the property does not have the correct
  * numeric format, then a <code>Long</code> object representing the default value that was
  * specified in the constructor is returned, or <code>null</code> if no default value was
  * specified.
  *
  * @return the <code>Long</code> value of the property.
  */
 public Long run() {
   Long value = Long.getLong(theProp);
   if ((value == null) && defaultSet) return new Long(defaultVal);
   return value;
 }
Пример #16
0
/**
 * A helper thread which does some computation in the background and displays incremental results
 * using JavaScript. This is appropriate when the computation may be slow—too slow to do
 * synchronously within the initial HTTP request—and has no side effects (since it may be canceled
 * if the user simply browses to another page while it is running).
 *
 * <ol>
 *   <li>Write a {@code <script>} section defining {@code function display(data)}. (Call {@code
 *       ts_refresh($('someid'))} if using a {@code sortable} table.)
 *   <li>Use {@code <l:progressiveRendering handler="${it.something()}" callback="display"/>} from
 *       your Jelly page to display a progress bar and initialize JavaScript infrastructure. (The
 *       callback attribute can take arbitrary JavaScript expression to be evaluated in the browser
 *       so long as it produces a function object.)
 *   <li>Implement {@code something()} to create an instance of your subclass of {@code
 *       ProgressiveRendering}.
 *   <li>Perform your work in {@link #compute}.
 *   <li>Periodically check {@link #canceled}.
 *   <li>As results become available, call {@link #progress}.
 *   <li>Make {@link #data} produce whatever JSON you want to send to the page to be displayed.
 * </ol>
 *
 * {@code ui-samples-plugin} demonstrates all this.
 *
 * @since 1.484
 */
public abstract class ProgressiveRendering {

  private static final Logger LOG = Logger.getLogger(ProgressiveRendering.class.getName());
  /**
   * May be set to a number of milliseconds to sleep in {@link #canceled}, useful for watching what
   * are normally fast computations.
   */
  private static final Long DEBUG_SLEEP =
      Long.getLong("jenkins.util.ProgressiveRendering.DEBUG_SLEEP");

  private static final int CANCELED = -1;
  private static final int ERROR = -2;

  private double status = 0;
  private long lastNewsTime;
  /** just for logging */
  private final String uri;

  private long start;

  /** Constructor for subclasses. */
  protected ProgressiveRendering() {
    StaplerRequest currentRequest = Stapler.getCurrentRequest();
    uri = currentRequest != null ? currentRequest.getRequestURI() : "?";
  }

  /** For internal use. */
  @SuppressWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
  public final void start() {
    final SecurityContext securityContext = SecurityContextHolder.getContext();
    executorService()
        .submit(
            new Runnable() {
              public void run() {
                lastNewsTime = start = System.currentTimeMillis();
                SecurityContext orig = SecurityContextHolder.getContext();
                try {
                  SecurityContextHolder.setContext(securityContext);
                  compute();
                  if (status != CANCELED && status != ERROR) {
                    status = 1;
                  }
                } catch (Exception x) {
                  LOG.log(Level.WARNING, "failed to compute " + uri, x);
                  status = ERROR;
                } finally {
                  SecurityContextHolder.setContext(orig);
                  LOG.log(
                      Level.FINE,
                      "{0} finished in {1}msec with status {2}",
                      new Object[] {uri, System.currentTimeMillis() - start, status});
                }
              }
            });
  }

  /**
   * Actually do the work.
   *
   * <p>The security context will be that in effect when the web request was made.
   *
   * @throws Exception whenever you like; the progress bar will indicate that an error occurred but
   *     details go to the log only
   */
  protected abstract void compute() throws Exception;

  /**
   * Provide current data to the web page for display.
   *
   * <p>While this could be an aggregate of everything that has been computed so far, more likely
   * you want to supply only that data that is new since the last call (maybe just {@code {}} or
   * {@code []}), so that the page can incrementally update bits of HTML rather than refreshing
   * everything.
   *
   * <p>You may want to make your implementation {@code synchronized}, so that it can track what was
   * sent on a previous call, in which case any code running in {@link #compute} which modifies
   * these fields should also <em>temporarily</em> be synchronized on the same monitor such as
   * {@code this}.
   *
   * @return any JSON data you like
   */
  protected abstract @Nonnull JSON data();

  /**
   * Indicate what portion of the work has been done. (Once {@link #compute} returns, the work is
   * assumed to be complete regardless of this method.)
   *
   * @param completedFraction estimated portion of work now done, from 0 (~ 0%) to 1 (~ 100%)
   */
  protected final void progress(double completedFraction) {
    if (completedFraction < 0 || completedFraction > 1) {
      throw new IllegalArgumentException(completedFraction + " should be in [0,1]");
    }
    status = completedFraction;
  }

  /**
   * Checks whether the task has been canceled. If the rendering page fails to send a heartbeat
   * within a certain amount of time, the user is assumed to have moved on. Therefore {@link
   * #compute} should periodically say: {@code if (canceled()) return;}
   *
   * @return true if user seems to have abandoned us, false if we should still run
   */
  protected final boolean canceled() {
    if (DEBUG_SLEEP != null) {
      try {
        Thread.sleep(DEBUG_SLEEP);
      } catch (InterruptedException x) {
      }
    }
    if (status == ERROR) {
      return true; // recent call to data() failed
    }
    long now = System.currentTimeMillis();
    long elapsed = now - lastNewsTime;
    if (elapsed > timeout()) {
      status = CANCELED;
      LOG.log(
          Level.FINE,
          "{0} canceled due to {1}msec inactivity after {2}msec",
          new Object[] {uri, elapsed, now - start});
      return true;
    } else {
      return false;
    }
  }

  /** For internal use. */
  @JavaScriptMethod
  public final JSONObject news() {
    lastNewsTime = System.currentTimeMillis();
    JSONObject r = new JSONObject();
    try {
      r.put("data", data());
    } catch (RuntimeException x) {
      LOG.log(Level.WARNING, "failed to update " + uri, x);
      status = ERROR;
    }
    r.put(
        "status",
        status == 1
            ? "done"
            : status == CANCELED ? "canceled" : status == ERROR ? "error" : status);
    lastNewsTime = System.currentTimeMillis();
    LOG.log(Level.FINER, "news from {0}", uri);
    return r;
  }

  /**
   * May be overridden to provide an alternate executor service.
   *
   * @return by default, {@link Timer#get}
   */
  protected ExecutorService executorService() {
    return Timer.get();
  }

  /**
   * May be overridden to control the inactivity timeout. If no request from the browser is received
   * within this time, the next call to {@link #canceled} will be true.
   *
   * @return timeout in milliseconds; by default, 15000 (~ 15 seconds)
   */
  protected long timeout() {
    return 15000;
  }
}
Пример #17
0
/** Implementation of AsyncContext interface that holds the state of request-response cycle. */
public class HttpChannelState {
  private static final Logger LOG = Log.getLogger(HttpChannelState.class);

  private static final long DEFAULT_TIMEOUT =
      Long.getLong("org.eclipse.jetty.server.HttpChannelState.DEFAULT_TIMEOUT", 30000L);

  /** The state of the HttpChannel,used to control the overall lifecycle. */
  public enum State {
    IDLE, // Idle request
    DISPATCHED, // Request dispatched to filter/servlet
    THROWN, // Exception thrown while DISPATCHED
    ASYNC_WAIT, // Suspended and waiting
    ASYNC_WOKEN, // Dispatch to handle from ASYNC_WAIT
    ASYNC_IO, // Dispatched for async IO
    COMPLETING, // Response is completable
    COMPLETED, // Response is completed
    UPGRADED // Request upgraded the connection
  }

  /** The actions to take as the channel moves from state to state. */
  public enum Action {
    DISPATCH, // handle a normal request dispatch
    ASYNC_DISPATCH, // handle an async request dispatch
    ERROR_DISPATCH, // handle a normal error
    WRITE_CALLBACK, // handle an IO write callback
    READ_CALLBACK, // handle an IO read callback
    COMPLETE, // Complete the response
    TERMINATED, // No further actions
    WAIT, // Wait for further events
  }

  /** The state of the servlet async API. */
  public enum Async {
    STARTED, // AsyncContext.startAsync() has been called
    DISPATCH, // AsyncContext.dispatch() has been called
    COMPLETE, // AsyncContext.complete() has been called
    EXPIRING, // AsyncContext timeout just happened
    EXPIRED, // AsyncContext timeout has been processed
    ERRORING, // An error just happened
    ERRORED // The error has been processed
  }

  private final boolean DEBUG = LOG.isDebugEnabled();
  private final Locker _locker = new Locker();
  private final HttpChannel _channel;

  private List<AsyncListener> _asyncListeners;
  private State _state;
  private Async _async;
  private boolean _initial;
  private boolean _asyncReadPossible;
  private boolean _asyncReadUnready;
  private boolean _asyncWrite; // TODO refactor same as read
  private long _timeoutMs = DEFAULT_TIMEOUT;
  private AsyncContextEvent _event;

  protected HttpChannelState(HttpChannel channel) {
    _channel = channel;
    _state = State.IDLE;
    _async = null;
    _initial = true;
  }

  public State getState() {
    try (Locker.Lock lock = _locker.lock()) {
      return _state;
    }
  }

  public void addListener(AsyncListener listener) {
    try (Locker.Lock lock = _locker.lock()) {
      if (_asyncListeners == null) _asyncListeners = new ArrayList<>();
      _asyncListeners.add(listener);
    }
  }

  public void setTimeout(long ms) {
    try (Locker.Lock lock = _locker.lock()) {
      _timeoutMs = ms;
    }
  }

  public long getTimeout() {
    try (Locker.Lock lock = _locker.lock()) {
      return _timeoutMs;
    }
  }

  public AsyncContextEvent getAsyncContextEvent() {
    try (Locker.Lock lock = _locker.lock()) {
      return _event;
    }
  }

  @Override
  public String toString() {
    try (Locker.Lock lock = _locker.lock()) {
      return toStringLocked();
    }
  }

  public String toStringLocked() {
    return String.format(
        "%s@%x{s=%s a=%s i=%b r=%s w=%b}",
        getClass().getSimpleName(),
        hashCode(),
        _state,
        _async,
        _initial,
        _asyncReadPossible
            ? (_asyncReadUnready ? "PU" : "P!U")
            : (_asyncReadUnready ? "!PU" : "!P!U"),
        _asyncWrite);
  }

  private String getStatusStringLocked() {
    return String.format("s=%s i=%b a=%s", _state, _initial, _async);
  }

  public String getStatusString() {
    try (Locker.Lock lock = _locker.lock()) {
      return getStatusStringLocked();
    }
  }

  /** @return Next handling of the request should proceed */
  protected Action handling() {
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("handling {}", toStringLocked());

      switch (_state) {
        case IDLE:
          _initial = true;
          _state = State.DISPATCHED;
          return Action.DISPATCH;

        case COMPLETING:
          return Action.COMPLETE;

        case COMPLETED:
          return Action.TERMINATED;

        case ASYNC_WOKEN:
          if (_asyncReadPossible) {
            _state = State.ASYNC_IO;
            _asyncReadUnready = false;
            return Action.READ_CALLBACK;
          }

          if (_asyncWrite) {
            _state = State.ASYNC_IO;
            _asyncWrite = false;
            return Action.WRITE_CALLBACK;
          }

          if (_async != null) {
            Async async = _async;
            switch (async) {
              case COMPLETE:
                _state = State.COMPLETING;
                return Action.COMPLETE;
              case DISPATCH:
                _state = State.DISPATCHED;
                _async = null;
                return Action.ASYNC_DISPATCH;
              case EXPIRED:
              case ERRORED:
                _state = State.DISPATCHED;
                _async = null;
                return Action.ERROR_DISPATCH;
              case STARTED:
              case EXPIRING:
              case ERRORING:
                return Action.WAIT;

              default:
                throw new IllegalStateException(getStatusStringLocked());
            }
          }

          return Action.WAIT;

        case ASYNC_IO:
        case ASYNC_WAIT:
        case DISPATCHED:
        case UPGRADED:
        default:
          throw new IllegalStateException(getStatusStringLocked());
      }
    }
  }

  public void startAsync(AsyncContextEvent event) {
    final List<AsyncListener> lastAsyncListeners;

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("startAsync {}", toStringLocked());

      if (_state != State.DISPATCHED || _async != null)
        throw new IllegalStateException(this.getStatusStringLocked());

      _async = Async.STARTED;
      _event = event;
      lastAsyncListeners = _asyncListeners;
      _asyncListeners = null;
    }

    if (lastAsyncListeners != null) {
      Runnable callback =
          new Runnable() {
            @Override
            public void run() {
              for (AsyncListener listener : lastAsyncListeners) {
                try {
                  listener.onStartAsync(event);
                } catch (Exception e) {
                  // TODO Async Dispatch Error
                  LOG.warn(e);
                }
              }
            }

            @Override
            public String toString() {
              return "startAsync";
            }
          };

      runInContext(event, callback);
    }
  }

  /**
   * Signal that the HttpConnection has finished handling the request. For blocking connectors,this
   * call may block if the request has been suspended (startAsync called).
   *
   * @return next actions be handled again (eg because of a resume that happened before unhandle was
   *     called)
   */
  protected Action unhandle() {
    Action action;
    AsyncContextEvent schedule_event = null;
    boolean read_interested = false;

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("unhandle {}", toStringLocked());

      switch (_state) {
        case COMPLETING:
        case COMPLETED:
          return Action.TERMINATED;

        case THROWN:
          _state = State.DISPATCHED;
          return Action.ERROR_DISPATCH;

        case DISPATCHED:
        case ASYNC_IO:
          break;

        default:
          throw new IllegalStateException(this.getStatusStringLocked());
      }

      if (_async != null) {
        _initial = false;
        switch (_async) {
          case COMPLETE:
            _state = State.COMPLETING;
            _async = null;
            action = Action.COMPLETE;
            break;

          case DISPATCH:
            _state = State.DISPATCHED;
            _async = null;
            action = Action.ASYNC_DISPATCH;
            break;

          case STARTED:
            if (_asyncReadUnready && _asyncReadPossible) {
              _state = State.ASYNC_IO;
              _asyncReadUnready = false;
              action = Action.READ_CALLBACK;
            } else if (_asyncWrite) // TODO refactor same as read
            {
              _asyncWrite = false;
              _state = State.ASYNC_IO;
              action = Action.WRITE_CALLBACK;
            } else {
              schedule_event = _event;
              read_interested = _asyncReadUnready;
              _state = State.ASYNC_WAIT;
              action = Action.WAIT;
            }
            break;

          case EXPIRING:
            // onTimeout callbacks still being called, so just WAIT
            _state = State.ASYNC_WAIT;
            action = Action.WAIT;
            break;

          case EXPIRED:
            // onTimeout handling is complete, but did not dispatch as
            // we were handling.  So do the error dispatch here
            _state = State.DISPATCHED;
            _async = null;
            action = Action.ERROR_DISPATCH;
            break;

          case ERRORED:
            _state = State.DISPATCHED;
            _async = null;
            action = Action.ERROR_DISPATCH;
            break;

          default:
            throw new IllegalStateException(this.getStatusStringLocked());
        }
      } else {
        _state = State.COMPLETING;
        action = Action.COMPLETE;
      }
    }

    if (schedule_event != null) scheduleTimeout(schedule_event);
    if (read_interested) _channel.asyncReadFillInterested();
    return action;
  }

  public void dispatch(ServletContext context, String path) {
    boolean dispatch = false;
    AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("dispatch {} -> {}", toStringLocked(), path);

      boolean started = false;
      event = _event;
      switch (_async) {
        case STARTED:
          started = true;
          break;
        case EXPIRING:
        case ERRORING:
        case ERRORED:
          break;
        default:
          throw new IllegalStateException(this.getStatusStringLocked());
      }
      _async = Async.DISPATCH;

      if (context != null) _event.setDispatchContext(context);
      if (path != null) _event.setDispatchPath(path);

      if (started) {
        switch (_state) {
          case DISPATCHED:
          case ASYNC_IO:
          case ASYNC_WOKEN:
            break;
          case ASYNC_WAIT:
            _state = State.ASYNC_WOKEN;
            dispatch = true;
            break;
          default:
            LOG.warn("async dispatched when complete {}", this);
            break;
        }
      }
    }

    cancelTimeout(event);
    if (dispatch) scheduleDispatch();
  }

  protected void onTimeout() {
    final List<AsyncListener> listeners;
    AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onTimeout {}", toStringLocked());

      if (_async != Async.STARTED) return;
      _async = Async.EXPIRING;
      event = _event;
      listeners = _asyncListeners;
    }

    final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
    if (listeners != null) {
      Runnable task =
          new Runnable() {
            @Override
            public void run() {
              for (AsyncListener listener : listeners) {
                try {
                  listener.onTimeout(event);
                } catch (Throwable x) {
                  LOG.warn(x + " while invoking onTimeout listener " + listener);
                  LOG.debug(x);
                  if (error.get() == null) error.set(x);
                  else error.get().addSuppressed(x);
                }
              }
            }

            @Override
            public String toString() {
              return "onTimeout";
            }
          };

      runInContext(event, task);
    }

    Throwable th = error.get();
    boolean dispatch = false;
    try (Locker.Lock lock = _locker.lock()) {
      switch (_async) {
        case EXPIRING:
          _async = th == null ? Async.EXPIRED : Async.ERRORING;
          break;

        case COMPLETE:
        case DISPATCH:
          if (th != null) {
            LOG.ignore(th);
            th = null;
          }
          break;

        default:
          throw new IllegalStateException();
      }

      if (_state == State.ASYNC_WAIT) {
        _state = State.ASYNC_WOKEN;
        dispatch = true;
      }
    }

    if (th != null) {
      if (LOG.isDebugEnabled()) LOG.debug("Error after async timeout {}", this, th);
      onError(th);
    }

    if (dispatch) {
      if (LOG.isDebugEnabled()) LOG.debug("Dispatch after async timeout {}", this);
      scheduleDispatch();
    }
  }

  public void complete() {

    // just like resume, except don't set _dispatched=true;
    boolean handle = false;
    AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("complete {}", toStringLocked());

      boolean started = false;
      event = _event;

      switch (_async) {
        case STARTED:
          started = true;
          break;
        case EXPIRING:
        case ERRORING:
        case ERRORED:
          break;
        case COMPLETE:
          return;
        default:
          throw new IllegalStateException(this.getStatusStringLocked());
      }
      _async = Async.COMPLETE;

      if (started && _state == State.ASYNC_WAIT) {
        handle = true;
        _state = State.ASYNC_WOKEN;
      }
    }

    cancelTimeout(event);
    if (handle) runInContext(event, _channel);
  }

  public void errorComplete() {
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("error complete {}", toStringLocked());

      _async = Async.COMPLETE;
      _event.setDispatchContext(null);
      _event.setDispatchPath(null);
    }

    cancelTimeout();
  }

  protected void onError(Throwable failure) {
    final List<AsyncListener> listeners;
    final AsyncContextEvent event;
    final Request baseRequest = _channel.getRequest();

    int code = HttpStatus.INTERNAL_SERVER_ERROR_500;
    String reason = null;
    if (failure instanceof BadMessageException) {
      BadMessageException bme = (BadMessageException) failure;
      code = bme.getCode();
      reason = bme.getReason();
    } else if (failure instanceof UnavailableException) {
      if (((UnavailableException) failure).isPermanent()) code = HttpStatus.NOT_FOUND_404;
      else code = HttpStatus.SERVICE_UNAVAILABLE_503;
    }

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onError {} {}", toStringLocked(), failure);

      // Set error on request.
      if (_event != null) {
        if (_event.getThrowable() != null)
          throw new IllegalStateException("Error already set", _event.getThrowable());
        _event.addThrowable(failure);
        _event.getSuppliedRequest().setAttribute(ERROR_STATUS_CODE, code);
        _event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION, failure);
        _event
            .getSuppliedRequest()
            .setAttribute(
                RequestDispatcher.ERROR_EXCEPTION_TYPE,
                failure == null ? null : failure.getClass());

        _event.getSuppliedRequest().setAttribute(ERROR_MESSAGE, reason != null ? reason : null);
      } else {
        Throwable error = (Throwable) baseRequest.getAttribute(ERROR_EXCEPTION);
        if (error != null) throw new IllegalStateException("Error already set", error);
        baseRequest.setAttribute(ERROR_STATUS_CODE, code);
        baseRequest.setAttribute(ERROR_EXCEPTION, failure);
        baseRequest.setAttribute(
            RequestDispatcher.ERROR_EXCEPTION_TYPE, failure == null ? null : failure.getClass());
        baseRequest.setAttribute(ERROR_MESSAGE, reason != null ? reason : null);
      }

      // Are we blocking?
      if (_async == null) {
        // Only called from within HttpChannel Handling, so much be dispatched, let's stay
        // dispatched!
        if (_state == State.DISPATCHED) {
          _state = State.THROWN;
          return;
        }
        throw new IllegalStateException(this.getStatusStringLocked());
      }

      // We are Async
      _async = Async.ERRORING;
      listeners = _asyncListeners;
      event = _event;
    }

    if (listeners != null) {
      Runnable task =
          new Runnable() {
            @Override
            public void run() {
              for (AsyncListener listener : listeners) {
                try {
                  listener.onError(event);
                } catch (Throwable x) {
                  LOG.warn(x + " while invoking onError listener " + listener);
                  LOG.debug(x);
                }
              }
            }

            @Override
            public String toString() {
              return "onError";
            }
          };
      runInContext(event, task);
    }

    boolean dispatch = false;
    try (Locker.Lock lock = _locker.lock()) {
      switch (_async) {
        case ERRORING:
          {
            // Still in this state ? The listeners did not invoke API methods
            // and the container must provide a default error dispatch.
            _async = Async.ERRORED;
            break;
          }
        case DISPATCH:
        case COMPLETE:
          {
            // The listeners called dispatch() or complete().
            break;
          }
        default:
          {
            throw new IllegalStateException(toString());
          }
      }

      if (_state == State.ASYNC_WAIT) {
        _state = State.ASYNC_WOKEN;
        dispatch = true;
      }
    }

    if (dispatch) {
      if (LOG.isDebugEnabled()) LOG.debug("Dispatch after error {}", this);
      scheduleDispatch();
    }
  }

  protected void onComplete() {
    final List<AsyncListener> aListeners;
    final AsyncContextEvent event;

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onComplete {}", toStringLocked());

      switch (_state) {
        case COMPLETING:
          aListeners = _asyncListeners;
          event = _event;
          _state = State.COMPLETED;
          _async = null;
          break;

        default:
          throw new IllegalStateException(this.getStatusStringLocked());
      }
    }

    if (event != null) {
      if (aListeners != null) {
        Runnable callback =
            new Runnable() {
              @Override
              public void run() {
                for (AsyncListener listener : aListeners) {
                  try {
                    listener.onComplete(event);
                  } catch (Exception e) {
                    LOG.warn(e + " while invoking onComplete listener " + listener);
                    LOG.debug(e);
                  }
                }
              }

              @Override
              public String toString() {
                return "onComplete";
              }
            };

        runInContext(event, callback);
      }
      event.completed();
    }
  }

  protected void recycle() {
    cancelTimeout();
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("recycle {}", toStringLocked());

      switch (_state) {
        case DISPATCHED:
        case ASYNC_IO:
          throw new IllegalStateException(getStatusStringLocked());
        case UPGRADED:
          return;
        default:
          break;
      }
      _asyncListeners = null;
      _state = State.IDLE;
      _async = null;
      _initial = true;
      _asyncReadPossible = _asyncReadUnready = false;
      _asyncWrite = false;
      _timeoutMs = DEFAULT_TIMEOUT;
      _event = null;
    }
  }

  public void upgrade() {
    cancelTimeout();
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("upgrade {}", toStringLocked());

      switch (_state) {
        case IDLE:
        case COMPLETED:
          break;
        default:
          throw new IllegalStateException(getStatusStringLocked());
      }
      _asyncListeners = null;
      _state = State.UPGRADED;
      _async = null;
      _initial = true;
      _asyncReadPossible = _asyncReadUnready = false;
      _asyncWrite = false;
      _timeoutMs = DEFAULT_TIMEOUT;
      _event = null;
    }
  }

  protected void scheduleDispatch() {
    _channel.execute(_channel);
  }

  protected void scheduleTimeout(AsyncContextEvent event) {
    Scheduler scheduler = _channel.getScheduler();
    if (scheduler != null && _timeoutMs > 0)
      event.setTimeoutTask(scheduler.schedule(event, _timeoutMs, TimeUnit.MILLISECONDS));
  }

  protected void cancelTimeout() {
    final AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      event = _event;
    }
    cancelTimeout(event);
  }

  protected void cancelTimeout(AsyncContextEvent event) {
    if (event != null) event.cancelTimeoutTask();
  }

  public boolean isIdle() {
    try (Locker.Lock lock = _locker.lock()) {
      return _state == State.IDLE;
    }
  }

  public boolean isExpired() {
    try (Locker.Lock lock = _locker.lock()) {
      return _async == Async.EXPIRED;
    }
  }

  public boolean isInitial() {
    try (Locker.Lock lock = _locker.lock()) {
      return _initial;
    }
  }

  public boolean isSuspended() {
    try (Locker.Lock lock = _locker.lock()) {
      return _state == State.ASYNC_WAIT || _state == State.DISPATCHED && _async == Async.STARTED;
    }
  }

  boolean isCompleting() {
    try (Locker.Lock lock = _locker.lock()) {
      return _state == State.COMPLETING;
    }
  }

  boolean isCompleted() {
    try (Locker.Lock lock = _locker.lock()) {
      return _state == State.COMPLETED;
    }
  }

  public boolean isAsyncStarted() {
    try (Locker.Lock lock = _locker.lock()) {
      if (_state == State.DISPATCHED) return _async != null;
      return _async == Async.STARTED || _async == Async.EXPIRING;
    }
  }

  public boolean isAsync() {
    try (Locker.Lock lock = _locker.lock()) {
      return !_initial || _async != null;
    }
  }

  public Request getBaseRequest() {
    return _channel.getRequest();
  }

  public HttpChannel getHttpChannel() {
    return _channel;
  }

  public ContextHandler getContextHandler() {
    final AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      event = _event;
    }
    return getContextHandler(event);
  }

  ContextHandler getContextHandler(AsyncContextEvent event) {
    if (event != null) {
      Context context = ((Context) event.getServletContext());
      if (context != null) return context.getContextHandler();
    }
    return null;
  }

  public ServletResponse getServletResponse() {
    final AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      event = _event;
    }
    return getServletResponse(event);
  }

  public ServletResponse getServletResponse(AsyncContextEvent event) {
    if (event != null && event.getSuppliedResponse() != null) return event.getSuppliedResponse();
    return _channel.getResponse();
  }

  void runInContext(AsyncContextEvent event, Runnable runnable) {
    ContextHandler contextHandler = getContextHandler(event);
    if (contextHandler == null) runnable.run();
    else contextHandler.handle(_channel.getRequest(), runnable);
  }

  public Object getAttribute(String name) {
    return _channel.getRequest().getAttribute(name);
  }

  public void removeAttribute(String name) {
    _channel.getRequest().removeAttribute(name);
  }

  public void setAttribute(String name, Object attribute) {
    _channel.getRequest().setAttribute(name, attribute);
  }

  /* ------------------------------------------------------------ */
  /**
   * Called to signal async read isReady() has returned false. This indicates that there is no
   * content available to be consumed and that once the channel enteres the ASYNC_WAIT state it will
   * register for read interest by calling {@link HttpChannel#asyncReadFillInterested()} either from
   * this method or from a subsequent call to {@link #unhandle()}.
   */
  public void onReadUnready() {
    boolean interested = false;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onReadUnready {}", toStringLocked());

      // We were already unready, this is not a state change, so do nothing
      if (!_asyncReadUnready) {
        _asyncReadUnready = true;
        _asyncReadPossible = false; // Assumes this has been checked in isReady() with lock held
        if (_state == State.ASYNC_WAIT) interested = true;
      }
    }

    if (interested) _channel.asyncReadFillInterested();
  }

  /* ------------------------------------------------------------ */
  /**
   * Called to signal that content is now available to read. If the channel is in ASYNC_WAIT state
   * and unready (ie isReady() has returned false), then the state is changed to ASYNC_WOKEN and
   * true is returned.
   *
   * @return True IFF the channel was unready and in ASYNC_WAIT state
   */
  public boolean onReadPossible() {
    boolean woken = false;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onReadPossible {}", toStringLocked());

      _asyncReadPossible = true;
      if (_state == State.ASYNC_WAIT && _asyncReadUnready) {
        woken = true;
        _state = State.ASYNC_WOKEN;
      }
    }
    return woken;
  }

  /* ------------------------------------------------------------ */
  /**
   * Called to signal that the channel is ready for a callback. This is similar to calling {@link
   * #onReadUnready()} followed by {@link #onReadPossible()}, except that as content is already
   * available, read interest is never set.
   *
   * @return true if woken
   */
  public boolean onReadReady() {
    boolean woken = false;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onReadReady {}", toStringLocked());

      _asyncReadUnready = true;
      _asyncReadPossible = true;
      if (_state == State.ASYNC_WAIT) {
        woken = true;
        _state = State.ASYNC_WOKEN;
      }
    }
    return woken;
  }

  public boolean isReadPossible() {
    try (Locker.Lock lock = _locker.lock()) {
      return _asyncReadPossible;
    }
  }

  public boolean onWritePossible() {
    boolean handle = false;

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onWritePossible {}", toStringLocked());

      _asyncWrite = true;
      if (_state == State.ASYNC_WAIT) {
        _state = State.ASYNC_WOKEN;
        handle = true;
      }
    }

    return handle;
  }
}
 @Transactional(readOnly = false)
 @RequestMapping(
     value = "/editperson",
     method = {RequestMethod.POST, RequestMethod.GET})
 public void personsEditor(
     @RequestParam String oper,
     @RequestParam long ID,
     Person person,
     BindingResult result,
     HttpServletRequest request,
     HttpServletResponse response)
     throws IOException {
   if (result.hasErrors()) {
     response.sendError(400, result.toString());
     return;
   }
   switch (oper) {
     case "add":
       {
         Counterparty counterparty = counterpartyRepository.findOne(ID);
         if (counterparty != null) {
           counterparty.addPerson(person);
           String headIDS = request.getParameter("headID_primary_key");
           if (headIDS != null && !headIDS.isEmpty()) {
             try {
               Long headid = Long.getLong(headIDS);
               Person headPerson = personRepository.findOne(headid);
               person.setHead(headPerson);
             } catch (NumberFormatException e) {
               // do nothing
             }
           }
           personRepository.save(person);
           counterpartyRepository.save(counterparty);
           response.setStatus(200);
         } else {
           response.sendError(404, "NO COUNTERPART WITH ID " + ID + " FOUND");
         }
       }
       break;
     case "edit":
       {
         Person prsn = personRepository.findOne(person.getId());
         if (prsn != null && prsn.getVersion() <= person.getVersion()) {
           prsn.setSurname(person.getSurname());
           prsn.setFirstName(person.getFirstName());
           prsn.setMiddleName(person.getMiddleName());
           prsn.setComments(person.getComments());
           prsn.setDate_of_birth(person.getDate_of_birth());
           String headIDS = request.getParameter("headID_primary_key");
           if (headIDS != null && !headIDS.isEmpty()) {
             try {
               Long headid = Long.getLong(headIDS);
               Person headPerson = personRepository.findOne(headid);
               person.setHead(headPerson);
             } catch (NumberFormatException e) {
               // do nothing
             }
           }
           personRepository.save(prsn);
           response.setStatus(200);
         } else {
           response.sendError(404, "NO Agreement WITH ID " + person.getId() + " FOUND");
         }
       }
       break;
     case "del":
       {
         Counterparty counterparty = counterpartyRepository.findOne(ID);
         if (counterparty != null) {
           Person prsn = personRepository.findOne(person.getId());
           if (prsn != null) {
             counterparty.removePerson(prsn);
             personRepository.delete(prsn);
             counterpartyRepository.save(counterparty);
             response.setStatus(200);
           } else {
             response.sendError(404, "NO Agreement WITH ID " + person.getId() + " FOUND");
           }
         } else {
           response.sendError(404, "NO COUNTERPART WITH ID " + ID + " FOUND");
         }
       }
       break;
     default:
       response.sendError(406, "UNKNOWN OPERATION");
   }
 }
Пример #19
0
/**
 * Test suite for distributing JUnit3 tests. Simply add tests to this suite just like you would for
 * regular JUnit3 suites, and these tests will be executed in parallel on the grid. Note that if
 * there are no other grid nodes, this suite will still ensure parallel test execution within single
 * JVM.
 *
 * <p>Below is an example of distributed JUnit3 test suite:
 *
 * <pre name="code" class="java">
 * public class GridJunit3ExampleTestSuite {
 *     // Standard JUnit3 static suite method.
 *     public static TestSuite suite() {
 *         TestSuite suite = new GridJunit3TestSuite("Example Grid Test Suite");
 *
 *         // Add tests.
 *         suite.addTestSuite(TestA.class);
 *         suite.addTestSuite(TestB.class);
 *         suite.addTestSuite(TestC.class);
 *
 *         return suite;
 *     }
 * }
 * </pre>
 *
 * If you have four tests A, B, C, and D, and if you need to run A and B sequentially, then you
 * should create a nested test suite with test A and B as follows:
 *
 * <pre name="code" class="java">
 * public class GridJunit3ExampleTestSuite {
 *     // Standard JUnit3 static suite method.
 *     public static TestSuite suite() {
 *         TestSuite suite = new GridJunit3TestSuite("Example Grid Test Suite");
 *
 *         // Nested test suite to run tests A and B sequentially.
 *         TestSuite nested = new TestSuite("Example Nested Sequential Suite");
 *
 *         nested.addTestSuite(TestA.class);
 *         nested.addTestSuite(TestB.class);
 *
 *         // Add tests A and B.
 *         suite.addTest(nested);
 *
 *         // Add other tests.
 *         suite.addTestSuite(TestC.class);
 *
 *         return suite;
 *     }
 * }
 * </pre>
 *
 * <p>Note that you can also grid-enable existing JUnit3 tests using {@link
 * GridifyTest @GridifyTest} annotation which you can attach to your {@code suite()} methods of
 * existing test suite. Refer to {@link GridifyTest @GridifyTest} documentation for more
 * information.
 *
 * <p>Also note that some tests can only be executed locally mostly due to some environment issues.
 * However they still can benefit from parallel execution with other tests. GridGain supports it via
 * {@link GridJunit3LocalTestSuite} suites that can be added to {@code GridJunit3TestSuite}. Refer
 * to {@link GridJunit3LocalTestSuite} documentation for more information.
 *
 * <h1 class="header">Logging</h1>
 *
 * When running distributed JUnit, all the logging that is done to {@link System#out} or {@link
 * System#err} is preserved. GridGain will accumulate all logging that is done on remote nodes, send
 * them back to originating node and associate all log statements with their corresponding tests.
 * This way, for example, if you are running tests from and IDEA or Eclipse (or any other IDE) you
 * would still see the logs as if it was a local run. However, since remote nodes keep all log
 * statements done within a single individual test case in memory, you must make sure that enough
 * memory is allocated on every node and that individual test cases do not spit out gigabytes of log
 * statements. Also note, that logs will be sent back to originating node upon completion of every
 * test, so don't be alarmed if you don't see any log statements for a while and then all of them
 * appear at once.
 *
 * <p>GridGain achieves such log transparency via reassigning {@link System#out} or {@link
 * System#err} to internal {@link PrintStream} implementation. However, when using {@code Log4J} (or
 * any other logging framework) within your tests you must make sure that it is configured with
 * {@link ConsoleAppender} and that {@link ConsoleAppender#setFollow(boolean)} attribute is set to
 * {@code true}. Logging to files is not supported yet and is planned for next point release.
 *
 * <p>
 *
 * <h1 class="header">Test Suite Nesting</h1>
 *
 * {@code GridJunit3TestSuite} instances can be nested within each other as deep as needed. However
 * all nested distributed test suites will be treated just like regular JUnit test suites, and not
 * as distributed test suites. This approach becomes convenient when you have several distributed
 * test suites that you would like to be able to execute separately in distributed fashion, but at
 * the same time you would like to be able to execute them as a part of larger distributed suites.
 *
 * <p>
 *
 * <h1 class="header">Configuration</h1>
 *
 * To run distributed JUnit tests you need to start other instances of GridGain. You can do so by
 * running {@code GRIDGAIN_HOME/bin/ggjunit.{sh|bat}} script, which will start default
 * configuration. If configuration other than default is required, then use regular {@code
 * GRIDGAIN_HOME/bin/ggstart.{sh|bat}} script and pass your own Spring XML configuration file as a
 * parameter to the script.
 *
 * <p>You can use the following configuration parameters to configure distributed test suite
 * locally. Note that many parameters can be overridden by setting corresponding VM parameters
 * defined in {@link GridTestVmParameters} at VM startup.
 *
 * <table class="doctable">
 *   <tr>
 *     <th>GridConfiguration Method</th>
 *     <th>Default Value</th>
 *     <th>Description</th>
 *   </tr>
 *   <tr>
 *     <td>{@link #setDisabled(boolean) setDisabled(boolean)}</td>
 *     <td>{@code false}</td>
 *     <td>
 *       If {@code true} then GridGain will be turned off and suite will run locally.
 *       This value can be overridden by setting {@link GridTestVmParameters#GRIDGAIN_DISABLED} VM
 *       parameter to {@code true}. This parameter comes handy when you would like to
 *       turn off GridGain without changing the actual code.
 *     </td>
 *   </tr>
 *   <tr>
 *     <td>{@link #setConfigurationPath(String) setConfigurationPath(String)}</td>
 *     <td>{@link #DFLT_JUNIT_CONFIG DFLT_JUNIT_CONFIG}</td>
 *     <td>
 *       Optional path to GridGain Spring XML configuration file for running JUnit tests. This
 *       property can be overridden by setting {@link GridTestVmParameters#GRIDGAIN_CONFIG} VM
 *       parameter. Note that the value can be either absolute value or relative to
 *       ${GRIDGAIN_HOME} installation folder.
 *     </td>
 *   </tr>
 *   <tr>
 *     <td>{@link #setRouterClassName(String) setRouterClassName(String)}</td>
 *     <td>{@link #DFLT_JUNIT_ROUTER DFLT_JUNIT_ROUTER}</td>
 *     <td>
 *       Optional name of test router class that implements {@link GridTestRouter} interface.
 *       If not provided, then tests will be routed in round-robin fashion using default
 *       {@link GridTestRouterAdapter}. The value of this parameter can be overridden by setting
 *       {@link GridTestVmParameters#GRIDGAIN_TEST_ROUTER} VM parameter to the name of your
 *       own customer router class.
 *     </td>
 *   </tr>
 *   <tr>
 *     <td>{@link #setRouterClass(Class) setRouterClass(Class)}</td>
 *     <td>{@code null}</td>
 *     <td>
 *       Same as {@link #setRouterClassName(String) setRouterClassName(String)}, but sets the
 *       actual class instead of the name.
 *     </td>
 *   </tr>
 *   <tr>
 *     <td>{@link #setTimeout(long) setTimeout(long)}</td>
 *     <td>{@code 0} which means that tests will never timeout.</td>
 *     <td>
 *       Maximum timeout value in milliseconds after which test suite will return without
 *       waiting for the remaining tests to complete. This value can be overridden by setting
 *       {@link GridTestVmParameters#GRIDGAIN_TEST_TIMEOUT} VM parameter to the timeout value
 *       for the tests.
 *     </td>
 *   </tr>
 * </table>
 *
 * @author 2005-2011 Copyright (C) GridGain Systems, Inc.
 * @version 3.1.1c.19062011
 */
public class GridJunit3TestSuite extends TestSuite {
  /**
   * Default GridGain configuration file for JUnits (value is {@code
   * config/junit/junit-spring.xml}).
   */
  public static final String DFLT_JUNIT_CONFIG = "config/junit/junit-spring.xml";

  /**
   * Default JUnit test router (value is {@link GridTestRouterAdapter
   * GridTestRouterAdapter.class.getName()}).
   */
  public static final String DFLT_JUNIT_ROUTER = GridTestRouterAdapter.class.getName();

  /** */
  private final Collection<String> locTests = new HashSet<String>();

  /** JUnit3 JavaAssist proxy. */
  private final GridJunit3ProxyFactory factory = new GridJunit3ProxyFactory();

  /** Flag indicating whether grid was started in this suite. */
  private boolean selfStarted;

  /** Junit3 Spring configuration path. */
  private String cfgPath =
      System.getProperty(GRIDGAIN_CONFIG.name()) == null
          ? DFLT_JUNIT_CONFIG
          : System.getProperty(GRIDGAIN_CONFIG.name());

  /**
   * Check if GridGain is disabled by checking {@link GridTestVmParameters#GRIDGAIN_DISABLED} system
   * property.
   */
  private boolean isDisabled = Boolean.getBoolean(GRIDGAIN_DISABLED.name());

  /** JUnit test router class name. */
  private String routerClsName =
      System.getProperty(GRIDGAIN_TEST_ROUTER.name()) == null
          ? DFLT_JUNIT_ROUTER
          : System.getProperty(GRIDGAIN_TEST_ROUTER.name());

  /** JUnit test router class. */
  private Class<? extends GridTestRouter> routerCls;

  /**
   * Local suite in case if grid is disabled or if this is a nested suite within other distributed
   * suite.
   */
  private TestSuite copy;

  /** JUnit grid name. */
  private String gridName;

  /** Test timeout. */
  private long timeout =
      Long.getLong(GRIDGAIN_TEST_TIMEOUT.name()) == null
          ? 0
          : Long.getLong(GRIDGAIN_TEST_TIMEOUT.name());

  /** */
  private ClassLoader clsLdr;

  /** Empty test suite. */
  public GridJunit3TestSuite() {
    if (copy == null) {
      copy = new TestSuite();
    }
  }

  /** @param name Test suite name. */
  public GridJunit3TestSuite(String name) {
    super(name);

    if (copy == null) {
      copy = new TestSuite(name);
    }
  }

  /**
   * Test suite for one class.
   *
   * @param cls Class for test suite.
   */
  public GridJunit3TestSuite(Class<? extends TestCase> cls) {
    super(cls);

    if (copy == null) {
      copy = new TestSuite(cls);
    }
  }

  /**
   * Test suite for a given test class with specified test name.
   *
   * @param cls Test class.
   * @param name Test name.
   */
  public GridJunit3TestSuite(Class<? extends TestCase> cls, String name) {
    super(cls, name);

    if (copy == null) {
      copy = new TestSuite(cls, name);
    }
  }

  /**
   * Copies non-distributed test suite into distributed one.
   *
   * @param suite Test suite to copy.
   */
  public GridJunit3TestSuite(TestSuite suite) {
    super(suite.getName());

    if (copy == null) {
      copy = new TestSuite(suite.getName());
    }

    for (int i = 0; i < suite.testCount(); i++) {
      addTest(suite.testAt(i));
    }
  }

  /**
   * Empty test suite with given class loader.
   *
   * @param clsLdr Tests class loader.
   */
  public GridJunit3TestSuite(ClassLoader clsLdr) {
    this();

    assert clsLdr != null;

    this.clsLdr = clsLdr;
  }

  /**
   * @param name Test suite name.
   * @param clsLdr Tests class loader.
   */
  public GridJunit3TestSuite(String name, ClassLoader clsLdr) {
    this(name);

    assert clsLdr != null;

    this.clsLdr = clsLdr;
  }

  /**
   * Test suite for one class.
   *
   * @param cls Class for test suite.
   * @param clsLdr Tests class loader.
   */
  public GridJunit3TestSuite(Class<? extends TestCase> cls, ClassLoader clsLdr) {
    this(cls);

    assert clsLdr != null;

    this.clsLdr = clsLdr;
  }

  /**
   * Test suite for a given test class with specified test name.
   *
   * @param cls Test class.
   * @param name Test name.
   * @param clsLdr Tests class loader.
   */
  public GridJunit3TestSuite(Class<? extends TestCase> cls, String name, ClassLoader clsLdr) {
    this(cls, name);

    assert clsLdr != null;

    this.clsLdr = clsLdr;
  }

  /**
   * Copies non-distributed test suite into distributed one.
   *
   * @param suite Test suite to copy.
   * @param clsLdr Tests class loader.
   */
  public GridJunit3TestSuite(TestSuite suite, ClassLoader clsLdr) {
    this(suite);

    assert clsLdr != null;

    this.clsLdr = clsLdr;
  }

  /**
   * Sets path to GridGain configuration file. By default {@code
   * {GRIDGAIN_HOME}/config/junit/junit-spring.xml} is used.
   *
   * @param cfgPath Path to GridGain configuration file.
   */
  public void setConfigurationPath(String cfgPath) {
    this.cfgPath = cfgPath;
  }

  /**
   * Gets path to GridGain configuration file. By default {@code
   * {GRIDGAIN_HOME}/config/junit/junit-spring.xml} is used.
   *
   * @return Path to GridGain configuration file.
   */
  public String getConfigurationPath() {
    return cfgPath;
  }

  /**
   * Disables GridGain. If set to {@code true} then this suite will execute locally as if GridGain
   * was not in a picture at all.
   *
   * @param disabled If set to {@code true} then this suite will execute locally as if GridGain was
   *     not in a picture at all.
   */
  public void setDisabled(boolean disabled) {
    isDisabled = disabled;
  }

  /**
   * Gets flag indicating whether GridGain should be enabled or not. If set to {@code true} then
   * this suite will execute locally as if GridGain was not in a picture at all.
   *
   * @return Flag indicating whether GridGain should be enabled or not. If set to {@code true} then
   *     this suite will execute locally as if GridGain was not in a picture at all.
   */
  public boolean isDisabled() {
    return isDisabled;
  }

  /**
   * Sets name of class for routing JUnit tests. By default {@link #DFLT_JUNIT_ROUTER} class name is
   * used.
   *
   * @param routerClsName Junit test router class name.
   */
  public void setRouterClassName(String routerClsName) {
    this.routerClsName = routerClsName;
  }

  /**
   * Gets JUnit test router class name.
   *
   * @return JUnit test router class name.
   */
  public String getRouterClassName() {
    return routerClsName;
  }

  /**
   * Sets router class. By default {@link GridTestRouterAdapter} is used.
   *
   * @param routerCls Router class to use for test routing.
   */
  public void setRouterClass(Class<? extends GridTestRouter> routerCls) {
    this.routerCls = routerCls;
  }

  /**
   * Gets router class used for test routing.
   *
   * @return Router class used for test routing.
   */
  public Class<? extends GridTestRouter> getRouterClass() {
    return routerCls;
  }

  /**
   * Gets identical suite for local (non-distributed) execution.
   *
   * @return Local suite.
   */
  public TestSuite getLocalCopy() {
    return copy;
  }

  /** {@inheritDoc} */
  @Override
  public void setName(String name) {
    if (copy != null) {
      copy.setName(name);
    }

    super.setName(name);
  }

  /**
   * Gets timeout for running distributed test suite.
   *
   * @return Timeout for tests.
   */
  public long getTimeout() {
    return timeout;
  }

  /**
   * Sets timeout for running distributed test suite. By default, test execution does not expire.
   *
   * @param timeout Timeout for tests.
   */
  public void setTimeout(long timeout) {
    this.timeout = timeout;
  }

  /** {@inheritDoc} */
  @Override
  public Test testAt(int index) {
    return isDisabled ? copy.testAt(index) : super.testAt(index);
  }

  /** {@inheritDoc} */
  @Override
  public int testCount() {
    return isDisabled ? copy.testCount() : super.testCount();
  }

  /** {@inheritDoc} */
  @Override
  public Enumeration<Test> tests() {
    return isDisabled ? copy.tests() : super.tests();
  }

  /**
   * The added suite will be always executed locally, but in parallel with other locally or remotely
   * running tests. This comes handy for tests that cannot be distributed for some environmental
   * reasons, but still would benefit from parallel execution.
   *
   * <p>Note, that local suites will be executed on local node even if grid topology only allows
   * remote nodes.
   *
   * @param localSuite Test to execute locally in parallel with other local or distributed tests.
   */
  @SuppressWarnings({"TypeMayBeWeakened"})
  public void addTest(GridJunit3LocalTestSuite localSuite) {
    if (!locTests.contains(localSuite.getName())) {
      locTests.add(localSuite.getName());
    }

    addTest((Test) localSuite);
  }

  /**
   * Adds a test to be executed on the grid. In case of test suite, all tests inside of test suite
   * will be executed sequentially on some remote node.
   *
   * @param test Test to add.
   */
  @Override
  public void addTest(Test test) {
    if (copy == null) {
      copy = new TestSuite(getName());
    }

    // Add test to the list of local ones.
    if (test instanceof GridJunit3LocalTestSuite) {
      String testName = ((TestSuite) test).getName();

      if (!locTests.contains(testName)) {
        locTests.add(testName);
      }
    }

    if (test instanceof GridJunit3TestSuite) {
      copy.addTest(((GridJunit3TestSuite) test).copy);

      super.addTest(new GridJunit3TestSuiteProxy(((GridJunit3TestSuite) test).copy, factory));
    } else if (test instanceof GridJunit3TestSuiteProxy) {
      copy.addTest(((GridJunit3TestSuiteProxy) test).getOriginal());

      super.addTest(test);
    } else if (test instanceof GridJunit3TestCaseProxy) {
      copy.addTest(((GridJunit3TestCaseProxy) test).getGridGainJunit3OriginalTestCase());

      super.addTest(test);
    } else if (test instanceof TestSuite) {
      copy.addTest(test);

      super.addTest(new GridJunit3TestSuiteProxy((TestSuite) test, factory));
    } else {
      assert test instanceof TestCase
          : "Test must be either instance of TestSuite or TestCase: " + test;

      copy.addTest(test);

      super.addTest(factory.createProxy((TestCase) test));
    }
  }

  /**
   * Creates JUnit test router. Note that router must have a no-arg constructor.
   *
   * @return JUnit router instance.
   */
  @SuppressWarnings({"unchecked"})
  private GridTestRouter createRouter() {
    try {
      if (routerCls == null) {
        routerCls = (Class<? extends GridTestRouter>) Class.forName(routerClsName);
      } else {
        routerClsName = routerCls.getName();
      }

      return routerCls.newInstance();
    } catch (ClassNotFoundException e) {
      throw new GridRuntimeException("Failed to initialize JUnit router: " + routerClsName, e);
    } catch (IllegalAccessException e) {
      throw new GridRuntimeException("Failed to initialize JUnit router: " + routerClsName, e);
    } catch (InstantiationException e) {
      throw new GridRuntimeException("Failed to initialize JUnit router: " + routerClsName, e);
    }
  }

  /**
   * Runs all tests belonging to this test suite on the grid.
   *
   * @param result Test result collector.
   */
  @Override
  public void run(TestResult result) {
    if (isDisabled) {
      copy.run(result);
    } else {
      GridTestRouter router = createRouter();

      Grid grid = startGrid();

      try {
        List<GridTaskFuture<?>> futs = new ArrayList<GridTaskFuture<?>>(testCount());

        List<GridJunit3SerializableTest> tests =
            new ArrayList<GridJunit3SerializableTest>(testCount());

        for (int i = 0; i < testCount(); i++) {
          Test junit = testAt(i);

          GridJunit3SerializableTest test;

          if (junit instanceof TestSuite) {
            test = new GridJunit3SerializableTestSuite((TestSuite) junit);
          } else {
            assert junit instanceof TestCase
                : "Test must be either TestSuite or TestCase: " + junit;

            test = new GridJunit3SerializableTestCase((TestCase) junit);
          }

          tests.add(test);

          if (clsLdr == null) {
            clsLdr = U.detectClassLoader(junit.getClass());
          }

          futs.add(
              grid.execute(
                  new GridJunit3Task(junit.getClass(), clsLdr),
                  new GridJunit3Argument(router, test, locTests.contains(test.getName())),
                  timeout));
        }

        for (int i = 0; i < testCount(); i++) {
          GridTaskFuture<?> fut = futs.get(i);

          GridJunit3SerializableTest origTest = tests.get(i);

          try {
            GridJunit3SerializableTest resTest = (GridJunit3SerializableTest) fut.get();

            origTest.setResult(resTest);

            origTest.getTest().run(result);
          } catch (GridException e) {
            handleFail(result, origTest, e);
          }
        }
      } finally {
        stopGrid();
      }
    }
  }

  /**
   * Handles test fail.
   *
   * @param result Test result.
   * @param origTest Original JUnit test.
   * @param e Exception thrown from grid.
   */
  private void handleFail(TestResult result, GridJunit3SerializableTest origTest, Throwable e) {
    // Simulate that all tests were run.
    origTest.getTest().run(result);

    // For the tests suite we assume that all tests failed because
    // entire test suite execution failed and there is no way to get
    // broken tests.
    if (origTest.getTest() instanceof GridJunit3TestSuiteProxy) {
      TestSuite suite = (((TestSuite) origTest.getTest()));

      for (int j = 0; j < suite.testCount(); j++) {
        result.addError(suite.testAt(j), e);
      }
    } else if (origTest.getTest() instanceof GridJunit3TestCaseProxy) {
      result.addError(origTest.getTest(), e);
    }
  }

  /**
   * Starts Grid instance. Note that if grid is already started, then it will be looked up and
   * returned from this method.
   *
   * @return Started grid.
   */
  private Grid startGrid() {
    Properties props = System.getProperties();

    gridName = props.getProperty(GRIDGAIN_NAME.name());

    if (!props.containsKey(GRIDGAIN_NAME.name()) || G.state(gridName) != GridFactoryState.STARTED) {
      selfStarted = true;

      // Set class loader for the spring.
      ClassLoader curCl = Thread.currentThread().getContextClassLoader();

      // Add no-op logger to remove no-appender warning.
      Appender app = new NullAppender();

      Logger.getRootLogger().addAppender(app);

      try {
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

        Grid grid = G.start(cfgPath);

        gridName = grid.name();

        System.setProperty(GRIDGAIN_NAME.name(), grid.name());

        return grid;
      } catch (GridException e) {
        throw new GridRuntimeException("Failed to start grid: " + cfgPath, e);
      } finally {
        Logger.getRootLogger().removeAppender(app);

        Thread.currentThread().setContextClassLoader(curCl);
      }
    }

    return G.grid(gridName);
  }

  /** Stops grid only if it was started by this test suite. */
  private void stopGrid() {
    // Only stop grid if it was started here.
    if (selfStarted) {
      G.stop(gridName, true);
    }
  }
}
Пример #20
0
/** Helper functions to run tests. */
public class Helpers implements play.mvc.Http.Status, play.mvc.Http.HeaderNames {

  public static String GET = "GET";
  public static String POST = "POST";
  public static String PUT = "PUT";
  public static String DELETE = "DELETE";
  public static String HEAD = "HEAD";

  // --

  public static Class<? extends WebDriver> HTMLUNIT = HtmlUnitDriver.class;
  public static Class<? extends WebDriver> FIREFOX = FirefoxDriver.class;

  // --
  @SuppressWarnings(value = "unchecked")
  private static Result invokeHandler(
      play.api.mvc.Handler handler, Request requestBuilder, long timeout) {
    if (handler instanceof play.api.mvc.Action) {
      play.api.mvc.Action action = (play.api.mvc.Action) handler;
      return wrapScalaResult(action.apply(requestBuilder._underlyingRequest()), timeout);
    } else if (handler instanceof JavaHandler) {
      return invokeHandler(
          ((JavaHandler) handler)
              .withComponents(
                  Play.application().injector().instanceOf(JavaHandlerComponents.class)),
          requestBuilder,
          timeout);
    } else {
      throw new RuntimeException("This is not a JavaAction and can't be invoked this way.");
    }
  }

  /**
   * Default Timeout (milliseconds) for fake requests issued by these Helpers. This value is
   * determined from System property <b>test.timeout</b>. The default value is <b>30000</b> (30
   * seconds).
   */
  public static final long DEFAULT_TIMEOUT = Long.getLong("test.timeout", 30000L);

  private static Result wrapScalaResult(
      scala.concurrent.Future<play.api.mvc.Result> result, long timeout) {
    if (result == null) {
      return null;
    } else {
      final play.api.mvc.Result scalaResult = Promise.wrap(result).get(timeout);
      return scalaResult.asJava();
    }
  }

  // --

  /** Calls a Callable which invokes a Controller or some other method with a Context */
  public static <V> V invokeWithContext(RequestBuilder requestBuilder, Callable<V> callable) {
    try {
      Context.current.set(new Context(requestBuilder));
      return callable.call();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      Context.current.remove();
    }
  }

  /** Build a new GET / fake request. */
  public static RequestBuilder fakeRequest() {
    return fakeRequest("GET", "/");
  }

  /** Build a new fake request. */
  public static RequestBuilder fakeRequest(String method, String uri) {
    return new RequestBuilder().method(method).uri(uri);
  }

  /** Build a new fake request corresponding to a given route call */
  public static RequestBuilder fakeRequest(Call call) {
    return fakeRequest(call.method(), call.url());
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication() {
    return new FakeApplication(
        new java.io.File("."), Helpers.class.getClassLoader(), new HashMap<String, Object>(), null);
  }

  /**
   * Build a new fake application.
   *
   * @deprecated Use dependency injection (since 2.5.0)
   */
  @Deprecated
  public static FakeApplication fakeApplication(GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."),
        Helpers.class.getClassLoader(),
        new HashMap<String, Object>(),
        global);
  }

  /**
   * A fake Global.
   *
   * @deprecated Use dependency injection (since 2.5.0)
   */
  @Deprecated
  public static GlobalSettings fakeGlobal() {
    return new GlobalSettings();
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase() {
    return inMemoryDatabase("default");
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase(String name) {
    return inMemoryDatabase(name, Collections.<String, String>emptyMap());
  }

  /** Constructs a in-memory (h2) database configuration to add to a FakeApplication. */
  public static Map<String, String> inMemoryDatabase(String name, Map<String, String> options) {
    return Scala.asJava(play.api.test.Helpers.inMemoryDatabase(name, Scala.asScala(options)));
  }

  /** Build a new fake application. */
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration) {
    return new FakeApplication(
        new java.io.File("."), Helpers.class.getClassLoader(), additionalConfiguration);
  }

  /**
   * Build a new fake application.
   *
   * @deprecated Use the version without GlobalSettings (since 2.5.0)
   */
  @Deprecated
  public static FakeApplication fakeApplication(
      Map<String, ? extends Object> additionalConfiguration, GlobalSettings global) {
    return new FakeApplication(
        new java.io.File("."), Helpers.class.getClassLoader(), additionalConfiguration, global);
  }

  /**
   * Extracts the content as a {@link akka.util.ByteString}.
   *
   * <p>This method is only capable of extracting the content of results with strict entities. To
   * extract the content of results with streamed entities, use {@link #contentAsBytes(Result,
   * Materializer)}.
   *
   * @param result The result to extract the content from.
   * @return The content of the result as a ByteString.
   * @throws UnsupportedOperationException if the result does not have a strict entity.
   */
  public static ByteString contentAsBytes(Result result) {
    if (result.body() instanceof HttpEntity.Strict) {
      return ((HttpEntity.Strict) result.body()).data();
    } else {
      throw new UnsupportedOperationException(
          "Tried to extract body from a non strict HTTP entity without a materializer, use the version of this method that accepts a materializer instead");
    }
  }

  /**
   * Extracts the content as a {@link akka.util.ByteString}.
   *
   * @param result The result to extract the content from.
   * @param mat The materialiser to use to extract the body from the result stream.
   * @return The content of the result as a ByteString.
   */
  public static ByteString contentAsBytes(Result result, Materializer mat) {
    return contentAsBytes(result, mat, DEFAULT_TIMEOUT);
  }

  /**
   * Extracts the content as a {@link akka.util.ByteString}.
   *
   * @param result The result to extract the content from.
   * @param mat The materialiser to use to extract the body from the result stream.
   * @param timeout The amount of time, in milliseconds, to wait for the body to be produced.
   * @return The content of the result as a ByteString.
   */
  public static ByteString contentAsBytes(Result result, Materializer mat, long timeout) {
    try {
      return result
          .body()
          .consumeData(mat)
          .thenApply(Function.identity())
          .toCompletableFuture()
          .get(timeout, TimeUnit.MILLISECONDS);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /** Extracts the content as bytes. */
  public static ByteString contentAsBytes(Content content) {
    return ByteString.fromString(content.body());
  }

  /** Extracts the content as a String. */
  public static String contentAsString(Content content) {
    return content.body();
  }

  /**
   * Extracts the content as a String.
   *
   * <p>This method is only capable of extracting the content of results with strict entities. To
   * extract the content of results with streamed entities, use {@link #contentAsString(Result,
   * Materializer)}.
   *
   * @param result The result to extract the content from.
   * @return The content of the result as a String.
   * @throws UnsupportedOperationException if the result does not have a strict entity.
   */
  public static String contentAsString(Result result) {
    return contentAsBytes(result).decodeString(result.charset().orElse("utf-8"));
  }

  /**
   * Extracts the content as a String.
   *
   * @param result The result to extract the content from.
   * @param mat The materialiser to use to extract the body from the result stream.
   * @return The content of the result as a String.
   */
  public static String contentAsString(Result result, Materializer mat) {
    return contentAsBytes(result, mat, DEFAULT_TIMEOUT)
        .decodeString(result.charset().orElse("utf-8"));
  }

  /**
   * Extracts the content as a String.
   *
   * @param result The result to extract the content from.
   * @param mat The materialiser to use to extract the body from the result stream.
   * @param timeout The amount of time, in milliseconds, to wait for the body to be produced.
   * @return The content of the result as a String.
   */
  public static String contentAsString(Result result, Materializer mat, long timeout) {
    return contentAsBytes(result, mat, timeout).decodeString(result.charset().orElse("utf-8"));
  }

  @SuppressWarnings(value = "unchecked")
  public static Result routeAndCall(RequestBuilder requestBuilder, long timeout) {
    try {
      return routeAndCall(
          (Class<? extends Router>) RequestBuilder.class.getClassLoader().loadClass("Routes"),
          requestBuilder,
          timeout);
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  public static Result routeAndCall(
      Class<? extends Router> router, RequestBuilder requestBuilder, long timeout) {
    try {
      Request request = requestBuilder.build();
      Router routes =
          (Router)
              router
                  .getClassLoader()
                  .loadClass(router.getName() + "$")
                  .getDeclaredField("MODULE$")
                  .get(null);
      if (routes.routes().isDefinedAt(request._underlyingRequest())) {
        return invokeHandler(routes.routes().apply(request._underlyingRequest()), request, timeout);
      } else {
        return null;
      }
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  public static Result routeAndCall(Router router, RequestBuilder requestBuilder) {
    return routeAndCall(router, requestBuilder, DEFAULT_TIMEOUT);
  }

  public static Result routeAndCall(Router router, RequestBuilder requestBuilder, long timeout) {
    try {
      Request request = requestBuilder.build();
      if (router.routes().isDefinedAt(request._underlyingRequest())) {
        return invokeHandler(router.routes().apply(request._underlyingRequest()), request, timeout);
      } else {
        return null;
      }
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  public static Result route(Call call) {
    return route(fakeRequest(call));
  }

  public static Result route(Call call, long timeout) {
    return route(fakeRequest(call), timeout);
  }

  public static Result route(Application app, Call call) {
    return route(app, fakeRequest(call));
  }

  public static Result route(Application app, Call call, long timeout) {
    return route(app, fakeRequest(call), timeout);
  }

  public static Result route(RequestBuilder requestBuilder) {
    return route(requestBuilder, DEFAULT_TIMEOUT);
  }

  public static Result route(RequestBuilder requestBuilder, long timeout) {
    return route(play.Play.application(), requestBuilder, timeout);
  }

  public static Result route(Application app, RequestBuilder requestBuilder) {
    return route(app, requestBuilder, DEFAULT_TIMEOUT);
  }

  @SuppressWarnings("unchecked")
  public static Result route(Application app, RequestBuilder requestBuilder, long timeout) {
    final scala.Option<scala.concurrent.Future<play.api.mvc.Result>> opt =
        play.api.test.Helpers.jRoute(
            app.getWrappedApplication(),
            requestBuilder.build()._underlyingRequest(),
            requestBuilder.body());
    return wrapScalaResult(Scala.orNull(opt), timeout);
  }

  /** Starts a new application. */
  public static void start(Application application) {
    play.api.Play.start(application.getWrappedApplication());
  }

  /** Stops an application. */
  public static void stop(Application application) {
    play.api.Play.stop(application.getWrappedApplication());
  }

  /** Executes a block of code in a running application. */
  public static void running(Application application, final Runnable block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      try {
        start(application);
        block.run();
      } finally {
        stop(application);
      }
    }
  }

  /**
   * Creates a new Test server listening on port defined by configuration setting "testserver.port"
   * (defaults to 19001).
   */
  public static TestServer testServer() {
    return testServer(play.api.test.Helpers.testServerPort());
  }

  /**
   * Creates a new Test server listening on port defined by configuration setting "testserver.port"
   * (defaults to 19001) and using the given FakeApplication.
   */
  public static TestServer testServer(Application app) {
    return testServer(play.api.test.Helpers.testServerPort(), app);
  }

  /** Creates a new Test server. */
  public static TestServer testServer(int port) {
    return new TestServer(port, fakeApplication());
  }

  /** Creates a new Test server. */
  public static TestServer testServer(int port, Application app) {
    return new TestServer(port, app);
  }

  /** Starts a Test server. */
  public static void start(TestServer server) {
    server.start();
  }

  /** Stops a Test server. */
  public static void stop(TestServer server) {
    server.stop();
  }

  /** Executes a block of code in a running server. */
  public static void running(TestServer server, final Runnable block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      try {
        start(server);
        block.run();
      } finally {
        stop(server);
      }
    }
  }

  /** Executes a block of code in a running server, with a test browser. */
  public static void running(
      TestServer server, Class<? extends WebDriver> webDriver, final Consumer<TestBrowser> block) {
    running(server, play.api.test.WebDriverFactory.apply(webDriver), block);
  }

  /** Executes a block of code in a running server, with a test browser. */
  public static void running(
      TestServer server, WebDriver webDriver, final Consumer<TestBrowser> block) {
    synchronized (PlayRunners$.MODULE$.mutex()) {
      TestBrowser browser = null;
      TestServer startedServer = null;
      try {
        start(server);
        startedServer = server;
        browser = testBrowser(webDriver, server.port());
        block.accept(browser);
      } finally {
        if (browser != null) {
          browser.quit();
        }
        if (startedServer != null) {
          stop(startedServer);
        }
      }
    }
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser() {
    return testBrowser(HTMLUNIT);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(int port) {
    return testBrowser(HTMLUNIT, port);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(Class<? extends WebDriver> webDriver) {
    return testBrowser(webDriver, Helpers$.MODULE$.testServerPort());
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(Class<? extends WebDriver> webDriver, int port) {
    try {
      return new TestBrowser(webDriver, "http://localhost:" + port);
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(WebDriver of, int port) {
    return new TestBrowser(of, "http://localhost:" + port);
  }

  /** Creates a Test Browser. */
  public static TestBrowser testBrowser(WebDriver of) {
    return testBrowser(of, Helpers$.MODULE$.testServerPort());
  }
}
Пример #21
0
/**
 * Holds strong references to a set of remote objects, or live remote references to remote objects,
 * after they have been marshalled (as remote references) as parts of the arguments or the result of
 * a remote invocation. The purpose is to prevent remote objects or live remote references that
 * might otherwise be determined to be unreachable in this VM from being locally garbage collected
 * before the receiver has had an opportunity to register the unmarshalled remote references for
 * DGC.
 *
 * <p>The references are held strongly until an acknowledgment has been received that the receiver
 * has had an opportunity to process the remote references or until a timeout has expired. For
 * remote references sent as parts of the arguments of a remote invocation, the acknowledgment is
 * the beginning of the response indicating completion of the remote invocation. For remote
 * references sent as parts of the result of a remote invocation, a UID is included as part of the
 * result, and the acknowledgment is a transport-level "DGCAck" message containing that UID.
 *
 * @author Ann Wollrath
 * @author Peter Jones
 */
public class DGCAckHandler {

  /** timeout for holding references without receiving an acknowledgment */
  private static final long dgcAckTimeout = // default 5 minutes
      AccessController.doPrivileged(
          (PrivilegedAction<Long>) () -> Long.getLong("sun.rmi.dgc.ackTimeout", 300000));

  /** thread pool for scheduling delayed tasks */
  private static final ScheduledExecutorService scheduler =
      AccessController.doPrivileged(new RuntimeUtil.GetInstanceAction()).getScheduler();

  /** table mapping ack ID to handler */
  private static final Map<UID, DGCAckHandler> idTable =
      Collections.synchronizedMap(new HashMap<UID, DGCAckHandler>());

  private final UID id;
  private List<Object> objList = new ArrayList<>(); // null if released
  private Future<?> task = null;

  /**
   * Creates a new DGCAckHandler, associated with the specified UID if the argument is not null.
   *
   * <p>References added to this DGCAckHandler will be held strongly until its "release" method is
   * invoked or (after the "startTimer" method has been invoked) the timeout has expired. If the
   * argument is not null, then invoking the static "received" method with the specified UID is
   * equivalent to invoking this instance's "release" method.
   */
  DGCAckHandler(UID id) {
    this.id = id;
    if (id != null) {
      assert !idTable.containsKey(id);
      idTable.put(id, this);
    }
  }

  /** Adds the specified reference to this DGCAckHandler. */
  synchronized void add(Object obj) {
    if (objList != null) {
      objList.add(obj);
    }
  }

  /**
   * Starts the timer for this DGCAckHandler. After the timeout has expired, the references are
   * released even if the acknowledgment has not been received.
   */
  synchronized void startTimer() {
    if (objList != null && task == null) {
      task =
          scheduler.schedule(
              new Runnable() {
                public void run() {
                  if (id != null) {
                    idTable.remove(id);
                  }
                  release();
                }
              },
              dgcAckTimeout,
              TimeUnit.MILLISECONDS);
    }
  }

  /** Releases the references held by this DGCAckHandler. */
  synchronized void release() {
    if (task != null) {
      task.cancel(false);
      task = null;
    }
    objList = null;
  }

  /** Causes the DGCAckHandler associated with the specified UID to release its references. */
  public static void received(UID id) {
    DGCAckHandler h = idTable.remove(id);
    if (h != null) {
      h.release();
    }
  }
}
Пример #22
0
/**
 * PoliciesCache retains PolicyDocument objects for inserted Files, and reloads them if file
 * modification time changes.
 *
 * @author Greg Schueler <a href="mailto:[email protected]">[email protected]</a>
 */
public class PoliciesCache implements Iterable<PolicyCollection> {
  static final long DIR_LIST_CHECK_DELAY =
      Long.getLong(PoliciesCache.class.getName() + ".DirListCheckDelay", 60000);
  static final long FILE_CHECK_DELAY =
      Long.getLong(PoliciesCache.class.getName() + ".FileCheckDelay", 60000);
  private static final Logger logger = Logger.getLogger(PoliciesCache.class);

  static final FilenameFilter filenameFilter =
      new FilenameFilter() {
        public boolean accept(File dir, String name) {
          return name.endsWith(".aclpolicy");
        }
      };

  private Set<File> warned = new HashSet<File>();
  private Map<File, CacheItem> cache = new HashMap<File, CacheItem>();
  private DocumentBuilder builder;
  private File rootDir;

  public PoliciesCache(File rootDir) throws ParserConfigurationException {
    this.rootDir = rootDir;
    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
    domFactory.setNamespaceAware(true);
    builder = domFactory.newDocumentBuilder();
    builder.setErrorHandler(null);
  }

  private static class CacheItem {
    PolicyCollection policyCollection;
    Long cacheTime;
    Long modTime;

    private CacheItem(PolicyCollection policyCollection, Long modTime) {
      this.policyCollection = policyCollection;
      this.modTime = modTime;
      this.cacheTime = System.currentTimeMillis();
    }

    public void touch(Long time) {
      this.cacheTime = time;
    }
  }

  long lastDirListCheckTime = 0;
  private File[] lastDirList;

  private File[] listDirFiles() {
    if (System.currentTimeMillis() - lastDirListCheckTime > DIR_LIST_CHECK_DELAY) {
      doListDir();
    }
    return lastDirList;
  }

  private void doListDir() {
    lastDirList = rootDir.listFiles(filenameFilter);
    lastDirListCheckTime = System.currentTimeMillis();
  }

  public synchronized void add(final File file) throws PoliciesParseException {
    getDocument(file);
  }

  private PolicyCollection createEntry(final File file) throws PoliciesParseException {
    try {
      return new YamlPolicyCollection(file);
    } catch (ParserException e1) {
      throw new PoliciesParseException("YAML syntax error: " + e1.toString(), e1);
    } catch (Exception e1) {
      throw new PoliciesParseException(e1);
    }
  }

  public synchronized PolicyCollection getDocument(final File file) throws PoliciesParseException {
    //        cacheTotal++;
    CacheItem entry = cache.get(file);

    long checkTime = System.currentTimeMillis();
    if (null == entry || ((checkTime - entry.cacheTime) > FILE_CHECK_DELAY)) {
      final long lastmod = file.lastModified();
      if (null == entry || lastmod > entry.modTime) {
        if (!file.exists()) {
          CacheItem remove = cache.remove(file);
          entry = null;
          //                        cacheRemove++;
        } else {
          //                        cacheMiss++;
          PolicyCollection entry1 = createEntry(file);
          if (null != entry1) {
            entry = new CacheItem(entry1, lastmod);
            cache.put(file, entry);
          } else {
            cache.remove(file);
            entry = null;
          }
        }
      } else {
        //                cacheUnmodifiedHit++;
        entry.touch(checkTime);
      }
    } else {
      //            cacheHit++;
    }
    return null != entry ? entry.policyCollection : null;
  }

  public Iterator<PolicyCollection> iterator() {
    final File[] files = listDirFiles();
    return new cacheIterator(
        null != files ? Arrays.asList(files).iterator() : new ArrayList<File>().iterator());
  }

  private Map<File, Long> cooldownset = Collections.synchronizedMap(new HashMap<File, Long>());
  /**
   * Iterator over the PoliciesDocuments for the cache's files. It skips files that cannot be
   * loaded.
   */
  private class cacheIterator implements Iterator<PolicyCollection> {
    Iterator<File> intIter;
    private File nextFile;
    private PolicyCollection nextDocument;

    public cacheIterator(final Iterator<File> intIter) {
      this.intIter = intIter;
      nextFile = this.intIter.hasNext() ? this.intIter.next() : null;
      loadNextDocument();
    }

    private void loadNextDocument() {
      while (hasNextFile() && null == nextDocument) {
        File nextFile2 = getNextFile();
        Long aLong = cooldownset.get(nextFile2);
        if (null != aLong && nextFile2.lastModified() == aLong.longValue()) {
          logger.debug(
              "Skip parsing of: " + nextFile2 + ". Reason: parse error cooldown until modified");
          continue;
        } else if (null != aLong) {
          // clear
          cooldownset.remove(nextFile2);
        }
        try {
          nextDocument = getDocument(nextFile2);
        } catch (PoliciesParseException e) {
          logger.error(
              "ERROR unable to parse aclpolicy: " + nextFile2 + ". Reason: " + e.getMessage());
          logger.debug(
              "ERROR unable to parse aclpolicy: " + nextFile2 + ". Reason: " + e.getMessage(), e);
          cache.remove(nextFile2);
          cooldownset.put(nextFile2, nextFile2.lastModified());
        }
      }
    }

    private File getNextFile() {
      File next = nextFile;
      nextFile = intIter.hasNext() ? intIter.next() : null;
      return next;
    }

    private PolicyCollection getNextDocument() {
      PolicyCollection doc = nextDocument;
      nextDocument = null;
      loadNextDocument();
      return doc;
    }

    public boolean hasNextFile() {
      return null != nextFile;
    }

    public boolean hasNext() {
      return null != nextDocument;
    }

    public PolicyCollection next() {
      return getNextDocument();
    }

    public void remove() {}
  }
}
Пример #23
0
/**
 * @author Filip Hanik
 * @version 1.0
 */
public class FairnessTest extends DefaultTestCase {
  public FairnessTest(String name) {
    super(name);
  }

  protected boolean run = true;
  protected long sleep = Long.getLong("sleep", 10).longValue();
  protected long complete = Long.getLong("complete", 20000).longValue();
  protected boolean printthread = Boolean.getBoolean("printthread");
  CountDownLatch latch = null;

  protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
    long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
    long maxwait = 0, minwait = Long.MAX_VALUE, totalwait = 0;
    for (int i = 0; i < threads.length; i++) {
      TestThread t = threads[i];
      totalfetch += t.nroffetch;
      totalwait += t.totalwait;
      maxwait = Math.max(maxwait, t.maxwait);
      minwait = Math.min(minwait, t.minwait);
      minfetch = Math.min(minfetch, t.nroffetch);
      maxfetch = Math.max(maxfetch, t.nroffetch);
      if (FairnessTest.this.printthread)
        System.out.println(
            t.getName()
                + " : Nr-of-fetch:"
                + t.nroffetch
                + " Max fetch Time:"
                + t.maxwait / 1000000f
                + "ms. :Max close time:"
                + t.cmax / 1000000f
                + "ms.");
    }
    System.out.println(
        "["
            + name
            + "] Max fetch:"
            + (maxfetch)
            + " Min fetch:"
            + (minfetch)
            + " Average fetch:"
            + (((float) totalfetch)) / (float) threads.length);
    System.out.println(
        "["
            + name
            + "] Max wait:"
            + maxwait / 1000000f
            + "ms. Min wait:"
            + minwait / 1000000f
            + "ms. Average wait:"
            + (((((float) totalwait)) / (float) totalfetch) / 1000000f)
            + " ms.");
    System.out.println("[" + name + "] Max active:" + active + " Expected Active:" + expected);
  }

  public void testDBCPThreads20Connections10() throws Exception {
    System.out.println("[testDBCPThreads20Connections10] Starting fairness - DBCP");
    init();
    this.datasource.getPoolProperties().setMaxActive(10);
    this.threadcount = 20;
    this.transferProperties();
    this.tDatasource.getConnection().close();
    latch = new CountDownLatch(threadcount);
    long start = System.currentTimeMillis();
    TestThread[] threads = new TestThread[threadcount];
    for (int i = 0; i < threadcount; i++) {
      threads[i] = new TestThread();
      threads[i].setName("tomcat-dbcp-" + i);
      threads[i].d = this.tDatasource;
    }
    for (int i = 0; i < threadcount; i++) {
      threads[i].start();
    }
    if (!latch.await(complete + 1000, TimeUnit.MILLISECONDS)) {
      System.out.println("Latch timed out.");
    }
    this.run = false;
    long delta = System.currentTimeMillis() - start;
    printThreadResults(
        threads, "testDBCPThreads20Connections10", this.tDatasource.getNumActive(), 10);
    System.out.println("Test completed in: " + delta + "ms.");
    tearDown();
  }

  public void testPoolThreads20Connections10() throws Exception {
    System.out.println(
        "[testPoolThreads20Connections10] Starting fairness - Tomcat JDBC - Non Fair");
    init();
    this.datasource.getPoolProperties().setMaxActive(10);
    this.datasource.getPoolProperties().setFairQueue(false);
    this.threadcount = 20;
    this.transferProperties();
    this.datasource.getConnection().close();
    latch = new CountDownLatch(threadcount);
    long start = System.currentTimeMillis();
    TestThread[] threads = new TestThread[threadcount];
    for (int i = 0; i < threadcount; i++) {
      threads[i] = new TestThread();
      threads[i].setName("tomcat-pool-" + i);
      threads[i].d = this.datasource;
    }
    for (int i = 0; i < threadcount; i++) {
      threads[i].start();
    }
    if (!latch.await(complete + 1000, TimeUnit.MILLISECONDS)) {
      System.out.println("Latch timed out.");
    }
    this.run = false;
    long delta = System.currentTimeMillis() - start;
    printThreadResults(threads, "testPoolThreads20Connections10", this.datasource.getSize(), 10);
    System.out.println("Test completed in: " + delta + "ms.");
    tearDown();
  }

  public void testPoolThreads20Connections10Fair() throws Exception {
    System.out.println(
        "[testPoolThreads20Connections10Fair] Starting fairness - Tomcat JDBC - Fair");
    init();
    this.datasource.getPoolProperties().setMaxActive(10);
    this.datasource.getPoolProperties().setFairQueue(true);
    this.threadcount = 20;
    this.transferProperties();
    this.datasource.getConnection().close();
    latch = new CountDownLatch(threadcount);
    long start = System.currentTimeMillis();
    TestThread[] threads = new TestThread[threadcount];
    for (int i = 0; i < threadcount; i++) {
      threads[i] = new TestThread();
      threads[i].setName("tomcat-pool-" + i);
      threads[i].d = this.datasource;
    }
    for (int i = 0; i < threadcount; i++) {
      threads[i].start();
    }
    if (!latch.await(complete + 1000, TimeUnit.MILLISECONDS)) {
      System.out.println("Latch timed out.");
    }
    this.run = false;
    long delta = System.currentTimeMillis() - start;
    printThreadResults(
        threads, "testPoolThreads20Connections10Fair", this.datasource.getSize(), 10);
    System.out.println("Test completed in: " + delta + "ms.");
    tearDown();
  }

  public void testPoolThreads20Connections10FairAsync() throws Exception {
    System.out.println(
        "[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
    init();
    this.datasource.getPoolProperties().setMaxActive(10);
    this.datasource.getPoolProperties().setFairQueue(true);
    this.threadcount = 20;
    this.transferProperties();
    this.datasource.getConnection().close();
    latch = new CountDownLatch(threadcount);
    long start = System.currentTimeMillis();
    TestThread[] threads = new TestThread[threadcount];
    for (int i = 0; i < threadcount; i++) {
      threads[i] = new TestThread();
      threads[i].setName("tomcat-pool-" + i);
      threads[i].async = true;
      threads[i].d = this.datasource;
    }
    for (int i = 0; i < threadcount; i++) {
      threads[i].start();
    }
    if (!latch.await(complete + 1000, TimeUnit.MILLISECONDS)) {
      System.out.println("Latch timed out.");
    }
    this.run = false;
    long delta = System.currentTimeMillis() - start;
    printThreadResults(
        threads, "testPoolThreads20Connections10FairAsync", this.datasource.getSize(), 10);
    System.out.println("Test completed in: " + delta + "ms.");
    tearDown();
  }

  //    public void testC3P0Threads20Connections10() throws Exception {
  //        System.out.println("[testC3P0Threads20Connections10] Starting fairness - C3P0");
  //        init();
  //        this.datasource.getPoolProperties().setMaxActive(10);
  //        this.datasource.getPoolProperties().setFairQueue(false);
  //        this.threadcount = 20;
  //        this.transferPropertiesToC3P0();
  //        this.datasource.getConnection().close();
  //        latch = new CountDownLatch(threadcount);
  //        long start = System.currentTimeMillis();
  //        TestThread[] threads = new TestThread[threadcount];
  //        for (int i=0; i<threadcount; i++) {
  //            threads[i] = new TestThread();
  //            threads[i].setName("tomcat-pool-"+i);
  //            threads[i].d = this.c3p0Datasource;
  //
  //        }
  //        for (int i=0; i<threadcount; i++) {
  //            threads[i].start();
  //        }
  //        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
  //            System.out.println("Latch timed out.");
  //        }
  //        this.run = false;
  //        long delta = System.currentTimeMillis() - start;
  //
  // printThreadResults(threads,"testC3P0Threads20Connections10",c3p0Datasource.getNumConnectionsAllUsers(),10);
  //        tearDown();
  //
  //    }

  public class TestThread extends Thread {
    protected DataSource d;
    protected String query = null;
    protected long sleep = 10;
    protected boolean async = false;
    long minwait = Long.MAX_VALUE,
        maxwait = -1,
        totalwait = 0,
        totalcmax = 0,
        cmax = -1,
        nroffetch = 0,
        totalruntime = 0;

    @Override
    public void run() {
      try {
        long now = System.currentTimeMillis();
        while (FairnessTest.this.run) {
          if ((System.currentTimeMillis() - now) >= FairnessTest.this.complete) break;
          long start = System.nanoTime();
          Connection con = null;
          try {
            if (async) {
              Future<Connection> cf = ((DataSourceProxy) d).getConnectionAsync();
              con = cf.get();
            } else {
              con = d.getConnection();
            }
            long delta = System.nanoTime() - start;
            totalwait += delta;
            maxwait = Math.max(delta, maxwait);
            minwait = Math.min(delta, minwait);
            nroffetch++;
            if (query != null) {
              Statement st = con.createStatement();
              ResultSet rs = st.executeQuery(query);
              while (rs.next()) {}
              rs.close();
              st.close();
            }
            try {
              if (FairnessTest.this.sleep > 0) sleep(FairnessTest.this.sleep);
            } catch (InterruptedException x) {
              interrupted();
            }
          } finally {
            long cstart = System.nanoTime();
            if (con != null)
              try {
                con.close();
              } catch (Exception x) {
                x.printStackTrace();
              }
            long cdelta = System.nanoTime() - cstart;
            totalcmax += cdelta;
            cmax = Math.max(cdelta, cmax);
          }
          totalruntime += (System.nanoTime() - start);
        }

      } catch (Exception x) {
        x.printStackTrace();
      } finally {
        FairnessTest.this.latch.countDown();
      }
      if (System.getProperty("print-thread-stats") != null) {
        System.out.println(
            "["
                + getName()
                + "] "
                + "\n\tMax time to retrieve connection:"
                + maxwait / 1000000f
                + " ms."
                + "\n\tTotal time to retrieve connection:"
                + totalwait / 1000000f
                + " ms."
                + "\n\tAverage time to retrieve connection:"
                + totalwait / 1000000f / nroffetch
                + " ms."
                + "\n\tMax time to close connection:"
                + cmax / 1000000f
                + " ms."
                + "\n\tTotal time to close connection:"
                + totalcmax / 1000000f
                + " ms."
                + "\n\tAverage time to close connection:"
                + totalcmax / 1000000f / nroffetch
                + " ms."
                + "\n\tRun time:"
                + totalruntime / 1000000f
                + " ms."
                + "\n\tNr of fetch:"
                + nroffetch);
      }
    }
  }
}
Пример #24
0
/**
 * {@link Trigger} that checks for SCM updates periodically.
 *
 * @author Kohsuke Kawaguchi
 */
public class SCMTrigger extends Trigger<SCMedItem> {
  @DataBoundConstructor
  public SCMTrigger(String scmpoll_spec) throws ANTLRException {
    super(scmpoll_spec);
  }

  @Override
  public void run() {
    run(null);
  }

  /**
   * Run the SCM trigger with additional build actions. Used by SubversionRepositoryStatus to
   * trigger a build at a specific revisionn number.
   *
   * @param additionalActions
   * @since 1.375
   */
  public void run(Action[] additionalActions) {
    if (Hudson.getInstance().isQuietingDown()) return; // noop

    DescriptorImpl d = getDescriptor();

    LOGGER.fine("Scheduling a polling for " + job);
    if (d.synchronousPolling) {
      LOGGER.fine(
          "Running the trigger directly without threading, "
              + "as it's already taken care of by Trigger.Cron");
      new Runner(additionalActions).run();
    } else {
      // schedule the polling.
      // even if we end up submitting this too many times, that's OK.
      // the real exclusion control happens inside Runner.
      LOGGER.fine("scheduling the trigger to (asynchronously) run");
      d.queue.execute(new Runner(additionalActions));
      d.clogCheck();
    }
  }

  @Override
  public DescriptorImpl getDescriptor() {
    return (DescriptorImpl) super.getDescriptor();
  }

  @Override
  public Collection<? extends Action> getProjectActions() {
    return Collections.singleton(new SCMAction());
  }

  /** Returns the file that records the last/current polling activity. */
  public File getLogFile() {
    return new File(job.getRootDir(), "scm-polling.log");
  }

  @Extension
  public static class DescriptorImpl extends TriggerDescriptor {
    /**
     * Used to control the execution of the polling tasks.
     *
     * <p>This executor implementation has a semantics suitable for polling. Namely, no two threads
     * will try to poll the same project at once, and multiple polling requests to the same job will
     * be combined into one. Note that because executor isn't aware of a potential workspace lock
     * between a build and a polling, we may end up using executor threads unwisely --- they may
     * block.
     */
    private final transient SequentialExecutionQueue queue =
        new SequentialExecutionQueue(Executors.newSingleThreadExecutor());

    /**
     * Whether the projects should be polled all in one go in the order of dependencies. The default
     * behavior is that each project polls for changes independently.
     */
    public boolean synchronousPolling = false;

    /** Max number of threads for SCM polling. 0 for unbounded. */
    private int maximumThreads;

    public DescriptorImpl() {
      load();
      resizeThreadPool();
    }

    public boolean isApplicable(Item item) {
      return item instanceof SCMedItem;
    }

    public ExecutorService getExecutor() {
      return queue.getExecutors();
    }

    /** Returns true if the SCM polling thread queue has too many jobs than it can handle. */
    public boolean isClogged() {
      return queue.isStarving(STARVATION_THRESHOLD);
    }

    /** Checks if the queue is clogged, and if so, activate {@link AdministrativeMonitorImpl}. */
    public void clogCheck() {
      AdministrativeMonitor.all().get(AdministrativeMonitorImpl.class).on = isClogged();
    }

    /** Gets the snapshot of {@link Runner}s that are performing polling. */
    public List<Runner> getRunners() {
      return Util.filter(queue.getInProgress(), Runner.class);
    }

    /** Gets the snapshot of {@link SCMedItem}s that are being polled at this very moment. */
    public List<SCMedItem> getItemsBeingPolled() {
      List<SCMedItem> r = new ArrayList<SCMedItem>();
      for (Runner i : getRunners()) r.add(i.getTarget());
      return r;
    }

    public String getDisplayName() {
      return Messages.SCMTrigger_DisplayName();
    }

    /**
     * Gets the number of concurrent threads used for polling.
     *
     * @return 0 if unlimited.
     */
    public int getPollingThreadCount() {
      return maximumThreads;
    }

    /**
     * Sets the number of concurrent threads used for SCM polling and resizes the thread pool
     * accordingly
     *
     * @param n number of concurrent threads, zero or less means unlimited, maximum is 100
     */
    public void setPollingThreadCount(int n) {
      // fool proof
      if (n < 0) n = 0;
      if (n > 100) n = 100;

      maximumThreads = n;

      resizeThreadPool();
    }

    /** Update the {@link ExecutorService} instance. */
    /*package*/ synchronized void resizeThreadPool() {
      queue.setExecutors(
          (maximumThreads == 0
              ? Executors.newCachedThreadPool()
              : Executors.newFixedThreadPool(maximumThreads)));
    }

    @Override
    public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
      String t = json.optString("pollingThreadCount", null);
      if (t == null || t.length() == 0) setPollingThreadCount(0);
      else setPollingThreadCount(Integer.parseInt(t));

      // Save configuration
      save();

      return true;
    }

    public FormValidation doCheckPollingThreadCount(@QueryParameter String value) {
      if (value != null && "".equals(value.trim())) return FormValidation.ok();
      return FormValidation.validateNonNegativeInteger(value);
    }
  }

  @Extension
  public static final class AdministrativeMonitorImpl extends AdministrativeMonitor {
    private boolean on;

    public boolean isActivated() {
      return on;
    }
  }

  /**
   * Associated with {@link AbstractBuild} to show the polling log that triggered that build.
   *
   * @since 1.376
   */
  public static class BuildAction implements Action {
    public final AbstractBuild build;

    public BuildAction(AbstractBuild build) {
      this.build = build;
    }

    /** Polling log that triggered the build. */
    public File getPollingLogFile() {
      return new File(build.getRootDir(), "polling.log");
    }

    public String getIconFileName() {
      return "clipboard.gif";
    }

    public String getDisplayName() {
      return Messages.SCMTrigger_BuildAction_DisplayName();
    }

    public String getUrlName() {
      return "pollingLog";
    }

    /** Sends out the raw polling log output. */
    public void doPollingLog(StaplerRequest req, StaplerResponse rsp) throws IOException {
      rsp.setContentType("text/plain;charset=UTF-8");
      // Prevent jelly from flushing stream so Content-Length header can be added afterwards
      FlushProofOutputStream out = new FlushProofOutputStream(rsp.getCompressedOutputStream(req));
      getPollingLogText().writeLogTo(0, out);
      out.close();
    }

    public AnnotatedLargeText getPollingLogText() {
      return new AnnotatedLargeText<BuildAction>(
          getPollingLogFile(), Charset.defaultCharset(), true, this);
    }

    /** Used from <tt>polling.jelly</tt> to write annotated polling log to the given output. */
    public void writePollingLogTo(long offset, XMLOutput out) throws IOException {
      // TODO: resurrect compressed log file support
      getPollingLogText().writeHtmlTo(offset, out.asWriter());
    }
  }

  /** Action object for {@link Project}. Used to display the last polling log. */
  public final class SCMAction implements Action {
    public AbstractProject<?, ?> getOwner() {
      return job.asProject();
    }

    public String getIconFileName() {
      return "clipboard.gif";
    }

    public String getDisplayName() {
      return Messages.SCMTrigger_getDisplayName(job.getScm().getDescriptor().getDisplayName());
    }

    public String getUrlName() {
      return "scmPollLog";
    }

    public String getLog() throws IOException {
      return Util.loadFile(getLogFile());
    }

    /**
     * Writes the annotated log to the given output.
     *
     * @since 1.350
     */
    public void writeLogTo(XMLOutput out) throws IOException {
      new AnnotatedLargeText<SCMAction>(getLogFile(), Charset.defaultCharset(), true, this)
          .writeHtmlTo(0, out.asWriter());
    }
  }

  private static final Logger LOGGER = Logger.getLogger(SCMTrigger.class.getName());

  /** {@link Runnable} that actually performs polling. */
  public class Runner implements Runnable {

    /** When did the polling start? */
    private volatile long startTime;

    private Action[] additionalActions;

    public Runner() {
      additionalActions = new Action[0];
    }

    public Runner(Action[] actions) {
      if (actions == null) {
        additionalActions = new Action[0];
      } else {
        additionalActions = actions;
      }
    }

    /** Where the log file is written. */
    public File getLogFile() {
      return SCMTrigger.this.getLogFile();
    }

    /** For which {@link Item} are we polling? */
    public SCMedItem getTarget() {
      return job;
    }

    /** When was this polling started? */
    public long getStartTime() {
      return startTime;
    }

    /** Human readable string of when this polling is started. */
    public String getDuration() {
      return Util.getTimeSpanString(System.currentTimeMillis() - startTime);
    }

    private boolean runPolling() {
      try {
        // to make sure that the log file contains up-to-date text,
        // don't do buffering.
        StreamTaskListener listener = new StreamTaskListener(getLogFile());

        try {
          PrintStream logger = listener.getLogger();
          long start = System.currentTimeMillis();
          logger.println("Started on " + DateFormat.getDateTimeInstance().format(new Date()));
          boolean result = job.poll(listener).hasChanges();
          logger.println(
              "Done. Took " + Util.getTimeSpanString(System.currentTimeMillis() - start));
          if (result) logger.println("Changes found");
          else logger.println("No changes");
          return result;
        } catch (Error e) {
          e.printStackTrace(listener.error("Failed to record SCM polling"));
          LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e);
          throw e;
        } catch (RuntimeException e) {
          e.printStackTrace(listener.error("Failed to record SCM polling"));
          LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e);
          throw e;
        } finally {
          listener.close();
        }
      } catch (IOException e) {
        LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e);
        return false;
      }
    }

    public void run() {
      String threadName = Thread.currentThread().getName();
      Thread.currentThread().setName("SCM polling for " + job);
      try {
        startTime = System.currentTimeMillis();
        if (runPolling()) {
          AbstractProject p = job.asProject();
          String name = " #" + p.getNextBuildNumber();
          SCMTriggerCause cause;
          try {
            cause = new SCMTriggerCause(getLogFile());
          } catch (IOException e) {
            LOGGER.log(WARNING, "Failed to parse the polling log", e);
            cause = new SCMTriggerCause();
          }
          if (p.scheduleBuild(p.getQuietPeriod(), cause, additionalActions)) {
            LOGGER.info("SCM changes detected in " + job.getName() + ". Triggering " + name);
          } else {
            LOGGER.info(
                "SCM changes detected in " + job.getName() + ". Job is already in the queue");
          }
        }
      } finally {
        Thread.currentThread().setName(threadName);
      }
    }

    private SCMedItem job() {
      return job;
    }

    // as per the requirement of SequentialExecutionQueue, value equality is necessary
    @Override
    public boolean equals(Object that) {
      return that instanceof Runner && job() == ((Runner) that).job();
    }

    @Override
    public int hashCode() {
      return job.hashCode();
    }
  }

  public static class SCMTriggerCause extends Cause {
    /**
     * Only used while ths cause is in the queue. Once attached to the build, we'll move this into a
     * file to reduce the memory footprint.
     */
    private String pollingLog;

    public SCMTriggerCause(File logFile) throws IOException {
      // TODO: charset of this log file?
      this(FileUtils.readFileToString(logFile));
    }

    public SCMTriggerCause(String pollingLog) {
      this.pollingLog = pollingLog;
    }

    /** @deprecated Use {@link #SCMTriggerCause(String)}. */
    public SCMTriggerCause() {
      this("");
    }

    @Override
    public void onAddedTo(AbstractBuild build) {
      BuildAction oldAction = build.getAction(BuildAction.class);
      if (oldAction != null) {
        build.getActions().remove(oldAction);
      }

      try {
        BuildAction a = new BuildAction(build);
        FileUtils.writeStringToFile(a.getPollingLogFile(), pollingLog);
        build.addAction(a);
      } catch (IOException e) {
        LOGGER.log(WARNING, "Failed to persist the polling log", e);
      }
      pollingLog = null;
    }

    @Override
    public String getShortDescription() {
      return Messages.SCMTrigger_SCMTriggerCause_ShortDescription();
    }

    @Override
    public boolean equals(Object o) {
      return o instanceof SCMTriggerCause;
    }

    @Override
    public int hashCode() {
      return 3;
    }
  }

  /** How long is too long for a polling activity to be in the queue? */
  public static long STARVATION_THRESHOLD =
      Long.getLong(
          SCMTrigger.class.getName() + ".starvationThreshold", TimeUnit2.HOURS.toMillis(1));
}
/**
 * {@link BuildWrapper} that terminates a build if it's taking too long.
 *
 * @author Kohsuke Kawaguchi
 */
public class BuildTimeoutWrapper extends BuildWrapper {

  public static long MINIMUM_TIMEOUT_MILLISECONDS =
      Long.getLong(
          BuildTimeoutWrapper.class.getName() + ".MINIMUM_TIMEOUT_MILLISECONDS", 3 * 60 * 1000);

  private /* final */ BuildTimeOutStrategy strategy;

  /** Fail the build rather than aborting it */
  public boolean failBuild;

  /** Writing the build description when timeout occurred. */
  public boolean writingDescription;

  @DataBoundConstructor
  public BuildTimeoutWrapper(
      BuildTimeOutStrategy strategy, boolean failBuild, boolean writingDescription) {
    this.strategy = strategy;
    this.failBuild = failBuild;
    this.writingDescription = writingDescription;
  }

  @Override
  public Environment setUp(
      final AbstractBuild build, Launcher launcher, final BuildListener listener)
      throws IOException, InterruptedException {
    class EnvironmentImpl extends Environment {
      final class TimeoutTimerTask extends SafeTimerTask {
        private final AbstractBuild build;
        private final BuildListener listener;
        // Did the task timeout?
        public boolean timeout = false;

        private TimeoutTimerTask(AbstractBuild build, BuildListener listener) {
          this.build = build;
          this.listener = listener;
        }

        public void doRun() {
          // timed out
          long effectiveTimeoutMinutes = MINUTES.convert(effectiveTimeout, MILLISECONDS);
          String msg;
          if (failBuild) {
            msg = Messages.Timeout_Message(effectiveTimeoutMinutes, Messages.Timeout_Failed());
          } else {
            msg = Messages.Timeout_Message(effectiveTimeoutMinutes, Messages.Timeout_Aborted());
          }

          listener.getLogger().println(msg);
          if (writingDescription) {
            try {
              build.setDescription(msg);
            } catch (IOException e) {
              listener.getLogger().println("failed to write to the build description!");
            }
          }

          timeout = true;
          Executor e = build.getExecutor();
          if (e != null) e.interrupt(failBuild ? Result.FAILURE : Result.ABORTED);
        }
      }

      private final TimeoutTimerTask task;

      private final long effectiveTimeout = strategy.getTimeOut(build);

      public EnvironmentImpl() {
        task = new TimeoutTimerTask(build, listener);
        Trigger.timer.schedule(task, effectiveTimeout);
      }

      @Override
      public boolean tearDown(AbstractBuild build, BuildListener listener)
          throws IOException, InterruptedException {
        task.cancel();
        return (!task.timeout || !failBuild);
      }
    }

    return new EnvironmentImpl();
  }

  protected Object readResolve() {
    if ("elastic".equalsIgnoreCase(timeoutType)) {
      strategy =
          new ElasticTimeOutStrategy(
              timeoutPercentage,
              timeoutMinutesElasticDefault != null ? timeoutMinutesElasticDefault.intValue() : 60,
              3);
    } else if ("likelyStuck".equalsIgnoreCase(timeoutType)) {
      strategy = new LikelyStuckTimeOutStrategy();
    } else if (strategy == null) {
      strategy = new AbsoluteTimeOutStrategy(timeoutMinutes);
    }
    return this;
  }

  @Override
  public Descriptor<BuildWrapper> getDescriptor() {
    return DESCRIPTOR;
  }

  @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

  public static final class DescriptorImpl extends BuildWrapperDescriptor {
    DescriptorImpl() {
      super(BuildTimeoutWrapper.class);
    }

    public String getDisplayName() {
      return Messages.Descriptor_DisplayName();
    }

    public boolean isApplicable(AbstractProject<?, ?> item) {
      return true;
    }
  }

  public BuildTimeOutStrategy getStrategy() {
    return strategy;
  }

  public List<BuildTimeOutStrategyDescriptor> getStrategies() {
    return Jenkins.getInstance().getDescriptorList(BuildTimeOutStrategy.class);
  }

  // --- legacy attributes, kept for backward compatibility

  public transient int timeoutMinutes;

  public transient int timeoutPercentage;

  public transient String timeoutType;

  public transient Integer timeoutMinutesElasticDefault;
}
Пример #26
0
 public static long getBlockSize() {
   return Long.getLong(BLOCK_SIZE, 0x1000);
 }
 /**
  * Constructs an instance for controlling a local process.
  *
  * @param arguments details about the controllable process
  * @param pid process id identifying the process to control
  * @throws IllegalArgumentException if pid is not a positive integer
  */
 public FileProcessController(final FileControllerParameters arguments, final int pid) {
   this(arguments, pid, Long.getLong(STATUS_TIMEOUT_PROPERTY, 60 * 1000), TimeUnit.MILLISECONDS);
 }
Пример #28
0
/**
 * {@link com.github.zhongl.api.Actor} is thread-bound {@link Runnable} executor.
 *
 * @author <a href="mailto:[email protected]">zhongl<a>
 */
@ThreadSafe
public abstract class Actor {
  public static final long TIMEOUT = Long.getLong("ipage.actor.poll.timeout", 500L);

  private final Core core;
  private final long timeout;
  private final BlockingQueue<Runnable> tasks; // TODO monitor

  private final Runnable SHUTDOWN =
      new Runnable() {
        public void run() {
          core.running = false;
        }
      };

  protected Actor(String name) {
    this(name, TIMEOUT);
  }

  protected Actor(String name, long timeout) {
    checkArgument(timeout >= 0);
    this.timeout = timeout;
    this.tasks = new LinkedBlockingQueue<Runnable>();
    core = new Core(name);
  }

  public synchronized void start() {
    if (core.isAlive()) return;
    core.start();
  }

  public synchronized void stop() {
    if (!core.isAlive()) return;
    try {
      tasks.put(SHUTDOWN);
      core.join();
    } catch (InterruptedException ignored) {
    }
  }

  protected final <T> Future<T> submit(Callable<T> task) {
    final FutureTask futureTask = new FutureTask(task);
    tasks.offer(futureTask);
    return futureTask;
  }

  /** Overwrite this method for some time-sensitive stuff. */
  protected void heartbeat() throws Throwable {}

  protected boolean onInterruptedBy(Throwable t) {
    return true;
  }

  private class Core extends Thread {
    @GuardedBy("this")
    private Boolean running = true;

    public Core(String name) {
      super(name);
    }

    @Override
    public void run() {
      while (running) {
        try {
          Runnable task = tasks.poll(timeout, MILLISECONDS);
          heartbeat();
          if (task == null) continue;
          task.run();
        } catch (Throwable t) {
          running = onInterruptedBy(t);
        }
      }
    }
  }
}
Пример #29
0
/**
 * Base class for JSR166 Junit TCK tests. Defines some constants, utility methods and classes, as
 * well as a simple framework for helping to make sure that assertions failing in generated threads
 * cause the associated test that generated them to itself fail (which JUnit does not otherwise
 * arrange). The rules for creating such tests are:
 *
 * <ol>
 *   <li>All assertions in code running in generated threads must use the forms {@link #threadFail},
 *       {@link #threadAssertTrue}, {@link #threadAssertEquals}, or {@link #threadAssertNull}, (not
 *       {@code fail}, {@code assertTrue}, etc.) It is OK (but not particularly recommended) for
 *       other code to use these forms too. Only the most typically used JUnit assertion methods are
 *       defined this way, but enough to live with.
 *   <li>If you override {@link #setUp} or {@link #tearDown}, make sure to invoke {@code
 *       super.setUp} and {@code super.tearDown} within them. These methods are used to clear and
 *       check for thread assertion failures.
 *   <li>All delays and timeouts must use one of the constants {@code SHORT_DELAY_MS}, {@code
 *       SMALL_DELAY_MS}, {@code MEDIUM_DELAY_MS}, {@code LONG_DELAY_MS}. The idea here is that a
 *       SHORT is always discriminable from zero time, and always allows enough time for the small
 *       amounts of computation (creating a thread, calling a few methods, etc) needed to reach a
 *       timeout point. Similarly, a SMALL is always discriminable as larger than SHORT and smaller
 *       than MEDIUM. And so on. These constants are set to conservative values, but even so, if
 *       there is ever any doubt, they can all be increased in one spot to rerun tests on slower
 *       platforms.
 *   <li>All threads generated must be joined inside each test case method (or {@code fail} to do
 *       so) before returning from the method. The {@code joinPool} method can be used to do this
 *       when using Executors.
 * </ol>
 *
 * <p><b>Other notes</b>
 *
 * <ul>
 *   <li>Usually, there is one testcase method per JSR166 method covering "normal" operation, and
 *       then as many exception-testing methods as there are exceptions the method can throw.
 *       Sometimes there are multiple tests per JSR166 method when the different "normal" behaviors
 *       differ significantly. And sometimes testcases cover multiple methods when they cannot be
 *       tested in isolation.
 *   <li>The documentation style for testcases is to provide as javadoc a simple sentence or two
 *       describing the property that the testcase method purports to test. The javadocs do not say
 *       anything about how the property is tested. To find out, read the code.
 *   <li>These tests are "conformance tests", and do not attempt to test throughput, latency,
 *       scalability or other performance factors (see the separate "jtreg" tests for a set intended
 *       to check these for the most central aspects of functionality.) So, most tests use the
 *       smallest sensible numbers of threads, collection sizes, etc needed to check basic
 *       conformance.
 *   <li>The test classes currently do not declare inclusion in any particular package to simplify
 *       things for people integrating them in TCK test suites.
 *   <li>As a convenience, the {@code main} of this class (JSR166TestCase) runs all JSR166 unit
 *       tests.
 * </ul>
 */
public class JSR166TestCase extends TestCase {
  private static final boolean useSecurityManager = Boolean.getBoolean("jsr166.useSecurityManager");

  protected static final boolean expensiveTests = Boolean.getBoolean("jsr166.expensiveTests");

  /**
   * If true, report on stdout all "slow" tests, that is, ones that take more than profileThreshold
   * milliseconds to execute.
   */
  private static final boolean profileTests = Boolean.getBoolean("jsr166.profileTests");

  /**
   * The number of milliseconds that tests are permitted for execution without being reported, when
   * profileTests is set.
   */
  private static final long profileThreshold = Long.getLong("jsr166.profileThreshold", 100);

  protected void runTest() throws Throwable {
    if (profileTests) runTestProfiled();
    else super.runTest();
  }

  protected void runTestProfiled() throws Throwable {
    // Warmup run, notably to trigger all needed classloading.
    super.runTest();
    long t0 = System.nanoTime();
    try {
      super.runTest();
    } finally {
      long elapsedMillis = millisElapsedSince(t0);
      if (elapsedMillis >= profileThreshold)
        System.out.printf("%n%s: %d%n", toString(), elapsedMillis);
    }
  }

  /** Runs all JSR166 unit tests using junit.textui.TestRunner */
  public static void main(String[] args) {
    if (useSecurityManager) {
      System.err.println("Setting a permissive security manager");
      Policy.setPolicy(permissivePolicy());
      System.setSecurityManager(new SecurityManager());
    }
    int iters = (args.length == 0) ? 1 : Integer.parseInt(args[0]);

    Test s = suite();
    for (int i = 0; i < iters; ++i) {
      junit.textui.TestRunner.run(s);
      System.gc();
      System.runFinalization();
    }
    System.exit(0);
  }

  public static TestSuite newTestSuite(Object... suiteOrClasses) {
    TestSuite suite = new TestSuite();
    for (Object suiteOrClass : suiteOrClasses) {
      if (suiteOrClass instanceof TestSuite) suite.addTest((TestSuite) suiteOrClass);
      else if (suiteOrClass instanceof Class) suite.addTest(new TestSuite((Class<?>) suiteOrClass));
      else throw new ClassCastException("not a test suite or class");
    }
    return suite;
  }

  /** Collects all JSR166 unit tests as one suite. */
  public static Test suite() {
    return newTestSuite(
        AtomicDoubleTest.suite(),
        AtomicDoubleArrayTest.suite(),
        CompletableFutureTest.suite(),
        ConcurrentHashMapV8Test.suite(),
        CountedCompleterTest.suite(),
        DoubleAdderTest.suite(),
        ForkJoinPoolTest.suite(),
        ForkJoinTaskTest.suite(),
        LongAdderTest.suite(),
        RecursiveTaskTest.suite(),
        RecursiveActionTest.suite(),
        StampedLockTest.suite(),
        ThreadLocalRandomTest.suite());
  }

  // Delays for timing-dependent tests, in milliseconds.

  public static long SHORT_DELAY_MS;
  public static long SMALL_DELAY_MS;
  public static long MEDIUM_DELAY_MS;
  public static long LONG_DELAY_MS;

  /**
   * Returns the shortest timed delay. This could be reimplemented to use for example a Property.
   */
  protected long getShortDelay() {
    return 50;
  }

  /** Sets delays as multiples of SHORT_DELAY. */
  protected void setDelays() {
    SHORT_DELAY_MS = getShortDelay();
    SMALL_DELAY_MS = SHORT_DELAY_MS * 5;
    MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10;
    LONG_DELAY_MS = SHORT_DELAY_MS * 200;
  }

  /**
   * Returns a timeout in milliseconds to be used in tests that verify that operations block or time
   * out.
   */
  long timeoutMillis() {
    return SHORT_DELAY_MS / 4;
  }

  /** Returns a new Date instance representing a time delayMillis milliseconds in the future. */
  Date delayedDate(long delayMillis) {
    return new Date(System.currentTimeMillis() + delayMillis);
  }

  /** The first exception encountered if any threadAssertXXX method fails. */
  private final AtomicReference<Throwable> threadFailure = new AtomicReference<Throwable>(null);

  /**
   * Records an exception so that it can be rethrown later in the test harness thread, triggering a
   * test case failure. Only the first failure is recorded; subsequent calls to this method from
   * within the same test have no effect.
   */
  public void threadRecordFailure(Throwable t) {
    threadFailure.compareAndSet(null, t);
  }

  public void setUp() {
    setDelays();
  }

  /**
   * Extra checks that get done for all test cases.
   *
   * <p>Triggers test case failure if any thread assertions have failed, by rethrowing, in the test
   * harness thread, any exception recorded earlier by threadRecordFailure.
   *
   * <p>Triggers test case failure if interrupt status is set in the main thread.
   */
  public void tearDown() throws Exception {
    Throwable t = threadFailure.getAndSet(null);
    if (t != null) {
      if (t instanceof Error) throw (Error) t;
      else if (t instanceof RuntimeException) throw (RuntimeException) t;
      else if (t instanceof Exception) throw (Exception) t;
      else {
        AssertionFailedError afe = new AssertionFailedError(t.toString());
        afe.initCause(t);
        throw afe;
      }
    }

    if (Thread.interrupted()) throw new AssertionFailedError("interrupt status set in main thread");
  }

  /**
   * Just like fail(reason), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadFail(String reason) {
    try {
      fail(reason);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      fail(reason);
    }
  }

  /**
   * Just like assertTrue(b), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertTrue(boolean b) {
    try {
      assertTrue(b);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    }
  }

  /**
   * Just like assertFalse(b), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertFalse(boolean b) {
    try {
      assertFalse(b);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    }
  }

  /**
   * Just like assertNull(x), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertNull(Object x) {
    try {
      assertNull(x);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    }
  }

  /**
   * Just like assertEquals(x, y), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertEquals(long x, long y) {
    try {
      assertEquals(x, y);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    }
  }

  /**
   * Just like assertEquals(x, y), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertEquals(Object x, Object y) {
    try {
      assertEquals(x, y);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    } catch (Throwable t) {
      threadUnexpectedException(t);
    }
  }

  /**
   * Just like assertSame(x, y), but additionally recording (using threadRecordFailure) any
   * AssertionFailedError thrown, so that the current testcase will fail.
   */
  public void threadAssertSame(Object x, Object y) {
    try {
      assertSame(x, y);
    } catch (AssertionFailedError t) {
      threadRecordFailure(t);
      throw t;
    }
  }

  /** Calls threadFail with message "should throw exception". */
  public void threadShouldThrow() {
    threadFail("should throw exception");
  }

  /** Calls threadFail with message "should throw" + exceptionName. */
  public void threadShouldThrow(String exceptionName) {
    threadFail("should throw " + exceptionName);
  }

  /**
   * Records the given exception using {@link #threadRecordFailure}, then rethrows the exception,
   * wrapping it in an AssertionFailedError if necessary.
   */
  public void threadUnexpectedException(Throwable t) {
    threadRecordFailure(t);
    t.printStackTrace();
    if (t instanceof RuntimeException) throw (RuntimeException) t;
    else if (t instanceof Error) throw (Error) t;
    else {
      AssertionFailedError afe = new AssertionFailedError("unexpected exception: " + t);
      afe.initCause(t);
      throw afe;
    }
  }

  /**
   * Delays, via Thread.sleep, for the given millisecond delay, but if the sleep is shorter than
   * specified, may re-sleep or yield until time elapses.
   */
  static void delay(long millis) throws InterruptedException {
    long startTime = System.nanoTime();
    long ns = millis * 1000 * 1000;
    for (; ; ) {
      if (millis > 0L) Thread.sleep(millis);
      else // too short to sleep
      Thread.yield();
      long d = ns - (System.nanoTime() - startTime);
      if (d > 0L) millis = d / (1000 * 1000);
      else break;
    }
  }

  /** Waits out termination of a thread pool or fails doing so. */
  void joinPool(ExecutorService exec) {
    try {
      exec.shutdown();
      assertTrue(
          "ExecutorService did not terminate in a timely manner",
          exec.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS));
    } catch (SecurityException ok) {
      // Allowed in case test doesn't have privs
    } catch (InterruptedException ie) {
      fail("Unexpected InterruptedException");
    }
  }

  /**
   * Checks that thread does not terminate within the default millisecond delay of {@code
   * timeoutMillis()}.
   */
  void assertThreadStaysAlive(Thread thread) {
    assertThreadStaysAlive(thread, timeoutMillis());
  }

  /** Checks that thread does not terminate within the given millisecond delay. */
  void assertThreadStaysAlive(Thread thread, long millis) {
    try {
      // No need to optimize the failing case via Thread.join.
      delay(millis);
      assertTrue(thread.isAlive());
    } catch (InterruptedException ie) {
      fail("Unexpected InterruptedException");
    }
  }

  /**
   * Checks that the threads do not terminate within the default millisecond delay of {@code
   * timeoutMillis()}.
   */
  void assertThreadsStayAlive(Thread... threads) {
    assertThreadsStayAlive(timeoutMillis(), threads);
  }

  /** Checks that the threads do not terminate within the given millisecond delay. */
  void assertThreadsStayAlive(long millis, Thread... threads) {
    try {
      // No need to optimize the failing case via Thread.join.
      delay(millis);
      for (Thread thread : threads) assertTrue(thread.isAlive());
    } catch (InterruptedException ie) {
      fail("Unexpected InterruptedException");
    }
  }

  /** Checks that future.get times out, with the default timeout of {@code timeoutMillis()}. */
  void assertFutureTimesOut(Future future) {
    assertFutureTimesOut(future, timeoutMillis());
  }

  /** Checks that future.get times out, with the given millisecond timeout. */
  void assertFutureTimesOut(Future future, long timeoutMillis) {
    long startTime = System.nanoTime();
    try {
      future.get(timeoutMillis, MILLISECONDS);
      shouldThrow();
    } catch (TimeoutException success) {
    } catch (Exception e) {
      threadUnexpectedException(e);
    } finally {
      future.cancel(true);
    }
    assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
  }

  /** Fails with message "should throw exception". */
  public void shouldThrow() {
    fail("Should throw exception");
  }

  /** Fails with message "should throw " + exceptionName. */
  public void shouldThrow(String exceptionName) {
    fail("Should throw " + exceptionName);
  }

  /** The number of elements to place in collections, arrays, etc. */
  public static final int SIZE = 20;

  // Some convenient Integer constants

  public static final Integer zero = new Integer(0);
  public static final Integer one = new Integer(1);
  public static final Integer two = new Integer(2);
  public static final Integer three = new Integer(3);
  public static final Integer four = new Integer(4);
  public static final Integer five = new Integer(5);
  public static final Integer six = new Integer(6);
  public static final Integer seven = new Integer(7);
  public static final Integer eight = new Integer(8);
  public static final Integer nine = new Integer(9);
  public static final Integer m1 = new Integer(-1);
  public static final Integer m2 = new Integer(-2);
  public static final Integer m3 = new Integer(-3);
  public static final Integer m4 = new Integer(-4);
  public static final Integer m5 = new Integer(-5);
  public static final Integer m6 = new Integer(-6);
  public static final Integer m10 = new Integer(-10);

  /**
   * Runs Runnable r with a security policy that permits precisely the specified permissions. If
   * there is no current security manager, the runnable is run twice, both with and without a
   * security manager. We require that any security manager permit getPolicy/setPolicy.
   */
  public void runWithPermissions(Runnable r, Permission... permissions) {
    SecurityManager sm = System.getSecurityManager();
    if (sm == null) {
      r.run();
      Policy savedPolicy = Policy.getPolicy();
      try {
        Policy.setPolicy(permissivePolicy());
        System.setSecurityManager(new SecurityManager());
        runWithPermissions(r, permissions);
      } finally {
        System.setSecurityManager(null);
        Policy.setPolicy(savedPolicy);
      }
    } else {
      Policy savedPolicy = Policy.getPolicy();
      AdjustablePolicy policy = new AdjustablePolicy(permissions);
      Policy.setPolicy(policy);

      try {
        r.run();
      } finally {
        policy.addPermission(new SecurityPermission("setPolicy"));
        Policy.setPolicy(savedPolicy);
      }
    }
  }

  /** Runs a runnable without any permissions. */
  public void runWithoutPermissions(Runnable r) {
    runWithPermissions(r);
  }

  /** A security policy where new permissions can be dynamically added or all cleared. */
  public static class AdjustablePolicy extends java.security.Policy {
    Permissions perms = new Permissions();

    AdjustablePolicy(Permission... permissions) {
      for (Permission permission : permissions) perms.add(permission);
    }

    void addPermission(Permission perm) {
      perms.add(perm);
    }

    void clearPermissions() {
      perms = new Permissions();
    }

    public PermissionCollection getPermissions(CodeSource cs) {
      return perms;
    }

    public PermissionCollection getPermissions(ProtectionDomain pd) {
      return perms;
    }

    public boolean implies(ProtectionDomain pd, Permission p) {
      return perms.implies(p);
    }

    public void refresh() {}
  }

  /** Returns a policy containing all the permissions we ever need. */
  public static Policy permissivePolicy() {
    return new AdjustablePolicy
    // Permissions j.u.c. needs directly
    (
        new RuntimePermission("modifyThread"),
        new RuntimePermission("getClassLoader"),
        new RuntimePermission("setContextClassLoader"),
        // Permissions needed to change permissions!
        new SecurityPermission("getPolicy"),
        new SecurityPermission("setPolicy"),
        new RuntimePermission("setSecurityManager"),
        // Permissions needed by the junit test harness
        new RuntimePermission("accessDeclaredMembers"),
        new PropertyPermission("*", "read"),
        new java.io.FilePermission("<<ALL FILES>>", "read"));
  }

  /** Sleeps until the given time has elapsed. Throws AssertionFailedError if interrupted. */
  void sleep(long millis) {
    try {
      delay(millis);
    } catch (InterruptedException ie) {
      AssertionFailedError afe = new AssertionFailedError("Unexpected InterruptedException");
      afe.initCause(ie);
      throw afe;
    }
  }

  /**
   * Spin-waits up to the specified number of milliseconds for the given thread to enter a wait
   * state: BLOCKED, WAITING, or TIMED_WAITING.
   */
  void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
    long startTime = System.nanoTime();
    for (; ; ) {
      Thread.State s = thread.getState();
      if (s == Thread.State.BLOCKED || s == Thread.State.WAITING || s == Thread.State.TIMED_WAITING)
        return;
      else if (s == Thread.State.TERMINATED) fail("Unexpected thread termination");
      else if (millisElapsedSince(startTime) > timeoutMillis) {
        threadAssertTrue(thread.isAlive());
        return;
      }
      Thread.yield();
    }
  }

  /**
   * Waits up to LONG_DELAY_MS for the given thread to enter a wait state: BLOCKED, WAITING, or
   * TIMED_WAITING.
   */
  void waitForThreadToEnterWaitState(Thread thread) {
    waitForThreadToEnterWaitState(thread, LONG_DELAY_MS);
  }

  /**
   * Returns the number of milliseconds since time given by startNanoTime, which must have been
   * previously returned from a call to {@link System.nanoTime()}.
   */
  static long millisElapsedSince(long startNanoTime) {
    return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime);
  }

  /** Returns a new started daemon Thread running the given runnable. */
  Thread newStartedThread(Runnable runnable) {
    Thread t = new Thread(runnable);
    t.setDaemon(true);
    t.start();
    return t;
  }

  /**
   * Waits for the specified time (in milliseconds) for the thread to terminate (using {@link
   * Thread#join(long)}), else interrupts the thread (in the hope that it may terminate later) and
   * fails.
   */
  void awaitTermination(Thread t, long timeoutMillis) {
    try {
      t.join(timeoutMillis);
    } catch (InterruptedException ie) {
      threadUnexpectedException(ie);
    } finally {
      if (t.getState() != Thread.State.TERMINATED) {
        t.interrupt();
        fail("Test timed out");
      }
    }
  }

  /**
   * Waits for LONG_DELAY_MS milliseconds for the thread to terminate (using {@link
   * Thread#join(long)}), else interrupts the thread (in the hope that it may terminate later) and
   * fails.
   */
  void awaitTermination(Thread t) {
    awaitTermination(t, LONG_DELAY_MS);
  }

  // Some convenient Runnable classes

  public abstract class CheckedRunnable implements Runnable {
    protected abstract void realRun() throws Throwable;

    public final void run() {
      try {
        realRun();
      } catch (Throwable t) {
        threadUnexpectedException(t);
      }
    }
  }

  public abstract class RunnableShouldThrow implements Runnable {
    protected abstract void realRun() throws Throwable;

    final Class<?> exceptionClass;

    <T extends Throwable> RunnableShouldThrow(Class<T> exceptionClass) {
      this.exceptionClass = exceptionClass;
    }

    public final void run() {
      try {
        realRun();
        threadShouldThrow(exceptionClass.getSimpleName());
      } catch (Throwable t) {
        if (!exceptionClass.isInstance(t)) threadUnexpectedException(t);
      }
    }
  }

  public abstract class ThreadShouldThrow extends Thread {
    protected abstract void realRun() throws Throwable;

    final Class<?> exceptionClass;

    <T extends Throwable> ThreadShouldThrow(Class<T> exceptionClass) {
      this.exceptionClass = exceptionClass;
    }

    public final void run() {
      try {
        realRun();
        threadShouldThrow(exceptionClass.getSimpleName());
      } catch (Throwable t) {
        if (!exceptionClass.isInstance(t)) threadUnexpectedException(t);
      }
    }
  }

  public abstract class CheckedInterruptedRunnable implements Runnable {
    protected abstract void realRun() throws Throwable;

    public final void run() {
      try {
        realRun();
        threadShouldThrow("InterruptedException");
      } catch (InterruptedException success) {
        threadAssertFalse(Thread.interrupted());
      } catch (Throwable t) {
        threadUnexpectedException(t);
      }
    }
  }

  public abstract class CheckedCallable<T> implements Callable<T> {
    protected abstract T realCall() throws Throwable;

    public final T call() {
      try {
        return realCall();
      } catch (Throwable t) {
        threadUnexpectedException(t);
        return null;
      }
    }
  }

  public abstract class CheckedInterruptedCallable<T> implements Callable<T> {
    protected abstract T realCall() throws Throwable;

    public final T call() {
      try {
        T result = realCall();
        threadShouldThrow("InterruptedException");
        return result;
      } catch (InterruptedException success) {
        threadAssertFalse(Thread.interrupted());
      } catch (Throwable t) {
        threadUnexpectedException(t);
      }
      return null;
    }
  }

  public static class NoOpRunnable implements Runnable {
    public void run() {}
  }

  public static class NoOpCallable implements Callable {
    public Object call() {
      return Boolean.TRUE;
    }
  }

  public static final String TEST_STRING = "a test string";

  public static class StringTask implements Callable<String> {
    public String call() {
      return TEST_STRING;
    }
  }

  public Callable<String> latchAwaitingStringTask(final CountDownLatch latch) {
    return new CheckedCallable<String>() {
      protected String realCall() {
        try {
          latch.await();
        } catch (InterruptedException quittingTime) {
        }
        return TEST_STRING;
      }
    };
  }

  public Runnable awaiter(final CountDownLatch latch) {
    return new CheckedRunnable() {
      public void realRun() throws InterruptedException {
        await(latch);
      }
    };
  }

  public void await(CountDownLatch latch) {
    try {
      assertTrue(latch.await(LONG_DELAY_MS, MILLISECONDS));
    } catch (Throwable t) {
      threadUnexpectedException(t);
    }
  }

  public void await(Semaphore semaphore) {
    try {
      assertTrue(semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS));
    } catch (Throwable t) {
      threadUnexpectedException(t);
    }
  }

  //     /**
  //      * Spin-waits up to LONG_DELAY_MS until flag becomes true.
  //      */
  //     public void await(AtomicBoolean flag) {
  //         await(flag, LONG_DELAY_MS);
  //     }

  //     /**
  //      * Spin-waits up to the specified timeout until flag becomes true.
  //      */
  //     public void await(AtomicBoolean flag, long timeoutMillis) {
  //         long startTime = System.nanoTime();
  //         while (!flag.get()) {
  //             if (millisElapsedSince(startTime) > timeoutMillis)
  //                 throw new AssertionFailedError("timed out");
  //             Thread.yield();
  //         }
  //     }

  public static class NPETask implements Callable<String> {
    public String call() {
      throw new NullPointerException();
    }
  }

  public static class CallableOne implements Callable<Integer> {
    public Integer call() {
      return one;
    }
  }

  public class ShortRunnable extends CheckedRunnable {
    protected void realRun() throws Throwable {
      delay(SHORT_DELAY_MS);
    }
  }

  public class ShortInterruptedRunnable extends CheckedInterruptedRunnable {
    protected void realRun() throws InterruptedException {
      delay(SHORT_DELAY_MS);
    }
  }

  public class SmallRunnable extends CheckedRunnable {
    protected void realRun() throws Throwable {
      delay(SMALL_DELAY_MS);
    }
  }

  public class SmallPossiblyInterruptedRunnable extends CheckedRunnable {
    protected void realRun() {
      try {
        delay(SMALL_DELAY_MS);
      } catch (InterruptedException ok) {
      }
    }
  }

  public class SmallCallable extends CheckedCallable {
    protected Object realCall() throws InterruptedException {
      delay(SMALL_DELAY_MS);
      return Boolean.TRUE;
    }
  }

  public class MediumRunnable extends CheckedRunnable {
    protected void realRun() throws Throwable {
      delay(MEDIUM_DELAY_MS);
    }
  }

  public class MediumInterruptedRunnable extends CheckedInterruptedRunnable {
    protected void realRun() throws InterruptedException {
      delay(MEDIUM_DELAY_MS);
    }
  }

  public Runnable possiblyInterruptedRunnable(final long timeoutMillis) {
    return new CheckedRunnable() {
      protected void realRun() {
        try {
          delay(timeoutMillis);
        } catch (InterruptedException ok) {
        }
      }
    };
  }

  public class MediumPossiblyInterruptedRunnable extends CheckedRunnable {
    protected void realRun() {
      try {
        delay(MEDIUM_DELAY_MS);
      } catch (InterruptedException ok) {
      }
    }
  }

  public class LongPossiblyInterruptedRunnable extends CheckedRunnable {
    protected void realRun() {
      try {
        delay(LONG_DELAY_MS);
      } catch (InterruptedException ok) {
      }
    }
  }

  /** For use as ThreadFactory in constructors */
  public static class SimpleThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
      return new Thread(r);
    }
  }

  public interface TrackedRunnable extends Runnable {
    boolean isDone();
  }

  public static TrackedRunnable trackedRunnable(final long timeoutMillis) {
    return new TrackedRunnable() {
      private volatile boolean done = false;

      public boolean isDone() {
        return done;
      }

      public void run() {
        try {
          delay(timeoutMillis);
          done = true;
        } catch (InterruptedException ok) {
        }
      }
    };
  }

  public static class TrackedShortRunnable implements Runnable {
    public volatile boolean done = false;

    public void run() {
      try {
        delay(SHORT_DELAY_MS);
        done = true;
      } catch (InterruptedException ok) {
      }
    }
  }

  public static class TrackedSmallRunnable implements Runnable {
    public volatile boolean done = false;

    public void run() {
      try {
        delay(SMALL_DELAY_MS);
        done = true;
      } catch (InterruptedException ok) {
      }
    }
  }

  public static class TrackedMediumRunnable implements Runnable {
    public volatile boolean done = false;

    public void run() {
      try {
        delay(MEDIUM_DELAY_MS);
        done = true;
      } catch (InterruptedException ok) {
      }
    }
  }

  public static class TrackedLongRunnable implements Runnable {
    public volatile boolean done = false;

    public void run() {
      try {
        delay(LONG_DELAY_MS);
        done = true;
      } catch (InterruptedException ok) {
      }
    }
  }

  public static class TrackedNoOpRunnable implements Runnable {
    public volatile boolean done = false;

    public void run() {
      done = true;
    }
  }

  public static class TrackedCallable implements Callable {
    public volatile boolean done = false;

    public Object call() {
      try {
        delay(SMALL_DELAY_MS);
        done = true;
      } catch (InterruptedException ok) {
      }
      return Boolean.TRUE;
    }
  }

  /** Analog of CheckedRunnable for RecursiveAction */
  public abstract class CheckedRecursiveAction extends RecursiveAction {
    protected abstract void realCompute() throws Throwable;

    public final void compute() {
      try {
        realCompute();
      } catch (Throwable t) {
        threadUnexpectedException(t);
      }
    }
  }

  /** Analog of CheckedCallable for RecursiveTask */
  public abstract class CheckedRecursiveTask<T> extends RecursiveTask<T> {
    protected abstract T realCompute() throws Throwable;

    public final T compute() {
      try {
        return realCompute();
      } catch (Throwable t) {
        threadUnexpectedException(t);
        return null;
      }
    }
  }

  /** For use as RejectedExecutionHandler in constructors */
  public static class NoOpREHandler implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {}
  }

  /**
   * A CyclicBarrier that uses timed await and fails with AssertionFailedErrors instead of throwing
   * checked exceptions.
   */
  public class CheckedBarrier extends CyclicBarrier {
    public CheckedBarrier(int parties) {
      super(parties);
    }

    public int await() {
      try {
        return super.await(2 * LONG_DELAY_MS, MILLISECONDS);
      } catch (TimeoutException e) {
        throw new AssertionFailedError("timed out");
      } catch (Exception e) {
        AssertionFailedError afe = new AssertionFailedError("Unexpected exception: " + e);
        afe.initCause(e);
        throw afe;
      }
    }
  }

  void checkEmpty(BlockingQueue q) {
    try {
      assertTrue(q.isEmpty());
      assertEquals(0, q.size());
      assertNull(q.peek());
      assertNull(q.poll());
      assertNull(q.poll(0, MILLISECONDS));
      assertEquals("[]", q.toString());
      assertTrue(Arrays.equals(q.toArray(), new Object[0]));
      assertFalse(q.iterator().hasNext());
      try {
        q.element();
        shouldThrow();
      } catch (NoSuchElementException success) {
      }
      try {
        q.iterator().next();
        shouldThrow();
      } catch (NoSuchElementException success) {
      }
      try {
        q.remove();
        shouldThrow();
      } catch (NoSuchElementException success) {
      }
    } catch (InterruptedException ie) {
      threadUnexpectedException(ie);
    }
  }

  @SuppressWarnings("unchecked")
  <T> T serialClone(T o) {
    try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(bos);
      oos.writeObject(o);
      oos.flush();
      oos.close();
      ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
      T clone = (T) ois.readObject();
      assertSame(o.getClass(), clone.getClass());
      return clone;
    } catch (Throwable t) {
      threadUnexpectedException(t);
      return null;
    }
  }
}
public class SGTestNGListener extends TestListenerAdapter {

  protected String testMethodName;
  protected String suiteName;
  protected String buildNumber;
  protected String version;
  protected ScriptingContainer container;
  private Process process = null;
  private Process process2 = null;
  private String logstashLogPath;
  private String logstashLogPath2;
  private static final boolean enableLogstash =
      Boolean.parseBoolean(System.getProperty("iTests.enableLogstash", "false"));
  protected static final String CREDENTIALS_FOLDER =
      System.getProperty(
          "iTests.credentialsFolder",
          SGTestHelper.getSGTestRootDir() + "/src/main/resources/credentials");
  private static File propsFile = new File(CREDENTIALS_FOLDER + "/logstash/logstash.properties");
  protected String logstashHost;

  private static long testInvocationCounter = 1;
  private static final long maxCount = Long.getLong("sgtest.webui.numberOfTestRetries", 3) + 1;

  public SGTestNGListener() {
    if (enableLogstash) {
      LogUtils.log("in SGTestNGListener constructor");
    }
  }

  @Override
  public void onStart(ITestContext iTestContext) {
    suiteName = System.getProperty("iTests.suiteName", "sgtest");
    LogUtils.log("suite number is now (on start) - " + suiteName);

    if (enableLogstash) {
      buildNumber = System.getProperty("iTests.buildNumber");
      LogUtils.log("build number is now (on start) - " + buildNumber);
      version = System.getProperty("cloudifyVersion");
    }
  }

  private void initLogstash2(ITestResult tr) {

    initLogstashHost();

    String simpleClassName = tr.getTestClass().getRealClass().getSimpleName();
    String pathToLogstash =
        SGTestHelper.getSGTestRootDir().replace("\\", "/") + "/src/main/resources/logstash";
    String confFilePath2 = pathToLogstash + "/logstash-shipper-client-2.conf";
    String backupFilePath2 =
        pathToLogstash + "/logstash-shipper-client-2-" + simpleClassName + ".conf";
    File backupFile2 = new File(backupFilePath2);

    LogUtils.log(
        "trying to start logstash agent number 2. simple class name is " + simpleClassName);
    if (backupFile2.exists()) {
      LogUtils.log("the file " + backupFilePath2 + " already exists. not starting logstash");
    }

    if (!isAfter(tr) && !backupFile2.exists()) {

      try {
        //                backupFilePath2 = IOUtils.backupFile(confFilePath2);
        LogUtils.log("copying file " + confFilePath2 + " to " + backupFilePath2);
        IOUtils.copyFile(confFilePath2, backupFilePath2);
        IOUtils.replaceTextInFile(backupFilePath2, "<path_to_build>", SGTestHelper.getBuildDir());
        IOUtils.replaceTextInFile(
            backupFilePath2,
            "<suite_number>",
            "suite_" + System.getProperty("iTests.suiteId", "0"));
        IOUtils.replaceTextInFile(
            backupFilePath2,
            "<path_to_test_class_folder>",
            SGTestHelper.getSGTestRootDir().replace("\\", "/")
                + "/../"
                + suiteName
                + "/"
                + tr.getTestClass().getName());
        IOUtils.replaceTextInFile(backupFilePath2, "<suite_name>", suiteName);
        IOUtils.replaceTextInFile(backupFilePath2, "<test_name>", simpleClassName);
        IOUtils.replaceTextInFile(backupFilePath2, "<build_number>", buildNumber);
        IOUtils.replaceTextInFile(backupFilePath2, "<version>", version);
        IOUtils.replaceTextInFile(backupFilePath2, "<host>", logstashHost);

        String logstashJarPath =
            DeploymentUtils.getLocalRepository() + "net/logstash/1.2.2/logstash-1.2.2.jar";
        logstashLogPath2 = pathToLogstash + "/logstash-" + simpleClassName + "-2.txt";
        String cmdLine =
            "java -jar "
                + logstashJarPath
                + " agent -f "
                + backupFilePath2
                + " -l "
                + logstashLogPath2;

        final String[] parts = cmdLine.split(" ");
        final ProcessBuilder pb = new ProcessBuilder(parts);
        LogUtils.log("Executing Command line: " + cmdLine);

        process2 = pb.start();

      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void initLogstash(String testName) {

    initLogstashHost();

    String pathToLogstash =
        SGTestHelper.getSGTestRootDir().replace("\\", "/") + "/src/main/resources/logstash";
    String confFilePath = pathToLogstash + "/logstash-shipper-client.conf";
    String fixedTestName = testName.substring(0, testName.length() - 2);
    String backupFilePath = pathToLogstash + "/logstash-shipper-client-" + fixedTestName + ".conf";

    if (process == null) {

      try {

        LogUtils.log("copying file " + confFilePath + " to " + backupFilePath);
        IOUtils.copyFile(confFilePath, backupFilePath);
        //                backupFilePath = IOUtils.backupFile(confFilePath);
        IOUtils.replaceTextInFile(
            backupFilePath,
            "<path_to_test_folder>",
            SGTestHelper.getSGTestRootDir().replace("\\", "/")
                + "/../"
                + suiteName
                + "/"
                + testName);
        IOUtils.replaceTextInFile(backupFilePath, "<suite_name>", suiteName);
        IOUtils.replaceTextInFile(backupFilePath, "<test_name>", testName);
        IOUtils.replaceTextInFile(backupFilePath, "<build_number>", buildNumber);
        IOUtils.replaceTextInFile(backupFilePath, "<version>", version);
        IOUtils.replaceTextInFile(backupFilePath, "<host>", logstashHost);

        String logstashJarPath =
            DeploymentUtils.getLocalRepository() + "net/logstash/1.2.2/logstash-1.2.2.jar";
        logstashLogPath = pathToLogstash + "/logstash-" + fixedTestName + ".txt";
        String cmdLine =
            "java -jar "
                + logstashJarPath
                + " agent -f "
                + backupFilePath
                + " -l "
                + logstashLogPath;

        final String[] parts = cmdLine.split(" ");
        final ProcessBuilder pb = new ProcessBuilder(parts);
        LogUtils.log("Executing Command line: " + cmdLine);

        TimeUnit.SECONDS.sleep(1);
        process = pb.start();

      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  @Override
  public void beforeConfiguration(ITestResult tr) {
    if (enableLogstash) {
      super.beforeConfiguration(tr);
      if (suiteName
          == null) { // this is in case the suite has a @BeforeSuite method. which is invoked before
                     // the onStart is.
        suiteName = System.getProperty("iTests.suiteName", "sgtest");
        buildNumber = System.getProperty("iTests.buildNumber");
        LogUtils.log("build number is now - " + buildNumber);
        version = System.getProperty("cloudifyVersion");
      }
    }
  }

  @Override
  public void onConfigurationSuccess(ITestResult iTestResult) {
    super.onConfigurationSuccess(iTestResult);
    String testName = iTestResult.getTestClass().getName();
    String configurationName = iTestResult.getMethod().toString().split("\\(|\\)")[0];
    if (isAfter(iTestResult) && !enableLogstash) {
      DumpUtils.copyBeforeConfigurationsLogToTestDir(testName, suiteName);
      testName = testMethodName;
    }
    if (suiteName
        == null) { // this is in case the suite has a @BeforeSuite method. which is invoked before
                   // the onStart is.
      suiteName = System.getProperty("iTests.suiteName", "sgtest");
    }
    LogUtils.log("Configuration Succeeded: " + configurationName);

    if (enableLogstash && iTestResult.getMethod().isBeforeClassConfiguration()) {
      initLogstash2(iTestResult);
    }

    String newmanTestFolder = System.getProperty("newman.test.path");
    if (newmanTestFolder != null) {
      File testFolder = new File(newmanTestFolder);
      ZipUtils.unzipArchive(testFolder);
      try {
        copyAllFilesToLogDir(testFolder, testFolder);
      } catch (IOException e) {
        LogUtils.log("Failed to copy all log files - caught " + e, e);
      }
    } else {
      ZipUtils.unzipArchive(testMethodName, suiteName);
    }

    if (enableLogstash
        && isAfter(iTestResult)
        && !iTestResult.getMethod().isAfterClassConfiguration()
        && !iTestResult.getMethod().isAfterSuiteConfiguration()) {
      testName = testMethodName;
    }

    write2LogFile(iTestResult, DumpUtils.createTestFolder(testName, suiteName));

    if (isAfter(iTestResult)) {
      if (enableLogstash) {
        if (process != null) {
          killLogstashAgent(1, logstashLogPath);
        }
        if (process2 != null && iTestResult.getMethod().isAfterClassConfiguration()) {
          killLogstashAgent(2, logstashLogPath2);
        }
      }
    }
  }

  @Override
  public void onConfigurationFailure(ITestResult iTestResult) {
    super.onConfigurationFailure(iTestResult);
    String testName = iTestResult.getTestClass().getName();
    String configurationName = iTestResult.getMethod().toString().split("\\(|\\)")[0];
    if (!enableLogstash && isAfter(iTestResult)) {
      DumpUtils.copyBeforeConfigurationsLogToTestDir(testName, suiteName);
      testName = testMethodName;
    }
    if (suiteName
        == null) { // this is in case the suite has a @BeforeSuite method. which is invoked before
                   // the onStart is.
      suiteName = System.getProperty("iTests.suiteName", "sgtest");
    }
    LogUtils.log("Configuration Failed: " + configurationName, iTestResult.getThrowable());

    if (enableLogstash && iTestResult.getMethod().isBeforeClassConfiguration()) {
      initLogstash2(iTestResult);
    }

    String newmanTestFolder = System.getProperty("newman.test.path");
    if (newmanTestFolder != null) {
      File testFolder = new File(newmanTestFolder);
      ZipUtils.unzipArchive(testFolder);
      try {
        copyAllFilesToLogDir(testFolder, testFolder);
      } catch (IOException e) {
        LogUtils.log("Failed to copy all log files");
      }
    } else {
      ZipUtils.unzipArchive(testMethodName, suiteName);
    }

    if (enableLogstash
        && isAfter(iTestResult)
        && !iTestResult.getMethod().isAfterClassConfiguration()
        && !iTestResult.getMethod().isAfterSuiteConfiguration()) {
      testName = testMethodName;
    }
    File testFolder = DumpUtils.createTestFolder(testName, suiteName);
    write2LogFile(iTestResult, testFolder);
    write2ErrorTxtFile(iTestResult, testFolder);

    if (isAfter(iTestResult)) {
      if (enableLogstash) {
        if (process != null) {
          killLogstashAgent(1, logstashLogPath);
        }
        if (process2 != null && iTestResult.getMethod().isAfterClassConfiguration()) {
          killLogstashAgent(2, logstashLogPath2);
        }
      }
    }
  }

  @Override
  public void onConfigurationSkip(ITestResult iTestResult) {
    super.onConfigurationFailure(iTestResult);
    String testName = iTestResult.getTestClass().getName();
    String configurationName = iTestResult.getMethod().toString().split("\\(|\\)")[0];
    if (!enableLogstash && isAfter(iTestResult)) {
      DumpUtils.copyBeforeConfigurationsLogToTestDir(testName, suiteName);
      testName = testMethodName;
    }
    LogUtils.log("Configuration Skipped: " + configurationName, iTestResult.getThrowable());

    if (enableLogstash && iTestResult.getMethod().isBeforeClassConfiguration()) {
      initLogstash2(iTestResult);
    }

    String newmanTestFolder = System.getProperty("newman.test.path");
    if (newmanTestFolder != null) {
      File testFolder = new File(newmanTestFolder);
      ZipUtils.unzipArchive(testFolder);
      try {
        copyAllFilesToLogDir(testFolder, testFolder);
      } catch (IOException e) {
        LogUtils.log("Failed to copy all log files");
      }
    } else {
      ZipUtils.unzipArchive(testMethodName, suiteName);
    }

    if (enableLogstash
        && isAfter(iTestResult)
        && !iTestResult.getMethod().isAfterClassConfiguration()
        && !iTestResult.getMethod().isAfterSuiteConfiguration()) {
      testName = testMethodName;
    }
    write2LogFile(iTestResult, DumpUtils.createTestFolder(testName, suiteName));

    if (isAfter(iTestResult)) {
      if (enableLogstash) {
        if (process != null) {
          killLogstashAgent(1, logstashLogPath);
        }
        if (process2 != null && iTestResult.getMethod().isAfterClassConfiguration()) {
          killLogstashAgent(2, logstashLogPath2);
        }
      }
    }
  }

  @Override
  public void onTestStart(ITestResult iTestResult) {
    super.onTestStart(iTestResult);
    String testName = TestNGUtils.constructTestMethodName(iTestResult);
    LogUtils.log("Test Start: " + testName);
    if (enableLogstash) {
      initLogstash(testName);
    }
  }

  @Override
  public void onTestFailure(ITestResult iTestResult) {
    if (suiteName.toLowerCase().contains("webui")) {
      if (testInvocationCounter < maxCount) {
        testInvocationCounter++;
        iTestResult.setAttribute("retry", true);
      } else {
        LogUtils.log("Number of retries expired.");
        iTestResult.setStatus(ITestResult.FAILURE);
        // reset count
        testInvocationCounter = 1;
        testMethodName = TestNGUtils.constructTestMethodName(iTestResult);
        LogUtils.log("Test Failed: " + testMethodName, iTestResult.getThrowable());
        File testFolder = DumpUtils.createTestFolder(testMethodName, suiteName);
        write2LogFile(iTestResult, testFolder);
        write2ErrorTxtFile(iTestResult, testFolder);
      }
    } else {
      testMethodName = TestNGUtils.constructTestMethodName(iTestResult);
      LogUtils.log("Test Failed: " + testMethodName, iTestResult.getThrowable());
      File testFolder = DumpUtils.createTestFolder(testMethodName, suiteName);
      write2LogFile(iTestResult, testFolder);
      write2ErrorTxtFile(iTestResult, testFolder);
    }
    super.onTestFailure(iTestResult);
  }

  @Override
  public void onTestSkipped(ITestResult iTestResult) {
    super.onTestSkipped(iTestResult);
    testMethodName = TestNGUtils.constructTestMethodName(iTestResult);
    LogUtils.log("Test Skipped: " + testMethodName, iTestResult.getThrowable());
    write2LogFile(iTestResult, DumpUtils.createTestFolder(testMethodName, suiteName));
  }

  @Override
  public void onTestSuccess(ITestResult iTestResult) {
    super.onTestSuccess(iTestResult);
    if (suiteName.toLowerCase().contains("webui")) {
      testInvocationCounter = 1;
    }
    testMethodName = TestNGUtils.constructTestMethodName(iTestResult);
    LogUtils.log("Test Passed: " + testMethodName);
    write2LogFile(iTestResult, DumpUtils.createTestFolder(testMethodName, suiteName));
  }

  @Override
  public void onFinish(ITestContext testContext) {
    super.onFinish(testContext);
    if (suiteName == null) suiteName = System.getProperty("iTests.suiteName", "sgtest");
    LogUtils.log("Finishing Suite: " + suiteName.toLowerCase());
    if (suiteName.toLowerCase().contains("webui")) {
      onFinishWebUITests(testContext);
    }
    try {
      SGTestNGReporter.reset();
    } catch (Exception e) {
      // ignore
    }
  }

  private void onFinishWebUITests(ITestContext testContext) {
    // List of test results which we will delete later because of duplication or because the test
    // eventually passed
    List<ITestResult> testsToBeRemoved = new ArrayList<ITestResult>();

    // collect all id's from passed test
    Set<Integer> passedTestIds = new HashSet<Integer>();
    for (ITestResult passedTest : testContext.getPassedTests().getAllResults()) {
      passedTestIds.add(getTestId(passedTest));
    }

    Set<Integer> failedTestIds = new HashSet<Integer>();
    for (ITestResult failedTest : testContext.getFailedTests().getAllResults()) {

      int failedTestId = getTestId(failedTest);
      // if this test failed before mark as to be deleted
      // or delete this failed test if there is at least one passed version
      if (failedTestIds.contains(failedTestId) || passedTestIds.contains(failedTestId)) {
        testsToBeRemoved.add(failedTest);
      } else {
        failedTestIds.add(failedTestId);
      }
    }
    // finally delete all tests that are marked
    for (Iterator<ITestResult> iterator = testContext.getFailedTests().getAllResults().iterator();
        iterator.hasNext(); ) {
      ITestResult testResult = iterator.next();
      if (testsToBeRemoved.contains(testResult)) {
        iterator.remove();
      }
    }
  }

  // returns an ID for each test result
  private int getTestId(ITestResult result) {
    int id = result.getTestClass().getName().hashCode();
    id = 31 * id + result.getMethod().getMethodName().hashCode();
    id = 31 * id + (result.getParameters() != null ? Arrays.hashCode(result.getParameters()) : 0);
    return id;
  }

  private void write2LogFile(ITestResult iTestResult, File testFolder) {
    BufferedWriter out = null;
    try {
      if (testFolder == null) {
        LogUtils.log("Can not write to file test folder is null");
        return;
      }
      String output = SGTestNGReporter.getOutput();
      if (StringUtils.isEmpty(output)) {
        LogUtils.log("nothing to write to log file");
        return;
      }
      String parameters = TestNGUtils.extractParameters(iTestResult);
      File testLogFile =
          new File(
              testFolder.getAbsolutePath()
                  + "/"
                  + iTestResult.getName()
                  + "("
                  + parameters
                  + ").log");
      if (!testLogFile.createNewFile()) {
        LogUtils.log(
            "Failed to create log file ["
                + testLogFile
                + "];\n log output: "
                + Reporter.getOutput());
        return;
      }
      FileWriter fstream = new FileWriter(testLogFile);
      out = new BufferedWriter(fstream);
      out.write(output);
    } catch (Exception e) {
      LogUtils.log("Failed to write to log file result - " + iTestResult, e);
    } finally {
      SGTestNGReporter.reset();
      if (out != null) {
        try {
          out.close();
        } catch (IOException e) {
          LogUtils.log("Failed closing stream", e);
          // ignore
        }
      }
    }
  }

  private void write2ErrorTxtFile(ITestResult iTestResult, File testFolder) {
    if (testFolder == null) {
      LogUtils.log("Can not write error.txt - test folder is null");
      return;
    }
    //noinspection ThrowableResultOfMethodCallIgnored
    if (iTestResult.getThrowable() == null) {
      LogUtils.log("nothing to write to error.txt - throwable is null");
      return;
    }
    // trim if too long
    //noinspection ThrowableResultOfMethodCallIgnored
    String errorMsg = iTestResult.getThrowable().toString();
    if (errorMsg.length() > 120) {
      errorMsg = errorMsg.substring(0, 120 - 3) + "...";
    }

    File errorTxtFile = new File(testFolder.getAbsolutePath(), "error.txt");
    PrintWriter out = null;
    try {
      out = new PrintWriter(new BufferedWriter(new FileWriter(errorTxtFile, true)));
      out.println(errorMsg);
    } catch (IOException ioe) {
      LogUtils.log("Failed to write contents into error.txt file", ioe);
    } finally {
      if (out != null) {
        out.close();
      }
    }
  }

  private boolean isAfter(ITestResult iTestResult) {
    ITestNGMethod method = iTestResult.getMethod();
    return (method.isAfterClassConfiguration()
        || method.isAfterMethodConfiguration()
        || method.isAfterSuiteConfiguration()
        || method.isAfterTestConfiguration());
  }

  private void killLogstashAgent(int logAgentNumber, String logstashLogPath) {

    FileObject listendir;
    CustomFileListener listener = new CustomFileListener();
    long TIMEOUT_BETWEEN_FILE_QUERYING = 1000;
    long LOOP_TIMEOUT_IN_MILLIS = 10 * 1000;

    try {
      FileSystemManager fileSystemManager = VFS.getManager();
      listendir = fileSystemManager.resolveFile(logstashLogPath);
    } catch (FileSystemException e) {
      e.printStackTrace();
      return;
    }

    DefaultFileMonitor fm = new DefaultFileMonitor(listener);
    fm.setRecursive(true);
    fm.addFile(listendir);
    fm.setDelay(TIMEOUT_BETWEEN_FILE_QUERYING);
    fm.start();

    LogUtils.log("waiting to destroy logger");
    long startTimeMillis = System.currentTimeMillis();

    while (true) {

      if (!listener.isProcessUp()) {
        break;
      }

      listener.setProcessUp(false);

      try {
        TimeUnit.MILLISECONDS.sleep(LOOP_TIMEOUT_IN_MILLIS);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    long endTimeMillis = System.currentTimeMillis();
    LogUtils.log("destroying logstash agent " + logAgentNumber);
    LogUtils.log("waited " + (endTimeMillis - startTimeMillis) / 1000 + " seconds");
    fm.stop();

    //        File logstashOutputFile = new File(logstashLogPath);

    if (logAgentNumber == 1) {

      process.destroy();
      process = null;
    } else {

      process2.destroy();
      process2 = null;
    }

    //        try {
    //            TimeUnit.SECONDS.sleep(5);
    //
    //            LogUtils.log("returning logstash config file to initial state");
    //            if(logAgentNumber == 1){
    //                IOUtils.replaceFileWithMove(new File(confFilePath), new File(backupFilePath));
    //                FileUtils.deleteQuietly(new File(backupFilePath));
    //            }
    //            else{
    //                IOUtils.replaceFileWithMove(new File(confFilePath2), new
    // File(backupFilePath2));
    //                FileUtils.deleteQuietly(new File(backupFilePath2));
    //
    //            }
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        } catch (InterruptedException e) {
    //            e.printStackTrace();
    //        }

    //        if(logstashOutputFile.exists()){
    //            FileUtils.deleteQuietly(logstashOutputFile);
    //        }
  }

  private void initLogstashHost() {

    if (logstashHost != null) {
      return;
    }

    Properties props;
    try {
      props = IOUtils.readPropertiesFromFile(propsFile);
    } catch (final Exception e) {
      throw new IllegalStateException("Failed reading properties file : " + e.getMessage());
    }
    logstashHost = props.getProperty("logstash_server_host");
  }

  private void copyAllFilesToLogDir(File node, File parent) throws IOException {
    if (!node.getAbsoluteFile().equals(parent.getAbsoluteFile())
        && node.isFile()
        && !node.getParentFile().equals(parent)) {
      String fileNamePrefix = node.getName().substring(0, node.getName().lastIndexOf('.'));
      String fileNameSuffix = node.getName().substring(node.getName().lastIndexOf('.'));
      String newFilePath =
          node.getParentFile().getAbsolutePath()
              + File.separator
              + fileNamePrefix.replace(".", "_")
              + fileNameSuffix;

      File newNode = new File(newFilePath);
      if (node.renameTo(newNode)) {
        FileUtils.copyFileToDirectory(newNode, parent);
      }
    }
    if (node.isDirectory()) {
      String[] subNote = node.list();
      for (String filename : subNote) {
        copyAllFilesToLogDir(new File(node, filename), parent);
      }
      if (!node.equals(parent)) {
        FileUtils.deleteDirectory(node);
      }
    }
  }
}