KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SOFA > SOFAnode > TR > Impl > TRImpl


1 /**
2  * TRImpl.java is a part of the SOFA project.
3  * This file was created by pepan on 19.3.2003.
4  */

5 package SOFA.SOFAnode.TR.Impl;
6
7 import SOFA.SOFAnode.InOut.Bundle;
8 import SOFA.SOFAnode.Run.Deployment.DeploymentDescriptorImpl;
9 import SOFA.SOFAnode.TR.*;
10 import SOFA.SOFAnode.TR.Connector.CNTR2InOut;
11 import SOFA.Util.Tools;
12
13 import javax.xml.parsers.ParserConfigurationException;
14 import java.io.*;
15 import java.rmi.RemoteException;
16 import java.util.*;
17
18 import org.xml.sax.SAXException;
19
20 /**
21  * The implementation of the Template Repository (TR). TR is used for storing components
22  * that are installed on a local SOFA node. It employs the standard file system.
23  * @author Petr Panuska and Ladislav Sobr
24  */

25 public class TRImpl implements CNTR2InOut, TR2InOut {
26
27   /**
28    * The root directory for storing content of this Template Repository.
29    */

30   private String dir;
31
32   /**
33    * Data structure for storing all installed components.
34    */

35   private class ComponentStore {
36
37     /**
38      * The collection of stored components. Each key as well as the associated value is an instance of
39      * {@link ComponentInfo}. It's used for getting the proper instance of <code>ComponentInfo</code>.
40      */

41     private Hashtable componentInfos;
42
43     /**
44      * The collection of component files.
45      * Each key is an instance of {@link ComponentInfo} class, the assigned value is an instance
46      * of {@link ComponentFiles} class - a list of files the components consist of.
47      */

48     private Hashtable componentFiles;
49
50     /**
51      * Creates instances of {@link #componentInfos} and {@link #componentFiles}.
52      */

53     private ComponentStore () {
54       componentInfos = new Hashtable();
55       componentFiles = new Hashtable();
56     }
57
58     /**
59      * Adds one component to this store and assigns the associated component files.
60      * @param info the component.
61      * @param files the list of files the component consists of.
62      */

63     private void addFiles (ComponentInfo info, ComponentFiles files) {
64       componentInfos.put(info, info);
65       componentFiles.put(info, files);
66     }
67
68     /**
69      * Gets component files the given component consists of.
70      * @param info the given component.
71      * @return files the given component consists of.
72      */

73     private ComponentFiles getFiles (ComponentInfo info) {
74       return (ComponentFiles) componentFiles.get(info);
75     }
76     
77     
78     /**
79      * Remove component files the given component consists of.
80      * @param info the given component.
81      * @return files the given component consists of.
82      */

83
84     private ComponentFiles removeFiles (ComponentInfo info) {
85       return (ComponentFiles) componentFiles.remove(info);
86     }
87     
88     /**
89      * Gets the instance of {@link ComponentInfoImpl} stored in this component store.
90      * @param info component info object where the component name and version are filled only.
91      * @return the instance stored in this store.
92      */

93     private ComponentInfoImpl getInfo (ComponentInfo info) {
94       return (ComponentInfoImpl) componentInfos.get(info);
95     }
96     
97     /**
98      * Gets the instance of {@link ComponentInfoImpl} stored in this component store.
99      * @param info component info object where the component name and version are filled only.
100      * @return the instance stored in this store.
101      */

102     private ComponentInfoImpl removeInfo (ComponentInfo info) {
103       return (ComponentInfoImpl) componentInfos.remove(info);
104     }
105     
106     /**
107      * Gets the instance of {@link ComponentInfoImpl} stored in this component store.
108      * @param fullName full name of the component (in format <em>name[version]</em>).
109      * @return the instance stored in this store.
110      */

111     private ComponentInfoImpl getInfo (String fullName) {
112       return getInfo(ComponentInfoImpl.fromString(fullName));
113     }
114
115     /**
116      * Gets all components stored in this store.
117      * @return set of components.
118      */

119     private Set getInfos () {
120       return componentInfos.keySet();
121     }
122
123     /**
124      * Is the given component stored in this component store?
125      * @param info the given component.
126      * @return <code>true</code> if the component is stored in here.
127      */

128     private boolean contains (ComponentInfo info) {
129       return componentInfos.contains(info);
130     }
131
132     /**
133      * Sets {@link ComponentInfoImpl#subComponents} of the given component. It allows for
134      * the existence of all sub-components in this store when performing this operation.
135      * If some sub-component is not stored in here, it throws the {@link TRException}.
136      * @param info the component its sub-components are going to be set.
137      * @throws IOException if some I/O operation fails.
138      * @throws ParserConfigurationException if the component assembly file is corrupted or missing.
139      * @throws SAXException if the component assembly file is corrupted or missing.
140      */

141     void setSubComponents (ComponentInfoImpl info) throws IOException, ParserConfigurationException, SAXException {
142       ComponentFiles files = (ComponentFiles) componentFiles.get(info);
143       if (files == null) // no files associated
144
return;
145       AssemblyDescriptorImpl ad = new AssemblyDescriptorImpl(files.getAssemblyDescriptorFile());
146       Set set = ad.getSubComponents(); // the set of strings decribing subcomponents of the component info
147
Set subComponents = new HashSet();// set of subcomponets (set of ComponentInfoImpl objects)
148
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
149         String fullName = (String) iterator.next();
150         iterator.remove();
151         ComponentInfo comp = ComponentInfoImpl.fromString(fullName);
152         subComponents.add(comp);
153       }
154
155       info.setSubComponents((ComponentInfoImpl[]) subComponents.toArray(new ComponentInfoImpl[subComponents.size()]));
156
157       /* commented by LS
158       if (!set.isEmpty()) // if the set is not empty, it means that some subcomponents are missing in the TR
159         throw new TRException("Some of components being processed use sub-components which are not stored in this TR.");
160       */

161
162     }
163   }
164
165   /**
166    * The set of all components installed in this TR.
167    */

168   private ComponentStore components;
169
170   /**
171    * A list of installed components.
172    */

173   private Properties implIndex;
174
175   /**
176    * A list of installed interfaces and types.
177    */

178   private Properties ifaceIndex;
179
180   /**
181    * A path to the index with installed components.
182    */

183   private String implPath;
184
185   /**
186    * A path to the index with installed interfaces.
187    */

188   private String ifacePath;
189
190   /**
191    * Creates the template repository.
192    * @param dir the directory where contents of this repository is stored.
193    * Since TR needs a write access to this directory, it must be a local directory.
194    */

195   public TRImpl (String dir) throws RemoteException, TRException {
196     this.dir = dir;
197     init();
198   }
199
200   /**
201    * Initializes internal structures of TR.
202    * @throws TRException when some error occurs (some necessary file is missing, etc.)
203    */

204   private synchronized void init () throws TRException {
205 // componentFiles = new Hashtable();
206
// components = new Hashtable();
207
components = new ComponentStore();
208
209     //create indexes
210
implIndex = new Properties();
211     ifaceIndex = new Properties();
212     implPath = dir + File.separator + "impl" + File.separator;
213     ifacePath = dir + File.separator + "iface" + File.separator;
214     try {
215       FileInputStream fis = new FileInputStream(implPath + "info");
216       implIndex.load(fis);
217       fis.close();
218
219       fis = new FileInputStream(ifacePath + "index");
220       ifaceIndex.load(fis);
221       fis.close();
222
223     } catch (java.io.IOException e) {
224       System.out.println("IOException: " + e.getMessage());
225       System.exit(1);
226     }
227
228     // look for all components stored in TR
229
// Enumeration enum = implIndex.keys();
230
Set collection = implIndex.keySet();
231 // while (enum.hasMoreElements()) {
232
for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
233 // String nameVer = (String) enum.nextElement(); // component name including implementation version
234
String nameVer = (String) iterator.next(); // component name including implementation version
235

236       String name = nameVer.substring(0, nameVer.lastIndexOf('[')); // component name
237
String path = fullNameToFileName(nameVer); // relative path to the component files
238

239
240       AssemblyDescriptorImpl ad = null;
241       try {
242         ad = new AssemblyDescriptorImpl(new File(dir + File.separator + "impl" + path + "index.dc"));
243       } catch (Exception e) {
244         throw new TRException("Exception thrown when initializing TR!\n" +
245           "When creating the assembly descriptor!\n" + path + "\n" + e, e);
246       }
247       ComponentInfo info = new ComponentInfoImpl(name, ad.getImplementationVersion());
248       ComponentFiles files = new ComponentFiles();
249       files.addFiles(dir + File.separator + "impl" + path, "");
250
251       Map cdl = ad.getCDLEntities();
252       for (Iterator javaNames = cdl.keySet().iterator(); javaNames.hasNext();) {
253         String key = (String) javaNames.next();
254         String value = (String) cdl.get(key);
255         String ifaceDir = (String) ifaceIndex.get(value);
256         String connPath = key.replace('.', File.separatorChar);
257         String connName = File.separator + connPath + ".class";
258         files.addFiles(ifacePath + ifaceDir + connName, connName);
259       }
260       components.addFiles(info, files);
261 // componentFiles.put(info, files);
262
// components.put(info, info);
263
}
264
265     // look for all components stored in TR
266
// enum = componentFiles.keys();
267
collection = components.getInfos();
268 // while (enum.hasMoreElements()) {
269
for (Iterator iterator = collection.iterator(); iterator.hasNext();) { // sets all subcomponents of the initialized components
270
// ComponentInfoImpl info = (ComponentInfoImpl) enum.nextElement();
271
ComponentInfoImpl info = (ComponentInfoImpl) iterator.next();
272
273       try {
274         components.setSubComponents(info);
275       } catch (Exception e) {
276         throw new TRException("Exception thrown when initializing TR!\n" +
277           "When setting subcomponents of the component:\n" + info + "\n" + e, e);
278       }
279     }
280
281   }
282
283   /**
284    * Just replaces all ocurences of '::', '[' and ']' with {@link File#separator}.
285    * @param clname the full name of a component.
286    * @return file name of the given component.
287    */

288   private static String fullNameToFileName (String clname) {
289     return clname.replaceAll("::|\\[|\\]", "\\" + File.separator);
290 /* StringBuffer sb = new StringBuffer();
291     boolean s = true;
292     for (int i=0; i<clname.length(); i++) {
293       if (clname.charAt(i)==':') {
294         if (s) {
295           sb.append(":");
296           s = false;
297         }
298       } else {
299         s = true;
300         sb.append(clname.charAt(i));
301       }
302     }
303     clname = sb.toString().replace(':', File.separatorChar);
304     clname = clname.replace('[', File.separatorChar);
305     clname = clname.replace(']', File.separatorChar);
306     return clname;
307 */

308   }
309
310   /**
311    * Stores components packed in the given bundle to this TR. If a received component
312    * is already stored in here, it rewrites its code with the given one. Since the
313    * bundle may contain description of components only, these components are
314    * (obviously) skipped.
315    * @param bundle the bundle containing received components.
316    * @throws TRException when some error occurs.
317    */

318   public synchronized void storeBundle (Bundle bundle) throws TRException {
319     ComponentInfo[] compInfos = bundle.getComponents();
320
321     System.out.println("TR: Storing a bundle containing following components:"); //todo debugging only
322

323     for (int i = 0; i < compInfos.length; i++) {
324       ComponentInfoImpl info = (ComponentInfoImpl) compInfos[i];
325 // if (contains(info))
326
// throw new TRException ("The component being stored to this TR is already contained in here!!\n"+info);
327
ComponentFiles files = (ComponentFiles) bundle.getComponent(info);
328       Hashtable filesTable = (files).getFiles();
329 // System.out.println(info + "\n" + filesTable); //tod debugging only
330
String location = info.getLocation();
331       if (location.startsWith("sofa://")) { // skip meta-components
332
System.out.println("Description of: " + info.getName() + "[" + info.getImplementationVersion() + "]"); //todo debugging only
333
continue;
334       }
335       String name = info.getName();
336       String version = info.getImplementationVersion();
337       System.out.println("Full component: " + name + "[" + version + "]"); //todo debugging only
338

339       File file = (File) filesTable.get("/" + "index.dc");
340       String indexPath = file.getPath();
341
342       DeploymentDescriptorImpl dd = null;
343       try {
344         dd = new DeploymentDescriptorImpl(indexPath);
345       } catch (Exception e) {
346         throw new TRException("Exception thrown when storing a bundle to TR!\n" +
347           "When creating the assembly descriptor of the component:\n" + info + "\n" + e, e);
348       }
349
350       Hashtable cdl = dd.getCDLEntities();
351
352       Enumeration enum = filesTable.keys();
353       while (enum.hasMoreElements()) {
354         String fileName = (String) enum.nextElement(); // name of the file in a bundle
355
File srcFile = (File) filesTable.get(fileName); // file in the TEMP dir
356
filesTable.remove(fileName);
357         fileName = fileName.replace('/', File.separatorChar);
358         if (fileName.endsWith(".class")) {
359           String key = fileName.substring(1, fileName.length() - ".class".length()).replace(File.separatorChar, '.');
360           if (cdl.containsKey(key)) {
361             String fullName = (String) cdl.get(key); // name including specification version
362
String ifaceDir;
363             try {
364               ifaceDir = getInterfaceDirectory(fullName);
365             } catch (IOException e) {
366               throw new TRException("Exception thrown when storing a bundle to TR!\n" +
367                 "When learning a directory where to store the interface '" + fullName + "'!\n" + e, e);
368             }
369             File destFile = new File(dir + File.separator + "iface" + File.separator + ifaceDir + fileName);
370             ifaceIndex.put(fullName, ifaceDir); // store the interface to the index file
371
moveFile(srcFile, destFile);
372             filesTable.put(fileName, destFile);
373             continue; // next
374
}
375         }
376         // it wasn't a generated file, it belongs into 'impl' directory
377

378         File destFile = new File(dir + File.separator + "impl" + fullNameToFileName(name + "[" + version) + fileName);
379         moveFile(srcFile, destFile);
380
381         filesTable.put(fileName, destFile);
382       } // for all component filesTable
383
String fullName = name + "[" + version + "]";
384       implIndex.put(fullName, "1"); // store the component to the index file
385
info.setLocation(fullName);
386       components.addFiles(info, files);
387     } // for all components in the bundle
388

389     System.out.println("End ------------------------------------------------------"); //todo debugging only
390

391     // set subcomponents of all components in the bundle that just has been installed
392
for (int i = 0; i < compInfos.length; i++) {
393       ComponentInfoImpl info = (ComponentInfoImpl) compInfos[i];
394       try {
395         components.setSubComponents(info);
396       } catch (Exception e) {
397         throw new TRException("Exception thrown when storing a bundle to TR!\n" +
398           "When setting subcomponents of the component:\n" + info + "\n" + e, e);
399       }
400     } // for all components in the bundle
401

402     // persist the TR to file system
403
try {
404       saveProperties();
405     } catch (IOException e) {
406       throw new TRException("Exception thrown when storing a bundle to TR!\n" +
407         "When saving properties!\n" + e);
408     }
409   }
410
411   /**
412    * Gets the directory name for an interface of a given name. Since there may be
413    * more interfaces of the same name (but of different specification versions) stored
414    * at TR, each of such interfaces must be stored in a different directory.
415    * If an interface of the same full name (name?specification version) has already been stored
416    * at this TR, it simply returns the directory. However, if the interface of the
417    * same full name has not been stored at this TR, it first tries to find a directory where
418    * no interface of the same (short) name is stored. If there exists such a directory, it
419    * returns its name, else it creates a new directory.
420    * @param fullName the full name of an interface. Full name consists of two fields delimited
421    * by '?'. The first one is the hierarchical name (short name), the second one is the
422    * specification version.
423    * @return the directory name. It either returns name of an already created directory,
424    * or it creates a new one.
425    * @throws IOException when some IO operation fails.
426    */

427   private String getInterfaceDirectory (String fullName) throws IOException {
428     synchronized (ifaceIndex) {
429       String ifaceDir = (String) ifaceIndex.get(fullName);
430       if (ifaceDir != null) // is the interface stored in here?
431
return ifaceDir; // return where it is stored
432
if (ifaceIndex.isEmpty()) // no interfaces are stored in here
433
return getLastIndex(); // returns the last index (normally 'a').
434
String name = fullName.substring(0, fullName.indexOf('?'));
435       HashSet temp = new HashSet();
436       temp.addAll(ifaceIndex.values()); // set of all already created directories
437
Iterator iter = ifaceIndex.keySet().iterator();
438       while (iter.hasNext()) { // for all names (short ones) in iface index
439
String fullName2 = (String) iter.next();
440         String name2 = fullName2.substring(0, fullName2.indexOf('?'));
441         if (name2.equals(name)) { // if the short name has been already stored in a directory
442
String ifaceDir2 = (String) ifaceIndex.get(fullName2);
443           temp.remove(ifaceDir2); // don't use this directory again
444
}
445       }
446       if (!temp.isEmpty()) // has left any directory?
447
return (String) temp.iterator().next(); // use it
448
ifaceDir = incrementLastIndex(getLastIndex()); // otherwise create a new one
449
storeLastIndex(ifaceDir);
450       File d = new File(dir + File.separator + "iface" + File.separator + ifaceDir);
451       d.mkdir();
452       return ifaceDir;
453     }
454   }
455
456   /**
457    * Generates a directory name which follows after the given one. The directory names
458    * are created as arabic numbers (but characters are used instead of figures). The directory name line is:
459    * 'a', 'b', 'c', ... 'z', 'aa', 'ab', 'ac', ..., 'az', 'ba', ... 'zz', 'aaa', ... ,'zzz...'.
460    * @param last the previous directory name.
461    * @return the next directory name.
462    */

463   private static String incrementLastIndex (String last) {
464     StringBuffer sb = new StringBuffer(last);
465     int now = last.length() - 1;
466     while (true) {
467       if (last.charAt(now) != 'z') {
468         sb.setCharAt(now, (char) (last.charAt(now) + (char) 1));
469         return sb.toString();
470       }
471       sb.setCharAt(now, 'a');
472       now--;
473       if (now < 0) {
474         sb.append('a');
475         return sb.toString();
476       }
477     }
478   }
479
480   /**
481    * Reads the name of an interface directory that has been used as the last one.
482    * The name is stored in the file 'last' in the directory with interfaces.
483    * @return the name of this directory.
484    * @throws IOException when some IO operation fails.
485    */

486   private String getLastIndex () throws IOException {
487     FileInputStream fis = new FileInputStream(dir + File.separator + "iface" + File.separator + "last");
488     StringBuffer sb = new StringBuffer();
489     int a = 0;
490     a = fis.read();
491     while (a != -1) {
492       sb.append((char) a);
493       a = fis.read();
494     }
495     fis.close();
496     return sb.toString();
497   }
498
499   /**
500    * Persists last index directory used for stored interfaces into a file.
501    * @param last the new value of the last index.
502    * @throws IOException when some IO operation fails.
503    */

504   private void storeLastIndex (String last) throws IOException {
505     FileOutputStream fos = new FileOutputStream(dir + File.separator + "iface" + File.separator + "last");
506     for (int i = 0; i < last.length(); i++) {
507       fos.write((byte) last.charAt(i));
508     }
509     fos.close();
510   }
511
512   /**
513    * Persists components and interfaces stored at this TR into 'TRdir/impl/info' and 'TRdir/iface/index' files.
514    * @throws IOException when some IO operation fails.
515    */

516   private void saveProperties () throws IOException {
517     FileOutputStream fos = new FileOutputStream(implPath + "info");
518     implIndex.store(fos, null);
519     fos.close();
520
521     fos = new FileOutputStream(ifacePath + "index");
522     ifaceIndex.store(fos, null);
523     fos.close();
524   }
525
526   /**
527    * Moves a file. First it tries to rename the file. If it fails, it simply copies
528    * the content of the source file to the destination file and deletes the source file.
529    * It keeps original time of last modification even in case of copying files.
530    * @param srcFile the source file name (what is to be moved).
531    * @param destFile the destination file (where it is to be moved).
532    */

533   private static void moveFile (File srcFile, File destFile)
534   {
535     try {
536       Tools.moveFile(srcFile, destFile);
537     } catch (IOException e) {
538       throw new TRException("Exception thrown when moving a component file!\n" +
539         "source file:" + srcFile.getName() + "\ndest file:" + destFile.getName(), e);
540     }
541   }
542
543   /**
544    * Creates a bundle containing and/or describing specified components.
545    * @param descs description of these components is stored into the bundle. Their code
546    * is not.
547    * @param comps description as well as code of these components is stored into the bundle.
548    * @param inferiors if <code>true</code> all inferiors (direct as well as indirect) of the
549    * specified components are included in the returned bundle.
550    * @return bundle containing specified components or their description.
551    * @throws TRException when a required component is not found on this TR.
552    */

553   public synchronized Bundle getBundle (ComponentInfo[] descs, ComponentInfo[] comps, boolean inferiors) throws TRException {
554     if (inferiors) {
555       descs = getTransitiveClosure(descs);
556       comps = getTransitiveClosure(comps);
557     }
558
559     System.out.println("TR: Getting a bundle containing following components:"); //todo debugging only
560

561     BundleImpl bundle = new BundleImpl();
562     if (comps != null) {
563       for (int i = 0; i < comps.length; i++) {
564         ComponentInfo info = comps[i];
565         System.out.println("Full component: " + info.getName() + "[" + info.getImplementationVersion() + "]"); //todo debugging only
566
ComponentFiles files = components.getFiles(info);
567         if (files == null) throw new TRException("Required component not stored in this TR!" + info);
568         bundle.add((ComponentInfoImpl) info, files);
569       }
570     }
571     if (descs != null) {
572       for (int i = 0; i < descs.length; i++) {
573         ComponentInfo info = descs[i];
574         System.out.println("Description of: " + info.getName() + "[" + info.getImplementationVersion() + "]"); //todo debugging only
575
bundle.add((ComponentInfoImpl) info, BundleImpl.NO_FILES);
576       }
577     }
578     System.out.println("End ------------------------------------------------------"); //todo debugging only
579
return bundle;
580   }
581   
582   /**
583    * Deletes specified components from TR.
584    * @param comps specification of components.
585    * @param interfaces if <code>true</code> interfaces of component are also removed
586    * @param inferiors if <code>true</code> all inferiors (direct as well as indirect) of the
587    * specified components are deleted.
588    * @throws TRException when a deleting component is not found in TR (incostistent TR).
589    */

590   public synchronized void deleteComponents (ComponentInfo[] comps, boolean interfaces, boolean inferiors) throws TRException
591   {
592     if (inferiors)
593     {
594       comps = getTransitiveClosure(comps);
595     }
596     String msg;
597     
598     if (!interfaces) msg = "TR: Deleting components (without interfaces):";
599     else msg = "TR: Deleting components (with interfaces):";
600     
601     System.out.println(msg); //todo debugging only
602
if (comps != null)
603     {
604       for (int i = 0; i < comps.length; i++)
605       {
606         ComponentInfo comp = comps[i];
607         System.out.println(comp.getName() + "[" + comp.getImplementationVersion() + "]"); //todo debugging only
608
try
609         {
610           ComponentInfoImpl info = components.removeInfo(comp);
611           ComponentFiles files = components.removeFiles(comp);
612           
613           if (info == null || files == null)
614           {
615             throw new TRException("The component not found in TR!" + comp);
616           }
617           
618           //remove component from implIndex
619

620           if (implIndex.remove(info.toString()) == null)
621           {
622             throw new TRException("Incosistent TR (implIndex)! The component not found!" + info);
623           }
624           
625           //find out interfaces of the component
626

627           AssemblyDescriptorImpl ad = null;
628           try
629           {
630             ad = new AssemblyDescriptorImpl(files.getAssemblyDescriptorFile());
631           }
632           catch (Exception e)
633           {
634             throw new TRException("Exception thrown when creating the assembly descriptor!\n" + e, e);
635           }
636           Map cdl = ad.getCDLEntities();
637           for (Iterator javaNames = cdl.keySet().iterator(); javaNames.hasNext();)
638           {
639             String key = (String) javaNames.next();
640             String value = (String) cdl.get(key);
641             
642             if (interfaces)
643             {
644               ifaceIndex.remove(value);
645               continue;
646             }
647             else
648             {
649               //if interfaces should stay in TR, we remove them from 'files' which will bew deleted
650
String ifaceDir = (String) ifaceIndex.get(value);
651               String connPath = key.replace('.', File.separatorChar);
652               String connName = File.separator + connPath + ".class";
653               files.getFiles().remove(connName);
654             }
655           }
656           
657           //delete all files (maybe except interfaces which has been already deleted from 'files')
658
Enumeration enumFiles = files.getFiles().elements();
659           
660           while (enumFiles.hasMoreElements())
661           {
662             File file = (File)enumFiles.nextElement();
663             file.delete();
664             Tools.deleteEmptyDirectoryTree(file.getParentFile(), null); //we assume, impl and iface directories will never be empty!
665
}
666 /* LS: no effect now
667           File compImplDir = new File(dir + File.separator + "impl" + fullNameToFileName(info.getName() + "[" + info.getImplementationVersion()));
668           Tools.deleteSubTree(compImplDir);
669 */

670         }
671         catch (TRException tre)
672         {
673           try
674           {
675             saveProperties();
676           }
677           catch (IOException e)
678           {
679             throw new TRException("Exception thrown when saving properties in exception handler!\n" + e + "\nHandled exception:" + tre);
680           }
681           throw tre;
682         }
683         
684         try
685         {
686           saveProperties();
687         }
688         catch (IOException e)
689         {
690           throw new TRException("Exception thrown when saving properties!\n" + e);
691         }
692         
693       }
694     }
695     System.out.println("End ------------------------------------------------------"); //todo debugging only
696
}
697   
698
699   private ComponentInfoImpl[] getTransitiveClosure (ComponentInfo[] comps) {
700     if (comps == null)
701       return null;
702     // list for iterating through all components and their (in the current time) known subcomponents
703
List list = new LinkedList();
704     // set for learning if a concrete component is in the list
705
Set set = new HashSet();
706
707     for (int i = 0; i < comps.length; i++) {
708       ComponentInfoImpl comp = components.getInfo(comps[i]); // use the instance filled not only with "key properties"
709
if (comp == null) comp = new ComponentInfoImpl(comps[i].getName(), comps[i].getImplementationVersion());
710       list.add(comp);
711       set.add(comp);
712     }
713
714     for (int i = 0; i < list.size(); i++) {
715       ComponentInfoImpl info = (ComponentInfoImpl) list.get(i);
716       ComponentInfo[] subs = info.getSubComponents();
717       if (subs != null) {
718         for (int j = 0; j < subs.length; j++) {
719           ComponentInfo sub = components.getInfo(subs[j]);
720           if (sub != null && !set.contains(sub)) { // the component is in the repository and is not in the set and thus in the list either
721
list.add(sub);
722             set.add(sub);
723           }
724         }
725       }
726     }
727
728     return (ComponentInfoImpl[]) list.toArray(new ComponentInfoImpl[list.size()]);
729   }
730
731   /**
732    * Returns <code>true</code> if the specified component is stored in this TR.
733    * Only two fields in <code>ComponentInfo</code> must be filled -
734    * the {@link ComponentInfo#getName component name} and it's
735    * {@link ComponentInfo#getImplementationVersion implementation version}.
736    * @param desc the component which is being asked.
737    * @return <code>true</code> if the component is in TR, <code>false</code> otherwise.
738    */

739   public synchronized boolean contains (ComponentInfo desc) {
740     return components.contains(desc);
741   }
742
743   /**
744    * Returns <code>true</code> if the specified component (including implementation) is stored in this TR.
745    * Only two fields in <code>ComponentInfo</code> must be filled -
746    * the {@link ComponentInfo#getName component name} and it's
747    * {@link ComponentInfo#getImplementationVersion implementation version}.
748    * @param comp the component which is being asked.
749    * @param inferiors if <code>true</code> all inferiors (direct as well as indirect) of the
750    * specified components are tested whether they are present.
751    * @return <code>true</code> if the component (including implementation) is in TR, <code>false</code> otherwise.
752    */

753   public synchronized boolean containsComponent (ComponentInfo comp, boolean inferiors)
754   {
755     ComponentInfo[] comps;
756     
757     ComponentInfo[] tmpComps = new ComponentInfo[1];
758     tmpComps[0] = comp;
759     
760     if (inferiors) comps = getTransitiveClosure(tmpComps);
761     else comps = tmpComps;
762     for (int i = 0; i < comps.length; i++)
763     {
764       ComponentInfo info = comps[i];
765       ComponentFiles files = components.getFiles(info);
766       if (files == null) return false;
767     }
768     
769     return true;
770   }
771   
772   /**
773    * Lists all components stored on this TR.
774    * @return a bundle containing all components stored on this TR.
775    */

776   public Bundle list () {
777     Set infos = components.getInfos();
778     ComponentInfo[] descs = (ComponentInfo[]) infos.toArray(new ComponentInfo[infos.size()]);
779     return getBundle(descs, null, false);
780   }
781
782 }
783
Popular Tags