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    package org.apache.oozie;
019    
020    import 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     */
031    public 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    }