1 /* 2 Copyright (C) 2004 Grid Systems, S.A. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2, as 6 published by the Free Software Foundation. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program; if not, write to the Free Software 15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 */ 17 package com.gridsystems.storage; 18 19 import java.io.File; 20 import java.lang.reflect.Constructor; 21 import java.lang.reflect.Method; 22 import java.util.Map; 23 24 import org.apache.commons.logging.Log; 25 import org.apache.commons.logging.LogFactory; 26 27 /** 28 * This class manages the safe load and stores. 29 * 30 * @version 1.0 31 */ 32 public final class FailSafeManager { 33 34 /** 35 * Class logger. 36 */ 37 private static final Log LOG = LogFactory.getLog(FailSafeManager.class); 38 39 /** 40 * Constructor. 41 */ 42 private FailSafeManager() { } 43 44 /** 45 * Manages the store information of the class. 46 * 47 * @param data The FailSafe instance to manage 48 * @throws Exception if the files cannot be stored correctly. 49 */ 50 public static void store(FailSafe data) throws Exception { 51 synchronized (data) { 52 try { 53 String[] fl = data.getFileNameList(); 54 String[] flbak = new String[fl.length]; 55 for (int i = 0; i < fl.length; i++) { 56 flbak[i] = fl[i] + ".bak"; 57 } 58 // First, it stores backup files 59 data.store(flbak); 60 61 // Once backups are made, stores actual files 62 data.store(fl); 63 } catch (Exception e) { 64 data.recoverFromStoreError(e); 65 } 66 } 67 } 68 69 /** 70 * Manages all load information of the class. 71 * 72 * @param data The FailSafe instance to manage 73 * @throws Exception if the files cannot be loaded correctly. 74 */ 75 public static void load(FailSafe data) throws Exception { 76 synchronized (data) { 77 String[] fl = data.getFileNameList(); 78 try { 79 data.load(fl); //load files 80 } catch (Exception e) { 81 //If there is any exception try to load backup file 82 try { 83 String[] flbak = new String[fl.length]; 84 for (int i = 0; i < fl.length; i++) { 85 flbak[i] = fl[i] + ".bak"; 86 } 87 data.load(flbak); //store backup files 88 data.store(fl); 89 } catch (Exception e1) { 90 data.recoverFromLoadError(e1); 91 } 92 } 93 } 94 } 95 96 /** 97 * Manages all load information of the class. 98 * <p> 99 * As this method does not use initialization data, it is preferred to use it 100 * only with classes implementing the Singleton pattern. 101 * 102 * @param c The class to load 103 * @return An initialized instance of the class 104 * @throws Exception In case of execution error 105 */ 106 public static FailSafe load(Class c) throws Exception { 107 return load(c, null); 108 } 109 110 /** 111 * Manages all load information of the class. 112 * <p> 113 * The map parameter will be used as the argument for the constructor. If no 114 * appropriate constructor is found, it will fall back to the "no-argument" 115 * version. 116 * 117 * @param c The class to load 118 * @param map The map to pass to the constructor 119 * @return An initialized instance of the class 120 * @throws Exception In case of execution error 121 */ 122 public static FailSafe load(Class c, Map map) throws Exception { 123 FailSafe fs = (FailSafe)instantiate(c, map, Map.class); 124 load(fs); 125 return fs; 126 } 127 128 /** 129 * Manages all load information of the class. 130 * <p> 131 * The object parameter will be used as the argument for the constructor. The object 132 * must be exactly of the same class than the expected constructor parameter. If no 133 * appropriate constructor is found, it will fall back to the "no-argument" 134 * version. 135 * 136 * @param c The class to load 137 * @param obj The object to pass to the constructor 138 * @return An initialized instance of the class 139 * @throws Exception In case of execution error 140 */ 141 public static FailSafe load(Class c, Object obj) throws Exception { 142 FailSafe fs = (FailSafe)instantiate(c, obj, obj == null ? null : obj.getClass()); 143 load(fs); 144 return fs; 145 } 146 147 /** 148 * Deletes all files (including backups) for the specified FailSafe instance. 149 * 150 * @param fs The instance whose files to delete 151 * @throws Exception In case of execution error 152 */ 153 public static void delete(FailSafe fs) throws Exception { 154 String[] files = fs.getFileNameList(); 155 156 int count = files == null ? 0 : files.length; 157 for (int i = 0; i < count; i++) { 158 attemptDelete(new File(files[i])); 159 attemptDelete(new File(files[i] + ".bak")); 160 } 161 } 162 163 /** 164 * Tries to delete a file. If it is not possible, logs the failure and 165 * marks the file for deletion on exit. 166 * 167 * @param f The file to delete 168 */ 169 private static void attemptDelete(File f) { 170 if (f != null && f.exists() && !f.delete()) { 171 LOG.info("Could not delete file '" + f.getPath() + "'"); 172 f.deleteOnExit(); 173 } 174 } 175 176 /** 177 * Creates a new instance of the specified class. 178 * <p> 179 * It first checks the existence of an static getInstance() method, and if found, it 180 * uses it. If no getInstance method is found, or an invocation error occurs, it 181 * tries to use the default constructor. If this also fails, it returns null. 182 * 183 * @param c The class to instantiate 184 * @return An instance of class c, or null 185 */ 186 private static Object instantiate(Class c) { 187 try { 188 Method m = c.getMethod("getInstance"); 189 return m.invoke(null); 190 } catch (Exception e) { 191 try { 192 return c.newInstance(); 193 } catch (Exception ee) { 194 return null; 195 } 196 } 197 } 198 199 /** 200 * Creates a new instance of the specified class using an initializer constructor. 201 * <p> 202 * It first checks the existence of an static getInstance() method, and if found, it 203 * uses it. If no getInstance method is found, or an invocation error occurs, it 204 * tries to use the default constructor. If this also fails, it returns null. 205 * 206 * @param c The class to instantiate 207 * @param obj The object to pass to the constructor 208 * @param objType The type of the parameter 209 * @return An instance of class c, or null 210 */ 211 private static Object instantiate(Class c, Object obj, Class objType) { 212 if (obj != null) { 213 try { 214 Constructor constr = c.getConstructor(new Class[] { objType }); 215 return constr.newInstance(new Object[] { obj }); 216 } catch (Exception e) { } 217 } 218 return instantiate(c); 219 } 220 }