001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie;
020
021import org.apache.oozie.util.XLog;
022
023/**
024 * Fault Injection support class. <p> Concrete classes should be available only during testing, not in production. <p>
025 * To activate fault injection the {@link #FAULT_INJECTION} system property must be set to true. <p> When fault
026 * injection is activated, the concrete class (specified by name) will be call for activation. <p> Concrete classes
027 * should be activated by presense of a second system property. <p> This fault injection pattern provides 3 levels of
028 * safeguard: a general 'fault injection' system property, the availabity of of the concrete 'fault injection' class in
029 * the classpath, a specifi 'fault injection' system property. <p> Refer to the <code>SkipCommitFaultInjection</code>
030 * class in the test classes for an example.
031 */
032public abstract class FaultInjection {
033
034    public static final String FAULT_INJECTION = "oozie.fault.injection";
035
036    private static FaultInjection getFaultInjection(String className) {
037        if (Boolean.parseBoolean(System.getProperty(FAULT_INJECTION, "false"))) {
038            try {
039                Class klass = Thread.currentThread().getContextClassLoader().loadClass(className);
040                return (FaultInjection) klass.newInstance();
041            }
042            catch (ClassNotFoundException ex) {
043                XLog.getLog(FaultInjection.class).warn("Trying to activate fault injection in production", ex);
044            }
045            catch (IllegalAccessException ex) {
046                throw new RuntimeException(XLog.format("Could not initialize [{0}]", className, ex), ex);
047            }
048            catch (InstantiationException ex) {
049                throw new RuntimeException(XLog.format("Could not initialize [{0}]", className, ex), ex);
050            }
051        }
052        return null;
053    }
054
055    public static boolean activate(String className) {
056        FaultInjection fi = getFaultInjection(className);
057        if (fi != null) {
058            className = className.substring(className.lastIndexOf(".") + 1);
059            if (fi.activate()) {
060                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, ACTIVATING [{0}]", className);
061                return true;
062            }
063            else {
064                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, DID NOT ACTIVATE [{0}]", className);
065            }
066        }
067        return false;
068    }
069
070    public static void deactivate(String className) {
071        FaultInjection fi = getFaultInjection(className);
072        if (fi != null) {
073            className = className.substring(className.lastIndexOf(".") + 1);
074            if (fi.isActive()) {
075                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, DEACTIVATING [{0}]", className);
076                fi.deactivate();
077            }
078            else {
079                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, CANNOT DEACTIVATE, NOT ACTIVE [{0}]",
080                                                       className);
081            }
082        }
083    }
084
085    public static boolean isActive(String className) {
086        FaultInjection fi = getFaultInjection(className);
087        if (fi != null) {
088            className = className.substring(className.lastIndexOf(".") + 1);
089            if (fi.isActive()) {
090                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, ACTIVE [{0}]", className);
091                return true;
092            }
093            else {
094                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, NOT ACTIVE [{0}]", className);
095            }
096        }
097        return false;
098    }
099
100    public abstract boolean activate();
101
102    public abstract void deactivate();
103
104    public abstract boolean isActive();
105
106}