KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > persistence > PersistenceManager


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.core.windows.persistence;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.InvalidObjectException JavaDoc;
29 import java.io.NotSerializableException JavaDoc;
30 import java.lang.ref.Reference JavaDoc;
31 import java.lang.ref.WeakReference JavaDoc;
32 import java.lang.reflect.Method JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.Enumeration JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Set JavaDoc;
43 import java.util.WeakHashMap JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46 import org.netbeans.core.windows.Debug;
47 import org.openide.cookies.InstanceCookie;
48 import org.openide.cookies.SaveCookie;
49 import org.openide.filesystems.FileLock;
50 import org.openide.filesystems.FileObject;
51 import org.openide.filesystems.FileUtil;
52 import org.openide.filesystems.Repository;
53 import org.openide.loaders.DataFolder;
54 import org.openide.loaders.DataObject;
55 import org.openide.loaders.DataObjectNotFoundException;
56 import org.openide.loaders.InstanceDataObject;
57 import org.openide.modules.ModuleInfo;
58 import org.openide.modules.SpecificationVersion;
59 import org.openide.util.Exceptions;
60 import org.openide.util.Lookup;
61 import org.openide.util.NbBundle;
62 import org.openide.util.io.SafeException;
63 import org.openide.windows.TopComponent;
64 import org.openide.xml.XMLUtil;
65 import org.xml.sax.EntityResolver JavaDoc;
66 import org.xml.sax.InputSource JavaDoc;
67 import org.xml.sax.SAXException JavaDoc;
68 import org.xml.sax.XMLReader JavaDoc;
69 import org.xml.sax.helpers.DefaultHandler JavaDoc;
70
71 /** Manages persistent data of window system, currently stored in XML format.
72  * Default setting of layers is that reading is done through default file system
73  * and writing into project layer.
74  *
75  * @author Dafe Simonek
76  */

77 public final class PersistenceManager implements PropertyChangeListener JavaDoc {
78     /** logger of what is happening in persistance */
79     static final Logger JavaDoc LOG = Logger.getLogger("org.netbeans.core.windows.persistence"); // NOI18N
80

81
82     /** Constants for default root folder name for winsys data representation */
83     static final String JavaDoc ROOT_MODULE_FOLDER = "Windows2"; // NOI18N
84
public static final String JavaDoc ROOT_LOCAL_FOLDER = "Windows2Local"; // NOI18N
85
static final String JavaDoc WINDOWMANAGER_FOLDER = "WindowManager"; // NOI18N
86
static final String JavaDoc GROUPS_FOLDER = "Groups"; // NOI18N
87
static final String JavaDoc MODES_FOLDER = "Modes"; // NOI18N
88
public static final String JavaDoc COMPS_FOLDER = "Components"; // NOI18N
89

90     /** Constants for file extensions that winsys uses */
91     public static final String JavaDoc WINDOWMANAGER_EXT = "wswmgr"; // NOI18N
92
public static final String JavaDoc WORKSPACE_EXT = "wswksp"; // NOI18N
93
public static final String JavaDoc MODE_EXT = "wsmode"; // NOI18N
94
public static final String JavaDoc TCREF_EXT = "wstcref"; // NOI18N
95
public static final String JavaDoc GROUP_EXT = "wsgrp"; // NOI18N
96
public static final String JavaDoc TCGROUP_EXT = "wstcgrp"; // NOI18N
97
public static final String JavaDoc COMPONENT_EXT = "settings"; // NOI18N
98

99     /** default base name for noname top components */
100     private static final String JavaDoc DEFAULT_TC_NAME = "untitled_tc"; // NOI18N
101

102     private static final boolean DEBUG = Debug.isLoggable(PersistenceManager.class);
103     
104     /** Root folder for win sys module */
105     private FileObject rootModuleFolder;
106     /** Root folder for win sys local */
107     private FileObject rootLocalFolder;
108     
109     /** Components module folder */
110     private FileObject compsModuleFolder;
111     
112     /** Groups folder */
113     private FileObject groupsModuleFolder;
114     /** Groups folder */
115     private FileObject groupsLocalFolder;
116     
117     /** Module modes folder */
118     private FileObject modesModuleFolder;
119     /** Local modes folder */
120     private FileObject modesLocalFolder;
121     
122     /** Loading/saving of window system configuration data */
123     private WindowManagerParser windowManagerParser;
124     
125     /** Handler of changes in module folder */
126     private ModuleChangeHandler changeHandler;
127     
128     /** Weak hash map between persistent TopComponents and their string IDs, used in lookup */
129     //<key=TopComponent, value=String>
130
private final Map JavaDoc<TopComponent, String JavaDoc> topComponent2IDMap = new WeakHashMap JavaDoc<TopComponent, String JavaDoc>(30);
131     
132     /** Weak hash map between nonpersistent TopComponents and their string IDs, used in lookup */
133     //<key=TopComponent, value=String>
134
private final Map JavaDoc<TopComponent, String JavaDoc> topComponentNonPersistent2IDMap =
135             new WeakHashMap JavaDoc<TopComponent, String JavaDoc>(30);
136     
137     /** Contains already used TopComponent ID. It is used to make sure unique
138      * ID is created for every TopComponent instance */

139     private Set JavaDoc<String JavaDoc> globalIDSet = new HashSet JavaDoc<String JavaDoc>(30);
140     
141     /** Map between string ids and weakly hold top components */
142     private final Map JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>> id2TopComponentMap =
143             Collections.synchronizedMap(new HashMap JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>>(30));
144     
145     /** Map between string ids and weakly hold top components */
146     private final Map JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>> id2TopComponentNonPersistentMap =
147             Collections.synchronizedMap(new HashMap JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>>(30));
148     
149     /** Weak map between data objects and top components, used to clean cache when module
150      * owning tc is disabled. */

151     private final Map JavaDoc<DataObject, String JavaDoc> dataobjectToTopComponentMap =
152             new WeakHashMap JavaDoc<DataObject, String JavaDoc>(30);
153     
154     /** A set of invalid Ids */
155     private Set JavaDoc invalidIds = new HashSet JavaDoc(10);
156     
157     /** A set of used TcIds. Used to clean unused settings files
158      * (ie. not referenced from tcRef or tcGroup). Cleaning is performed
159      * when window system is loaded. */

160     private final Set JavaDoc<String JavaDoc> usedTcIds = new HashSet JavaDoc<String JavaDoc>(10); // <String>
161

162     /** Lock for synchronizing access to IDs. */
163     private final Object JavaDoc LOCK_IDS = new Object JavaDoc();
164     
165     /** xml parser */
166     private XMLReader JavaDoc parser;
167     
168     private static PersistenceManager defaultInstance;
169     
170     /** Creates new PersistenceManager */
171     private PersistenceManager() {
172     }
173     
174     /** Returns reference to singleton instance of PersistenceManager.
175      */

176     public static synchronized PersistenceManager getDefault() {
177         if(defaultInstance == null) {
178             defaultInstance = new PersistenceManager();
179         }
180         
181         return defaultInstance;
182     }
183
184     public void reset() {
185         rootModuleFolder = null;
186         rootLocalFolder = null;
187         compsModuleFolder = null;
188         groupsModuleFolder = null;
189         groupsLocalFolder = null;
190         modesModuleFolder = null;
191         modesLocalFolder = null;
192         windowManagerParser = null;
193         if (changeHandler != null) {
194             changeHandler.stopHandling();
195         }
196         changeHandler = null;
197     }
198     
199     /** Clears our internal state. */
200     public void clear() {
201         reset();
202         topComponent2IDMap.clear();
203         topComponentNonPersistent2IDMap.clear();
204         globalIDSet = new HashSet JavaDoc<String JavaDoc>(30);
205         id2TopComponentMap.clear();
206         id2TopComponentNonPersistentMap.clear();
207         dataobjectToTopComponentMap.clear();
208         invalidIds = new HashSet JavaDoc(10);
209         usedTcIds.clear();
210     }
211     
212     FileObject getRootModuleFolder () throws IOException JavaDoc {
213         try {
214             if (rootModuleFolder == null) {
215                 rootModuleFolder = FileUtil.createFolder(
216                     Repository.getDefault().getDefaultFileSystem().getRoot(), ROOT_MODULE_FOLDER
217                 );
218             }
219             return rootModuleFolder;
220         } catch (IOException JavaDoc exc) {
221             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
222                 "EXC_RootFolder", ROOT_MODULE_FOLDER);
223             Exceptions.attachLocalizedMessage(exc, annotation);
224             throw exc;
225         }
226     }
227     
228     FileObject getRootLocalFolder () throws IOException JavaDoc {
229         try {
230             if (rootLocalFolder == null) {
231                 rootLocalFolder = FileUtil.createFolder(
232                     Repository.getDefault().getDefaultFileSystem().getRoot(), ROOT_LOCAL_FOLDER
233                 );
234             }
235             return rootLocalFolder;
236         } catch (IOException JavaDoc exc) {
237             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
238                 "EXC_RootFolder", ROOT_LOCAL_FOLDER);
239             Exceptions.attachLocalizedMessage(exc, annotation);
240             throw exc;
241         }
242     }
243     
244     /** Sets root module folder for window system configuration data. It is used
245      * by tests to be able to test on test data.
246      */

247     void setRootModuleFolder (FileObject rootModuleFolder) {
248         this.rootModuleFolder = rootModuleFolder;
249     }
250     
251     /** Sets root local folder for window system configuration data. It is used
252      * by tests to be able to test on test data.
253      */

254     void setRootLocalFolder (FileObject rootLocalFolder) {
255         this.rootLocalFolder = rootLocalFolder;
256     }
257
258     /** @return Module folder for TopComponents */
259     public FileObject getComponentsModuleFolder () throws IOException JavaDoc {
260         try {
261             if (compsModuleFolder == null) {
262                 compsModuleFolder = FileUtil.createFolder(
263                     getRootModuleFolder(), COMPS_FOLDER
264                 );
265             }
266             return compsModuleFolder;
267         } catch (IOException JavaDoc exc) {
268             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
269                 "EXC_CompsFolder", COMPS_FOLDER);
270             Exceptions.attachLocalizedMessage(exc, annotation);
271             throw exc;
272         }
273     }
274     
275     /** @return Local folder for TopComponents. Do not cache ti because it can change
276      * during project switch. */

277     public FileObject getComponentsLocalFolder () throws IOException JavaDoc {
278         try {
279             FileObject compsLocalFolder = FileUtil.createFolder(
280                 getRootLocalFolder(), COMPS_FOLDER
281             );
282             return compsLocalFolder;
283         } catch (IOException JavaDoc exc) {
284             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
285                 "EXC_CompsFolder", COMPS_FOLDER);
286             Exceptions.attachLocalizedMessage(exc, annotation);
287             throw exc;
288         }
289     }
290     
291     /** @return Module folder for groups */
292     public FileObject getGroupsModuleFolder () throws IOException JavaDoc {
293         try {
294             if (groupsModuleFolder == null) {
295                 groupsModuleFolder = FileUtil.createFolder(
296                     getRootModuleFolder(), GROUPS_FOLDER
297                 );
298             }
299             return groupsModuleFolder;
300         } catch (IOException JavaDoc exc) {
301             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
302                 "EXC_GroupsFolder", GROUPS_FOLDER);
303             Exceptions.attachLocalizedMessage(exc, annotation);
304             throw exc;
305         }
306     }
307     
308     /** @return Folder for groups */
309     public FileObject getGroupsLocalFolder () throws IOException JavaDoc {
310         try {
311             if (groupsLocalFolder == null) {
312                 groupsLocalFolder = FileUtil.createFolder(
313                     getRootLocalFolder(), GROUPS_FOLDER
314                 );
315             }
316             return groupsLocalFolder;
317         } catch (IOException JavaDoc exc) {
318             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
319                 "EXC_GroupsFolder", GROUPS_FOLDER);
320             Exceptions.attachLocalizedMessage(exc, annotation);
321             throw exc;
322         }
323     }
324     
325     /** @return Module folder for modes */
326     public FileObject getModesModuleFolder () throws IOException JavaDoc {
327         try {
328             if (modesModuleFolder == null) {
329                 modesModuleFolder = FileUtil.createFolder(
330                     getRootModuleFolder(), MODES_FOLDER
331                 );
332             }
333             return modesModuleFolder;
334         } catch (IOException JavaDoc exc) {
335             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
336                 "EXC_ModesFolder", MODES_FOLDER);
337             Exceptions.attachLocalizedMessage(exc, annotation);
338             throw exc;
339         }
340     }
341     
342     /** @return Local folder for modes */
343     public FileObject getModesLocalFolder () throws IOException JavaDoc {
344         try {
345             if (modesLocalFolder == null) {
346                 modesLocalFolder = FileUtil.createFolder(
347                     getRootLocalFolder(), MODES_FOLDER
348                 );
349             }
350             return modesLocalFolder;
351         } catch (IOException JavaDoc exc) {
352             String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
353                 "EXC_ModesFolder", MODES_FOLDER);
354             Exceptions.attachLocalizedMessage(exc, annotation);
355             throw exc;
356         }
357     }
358     
359     /** Listens to property changes in InstanceDataObject. Used to clean top component
360      * cache when module owning given top component is disabled. */

361     public void propertyChange (PropertyChangeEvent JavaDoc evt) {
362         if (DataObject.PROP_COOKIE.equals(evt.getPropertyName())) {
363             Object JavaDoc obj = evt.getSource();
364             removeTopComponentForDataObject((DataObject)obj);
365         }
366     }
367     
368     private void removeTopComponentForDataObject(DataObject dob) {
369         //System.out.println("PM.removeTopComponentForDataObject ENTER"
370
//+ " dob:" + dob.getName());
371
InstanceCookie ic = (InstanceCookie)dob.getCookie(InstanceCookie.class);
372         //Remove corresponding tc from cache because its module was disabled
373
if (ic == null) {
374             synchronized(LOCK_IDS) {
375                 String JavaDoc tc_id = (String JavaDoc) dataobjectToTopComponentMap.remove(dob);
376                 if (tc_id != null) {
377                     /*System.out.println("- - - - - - - - - - - - - - - - - - - - -");
378                     System.out.println("-- -- PM.removeTopComponentForDataObject"
379                     + " tc_id:" + tc_id);
380                     System.out.println("-- -- dob:" + dob.getClass().getName()
381                     + " isValid:" + dob.isValid());*/

382                     //Thread.dumpStack();
383
WeakReference JavaDoc result = (WeakReference JavaDoc)id2TopComponentMap.remove(tc_id);
384                     if (result != null) {
385                         TopComponent tc = (TopComponent)result.get();
386                         if (tc != null) {
387                             topComponent2IDMap.remove(tc);
388                         }
389                     }
390                 }
391             }
392         }
393     }
394     
395     /** Returns unique TopComponent ID for given TopComponent both persistent
396      * and non persistent.
397      * @param tc TopComponent the component for which is ID returned
398      * @param preferredID first approximation used for creation of unique ID
399      * @return unique TopComponent ID
400      */

401     public String JavaDoc getGlobalTopComponentID (TopComponent tc, String JavaDoc preferredID) {
402         synchronized(LOCK_IDS) {
403             //First check caches
404
String JavaDoc result = (String JavaDoc) topComponent2IDMap.get(tc);
405             if (result != null) {
406                 if (isInvalidId(result)) {
407                     restorePair(tc, result);
408                 }
409                 return result;
410             }
411             result = (String JavaDoc) topComponentNonPersistent2IDMap.get(tc);
412             if (result != null) {
413                 return result;
414             }
415         }
416         
417         //Not found create new TopComponent Id
418
if (isTopComponentProbablyPersistent(tc)) {
419             try {
420                 return createTopComponentPersistentID(tc, preferredID);
421             } catch (IOException JavaDoc exc) {
422                 LOG.log(Level.WARNING, "[Winsys.PersistenceManager.getGlobalTopComponentID]: Cannot create TC ID", exc); //NOI18N
423
return createTopComponentNonPersistentID(tc, preferredID);
424             }
425         } else {
426             return createTopComponentNonPersistentID(tc, preferredID);
427         }
428     }
429     
430     /** performance related, TCs get GCed anyway, but the strings were kept in the maps.
431      * make sure you call this only on TCs that are NOT TC.PERSISTENT_ALWAYS
432      */

433     public void removeGlobalTopComponentID(String JavaDoc id) {
434 // System.out.println("removing id=" + id);
435
synchronized(LOCK_IDS) {
436             globalIDSet.remove(id.toUpperCase(Locale.ENGLISH));
437             WeakReference JavaDoc result = (WeakReference JavaDoc)id2TopComponentMap.remove(id);
438             if (result != null) {
439                 TopComponent tc = (TopComponent)result.get();
440                 if (tc != null) {
441                     topComponent2IDMap.remove(tc);
442                 }
443             }
444             result = (WeakReference JavaDoc)id2TopComponentNonPersistentMap.remove(id);
445             if (result != null) {
446                 TopComponent tc = (TopComponent)result.get();
447                 if (tc != null) {
448                     topComponentNonPersistent2IDMap.remove(tc);
449                 }
450             }
451         }
452     }
453     
454     /** @return Searches for top component with given string id and returns
455      * found lookup item.
456      */

457     private TopComponent getTopComponentPersistentForID(String JavaDoc stringId) {
458         synchronized(LOCK_IDS) {
459             //Search in cache first
460
WeakReference JavaDoc result = (WeakReference JavaDoc)id2TopComponentMap.get(stringId);
461             if (result != null) {
462                 TopComponent tc = (TopComponent)result.get();
463                 if (tc != null) {
464                     return tc;
465                 } else {
466                     //TopComponent instance was garbage collected.
467
id2TopComponentMap.remove(stringId);
468                 }
469             }
470         }
471         // search on disk
472
IOException JavaDoc resultExc = null;
473         try {
474             DataObject dob = findTopComponentDataObject(getComponentsLocalFolder(), stringId);
475             if (dob == null) {
476                 // #84101, 85052: try to find component in module folder also, used in "safe" mode
477
// when loading winsys config from local folders failed for some IOExc reason
478
dob = findTopComponentDataObject(getComponentsModuleFolder(), stringId);
479             }
480             if (dob != null) {
481                 InstanceCookie ic = (InstanceCookie)dob.getCookie(InstanceCookie.class);
482                 if (ic != null) {
483                     TopComponent tc = (TopComponent)ic.instanceCreate();
484                     synchronized(LOCK_IDS) {
485                         topComponent2IDMap.put(tc, stringId);
486                         id2TopComponentMap.put(stringId, new WeakReference JavaDoc<TopComponent>(tc));
487                         dataobjectToTopComponentMap.put(dob, stringId);
488                     }
489                     dob.addPropertyChangeListener(this);
490                     return tc;
491                 } else {
492                     // no instance cookie, which means that module which owned top
493
// component is gone or versions of data and module are incompatible
494
String JavaDoc excAnnotation = NbBundle.getMessage(
495                             PersistenceManager.class, "EXC_BrokenTCSetting",
496                             stringId);
497                     resultExc = new SafeException(new IOException JavaDoc(excAnnotation));
498                     LOG.log(Level.WARNING,
499                         "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
500
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
501
+ excAnnotation, resultExc);
502                 }
503             }
504             else {
505                 // not found
506
String JavaDoc excAnnotation = NbBundle.getMessage(PersistenceManager.class,
507                         "EXC_FailedLocateTC", stringId);
508                 resultExc = new FileNotFoundException JavaDoc(excAnnotation);
509                 LOG.warning(
510                     "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
511
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
512
+ excAnnotation);
513 // can happen quite often when switching projects (in pre-40 codebase).. TC are project layer based while the winmanager+mainwindow are session based.
514
// IMHO not really a problem. (mkleint) - issue #40244
515
// with new projects should not happen, since projects are not switched in winsys anymore.
516
// ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, resultExc);
517
}
518         } catch (NoClassDefFoundError JavaDoc ndfe) { // TEMP>>
519
LOG.log(Level.WARNING,
520                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
521
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
522
+ ndfe.getMessage(), ndfe);
523         } catch (InvalidObjectException JavaDoc ioe) {
524             LOG.log(Level.WARNING,
525                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
526
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
527
+ ioe.getMessage(), ioe);
528         } catch (DataObjectNotFoundException dnfe) {
529             LOG.log(Level.WARNING,
530                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
531
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
532
+ " Object not found: " + dnfe.getMessage() // NOI18N
533
+ ". It was probably deleted.", dnfe); // NOI18N
534
} catch (ClassNotFoundException JavaDoc exc) {
535             // ignore, will result in IOException fail below, annotate
536
// and turn into IOExc
537
LOG.log(Level.WARNING,
538                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
539
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
540
+ exc.getMessage(), exc);
541         } catch (ClassCastException JavaDoc exc) {
542             // instance is not top component (is broken), annotate and
543
// turn into IOExc
544
LOG.log(Level.WARNING,
545                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
546
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
547
+ exc.getMessage(), exc);
548         } catch (IOException JavaDoc ioe) {
549             LOG.log(Level.WARNING,
550                 "[WinSys.PersistenceManager.getTopComponentForID]" // NOI18N
551
+ " Problem when deserializing TopComponent for tcID:'" + stringId + "'. Reason: " // NOI18N
552
+ ioe.getMessage(), ioe);
553         }
554         return null;
555     }
556     
557     /** @return Searches for TopComponent with given string id and returns
558      * found lookup item.
559      */

560     private TopComponent getTopComponentNonPersistentForID (String JavaDoc stringId) {
561         synchronized(LOCK_IDS) {
562             //Search in cache first
563
WeakReference JavaDoc result = (WeakReference JavaDoc) id2TopComponentNonPersistentMap.get(stringId);
564             if (result != null) {
565                 TopComponent tc = (TopComponent) result.get();
566                 if (tc != null) {
567                     return tc;
568                 } else {
569                     //TopComponent instance was garbage collected.
570
id2TopComponentNonPersistentMap.remove(stringId);
571                 }
572             }
573             return null;
574         }
575     }
576     
577     /** @return Searches for top component with given string id and returns
578      * found lookup item.
579      */

580     public TopComponent getTopComponentForID (String JavaDoc stringId) {
581         TopComponent tc = getTopComponentNonPersistentForID(stringId);
582         if (tc == null) {
583             return getTopComponentPersistentForID(stringId);
584         } else {
585             return tc;
586         }
587     }
588     
589     /** Try to find the data object representing a top component ref in some folder.
590      * Only the TC name is known, but we can guess at some likely filenames before
591      * doing an exhaustive search. Produces either a FileObject or DataObject,
592      * DataObject if possible but FileObject if it would not need to recognize it.
593      */

594     private static DataObject findTopComponentDataObject(FileObject folder, String JavaDoc name) throws IOException JavaDoc {
595         // First try the usual suspects.
596
FileObject fo = folder.getFileObject(name, "settings"); // NOI18N
597
if (fo == null) {
598             fo = folder.getFileObject(name, "ser"); // NOI18N
599
}
600         if (fo == null) {
601             fo = folder.getFileObject(name, "xml"); // NOI18N
602
}
603         
604         if (fo != null) {
605             return DataObject.find(fo);
606         }
607         
608         // Don't accept name.instance so easily: if it has a 'name' attr etc., the
609
// DataObject.name may not in fact be name. For the three extensions above,
610
// the data object should in fact have the expected name. So now try to find
611
// a file object with that name and check the DataObject.name.
612
Enumeration JavaDoc e = folder.getChildren(false);
613         while (e.hasMoreElements()) {
614             fo = (FileObject)e.nextElement();
615             DataObject dob = DataObject.find(fo);
616             if (dob.getName().equals(name)) return dob;
617         }
618         // Finally look for any data object in this folder with the right name.
619
// Slow but should not happen often.
620
DataFolder dfolder = DataFolder.findFolder(folder);
621         e = dfolder.children();
622         while (e.hasMoreElements()) {
623             DataObject dob = (DataObject)e.nextElement();
624             if (dob.getName().equals(name)) return dob;
625         }
626         // Oh well.
627
return null;
628     }
629     
630     /** Tests if given top component with specified stringId is persistent.
631      * This is used to split TopComponents to 2 groups:
632      * First group contains all persistent TopComponents (default) and all
633      * TopComponents which could be persistent client property is set
634      * to persistent only when opened.
635      * Second group contains TopComponents which are never persistent.
636      * @param tc top component in question
637      * @return true if component is persistent (which is by default) or it can be
638      * persistent when opened.
639      */

640     private boolean isTopComponentProbablyPersistent (TopComponent tc) {
641         int persistenceType = tc.getPersistenceType();
642         if (TopComponent.PERSISTENCE_NEVER == persistenceType) {
643             return false;
644         }
645         return true;
646     }
647     
648     /** Tests if given top component with specified stringId is persistent.
649      * This method is used for saving of TopComponent.
650      * @param tc top component in question
651      * @return true if component is persistent (which is by default), false
652      * otherwise - top component's property exists saying "don't make me persistent"
653      */

654     public boolean isTopComponentPersistent (TopComponent tc) {
655         int persistenceType = tc.getPersistenceType();
656         if ((TopComponent.PERSISTENCE_NEVER == persistenceType)
657         || ((TopComponent.PERSISTENCE_ONLY_OPENED == persistenceType) && !tc.isOpened())) {
658             return false;
659         }
660         return true;
661     }
662     
663     /** Asks all top components active in the system to save their current state.
664      */

665     private void saveTopComponents (WindowManagerConfig wmc) {
666         DataFolder compsFolder;
667         try {
668             compsFolder = DataFolder.findFolder(getComponentsLocalFolder());
669         } catch (IOException JavaDoc exc) {
670             LOG.log(Level.WARNING,
671                 "[WinSys.PersistenceManager.saveTopComponents]" // NOI18N
672
+ " Cannot get components folder", exc); // NOI18N
673
return;
674         }
675         Map JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>> copyIdToTopComponentMap;
676         // must be synced, as Hashmap constructor iterates over original map
677
synchronized(LOCK_IDS) {
678             copyIdToTopComponentMap = new HashMap JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>>(id2TopComponentMap);
679         }
680
681         for (Map.Entry JavaDoc<String JavaDoc, Reference JavaDoc<TopComponent>> curEntry: copyIdToTopComponentMap.entrySet()) {
682             TopComponent curTC = curEntry.getValue().get();
683             if (curTC != null) {
684                 try {
685                     // bugfix #21223 top components are stored by IDO.SaveCookie
686
FileObject fo = compsFolder.getPrimaryFile ().getFileObject
687                             (curEntry.getKey (), "settings"); // NOI18N
688
DataObject ido = null;
689                     if (fo != null) {
690                         ido = DataObject.find(fo);
691                     }
692                     if (ido == null) {
693                         // create new settings file
694
InstanceDataObject.create(
695                             compsFolder, unescape(curEntry.getKey()), curTC, null
696                           );
697                     } else {
698                         // save to settings file if there is already
699
SaveCookie sc = (SaveCookie)ido.getCookie(SaveCookie.class);
700                         if (sc != null) {
701                             sc.save();
702                         } else {
703                             ido.delete();
704                             InstanceDataObject.create(
705                             compsFolder, unescape((String JavaDoc)curEntry.getKey()), curTC, null
706                             );
707                         }
708                     }
709                 } catch (NotSerializableException JavaDoc nse) {
710                     // #36916: Handle case when TC is not serializable.
711
String JavaDoc id = (String JavaDoc) topComponent2IDMap.get(curTC);
712                     // #75247: Log warning when TC is not serializable.
713
LOG.log(Level.WARNING, "TopComponent " + id + " is not serializable.", nse); //NOI18N
714
removeTCFromConfig(wmc,id);
715                 } catch (IOException JavaDoc exc) {
716                     // some problem with saving of top component, log warning
717
LOG.log(Level.WARNING, null, exc);
718                     String JavaDoc id = (String JavaDoc) topComponent2IDMap.get(curTC);
719                     removeTCFromConfig(wmc,id);
720                 } catch (RuntimeException JavaDoc exc) {
721                     //Bugfix #19688: Catch all other exceptions to be able to continue with saving process
722
String JavaDoc annotation = NbBundle.getMessage(
723                             PersistenceManager.class,"EXC_CannotSaveTCSettings",
724                             curTC.getName());
725                     Exceptions.attachLocalizedMessage(exc, annotation);
726                     LOG.log(Level.WARNING, null, exc);
727                     String JavaDoc id = (String JavaDoc) topComponent2IDMap.get(curTC);
728                     removeTCFromConfig(wmc,id);
729                 } catch (LinkageError JavaDoc le) {
730                     String JavaDoc annotation = NbBundle.getMessage(
731                             PersistenceManager.class,"EXC_CannotSaveTCSettings",
732                             curTC.getName());
733                     Exceptions.attachLocalizedMessage(le, annotation);
734                     LOG.log(Level.WARNING, null, le);
735                     String JavaDoc id = (String JavaDoc) topComponent2IDMap.get(curTC);
736                     removeTCFromConfig(wmc,id);
737                 }
738             }
739         }
740     }
741
742     /** Recursive method searching for file object with given name */
743     private static FileObject findTopComponentRefFile (FileObject folder, String JavaDoc tcId) {
744         FileObject result = folder.getFileObject(tcId, TCREF_EXT);
745         if (result != null) {
746             return result;
747         }
748         FileObject[] childrenArray = folder.getChildren();
749         for (int i = 0; i < childrenArray.length; i++) {
750             if (childrenArray[i].isFolder()) {
751                 result = findTopComponentRefFile(childrenArray[i], tcId);
752                 if (result != null) {
753                     return result;
754                 }
755             }
756         }
757         return null;
758     }
759     
760     /** compute filename in the same manner as InstanceDataObject.create
761      * [PENDING] in next version this should be replaced by public support
762      * likely from FileUtil
763      * @see issue #17142
764      */

765     private static String JavaDoc escape(String JavaDoc name) {
766         try {
767             Method JavaDoc escape =
768                 InstanceDataObject.class.getDeclaredMethod(
769                     "escapeAndCut", new Class JavaDoc[] {String JavaDoc.class}); //NOI18N
770
escape.setAccessible(true);
771             return (String JavaDoc) escape.invoke(null, name);
772         } catch (Exception JavaDoc ex) {
773             LOG.log(Level.WARNING,
774                 "Escape support failed", ex); // NOI18N
775
return name;
776         }
777     }
778     
779     /** compute filename in the same manner as InstanceDataObject.create
780      * [PENDING] in next version this should be replaced by public support
781      * likely from FileUtil
782      * @see issue #17142
783      */

784     private static String JavaDoc unescape(String JavaDoc name) {
785         try {
786             Method JavaDoc unescape =
787             InstanceDataObject.class.getDeclaredMethod(
788             "unescape", new Class JavaDoc[] {String JavaDoc.class}); //NOI18N
789
unescape.setAccessible(true);
790             return (String JavaDoc) unescape.invoke(null, name);
791         } catch (Exception JavaDoc ex) {
792             LOG.log(Level.WARNING,
793             "Escape support failed", ex); // NOI18N
794
return name;
795         }
796     }
797     
798     private String JavaDoc createTopComponentNonPersistentID (TopComponent tc, String JavaDoc preferredID) {
799         String JavaDoc compName = preferredID != null ? preferredID : null;
800         // be prepared for null names, empty names and convert to filesystem friendly name
801
if ((compName == null) || (compName.length() == 0)) {
802             compName = DEFAULT_TC_NAME;
803         }
804         //Check if component id is not already present in cache of invalid ids
805
boolean isUsed = true;
806         compName = escape(compName);
807         String JavaDoc srcName = compName;
808         int i = 1;
809         synchronized(LOCK_IDS) {
810             while (isUsed) {
811                 isUsed = false;
812                 if (globalIDSet.contains(srcName.toUpperCase(Locale.ENGLISH))) {
813                     isUsed = true;
814                     srcName = compName + "_" + i;
815                     i++;
816                 }
817             }
818
819             topComponentNonPersistent2IDMap.put(tc, srcName);
820             id2TopComponentNonPersistentMap.put(srcName, new WeakReference JavaDoc<TopComponent>(tc));
821             globalIDSet.add(srcName.toUpperCase(Locale.ENGLISH));
822         }
823         
824         return srcName;
825     }
826     
827     private String JavaDoc createTopComponentPersistentID (TopComponent tc, String JavaDoc preferredID) throws IOException JavaDoc {
828         String JavaDoc compName = preferredID != null ? preferredID : null;
829         // be prepared for null names, empty names and convert to filesystem friendly name
830
if ((compName == null) || (compName.length() == 0)) {
831             compName = DEFAULT_TC_NAME;
832         }
833         //Check if component id is not already present in cache of invalid ids
834
boolean isUsed = true;
835         String JavaDoc origName = compName;
836         compName = escape(compName);
837         String JavaDoc srcName = compName;
838         int i = 1;
839         synchronized(LOCK_IDS) {
840             while (isUsed) {
841                 isUsed = false;
842                 String JavaDoc uniqueName = FileUtil.findFreeFileName(
843                     getComponentsLocalFolder(), srcName, "settings" // NOI18N
844
);
845
846                 if (!srcName.equals(uniqueName) || globalIDSet.contains(uniqueName.toUpperCase(Locale.ENGLISH))) {
847                     isUsed = true;
848                     // #44293 - proper escaping to keep name synced with InstanceDataObject naming
849
srcName = escape(origName + "_" + i);
850                     i++;
851                 }
852                 
853             }
854
855             topComponent2IDMap.put(tc, srcName);
856             id2TopComponentMap.put(srcName, new WeakReference JavaDoc<TopComponent>(tc));
857             globalIDSet.add(srcName.toUpperCase(Locale.ENGLISH));
858         }
859         
860         return srcName;
861     }
862     
863     /** Reuses existing settings files */
864     private String JavaDoc restorePair (TopComponent tc, String JavaDoc id) {
865         //System.out.println("++ PM.restorePair ENTER"
866
//+ " tc:" + tc.getName() + " id:" + id);
867
FileObject compsFO = null;
868         try {
869             compsFO = getComponentsLocalFolder();
870         } catch (IOException JavaDoc exc) {
871             LOG.log(Level.WARNING,
872                 "[WinSys.PersistenceManager.restorePair]" // NOI18N
873
+ " Cannot get components folder", exc); // NOI18N
874
return null;
875         }
876         FileObject fo = compsFO.getFileObject(id, "settings");
877         if (fo != null) {
878             //System.out.println("++ PM.restorePair tc:" + tc.getName()
879
//+ " id:" + id);
880
//Thread.dumpStack();
881
synchronized(LOCK_IDS) {
882                 id2TopComponentMap.put(id, new WeakReference JavaDoc<TopComponent>(tc));
883                 validateId(id);
884             }
885             return id;
886         } else {
887             return null;
888         }
889     }
890     
891     private boolean isInvalidId (String JavaDoc id) {
892         return invalidIds.contains(id);
893     }
894     
895     private void validateId (String JavaDoc id) {
896         if (invalidIds != null) {
897             invalidIds.remove(id);
898         }
899     }
900     
901     /** map of exceptions to names of badly persistenced top components,
902      * serves as additional annotation of main exception */

903     private Map JavaDoc<Exception JavaDoc, String JavaDoc> failedCompsMap;
904     
905     /** Annotate persistence exception. Exception is added to the exception
906      * list, which is displayed at once when whole persistence process
907      * (either serialization or deserialization) is about to finish.
908      */

909     public void annotatePersistenceError(Exception JavaDoc exc, String JavaDoc tcName) {
910         if (failedCompsMap == null) {
911             failedCompsMap = new HashMap JavaDoc<Exception JavaDoc, String JavaDoc>();
912         }
913         failedCompsMap.put(exc, tcName);
914     }
915     
916     /** Checks for some persistence errors and notifies the user if some
917      * persistence errors occured. Shouild be called after serialization
918      * and deserialization of window manager.
919      */

920     public void checkPersistenceErrors(boolean reading) {
921         if(failedCompsMap == null || failedCompsMap.isEmpty()) {
922             return;
923         }
924
925         for(Iterator JavaDoc it = failedCompsMap.keySet().iterator(); it.hasNext(); ) {
926             Exception JavaDoc e = (Exception JavaDoc)it.next();
927             Object JavaDoc name = failedCompsMap.get(e);
928             // create message
929
String JavaDoc message = NbBundle.getMessage(PersistenceManager.class,
930                     (reading ? "FMT_TCReadError" : "FMT_TCWriteError"),
931                     new Object JavaDoc[] {name});
932             Exceptions.attachLocalizedMessage(e, message);
933             LOG.log(Level.WARNING, null, e);
934         }
935         
936         // clear for futher use
937
failedCompsMap = null;
938     }
939     
940     /** Accessor to WindowManagerParser instance. */
941     public WindowManagerParser getWindowManagerParser () {
942         if (windowManagerParser == null) {
943             windowManagerParser = new WindowManagerParser(this, WINDOWMANAGER_FOLDER);
944         }
945         return windowManagerParser;
946     }
947     
948     /** Returns a XML parser. The same parser can be returned assuming that config files
949      * are parser sequentially.
950      *
951      * @return XML parser with set content handler, errror handler
952      * and entity resolver.
953      */

954     public XMLReader JavaDoc getXMLParser (DefaultHandler JavaDoc h) throws SAXException JavaDoc {
955         if (parser == null) {
956             // get non validating, not namespace aware parser
957
parser = XMLUtil.createXMLReader();
958             parser.setEntityResolver(new EntityResolver JavaDoc () {
959                 /** Implementation of entity resolver. Points to the local DTD
960                  * for our public ID */

961                 public InputSource JavaDoc resolveEntity (String JavaDoc publicId, String JavaDoc systemId)
962                 throws SAXException JavaDoc {
963                     if (ModeParser.INSTANCE_DTD_ID_1_0.equals(publicId)
964                     || ModeParser.INSTANCE_DTD_ID_1_1.equals(publicId)
965                     || ModeParser.INSTANCE_DTD_ID_1_2.equals(publicId)
966                     || ModeParser.INSTANCE_DTD_ID_2_0.equals(publicId)
967                     || ModeParser.INSTANCE_DTD_ID_2_1.equals(publicId)
968                     || ModeParser.INSTANCE_DTD_ID_2_2.equals(publicId)
969                     || ModeParser.INSTANCE_DTD_ID_2_3.equals(publicId)
970                     || GroupParser.INSTANCE_DTD_ID_2_0.equals(publicId)
971                     || TCGroupParser.INSTANCE_DTD_ID_2_0.equals(publicId)
972                     || TCRefParser.INSTANCE_DTD_ID_1_0.equals(publicId)
973                     || TCRefParser.INSTANCE_DTD_ID_2_0.equals(publicId)
974                     || TCRefParser.INSTANCE_DTD_ID_2_1.equals(publicId)
975                     || TCRefParser.INSTANCE_DTD_ID_2_2.equals(publicId)
976                     || WindowManagerParser.INSTANCE_DTD_ID_1_0.equals(publicId)
977                     || WindowManagerParser.INSTANCE_DTD_ID_1_1.equals(publicId)
978                     || WindowManagerParser.INSTANCE_DTD_ID_2_0.equals(publicId)
979                     || WindowManagerParser.INSTANCE_DTD_ID_2_1.equals(publicId)) {
980                         InputStream JavaDoc is = new ByteArrayInputStream JavaDoc(new byte[0]);
981                         return new InputSource JavaDoc(is);
982                     }
983                     return null; // i.e. follow advice of systemID
984
}
985             });
986         }
987         parser.setContentHandler(h);
988         parser.setErrorHandler(h);
989         return parser;
990     }
991     
992     /** Adds TopComponent Id to set of used Ids. Called from ModeParser and
993      * SetParser when loading tcRefs and tcGroups.
994      */

995     public void addUsedTCId (String JavaDoc tc_id) {
996         synchronized(LOCK_IDS) {
997             usedTcIds.add(tc_id);
998         }
999     }
1000    
1001    /** Removes TopComponent Id from set of used Ids. Called when module defining
1002     * TopComponent is disabled.
1003     */

1004    public void removeUsedTCId (String JavaDoc tc_id) {
1005        synchronized(LOCK_IDS) {
1006            usedTcIds.remove(tc_id);
1007        }
1008    }
1009    
1010    /** Returns true if given TopComponent ID is used as name of settings file.
1011     */

1012    public boolean isUsedTCId (String JavaDoc tc_id) {
1013        synchronized(LOCK_IDS) {
1014            return usedTcIds.contains(tc_id);
1015        }
1016    }
1017    
1018    /** Checks used TopComponent Ids. If TopComponent Id is not used its settings
1019     * file is deleted from local component folder.
1020     */

1021    private void checkUsedTCId () throws IOException JavaDoc {
1022        FileObject [] files = getComponentsLocalFolder().getChildren();
1023        for (int i = 0; i < files.length; i++) {
1024            if (!files[i].isFolder() && "settings".equals(files[i].getExt())) { // NOI18N
1025
String JavaDoc tc_id = files[i].getName();
1026                boolean contains;
1027                synchronized(LOCK_IDS) {
1028                    contains = usedTcIds.contains(tc_id);
1029                }
1030                if (!contains) {
1031                    deleteOneFO(files[i]);
1032                }
1033            }
1034        }
1035        //Fill global set of used TopComponent IDs
1036
files = getComponentsLocalFolder().getChildren();
1037        for (int i = 0; i < files.length; i++) {
1038            if (!files[i].isFolder() && "settings".equals(files[i].getExt())) { // NOI18N
1039
String JavaDoc tc_id = files[i].getName();
1040                synchronized(LOCK_IDS) {
1041                    globalIDSet.add(tc_id.toUpperCase(Locale.ENGLISH));
1042                }
1043            }
1044        }
1045    }
1046    
1047    /** Loads window system configuration from disk.
1048     * @return window system configuration
1049     */

1050    public WindowManagerConfig loadWindowSystem () throws IOException JavaDoc {
1051// long start = System.currentTimeMillis();
1052

1053        //Clear set of used tc_id
1054
synchronized (LOCK_IDS) {
1055            usedTcIds.clear();
1056        }
1057        
1058        copySettingsFiles();
1059        
1060        WindowManagerParser wmParser = getWindowManagerParser();
1061        WindowManagerConfig wmc = wmParser.load();
1062        
1063        //Check used TcIds
1064
checkUsedTCId();
1065        
1066        if (changeHandler == null) {
1067            changeHandler = new ModuleChangeHandler();
1068            changeHandler.startHandling();
1069        }
1070        parser = null; // clear the ref to XML parser
1071

1072// long end = System.currentTimeMillis();
1073
// long diff = end - start;
1074
// System.out.println("Loading of window system takes " + diff + " ms");
1075
return wmc;
1076    }
1077    
1078    /** Saves window system configuration to disk.
1079     * @param wmc snapshot of windoes system configuration
1080     */

1081    public void saveWindowSystem (WindowManagerConfig wmc) {
1082        //long start, end, diff;
1083
WindowManagerParser wmParser = getWindowManagerParser();
1084        try {
1085            //start = System.currentTimeMillis();
1086
saveTopComponents(wmc);
1087            //end = System.currentTimeMillis();
1088
//diff = end - start;
1089
//System.out.println("Saving of top components takes " + diff + " ms");
1090

1091            //start = System.currentTimeMillis();
1092
wmParser.save(wmc);
1093            //end = System.currentTimeMillis();
1094
//diff = end - start;
1095
//System.out.println("Saving of window system takes " + diff + " ms");
1096
} catch (IOException JavaDoc exc) {
1097            LOG.log(Level.WARNING, null, exc);
1098        }
1099    }
1100    
1101    /** Removes any occurence of TC id from configuration. It is necessary when
1102     * serialization of some TC fails ie. tc throws NotSerializableException.
1103     */

1104    private void removeTCFromConfig (WindowManagerConfig wmc, String JavaDoc id) {
1105        boolean removeFromRecent = false;
1106        for (int i = 0; i < wmc.tcIdViewList.length; i++) {
1107            if (id.equals(wmc.tcIdViewList[i])) {
1108                removeFromRecent = true;
1109                break;
1110            }
1111        }
1112        if (removeFromRecent) {
1113            List JavaDoc<String JavaDoc> l = new ArrayList JavaDoc<String JavaDoc>(wmc.tcIdViewList.length);
1114            for (int i = 0; i < wmc.tcIdViewList.length; i++) {
1115                if (!id.equals(wmc.tcIdViewList[i])) {
1116                    l.add(wmc.tcIdViewList[i]);
1117                }
1118            }
1119            wmc.tcIdViewList = l.toArray(new String JavaDoc[l.size()]);
1120        }
1121        for (int i = 0; i < wmc.modes.length; i++) {
1122            ModeConfig mc = wmc.modes[i];
1123            if (id.equals(mc.selectedTopComponentID)) {
1124                mc.selectedTopComponentID = "";
1125            }
1126            if (id.equals(mc.previousSelectedTopComponentID)) {
1127                mc.previousSelectedTopComponentID = "";
1128            }
1129            boolean removeFromMode = false;
1130            for (int j = 0; j < mc.tcRefConfigs.length; j++) {
1131                if (id.equals(mc.tcRefConfigs[j].tc_id)) {
1132                    removeFromMode = true;
1133                    break;
1134                }
1135            }
1136            if (removeFromMode) {
1137                List JavaDoc<TCRefConfig> l = new ArrayList JavaDoc<TCRefConfig>(mc.tcRefConfigs.length);
1138                for (int j = 0; j < mc.tcRefConfigs.length; j++) {
1139                    if (!id.equals(mc.tcRefConfigs[j].tc_id)) {
1140                        l.add(mc.tcRefConfigs[j]);
1141                    }
1142                }
1143                mc.tcRefConfigs = l.toArray(new TCRefConfig[l.size()]);
1144            }
1145        }
1146        for (int i = 0; i < wmc.groups.length; i++) {
1147            GroupConfig gc = wmc.groups[i];
1148            boolean removeFromGroup = false;
1149            for (int j = 0; j < gc.tcGroupConfigs.length; j++) {
1150                if (id.equals(gc.tcGroupConfigs[j].tc_id)) {
1151                    removeFromGroup = true;
1152                    break;
1153                }
1154            }
1155            if (removeFromGroup) {
1156                List JavaDoc<TCGroupConfig> l = new ArrayList JavaDoc<TCGroupConfig>(gc.tcGroupConfigs.length);
1157                for (int j = 0; j < gc.tcGroupConfigs.length; j++) {
1158                    if (!id.equals(gc.tcGroupConfigs[j].tc_id)) {
1159                        l.add(gc.tcGroupConfigs[j]);
1160                    }
1161                }
1162                gc.tcGroupConfigs = l.toArray(new TCGroupConfig[l.size()]);
1163            }
1164        }
1165    }
1166    
1167    /** Copy all settings files from module folder to local folder. */
1168    private void copySettingsFiles () throws IOException JavaDoc {
1169        //long start, end, diff;
1170
//start = System.currentTimeMillis();
1171
if (DEBUG) Debug.log(PersistenceManager.class, "copySettingsFiles ENTER");
1172        Set JavaDoc<String JavaDoc> localSet = new HashSet JavaDoc<String JavaDoc>(100);
1173        FileObject [] filesLocal = getComponentsLocalFolder().getChildren();
1174        for (int i = 0; i < filesLocal.length; i++) {
1175            if (!filesLocal[i].isFolder() && "settings".equals(filesLocal[i].getExt())) { // NOI18N
1176
localSet.add(filesLocal[i].getName());
1177            }
1178        }
1179        
1180        FileObject [] filesModule = getComponentsModuleFolder().getChildren();
1181        for (int i = 0; i < filesModule.length; i++) {
1182            if (!filesModule[i].isFolder() && "settings".equals(filesModule[i].getExt())) { // NOI18N
1183
if (!localSet.contains(filesModule[i].getName())) {
1184                    copySettingsFile(filesModule[i]);
1185                }
1186            }
1187        }
1188        if (DEBUG) Debug.log(PersistenceManager.class, "copySettingsFiles LEAVE");
1189        //end = System.currentTimeMillis();
1190
//diff = end - start;
1191
//System.out.println("Copying of settings files takes " + diff + " ms");
1192
}
1193    
1194    /** Copy settings file from Module Components module folder (Windows2/Components)
1195     * to Local Components folder (Windows2Local/Components). */

1196    private void copySettingsFile (FileObject fo) throws IOException JavaDoc {
1197        if (DEBUG) Debug.log(PersistenceManager.class, "copySettingsFile fo:" + fo);
1198        FileObject destFolder = getComponentsLocalFolder();
1199        try {
1200            fo.copy(destFolder,fo.getName(),fo.getExt());
1201        } catch (IOException JavaDoc exc) {
1202            String JavaDoc annotation = NbBundle.getMessage(PersistenceManager.class,
1203                "EXC_CopyFails", destFolder);
1204            Exceptions.attachLocalizedMessage(exc, annotation);
1205            LOG.log(Level.WARNING, null, exc);
1206        }
1207    }
1208
1209    /** Copies given file object into Local Components folder (Windows2Local/Components)
1210     * if it doesn't exist already
1211     */

1212    void copySettingsFileIfNeeded (FileObject fo) throws IOException JavaDoc {
1213        FileObject localSettingsFO = getComponentsLocalFolder().getFileObject(fo.getNameExt());
1214        if (localSettingsFO == null) {
1215            copySettingsFile(fo);
1216        }
1217    }
1218    
1219    /** Deletes specified file object */
1220    public static void deleteOneFO (FileObject fo) {
1221        FileLock lock = null;
1222        if (fo.isValid()) {
1223            try {
1224                lock = fo.lock();
1225                fo.delete(lock);
1226            } catch (IOException JavaDoc ex) {
1227                Exceptions.printStackTrace(ex);
1228            } finally {
1229                if (lock != null) {
1230                    lock.releaseLock();
1231                }
1232            }
1233        }
1234    }
1235
1236
1237    /** Searches for module with given code name and specification version.
1238     * @param codeNameBase unique string base name of the module
1239     * (without release number)
1240     * @param spec string form of specification version of the module, null if
1241     * not important
1242     * @param strRelease release number of the module or null if not important
1243     *
1244     * @return module info of found module or null if module not found
1245     * (not installed).
1246     * @deprecated will be replaced by similar method in Modules Open APIs in
1247     * future releases
1248     */

1249    static final ModuleInfo findModule (String JavaDoc codeNameBase, String JavaDoc strRelease, String JavaDoc strSpec) {
1250        SpecificationVersion spec = null;
1251        int release = -1;
1252        
1253        if(strRelease != null) {
1254            try {
1255                release = Integer.parseInt(strRelease);
1256            } catch(NumberFormatException JavaDoc nfe) {
1257                LOG.log(Level.WARNING, null, nfe);
1258            }
1259        }
1260        if(strSpec != null) {
1261            spec = new SpecificationVersion(strSpec);
1262        }
1263        
1264        Lookup.Result<ModuleInfo> modulesResult =
1265            Lookup.getDefault().lookup(new Lookup.Template<ModuleInfo>(ModuleInfo.class));
1266        for (ModuleInfo curInfo: modulesResult.allInstances()) {
1267            // search for equal base name and then compare release and
1268
// spec numbers, if present
1269
if (curInfo.getCodeNameBase().equals(codeNameBase)) {
1270                if((release < 0 && spec == null)
1271                || (curInfo.getCodeNameRelease() > release)) {
1272                    return curInfo;
1273                } else if(release < 0
1274                || curInfo.getCodeNameRelease() == release) {
1275                    if(spec == null
1276                    || curInfo.getSpecificationVersion().compareTo(spec) >= 0) {
1277                        return curInfo;
1278                    }
1279                }
1280            }
1281        }
1282        return null;
1283    }
1284    
1285    /**
1286     * #69505 - handle chars like & and ' in names of top components
1287     */

1288    public static String JavaDoc escapeTcId4XmlContent (String JavaDoc tcName) {
1289        if (tcName.indexOf('&') != -1 || tcName.indexOf('\'') != -1) {
1290            tcName = tcName.replaceAll("&", "&amp;");
1291            tcName = tcName.replaceAll("'", "&apos;");
1292        }
1293        return tcName;
1294    }
1295
1296}
1297
Popular Tags