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.alibaba.wasp.util;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import java.io.IOException;
  
  /**
   * The InjectionHandler is an object provided to a class, which can perform
   * custom actions for JUnit testing. JUnit test can implement custom version of
   * the handler. For example, let's say we want to supervise FSImage object:
   * 
   * // JUnit test code class MyInjectionHandler extends InjectionHandler {
   * protected void _processEvent(InjectionEvent event, Object... args) { if
   * (event = InjectionEvent.MY_EVENT) {
   * LOG.info("Handling my event for fsImage: " + args[0].toString()); } } }
   * 
   * public void testMyEvent() { InjectionHandler ih = new MyInjectionHandler();
   * InjectionHandler.set(ih); ...
   * 
   * InjectionHandler.clear(); }
   * 
   * // supervised code example
   * 
   * class FSImage {
   * 
   * private doSomething() { ... if (condition1 &&
   * InjectionHandler.trueCondition(MY_EVENT1) { ... } if (condition2 ||
   * condition3 || InjectionHandler.falseCondition(MY_EVENT1) { ... } ...
   * InjectionHandler.processEvent(MY_EVENT2, this) ... try { read();
   * InjectionHandler.processEventIO(MY_EVENT3, this, object); // might throw an
   * exception when testing catch (IOEXception) { LOG.info("Exception") } ... }
   * ... }
   * 
   * Each unit test should use a unique event type. The types can be defined by
   * adding them to InjectionEvent class.
   * 
   * methods:
   * 
   * // simulate actions void processEvent() // simulate exceptions void
   * processEventIO() throws IOException
   * 
   * // simulate conditions boolean trueCondition() boolean falseCondition()
   * 
   * The class implementing InjectionHandler must override respective protected
   * methods _processEvent() _processEventIO() _trueCondition() _falseCondition()
   */
  public class InjectionHandler {
  
    private static final Log LOG = LogFactory.getLog(InjectionHandler.class);
  
    // the only handler to which everyone reports
    private static InjectionHandler handler = new InjectionHandler();
  
    // can not be instantiated outside, unless a testcase extends it
    protected InjectionHandler() {
    }
  
    // METHODS FOR PRODUCTION CODE
  
    protected void _processEvent(InjectionEvent event, Object... args) {
      // by default do nothing
    }
  
    protected void _processEventIO(InjectionEvent event, Object... args)
        throws IOException {
      // by default do nothing
    }
  
    protected boolean _trueCondition(InjectionEvent event, Object... args) {
      return true; // neutral in conjunction
    }
  
    protected boolean _falseCondition(InjectionEvent event, Object... args) {
      return false; // neutral in alternative
    }
  
    // //////////////////////////////////////////////////////////
  
    /**
     * Set to the empty/production implementation.
     */
    public static void clear() {
      handler = new InjectionHandler();
    }
  
    /**
     * Set custom implementation of the handler.
     */
    public static void set(InjectionHandler custom) {
      LOG.warn("WARNING: SETTING INJECTION HANDLER"
          + " - THIS SHOULD NOT BE USED IN PRODUCTION !!!");
      handler = custom;
    }
  
    /*
     * Static methods for reporting to the handler
     */
  
    public static void processEvent(InjectionEvent event, Object... args) {
      handler._processEvent(event, args);
    }
  
    public static void processEventIO(InjectionEvent event, Object... args)
        throws IOException {
      handler._processEventIO(event, args);
    }
  
    public static boolean trueCondition(InjectionEvent event, Object... args) {
      return handler._trueCondition(event, args);
    }
  
    public static boolean falseCondition(InjectionEvent event, Object... args) {
      return handler._falseCondition(event, args);
    }
  }
  