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 }