View Javadoc

1   /*
2    * $Id: BasicHierarchicalRepository.java,v 1.1 2008/12/09 16:37:13 oeuillot Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.repository;
6   
7   import java.io.InputStream;
8   import java.net.MalformedURLException;
9   import java.net.URL;
10  import java.util.ArrayList;
11  import java.util.Arrays;
12  import java.util.Collection;
13  import java.util.HashMap;
14  import java.util.HashSet;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.Map;
18  import java.util.Set;
19  import java.util.StringTokenizer;
20  
21  import javax.servlet.ServletContext;
22  
23  import org.apache.commons.digester.Digester;
24  import org.apache.commons.digester.Rule;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.rcfaces.core.internal.util.ClassLocator;
28  import org.rcfaces.core.internal.util.URLContentProvider;
29  import org.xml.sax.Attributes;
30  
31  /**
32   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
33   * @version $Revision: 1.1 $ $Date: 2008/12/09 16:37:13 $
34   */
35  public class BasicHierarchicalRepository extends AbstractRepository
36          implements IHierarchicalRepository {
37  
38      private static final String REVISION = "$Revision: 1.1 $";
39  
40      private static final long serialVersionUID = -6882051141540673466L;
41  
42      private static final Log LOG = LogFactory
43              .getLog(BasicHierarchicalRepository.class);
44  
45      protected static final IHierarchicalFile[] HIERARCHICAL_FILE_EMPTY_ARRAY = new IHierarchicalFile[0];
46  
47      private static final IModule[] MODULE_EMPTY_ARRAY = new IModule[0];
48  
49      private static final Integer FILE_TYPE = new Integer(0);
50  
51      private static final Integer MODULE_TYPE = new Integer(1);
52  
53      private static final Integer SET_TYPE = new Integer(2);
54  
55      private final Map modulesByName = new HashMap();
56  
57      private final Map setsByName = new HashMap();
58  
59      private final Map resourcesByName = new HashMap();
60  
61      private ISet bootSet;
62  
63      public BasicHierarchicalRepository(String servletURI,
64              String repositoryVersion) {
65          super(servletURI, repositoryVersion);
66      }
67  
68      public ISet getBootSet() {
69          return bootSet;
70      }
71  
72      public void setBootSet(ISet set) {
73          this.bootSet = set;
74      }
75  
76      protected IContentProvider getDefaultContentProvider() {
77          return URLContentProvider.SINGLETON;
78      }
79  
80      public void loadRepository(InputStream input, Object container) {
81  
82          Digester digester = new Digester();
83  
84          addRules(digester, container);
85  
86          try {
87              digester.parse(input);
88  
89          } catch (Exception ex) {
90              LOG.error("Can not parse '" + container + "' ", ex);
91          }
92      }
93  
94      protected void addRules(Digester digester, final Object container) {
95  
96          final String baseDirectory[] = new String[1];
97  
98          digester.addRule("repository", new Rule() {
99              private static final String REVISION = "$Revision: 1.1 $";
100 
101             public void begin(String namespace, String name,
102                     Attributes attributes) throws Exception {
103 
104                 String contentLocationDirectory = attributes
105                         .getValue("baseDirectory");
106 
107                 if (contentLocationDirectory != null) {
108                     if (contentLocationDirectory.length() > 0
109                             && contentLocationDirectory.endsWith("/") == false) {
110                         contentLocationDirectory += "/";
111                     }
112 
113                     baseDirectory[0] = contentLocationDirectory;
114                 }
115 
116             }
117         });
118 
119         digester.addRule("repository/module", new Rule() {
120             private static final String REVISION = "$Revision: 1.1 $";
121 
122             public void begin(String namespace, String name,
123                     Attributes attributes) throws Exception {
124                 String id = attributes.getValue("id");
125                 if (id == null) {
126                     throw new IllegalArgumentException(
127                             "No 'id' attribute for <module> element !");
128                 }
129 
130                 String filename = getModuleFilename(id);
131                 String uri = getURI(filename);
132                 boolean groupAllFiles = "true".equalsIgnoreCase(attributes
133                         .getValue("groupAll"));
134 
135                 String rid = "m:" + id;
136 
137                 IModule m = new Module(rid, filename, uri, groupAllFiles);
138 
139                 if ("true".equals(attributes.getValue("defaultCoreModule"))) {
140                     m.setDefaultCoreModule();
141                 }
142 
143                 filesByURI.put(uri, m);
144                 modulesByName.put(id, m);
145                 resourcesByName.put(rid, m);
146 
147                 this.digester.push(m);
148             }
149 
150             public void end(String namespace, String name) throws Exception {
151                 this.digester.pop();
152             }
153 
154         });
155 
156         digester.addRule("repository/module/file", new Rule() {
157             private static final String REVISION = "$Revision: 1.1 $";
158 
159             public void begin(String namespace, String xname,
160                     Attributes attributes) throws Exception {
161 
162                 String name = attributes.getValue("name");
163                 if (name == null) {
164                     throw new IllegalArgumentException(
165                             "No 'name' attribute for <file> element !");
166                 }
167 
168                 IHierarchicalFile ds[] = HIERARCHICAL_FILE_EMPTY_ARRAY;
169 
170                 String depends = attributes.getValue("depends");
171                 if (depends != null) {
172                     List l = null;
173                     for (StringTokenizer st = new StringTokenizer(depends, ", "); st
174                             .hasMoreTokens();) {
175                         String dname = st.nextToken();
176 
177                         IHierarchicalFile fd = (IHierarchicalFile) getFileByName(dname);
178                         if (fd == null) {
179                             throw new IllegalArgumentException("Can not find '"
180                                     + dname + "' referenced by file '" + name
181                                     + "' !");
182                         }
183 
184                         if (l == null) {
185                             l = new ArrayList();
186                         }
187 
188                         l.add(fd);
189                     }
190 
191                     if (l != null) {
192                         ds = (IHierarchicalFile[]) l
193                                 .toArray(new IHierarchicalFile[l.size()]);
194                     }
195                 }
196 
197                 IContentProvider contentProvider = null;
198                 String contentProviderClassName = attributes
199                         .getValue("contentProvider");
200 
201                 if (contentProviderClassName != null) {
202                     try {
203                         Class clazz = ClassLocator.load(
204                                 contentProviderClassName, null, container);
205 
206                         contentProvider = (IContentProvider) clazz
207                                 .newInstance();
208 
209                     } catch (Exception ex) {
210                         LOG.error("Can not find contentProvider class '"
211                                 + contentProviderClassName + "'.", ex);
212 
213                         throw ex;
214                     }
215                 }
216 
217                 IModule module = (IModule) this.digester.peek();
218 
219                 IHierarchicalFile f = declareFile(name, baseDirectory[0],
220                         module, ds, container, contentProvider);
221 
222                 String uri = getURI(name);
223                 filesByURI.put(uri, f);
224 
225                 this.digester.push(f);
226             }
227 
228             public void end(String namespace, String name) throws Exception {
229                 this.digester.pop();
230             }
231         });
232     }
233 
234     public final IHierarchicalFile declareFile(String name, String directory,
235             IModule module, IHierarchicalFile depends[], Object container,
236             IContentProvider contentProvider) {
237         final String contentLocation = getContentLocation(name, directory);
238 
239         URL url = null;
240         if (container instanceof ClassLoader) {
241             String cl = contentLocation;
242             if (cl.startsWith("/")) {
243                 cl = cl.substring(1);
244             }
245 
246             url = ((ClassLoader) container).getResource(cl);
247 
248             if (LOG.isDebugEnabled()) {
249                 LOG.debug("Get resource '" + cl + "' from classloader => "
250                         + url);
251             }
252         }
253 
254         if (url == null && (container instanceof ServletContext)) {
255             String cl = contentLocation;
256             if (cl.startsWith("/") == false) {
257                 cl = "/" + cl;
258             }
259 
260             try {
261                 url = ((ServletContext) container).getResource(cl);
262 
263             } catch (MalformedURLException e) {
264                 IllegalArgumentException ex = new IllegalArgumentException(
265                         "Can not get resource '" + contentLocation
266                                 + "' into servlet context (file=" + name + ").");
267                 ex.initCause(e);
268 
269                 throw ex;
270             }
271 
272             if (LOG.isDebugEnabled()) {
273                 LOG.debug("Get resource '" + cl + "' from classloader => "
274                         + url);
275             }
276         }
277 
278         if (url == null) {
279             throw new IllegalArgumentException("Can not locate file '" + name
280                     + "'  (location='" + contentLocation + "')");
281         }
282 
283         String rname = "f:" + name;
284         IHierarchicalFile f = createFile(module, rname, name, name, url,
285                 depends, contentProvider);
286 
287         filesByName.put(name, f);
288         resourcesByName.put(rname, f);
289 
290         return f;
291     }
292 
293     protected HierarchicalFile createFile(IModule module, String name,
294             String filename, String unlocalizedURI,
295             URL unlocalizedContentLocation, IHierarchicalFile dependencies[],
296             IContentProvider contentProvider) {
297 
298         return new HierarchicalFile(module, name, filename, unlocalizedURI,
299                 unlocalizedContentLocation, dependencies, contentProvider);
300     }
301 
302     private String getContentLocation(String name, String directory) {
303         if (directory == null) {
304             return name;
305         }
306         return directory + name;
307     }
308 
309     public IModule getModuleByName(String name) {
310         return (IModule) modulesByName.get(name);
311     }
312 
313     public IHierarchicalFile getFileById(String id) {
314         return (IHierarchicalFile) resourcesByName.get(id);
315     }
316 
317     public ISet getSetByName(String name) {
318         return (ISet) setsByName.get(name);
319     }
320 
321     private String getModuleFilename(String id) {
322         return "vfm-" + id + ".js";
323     }
324 
325     private String getURI(String name) {
326         return name;
327     }
328 
329     public IHierarchicalFile[] computeFiles(Collection files,
330             int typeOfCollection, IContext context) {
331         List dependencies = null;
332         List deps = null;
333 
334         for (Iterator it = files.iterator(); it.hasNext();) {
335             Object next = it.next();
336 
337             IHierarchicalFile file = convertType(next, typeOfCollection);
338 
339             if (file == null) {
340                 throw new IllegalArgumentException("Object '" + next
341                         + "' can not be converted to file !");
342             }
343 
344             if (context.contains(file)) {
345                 continue;
346             }
347 
348             if (deps == null && dependencies != null) {
349                 deps = new ArrayList(dependencies);
350             }
351 
352             deps = computeFile(file, context, deps);
353 
354             if (deps == null
355                     || deps.isEmpty()
356                     || (dependencies != null && deps.size() == dependencies
357                             .size())) {
358                 // La liste n'a pas chang?e !
359                 continue;
360             }
361 
362             // La liste a chang?e !
363             if (dependencies == null) {
364                 dependencies = new ArrayList(files.size() * 2);
365 
366             } else {
367                 deps.removeAll(dependencies); // Retire les doublons
368             }
369 
370             dependencies.addAll(deps); // Ajoute les nouvelles dependances
371 
372             deps = null; // Reset la liste !
373         }
374 
375         if (dependencies == null || dependencies.isEmpty()) {
376             return HIERARCHICAL_FILE_EMPTY_ARRAY;
377         }
378 
379         return (IHierarchicalFile[]) dependencies
380                 .toArray(new IHierarchicalFile[dependencies.size()]);
381     }
382 
383     protected IHierarchicalFile convertType(Object next, int typeOfCollection) {
384         if (typeOfCollection == FILENAME_COLLECTION_TYPE) {
385             String filename = (String) next;
386 
387             // On recherches les fichiers associ?s
388             IHierarchicalFile file = (IHierarchicalFile) filesByName
389                     .get(filename);
390             if (file == null) {
391                 throw new IllegalArgumentException("File '" + filename
392                         + "' is not known into repository !");
393             }
394             return file;
395         }
396 
397         if (typeOfCollection == FILE_COLLECTION_TYPE) {
398             return (IHierarchicalFile) next;
399         }
400 
401         return null;
402     }
403 
404     private List computeFile(IHierarchicalFile file, IContext context,
405             List newFiles) {
406         if (context.contains(file)) {
407             return newFiles;
408         }
409 
410         ISet set = null;
411         IModule module = null;
412 
413         if (file instanceof ISet) {
414             set = (ISet) file;
415             file = null;
416 
417         } else if (file instanceof IModule) {
418             module = (IModule) file;
419             set = module.getSet();
420             file = null;
421 
422         } else {
423             module = file.getModule();
424             set = module.getSet();
425         }
426 
427         if (module != null && module.getGroupAllFiles()) {
428             if (context.contains(module)) {
429                 // Il fait parti d'un module qui a été envoyé !
430                 return newFiles;
431             }
432             file = module;
433         }
434 
435         if (set != null) {
436             if (context.contains(set)) {
437                 // Il fait parti d'un set de modules qui a ?t? envoy? !
438                 return newFiles;
439             }
440             file = set;
441         }
442 
443         IHierarchicalFile ds[];
444 
445         if (file == set) {
446             ds = set.listExternalDependencies();
447 
448         } else if (file == module) {
449             ds = module.listExternalDependencies();
450 
451         } else {
452             ds = file.listDependencies();
453         }
454 
455         if (ds.length > 0) {
456             for (int i = 0; i < ds.length; i++) {
457                 newFiles = computeFile(ds[i], context, newFiles);
458             }
459 
460             if (set != null && context.contains(set)) {
461                 return newFiles;
462             }
463 
464             // On retente, car il fait parti d'un module qui a ?t? envoy? !
465             if (context.contains(module)) {
466                 return newFiles;
467             }
468         }
469 
470         if (context.contains(file)) {
471             return newFiles;
472         }
473 
474         context.add(file);
475 
476         if (newFiles == null) {
477             newFiles = new ArrayList();
478         }
479 
480         newFiles.add(file);
481 
482         return newFiles;
483     }
484 
485     public IModule[] listModules() {
486         Collection c = modulesByName.values();
487 
488         return (IModule[]) c.toArray(new IModule[c.size()]);
489     }
490 
491     public ISet[] listSets() {
492         Collection c = setsByName.values();
493 
494         return (ISet[]) c.toArray(new ISet[c.size()]);
495     }
496 
497     public ISet declareSet(String name, String uri, String[] modules) {
498         List l = new ArrayList(modules.length);
499 
500         for (int i = 0; i < modules.length; i++) {
501             String moduleName = modules[i];
502 
503             IModule module = getModuleByName(moduleName);
504             if (module == null) {
505                 throw new IllegalArgumentException(
506                         "Can not find module '"
507                                 + moduleName
508                                 + "', please check the name or remove it from the web.xml !");
509             }
510 
511             addModules(l, module);
512         }
513 
514         IModule ms[] = (IModule[]) l.toArray(new IModule[l.size()]);
515 
516         return declareSet(name, uri, ms);
517     }
518 
519     public ISet declareSet(String name, String uri, IModule[] ms) {
520         for (int i = 0; i < ms.length; i++) {
521             ms[i].setGroupAllFiles(true);
522         }
523 
524         String rname = "s:" + name;
525         ISet set = new SetImpl(rname, name, uri, ms);
526 
527         filesByURI.put(uri, set);
528         setsByName.put(name, set);
529         resourcesByName.put(rname, set);
530 
531         return set;
532     }
533 
534     private void addModules(List modules, IModule module) {
535         if (modules.contains(module)) {
536             return;
537         }
538 
539         if (module.getSet() != null) {
540             return;
541         }
542 
543         IModule extMods[] = module.listExternalModules();
544         if (extMods != null && extMods.length > 0) {
545             for (int i = 0; i < extMods.length; i++) {
546                 addModules(modules, extMods[i]);
547             }
548         }
549 
550         modules.add(module);
551     }
552 
553     private static IModule[] filterModules(IModule[] modules) {
554         List l = new ArrayList(modules.length);
555 
556         for (int i = 0; i < modules.length; i++) {
557             IModule module = modules[i];
558 
559             if (module.getSet() != null) {
560                 continue;
561             }
562 
563             l.add(module);
564         }
565 
566         return (IModule[]) l.toArray(new IModule[l.size()]);
567     }
568 
569     /**
570      * 
571      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
572      * @version $Revision: 1.1 $ $Date: 2008/12/09 16:37:13 $
573      */
574     public class HierarchicalFile extends File implements IHierarchicalFile {
575 
576         private static final String REVISION = "$Revision: 1.1 $";
577 
578         private static final long serialVersionUID = -4635130019371035269L;
579 
580         private final IModule module;
581 
582         private final int hashCode;
583 
584         private IHierarchicalFile[] dependencies;
585 
586         public HierarchicalFile(IModule module, String name, String filename,
587                 String unlocalizedURI, Object unlocalizedContentLocation,
588                 IHierarchicalFile[] dependencies,
589                 IContentProvider contentProvider) {
590             super(name, filename, unlocalizedURI, unlocalizedContentLocation,
591                     contentProvider);
592 
593             this.module = module;
594             this.dependencies = dependencies;
595 
596             if (module != null) {
597                 ((Module) module).addFile(this);
598             }
599 
600             int h = super.hashCode();
601             if (module != null) {
602                 // ((Module) module).addFile(this);
603                 h ^= module.getFilename().hashCode();
604             }
605 
606             this.hashCode = h;
607         }
608 
609         public void addDependencies(IHierarchicalFile dependencies[]) {
610             List l = new ArrayList(Arrays.asList(this.dependencies));
611 
612             for (int i = 0; i < dependencies.length; i++) {
613                 IHierarchicalFile f = dependencies[i];
614                 if (l.contains(f)) {
615                     continue;
616                 }
617 
618                 l.add(f);
619             }
620 
621             if (LOG.isDebugEnabled()) {
622                 LOG.debug("Dependencies of HFile[" + getId() + "]=" + l);
623             }
624 
625             this.dependencies = (IHierarchicalFile[]) l
626                     .toArray(new IHierarchicalFile[l.size()]);
627         }
628 
629         public IHierarchicalFile[] listDependencies() {
630             return dependencies;
631         }
632 
633         public IModule getModule() {
634             return module;
635         }
636 
637         public int hashCode() {
638             return hashCode;
639         }
640 
641         public String toString() {
642             return "[HFile " + getId() + "]";
643         }
644     }
645 
646     /**
647      * 
648      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
649      * @version $Revision: 1.1 $ $Date: 2008/12/09 16:37:13 $
650      */
651     public class SetImpl extends HierarchicalFile implements ISet {
652         private static final String REVISION = "$Revision: 1.1 $";
653 
654         private static final long serialVersionUID = -5572999892750207302L;
655 
656         private IHierarchicalFile externalDependencies[];
657 
658         private IHierarchicalFile dependencies[];
659 
660         public SetImpl(String id, String filename, String uri,
661                 IModule modules[]) {
662             super(null, id, filename, uri, null, filterModules(modules), null);
663 
664             modules = (IModule[]) super.listDependencies();
665             for (int i = 0; i < modules.length; i++) {
666                 if (modules[i].getSet() != null) {
667                     throw new IllegalArgumentException("Module '"
668                             + modules[i].getFilename()
669                             + "' is already associated to a Set !");
670                 }
671 
672                 ((Module) modules[i]).setSet(this);
673             }
674 
675             if (LOG.isDebugEnabled()) {
676                 LOG.debug("Declare SET [" + id + "] => "
677                         + Arrays.asList(modules));
678             }
679         }
680 
681         public IHierarchicalFile[] listExternalDependencies() {
682             if (externalDependencies != null) {
683                 return externalDependencies;
684             }
685 
686             Set l = null;
687             IHierarchicalFile files[] = listDependencies();
688 
689             for (int i = 0; i < files.length; i++) {
690                 IHierarchicalFile file = files[i];
691 
692                 IHierarchicalFile dfiles[] = file.listDependencies();
693 
694                 for (int j = 0; j < dfiles.length; j++) {
695                     IHierarchicalFile dfile = dfiles[j];
696 
697                     IModule module = dfile.getModule();
698 
699                     if (module.getSet() == this) {
700                         continue;
701                     }
702 
703                     if (l == null) {
704                         l = new HashSet();
705                     }
706 
707                     l.add(dfile);
708                 }
709             }
710 
711             if (LOG.isDebugEnabled()) {
712                 LOG.debug("ExternalDependencies of SET[" + getId() + "]=" + l);
713             }
714 
715             if (l == null) {
716                 externalDependencies = HIERARCHICAL_FILE_EMPTY_ARRAY;
717 
718                 return externalDependencies;
719             }
720 
721             externalDependencies = (IHierarchicalFile[]) l
722                     .toArray(new IHierarchicalFile[l.size()]);
723 
724             return externalDependencies;
725         }
726 
727         public IHierarchicalFile[] listDependencies() {
728             if (dependencies != null) {
729                 return dependencies;
730             }
731 
732             List l = new ArrayList();
733             IModule modules[] = (IModule[]) super.listDependencies();
734             for (int i = 0; i < modules.length; i++) {
735 
736                 IHierarchicalFile fs[] = modules[i].listDependencies();
737 
738                 l.addAll(Arrays.asList(fs));
739             }
740 
741             if (LOG.isDebugEnabled()) {
742                 LOG.debug("Dependencies of SET[" + getId() + "]=" + l);
743             }
744 
745             dependencies = (IHierarchicalFile[]) l
746                     .toArray(new IHierarchicalFile[l.size()]);
747 
748             return dependencies;
749         }
750 
751         public String toString() {
752             return "[Set " + getId() + "]";
753         }
754 
755     }
756 
757     /**
758      * 
759      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
760      * @version $Revision: 1.1 $ $Date: 2008/12/09 16:37:13 $
761      */
762     public class Module extends HierarchicalFile implements IModule {
763         private static final String REVISION = "$Revision: 1.1 $";
764 
765         private static final long serialVersionUID = -5299468486306880225L;
766 
767         private boolean groupAllFiles;
768 
769         private List filesList = new ArrayList(8);
770 
771         private IHierarchicalFile files[];
772 
773         private ISet set;
774 
775         private IHierarchicalFile externalDependencies[];
776 
777         private IModule externalModules[];
778 
779         private boolean isDefaultCoreModule;
780 
781         public Module(String name, String filename, String uri,
782                 boolean groupAllFiles) {
783             super(null, name, filename, uri, null, null, null);
784 
785             this.groupAllFiles = groupAllFiles;
786         }
787 
788         public boolean isDefaultCoreModule() {
789             return isDefaultCoreModule;
790         }
791 
792         public void setDefaultCoreModule() {
793             isDefaultCoreModule = true;
794         }
795 
796         public void setGroupAllFiles(boolean enable) {
797             this.groupAllFiles = enable;
798         }
799 
800         public boolean getGroupAllFiles() {
801             return groupAllFiles;
802         }
803 
804         public void addFile(IHierarchicalFile file) {
805             filesList.add(file);
806         }
807 
808         public IHierarchicalFile[] listDependencies() {
809             if (files != null) {
810                 return files;
811             }
812 
813             files = (IHierarchicalFile[]) filesList
814                     .toArray(new IHierarchicalFile[filesList.size()]);
815             filesList = null;
816 
817             return files;
818         }
819 
820         public IHierarchicalFile[] listExternalDependencies() {
821             if (externalDependencies != null) {
822                 return externalDependencies;
823             }
824 
825             Set l = null;
826             IHierarchicalFile files[] = listDependencies();
827 
828             for (int i = 0; i < files.length; i++) {
829                 IHierarchicalFile file = files[i];
830 
831                 IHierarchicalFile dfiles[] = file.listDependencies();
832 
833                 for (int j = 0; j < dfiles.length; j++) {
834                     IHierarchicalFile dfile = dfiles[j];
835 
836                     if (dfile.getModule() == this) {
837                         continue;
838                     }
839 
840                     if (l == null) {
841                         l = new HashSet();
842                     }
843 
844                     l.add(dfile);
845                 }
846             }
847 
848             if (LOG.isDebugEnabled()) {
849                 LOG.debug("ExternalDependencies of MODULE[" + getId() + "]="
850                         + l);
851             }
852 
853             if (l == null) {
854                 externalDependencies = HIERARCHICAL_FILE_EMPTY_ARRAY;
855 
856                 return externalDependencies;
857             }
858 
859             externalDependencies = (IHierarchicalFile[]) l
860                     .toArray(new IHierarchicalFile[l.size()]);
861 
862             return externalDependencies;
863         }
864 
865         public IModule[] listExternalModules() {
866             if (externalModules != null) {
867                 return externalModules;
868             }
869 
870             Set l = null;
871             IHierarchicalFile files[] = listExternalDependencies();
872 
873             for (int i = 0; i < files.length; i++) {
874                 IModule module = files[i].getModule();
875                 if (module == null) {
876                     continue;
877                 }
878 
879                 if (l == null) {
880                     l = new HashSet();
881                 }
882 
883                 l.add(module);
884             }
885 
886             if (LOG.isDebugEnabled()) {
887                 LOG.debug("Dependencies of MODULE[" + getId() + "]=" + l);
888             }
889 
890             if (l == null) {
891                 externalModules = MODULE_EMPTY_ARRAY;
892 
893                 return externalModules;
894             }
895 
896             externalModules = (IModule[]) l.toArray(new IModule[l.size()]);
897 
898             return externalModules;
899         }
900 
901         public void setSet(ISet set) {
902             this.set = set;
903         }
904 
905         public ISet getSet() {
906             return set;
907         }
908 
909         public String toString() {
910             return "[Module " + getId() + "]";
911         }
912     }
913 }