content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.datastax.oss.driver.api.testinfra.ccm;
  
  import com.datastax.oss.driver.categories.ParallelizableTests;
  import java.lang.reflect.Method;
  import org.junit.AssumptionViolatedException;
  import org.junit.experimental.categories.Category;
  import org.junit.runner.Description;
  import org.junit.runners.model.Statement;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * A rule that creates a globally shared single node Ccm cluster that is only shut down after the
   * JVM exists.
   *
   * <p>Note that this rule should be considered mutually exclusive with {@link CustomCcmRule}.
   * Creating instances of these rules can create resource issues.
   */
  public class CcmRule extends BaseCcmRule {
  
    private static final CcmRule INSTANCE = new CcmRule();
  
    private volatile boolean started = false;
  
    private CcmRule() {
      super(configureCcmBridge(CcmBridge.builder()).build());
    }
  
    public static CcmBridge.Builder configureCcmBridge(CcmBridge.Builder builder) {
      Logger logger = LoggerFactory.getLogger(CcmRule.class);
      String customizerClass =
          System.getProperty(
              "ccmrule.bridgecustomizer",
              "com.datastax.oss.driver.api.testinfra.ccm.DefaultCcmBridgeBuilderCustomizer");
      try {
        Class<?> clazz = Class.forName(customizerClass);
        Method method = clazz.getMethod("configureBuilder", CcmBridge.Builder.class);
        return (CcmBridge.Builder) method.invoke(null, builder);
      } catch (Exception e) {
        logger.warn(
            "Could not find CcmRule customizer {}, will use the default CcmBridge.",
            customizerClass,
            e);
        return builder;
      }
    }
  
    @Override
    protected synchronized void before() {
      if (!started) {
        // synchronize before so blocks on other before() call waiting to finish.
        super.before();
        started = true;
      }
    }
  
    @Override
    protected void after() {
      // override after so we don't remove when done.
    }
  
    @Override
    public Statement apply(Statement base, Description description) {
  
      Category categoryAnnotation = description.getTestClass().getAnnotation(Category.class);
      if (categoryAnnotation == null
          || categoryAnnotation.value().length != 1
          || categoryAnnotation.value()[0] != ParallelizableTests.class) {
        return new Statement() {
          @Override
          public void evaluate() {
            throw new AssumptionViolatedException(
                String.format(
                    "Tests using %s must be annotated with `@Category(%s.class)`. Description: %s",
                    CcmRule.class.getSimpleName(),
                    ParallelizableTests.class.getSimpleName(),
                    description));
          }
        };
      }
  
      return super.apply(base, description);
    }
  
    public static CcmRule getInstance() {
      return INSTANCE;
    }
  }
  