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