KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > autoupdate > catalog > ModuleDeleterImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.autoupdate.catalog;
21
22 import java.util.logging.Logger JavaDoc;
23 import org.netbeans.Module;
24 import org.openide.filesystems.FileUtil;
25 import org.openide.modules.InstalledFileLocator;
26 import org.openide.util.RequestProcessor;
27 import org.openide.xml.XMLUtil;
28
29 import java.io.File JavaDoc;
30 import java.io.FileInputStream JavaDoc;
31 import java.io.IOException JavaDoc;
32 import java.io.InputStream JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.logging.Level JavaDoc;
37 import org.openide.filesystems.FileObject;
38 import org.openide.filesystems.Repository;
39 import org.openide.util.Exceptions;
40
41 import org.w3c.dom.Document JavaDoc;
42 import org.w3c.dom.Element JavaDoc;
43 import org.w3c.dom.NamedNodeMap JavaDoc;
44 import org.w3c.dom.Node JavaDoc;
45 import org.w3c.dom.NodeList JavaDoc;
46 import org.xml.sax.InputSource JavaDoc;
47 import org.xml.sax.SAXException JavaDoc;
48
49
50 /** Control if the module's file can be deleted and can delete them from disk.
51  * <p> Deletes all files what are installed together with given module, info about
52  * these files read from <code>update_tracking</code> file corresponed to the module.
53  * If this <code>update_tracking</code> doesn't exist the files cannot be deleted.
54  * The Deleter waits until the module is enabled before start delete its files.
55  *
56  * @author Jiri Rechtacek
57  */

58 public final class ModuleDeleterImpl implements ModuleDeleter {
59
60     private static final String JavaDoc ELEMENT_MODULE = "module"; // NOI18N
61
private static final String JavaDoc ELEMENT_VERSION = "module_version"; // NOI18N
62
private static final String JavaDoc ATTR_ORIGIN = "origin"; // NOI18N
63
private static final String JavaDoc ATTR_LAST = "last"; // NOI18N
64
private static final String JavaDoc ATTR_FILE_NAME = "name"; // NOI18N
65
private static final String JavaDoc UPDATE_TRACKING = "update_tracking"; // NOI18N
66
private static final String JavaDoc INST_ORIGIN = "updater"; // NOI18N
67
private static final boolean ONLY_FROM_AUTOUPDATE = false;
68     private static final int TIME_TO_CHECK = 2000;
69     private static final int MAX_CHECKS_OF_STATE = 50;
70     private static final int HOLD_ON_PROPAGATE_DISABLE = 1000;
71     
72     private Logger JavaDoc err = Logger.getLogger("org.netbeans.modules.autoupdate.catalog.ModuleDeleterImpl"); // NOI18N
73

74     public boolean canDelete (Module module) {
75         if (module.isFixed ()) {
76             err.log(Level.FINE,
77                     "Cannot delete module because module " +
78                     module.getCodeName() + " isFixed.");
79         } else if (module.isAutoload ()) {
80             err.log(Level.FINE,
81                     "Cannot delete module because module " +
82                     module.getCodeName() + " isAutoload. See issue #74819.");
83         } else if (module.isEager ()) {
84             err.log(Level.FINE,
85                     "Cannot delete module because module " +
86                     module.getCodeName() + " isEager. See issue #74819.");
87         }
88         return ModuleNodeUtils.isUninstallAllowed (module) && findUpdateTracking (module, ONLY_FROM_AUTOUPDATE);
89     }
90     
91     public void delete (final Module module) throws IOException JavaDoc {
92         if (module == null) {
93             throw new IllegalArgumentException JavaDoc ("Module argument cannot be null.");
94         }
95         
96         err.log(Level.FINE,
97                 "Locate and remove config file of " + module.getCodeNameBase ());
98         removeControlModuleFile (module);
99         
100         RequestProcessor.Task cleaner = RequestProcessor.getDefault().create(new Runnable JavaDoc() {
101
102                                                  public void run() {
103                                                      try {
104                                                          removeModuleFiles(module);
105                                                      }
106                                                      catch (IOException JavaDoc ioe) {
107                                                          Exceptions.attachLocalizedMessage(ioe,
108                                                                                            "ERROR: During processing removeModuleFiles (" +
109                                                                                            module.getDisplayName() +
110                                                                                            ")");
111                                                          Exceptions.printStackTrace(ioe);
112                                                      }
113                                                  }
114                                              });
115         
116         // maybe there call refresh?
117
// XXX: RequestProcessor.post() is useless
118
if (! module.isAutoload () && ! module.isEager ()) {
119             RequestProcessor.getDefault ().post (new HackModuleListRefresher ());
120         }
121         
122         if (! module.isAutoload () && ! module.isEager ()) {
123             RequestProcessor.getDefault ().post (new ModuleStateChecker (module, cleaner), TIME_TO_CHECK);
124         } else {
125             cleaner.run ();
126         }
127     }
128
129     private File JavaDoc locateControlFile (Module m) {
130         String JavaDoc configFile = "config" + '/' + "Modules" + '/' + m.getCodeNameBase ().replace ('.', '-') + ".xml"; // NOI18N
131
return InstalledFileLocator.getDefault ().locate (configFile, m.getCodeNameBase (), false);
132     }
133     
134     private void removeControlModuleFile (Module m) throws IOException JavaDoc {
135         File JavaDoc configFile = null;
136         while ((configFile = locateControlFile (m)) != null) {
137             if (configFile != null && configFile.exists ()) {
138                 err.log(Level.FINE, "Try delete the config File " + configFile);
139                 FileUtil.toFileObject (configFile).delete ();
140             } else {
141                 err.log(Level.FINE,
142                         "Warning: Config File " + configFile + " doesn\'t exist!");
143             }
144         }
145     }
146     
147     private File JavaDoc locateUpdateTracking (Module m) {
148         String JavaDoc fileNameToFind = UPDATE_TRACKING + '/' + m.getCodeNameBase ().replace ('.', '-') + ".xml"; // NOI18N
149
return InstalledFileLocator.getDefault ().locate (fileNameToFind, m.getCodeNameBase (), false);
150     }
151     
152     private boolean findUpdateTracking (Module module, boolean checkIfFromAutoupdate) {
153         File JavaDoc updateTracking = locateUpdateTracking (module);
154         if (updateTracking != null && updateTracking.exists ()) {
155             //err.log ("Find UPDATE_TRACKING: " + updateTracking + " found.");
156
// check the write permission
157
if (! updateTracking.getParentFile ().canWrite ()) {
158                 err.log(Level.FINE,
159                         "Cannot delete module " + module.getCodeName() +
160                         " because no write permission to directory " +
161                         updateTracking.getParent());
162                 return false;
163             }
164             if (checkIfFromAutoupdate) {
165                 boolean isFromAutoupdate = fromAutoupdate (getModuleConfiguration (updateTracking));
166                 err.log(Level.FINE,
167                         "Is Module " + module.getCodeName() +
168                         " installed by AutoUpdate? " + isFromAutoupdate);
169                 return isFromAutoupdate;
170             } else {
171                 return true;
172             }
173         } else {
174             err.log(Level.FINE,
175                     "Cannot delete module " + module.getCodeName() +
176                     " because no update_tracking file found.");
177             return false;
178         }
179     }
180             
181     private boolean fromAutoupdate (Node JavaDoc moduleNode) {
182         Node JavaDoc attrOrigin = moduleNode.getAttributes ().getNamedItem (ATTR_ORIGIN);
183         assert attrOrigin != null : "ELEMENT_VERSION must contain ATTR_ORIGIN attribute.";
184         String JavaDoc origin = attrOrigin.getNodeValue ();
185         return INST_ORIGIN.equals (origin);
186     }
187     
188     private void removeModuleFiles (Module m) throws IOException JavaDoc {
189         err.log (Level.FINE, "Entry removing files of module " + m);
190         File JavaDoc updateTracking = null;
191         while ((updateTracking = locateUpdateTracking (m)) != null) {
192             removeModuleFilesInCluster (m, updateTracking);
193         }
194         err.log (Level.FINE, "Exit removing files of module " + m);
195     }
196     
197     private void removeModuleFilesInCluster (Module module, File JavaDoc updateTracking) throws IOException JavaDoc {
198         err.log(Level.FINE, "Read update_tracking " + updateTracking + " file.");
199         Set JavaDoc/*<String>*/ moduleFiles = readModuleFiles (getModuleConfiguration (updateTracking));
200         String JavaDoc configFile = "config" + '/' + "Modules" + '/' + module.getCodeNameBase ().replace ('.', '-') + ".xml"; // NOI18N
201
if (moduleFiles.contains (configFile)) {
202             File JavaDoc file = InstalledFileLocator.getDefault ().locate (configFile, module.getCodeNameBase (), false);
203             assert file == null || ! file.exists () : "Config file " + configFile + " must be already removed.";
204         }
205         Iterator JavaDoc it = moduleFiles.iterator ();
206         while (it.hasNext ()) {
207             String JavaDoc fileName = (String JavaDoc) it.next ();
208             if (fileName.equals (configFile)) {
209                 continue;
210             }
211             File JavaDoc file = InstalledFileLocator.getDefault ().locate (fileName, module.getCodeNameBase (), false);
212             if (file.equals (updateTracking)) {
213                 continue;
214             }
215             assert file.exists () : "File " + file + " exists.";
216             if (file.exists ()) {
217                 err.log(Level.FINE, "File " + file + " is deleted.");
218                 try {
219                     FileUtil.toFileObject (file).delete ();
220                 } catch (IOException JavaDoc ioe) {
221                     assert false : "Waring: IOException " + ioe.getMessage () + " was caught. Propably file lock on the file.";
222                     err.log(Level.FINE,
223                             "Waring: IOException " + ioe.getMessage() +
224                             " was caught. Propably file lock on the file.");
225                     err.log(Level.FINE,
226                             "Try call File.deleteOnExit() on " + file);
227                     file.deleteOnExit ();
228                 }
229             }
230         }
231         FileUtil.toFileObject (updateTracking).delete ();
232         err.log(Level.FINE, "File " + updateTracking + " is deleted.");
233     }
234     
235     private Node JavaDoc getModuleConfiguration (File JavaDoc moduleUpdateTracking) {
236         Document JavaDoc document = null;
237         InputStream JavaDoc is;
238         try {
239             is = new FileInputStream JavaDoc (moduleUpdateTracking);
240             InputSource JavaDoc xmlInputSource = new InputSource JavaDoc (is);
241             document = XMLUtil.parse (xmlInputSource, false, false, null, org.openide.xml.EntityCatalog.getDefault ());
242             if (is != null) {
243                 is.close ();
244             }
245         } catch (SAXException JavaDoc saxe) {
246             err.log(Level.WARNING, null, saxe);
247             return null;
248         } catch (IOException JavaDoc ioe) {
249             err.log(Level.WARNING, null, ioe);
250         }
251
252         assert document.getDocumentElement () != null : "File " + moduleUpdateTracking + " must contain <module> element.";
253         return getModuleElement (document.getDocumentElement ());
254     }
255     
256     private Node JavaDoc getModuleElement (Element JavaDoc element) {
257         Node JavaDoc lastElement = null;
258         assert ELEMENT_MODULE.equals (element.getTagName ()) : "The root element is: " + ELEMENT_MODULE + " but was: " + element.getTagName ();
259         NodeList JavaDoc listModuleVersions = element.getElementsByTagName (ELEMENT_VERSION);
260         for (int i = 0; i < listModuleVersions.getLength (); i++) {
261             lastElement = getModuleLastVersion (listModuleVersions.item (i));
262             if (lastElement != null) {
263                 break;
264             }
265         }
266         return lastElement;
267     }
268     
269     private Node JavaDoc getModuleLastVersion (Node JavaDoc version) {
270         Node JavaDoc attrLast = version.getAttributes ().getNamedItem (ATTR_LAST);
271         assert attrLast != null : "ELEMENT_VERSION must contain ATTR_LAST attribute.";
272         if (Boolean.valueOf (attrLast.getNodeValue ()).booleanValue ()) {
273             return version;
274         } else {
275             return null;
276         }
277     }
278     
279     private Set JavaDoc/*<String>*/ readModuleFiles (Node JavaDoc version) {
280         Set JavaDoc/*<String>*/ files = new HashSet JavaDoc ();
281         NodeList JavaDoc fileNodes = version.getChildNodes ();
282         for (int i = 0; i < fileNodes.getLength (); i++) {
283             if (fileNodes.item (i).hasAttributes ()) {
284                 NamedNodeMap JavaDoc map = fileNodes.item (i).getAttributes ();
285                 files.add (map.getNamedItem (ATTR_FILE_NAME).getNodeValue ());
286                 err.log(Level.FINE,
287                         "Mark to delete: " +
288                         map.getNamedItem(ATTR_FILE_NAME).getNodeValue());
289             }
290         }
291         return files;
292     }
293
294     private class ModuleStateChecker implements Runnable JavaDoc {
295         RequestProcessor.Task cleaner;
296         Module m;
297         int checks;
298         public ModuleStateChecker (Module module, RequestProcessor.Task filesCleaner) {
299             cleaner = filesCleaner;
300             m = module;
301             checks = 0;
302         }
303         
304         public void run () {
305             checks ++;
306             if (m.isEnabled () && m.isValid ()) {
307                 if (checks < MAX_CHECKS_OF_STATE) {
308                     err.log(Level.FINE,
309                             "Module " + m.getCodeNameBase() +
310                             " is still valid, repost later.");
311                     RequestProcessor.getDefault ().post (this, TIME_TO_CHECK);
312                 } else {
313                     err.log(Level.FINE,
314                             "Warning: Module " + m.getCodeNameBase() +
315                             " is still valid but time-out. Task is terminated.");
316                 }
317                 return ;
318             }
319             
320             // post clean task
321
cleaner.schedule (HOLD_ON_PROPAGATE_DISABLE);
322         }
323         
324     }
325     
326     private class HackModuleListRefresher implements Runnable JavaDoc {
327         public void run () {
328             // XXX: the modules list should be delete automatically when config/Modules/module.xml is removed
329
FileObject modulesRoot = Repository.getDefault ().getDefaultFileSystem ().findResource ("Modules"); // NOI18N
330
err.log(Level.FINE,
331                     "It\'s a hack: Call refresh on " + modulesRoot +
332                     " file object.");
333             if (modulesRoot != null) {
334                 modulesRoot.refresh ();
335             }
336             // end of hack
337
}
338     }
339 }
340
Popular Tags