001/* 002 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved. 003 * 004 * http://www.izforge.com/izpack/ 005 * http://developer.berlios.de/projects/izpack/ 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020package com.izforge.izpack.uninstaller; 021 022import java.io.BufferedReader; 023import java.io.File; 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.ObjectInputStream; 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.Iterator; 030import java.util.List; 031import java.util.TreeSet; 032 033import com.izforge.izpack.ExecutableFile; 034import com.izforge.izpack.event.UninstallerListener; 035import com.izforge.izpack.util.AbstractUIProgressHandler; 036import com.izforge.izpack.util.FileExecutor; 037 038/** 039 * The files destroyer class. 040 * 041 * @author Julien Ponge 042 */ 043public class Destroyer extends Thread 044{ 045 046 /** True if the destroyer must force the recursive deletion. */ 047 private boolean forceDestroy; 048 049 /** The installation path. */ 050 private String installPath; 051 052 /** the destroyer listener. */ 053 private AbstractUIProgressHandler handler; 054 055 /** 056 * The constructor. 057 * 058 * @param installPath The installation path. 059 * @param forceDestroy Shall we force the recursive deletion. 060 * @param handler The destroyer listener. 061 */ 062 public Destroyer(String installPath, boolean forceDestroy, AbstractUIProgressHandler handler) 063 { 064 super("IzPack - Destroyer"); 065 066 this.installPath = installPath; 067 this.forceDestroy = forceDestroy; 068 this.handler = handler; 069 } 070 071 /** The run method. */ 072 public void run() 073 { 074 try 075 { 076 // We get the list of uninstaller listeners 077 List[] listeners = getListenerLists(); 078 // We get the list of the files to delete 079 ArrayList executables = getExecutablesList(); 080 081 FileExecutor executor = new FileExecutor(executables); 082 executor.executeFiles(ExecutableFile.UNINSTALL, this.handler); 083 084 ArrayList files = getFilesList(); 085 int size = files.size(); 086 087 // Custem action listener stuff --- beforeDeletion ---- 088 informListeners(listeners[0], UninstallerListener.BEFORE_DELETION, files, handler); 089 090 handler.startAction("destroy", size); 091 092 // We destroy the files 093 for (int i = 0; i < size; i++) 094 { 095 File file = (File) files.get(i); 096 // Custem action listener stuff --- beforeDelete ---- 097 informListeners(listeners[1], UninstallerListener.BEFORE_DELETE, file, handler); 098 099 file.delete(); 100 101 // Custem action listener stuff --- afterDelete ---- 102 informListeners(listeners[1], UninstallerListener.AFTER_DELETE, file, handler); 103 104 handler.progress(i, file.getAbsolutePath()); 105 } 106 107 // Custem action listener stuff --- afterDeletion ---- 108 informListeners(listeners[0], UninstallerListener.AFTER_DELETION, files, handler); 109 110 // We make a complementary cleanup 111 handler.progress(size, "[ cleanups ]"); 112 cleanup(new File(installPath)); 113 114 handler.stopAction(); 115 } 116 catch (Exception err) 117 { 118 handler.stopAction(); 119 err.printStackTrace(); 120 handler.emitError("exception caught", err.toString()); 121 } 122 } 123 124 /** 125 * Asks the JVM for the uninstaller deletion. 126 * 127 * @exception Exception Description of the Exception 128 */ 129// private void askUninstallerRemoval() throws Exception 130// { 131// // Initialisations 132// InputStream in = Destroyer.class.getResourceAsStream("/jarlocation.log"); 133// InputStreamReader inReader = new InputStreamReader(in); 134// BufferedReader reader = new BufferedReader(inReader); 135// 136// // We delete 137// File jar = new File(reader.readLine()); 138// File path = new File(reader.readLine()); 139// File inst = new File(installPath); 140// jar.deleteOnExit(); 141// path.deleteOnExit(); 142// inst.deleteOnExit(); 143// } 144 145 /** 146 * Returns an ArrayList of the files to delete. 147 * 148 * @return The files list. 149 * @exception Exception Description of the Exception 150 */ 151 private ArrayList getFilesList() throws Exception 152 { 153 // Initialisations 154 TreeSet files = new TreeSet(Collections.reverseOrder()); 155 InputStream in = Destroyer.class.getResourceAsStream("/install.log"); 156 InputStreamReader inReader = new InputStreamReader(in); 157 BufferedReader reader = new BufferedReader(inReader); 158 159 // We skip the first line (the installation path) 160 reader.readLine(); 161 162 // We read it 163 String read = reader.readLine(); 164 while (read != null) 165 { 166 files.add(new File(read)); 167 read = reader.readLine(); 168 } 169 170 // We return it 171 return new ArrayList(files); 172 } 173 174 private ArrayList getExecutablesList() throws Exception 175 { 176 ArrayList executables = new ArrayList(); 177 ObjectInputStream in = new ObjectInputStream(Destroyer.class 178 .getResourceAsStream("/executables")); 179 int num = in.readInt(); 180 for (int i = 0; i < num; i++) 181 { 182 ExecutableFile file = (ExecutableFile) in.readObject(); 183 executables.add(file); 184 } 185 return executables; 186 } 187 188 /** 189 * Makes some reccursive cleanups. 190 * 191 * @param file The file to wipe. 192 * @exception Exception Description of the Exception 193 */ 194 private void cleanup(File file) throws Exception 195 { 196 if (file.isDirectory()) 197 { 198 File[] files = file.listFiles(); 199 int size = files.length; 200 for (int i = 0; i < size; i++) 201 cleanup(files[i]); 202 file.delete(); 203 } 204 else if (forceDestroy) file.delete(); 205 206 } 207 208 // CUSTOM ACTION STUFF -------------- start ----------------- 209 210 /** 211 * Load the defined uninstall listener objects. 212 * 213 * @return a list with the defined uninstall listeners 214 * @throws Exception 215 */ 216 private List[] getListenerLists() throws Exception 217 { 218 ArrayList[] uninstaller = new ArrayList[] { new ArrayList(), new ArrayList()}; 219 // Load listeners if exist 220 InputStream in; 221 ObjectInputStream objIn; 222 in = Destroyer.class.getResourceAsStream("/uninstallerListeners"); 223 if (in != null) 224 { 225 objIn = new ObjectInputStream(in); 226 List listeners = (List) objIn.readObject(); 227 objIn.close(); 228 Iterator iter = listeners.iterator(); 229 while (iter != null && iter.hasNext()) 230 { 231 Class clazz = Class.forName(((String) iter.next())); 232 UninstallerListener ul = (UninstallerListener) clazz.newInstance(); 233 if (ul.isFileListener()) uninstaller[1].add(ul); 234 uninstaller[0].add(ul); 235 } 236 } 237 return uninstaller; 238 } 239 240 /** 241 * Informs all listeners. 242 * 243 * @param listeners list with the listener objects 244 * @param action identifier which callback should be called 245 * @param param parameter for the call 246 * @param handler the current progress handler 247 */ 248 249 private void informListeners(List listeners, int action, Object param, 250 AbstractUIProgressHandler handler) 251 { 252 // Iterate the action list. 253 Iterator iter = listeners.iterator(); 254 UninstallerListener il = null; 255 while (iter.hasNext()) 256 { 257 try 258 { 259 il = (UninstallerListener) iter.next(); 260 switch (action) 261 { 262 case UninstallerListener.BEFORE_DELETION: 263 il.beforeDeletion((List) param, handler); 264 break; 265 case UninstallerListener.AFTER_DELETION: 266 il.afterDeletion((List) param, handler); 267 break; 268 case UninstallerListener.BEFORE_DELETE: 269 il.beforeDelete((File) param, handler); 270 break; 271 case UninstallerListener.AFTER_DELETE: 272 il.afterDelete((File) param, handler); 273 break; 274 } 275 } 276 catch (Throwable e) 277 { // Catch it to prevent for a block of uninstallation. 278 handler.emitError("Skipping custom action because exception caught during " 279 + il.getClass().getName(), e.toString()); 280 } 281 } 282 } 283 284 // CUSTOM ACTION STUFF -------------- end ----------------- 285 286}