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 */
018package org.apache.oozie;
019
020import org.apache.oozie.util.XLog;
021
022/**
023 * Fault Injection support class. <p/> Concrete classes should be available only during testing, not in production. <p/>
024 * To activate fault injection the {@link #FAULT_INJECTION} system property must be set to true. <p/> When fault
025 * injection is activated, the concrete class (specified by name) will be call for activation. <p/> Concrete classes
026 * should be activated by presense of a second system property. <p/> This fault injection pattern provides 3 levels of
027 * safeguard: a general 'fault injection' system property, the availabity of of the concrete 'fault injection' class in
028 * the classpath, a specifi 'fault injection' system property. <p/> Refer to the <code>SkipCommitFaultInjection</code>
029 * class in the test classes for an example.
030 */
031public abstract class FaultInjection {
032
033    public static final String FAULT_INJECTION = "oozie.fault.injection";
034
035    private static FaultInjection getFaultInjection(String className) {
036        if (Boolean.parseBoolean(System.getProperty(FAULT_INJECTION, "false"))) {
037            try {
038                Class klass = Thread.currentThread().getContextClassLoader().loadClass(className);
039                return (FaultInjection) klass.newInstance();
040            }
041            catch (ClassNotFoundException ex) {
042                XLog.getLog(FaultInjection.class).warn("Trying to activate fault injection in production", ex);
043            }
044            catch (IllegalAccessException ex) {
045                throw new RuntimeException(XLog.format("Could not initialize [{0}]", className, ex), ex);
046            }
047            catch (InstantiationException ex) {
048                throw new RuntimeException(XLog.format("Could not initialize [{0}]", className, ex), ex);
049            }
050        }
051        return null;
052    }
053
054    public static boolean activate(String className) {
055        FaultInjection fi = getFaultInjection(className);
056        if (fi != null) {
057            className = className.substring(className.lastIndexOf(".") + 1);
058            if (fi.activate()) {
059                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, ACTIVATING [{0}]", className);
060                return true;
061            }
062            else {
063                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, DID NOT ACTIVATE [{0}]", className);
064            }
065        }
066        return false;
067    }
068
069    public static void deactivate(String className) {
070        FaultInjection fi = getFaultInjection(className);
071        if (fi != null) {
072            className = className.substring(className.lastIndexOf(".") + 1);
073            if (fi.isActive()) {
074                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, DEACTIVATING [{0}]", className);
075                fi.deactivate();
076            }
077            else {
078                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, CANNOT DEACTIVATE, NOT ACTIVE [{0}]",
079                                                       className);
080            }
081        }
082    }
083
084    public static boolean isActive(String className) {
085        FaultInjection fi = getFaultInjection(className);
086        if (fi != null) {
087            className = className.substring(className.lastIndexOf(".") + 1);
088            if (fi.isActive()) {
089                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, ACTIVE [{0}]", className);
090                return true;
091            }
092            else {
093                XLog.getLog(FaultInjection.class).warn("FAULT INJECTION, NOT ACTIVE [{0}]", className);
094            }
095        }
096        return false;
097    }
098
099    public abstract boolean activate();
100
101    public abstract void deactivate();
102
103    public abstract boolean isActive();
104
105}