KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > jawe > xml > XML


1 /* XML.java
2  *
3  * Authors:
4  * Stefanovic Nenad chupo@iis.ns.ac.yu
5  * Bojanic Sasa sasaboy@neobee.net
6  * Puskas Vladimir vpuskas@eunet.yu
7  * Pilipovic Goran zboniek@uns.ac.yu
8  *
9  */

10
11 package org.enhydra.jawe.xml;
12
13 import org.enhydra.jawe.xml.elements.*;
14 import org.enhydra.jawe.xml.elements.Package;
15
16 import java.util.*;
17 import java.io.*;
18 import java.nio.*;
19 import java.nio.channels.*;
20
21 import javax.xml.transform.*;
22 import javax.xml.transform.dom.*;
23 import javax.xml.transform.stream.*;
24 import org.w3c.dom.*;
25
26 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
27 import javax.xml.parsers.DocumentBuilder JavaDoc;
28 import org.apache.xml.serialize.XMLSerializer;
29 import org.apache.xml.serialize.OutputFormat;
30 import org.apache.xerces.parsers.DOMParser;
31 import org.xml.sax.*;
32
33 /**
34  * Class which purpose is to provide methods which are
35  * used by classes that represents program apstraction of
36  * XML elements. These methods offers support for reading or
37  * writting an XML document and for generating the tooltips for
38  * for the classes that needs it.
39  */

40 public class XML implements XMLInterface {
41
42    private LinkedHashMap idToPackage=new LinkedHashMap();
43    private LinkedHashMap xmlFileToPackage=new LinkedHashMap();
44    private LinkedHashMap pkgIdToFileContent=new LinkedHashMap();
45    private LinkedHashMap packageToParentDirectory=new LinkedHashMap();
46
47    private Map fileLocks=new HashMap();
48    private Map rndAccessFiles=new HashMap();
49
50    private String JavaDoc mainPackageReference;
51
52    private boolean fileLocking=true;
53
54    private Map parsingErrorMessages=new HashMap();
55    private boolean isValidationON=true;
56
57    public void setValidation (boolean isActive) {
58       isValidationON=isActive;
59    }
60
61    public void setFileLockingStatus (boolean status) {
62       fileLocking=status;
63    }
64
65    public void clearParserErrorMessages () {
66       parsingErrorMessages.clear();
67    }
68
69    /**
70     * This method has to be called from the newly created package after its
71     * Id is entered.
72     * @param pkg
73     */

74    public void register (Package JavaDoc pkg) {
75       idToPackage.put(pkg.get("Id").toString(),pkg);
76    }
77
78    /**
79     * This method is called when first saving new package, or when saving it with
80     * a different name.
81     * @param filename
82     * @param pkg
83     */

84    public void registerPackageFilename (String JavaDoc filename,Package JavaDoc pkg) {
85       String JavaDoc pkgId=pkg.get("Id").toString();
86       Iterator it=xmlFileToPackage.entrySet().iterator();
87       String JavaDoc uToRem=getAbsoluteFilePath(pkg);
88       if (uToRem!=null) {
89          xmlFileToPackage.remove(uToRem);
90       }
91       // release lock
92
try {
93          FileLock fl=(FileLock)fileLocks.remove(pkg);
94          fl.release();
95       } catch (Exception JavaDoc ex) {}
96       // close the file stream
97
try {
98          RandomAccessFile raf=(RandomAccessFile)rndAccessFiles.remove(pkg);
99          raf.close();
100       } catch (Exception JavaDoc ex) {}
101
102       String JavaDoc cp=XMLUtil.getCanonicalPath(filename, false);
103       xmlFileToPackage.put(cp,pkg);
104
105       File f=new File(cp);
106
107       try {
108          RandomAccessFile raf=new RandomAccessFile(f,"rw");
109          rndAccessFiles.put(pkg,raf);
110          if (fileLocking) {
111             FileLock fl=raf.getChannel().tryLock();
112             if (fl!=null) {
113                fileLocks.put(pkg,fl);
114                // this should never happend
115
} else {
116                System.out.println("Can't lock");
117             }
118          }
119          // this happens when using jdk1.4.0 under Linux, where
120
// the locking is not supported
121
} catch (IOException ex) {
122       } catch (Exception JavaDoc ex) {}
123
124       // register parent directory with the package
125
try {
126          packageToParentDirectory.put(pkg,f.getParentFile().getCanonicalPath());
127       } catch (Exception JavaDoc ex) {
128          packageToParentDirectory.put(pkg,f.getParentFile().getAbsolutePath());
129       }
130    }
131
132    public boolean isPackageOpened (String JavaDoc pkgId) {
133       return idToPackage.containsKey(pkgId);
134    }
135
136    public void putPkgIdToFileContentMapping (String JavaDoc pkgId,
137                                              String JavaDoc fileContent) {
138       //System.out.println("Adding mapping for file with id="+pkgId);
139
pkgIdToFileContent.put(pkgId,fileContent);
140    }
141
142    public String JavaDoc getPackageFileContent (String JavaDoc pkgId) {
143       return (String JavaDoc)pkgIdToFileContent.get(pkgId);
144    }
145
146    public Package JavaDoc getPackageById (String JavaDoc pkgId) {
147       return (Package JavaDoc)idToPackage.get(pkgId);
148    }
149
150    public Package JavaDoc getPackageByFilename (String JavaDoc filename) {
151       filename=XMLUtil.getCanonicalPath(filename, false);
152       return (Package JavaDoc)xmlFileToPackage.get(filename);
153    }
154
155    public RandomAccessFile getRaf (Package JavaDoc pkg){
156       return (RandomAccessFile)rndAccessFiles.get(pkg);
157    }
158
159    public Package JavaDoc getExternalPackageByRelativeFilePath (
160                                                         String JavaDoc relativePathToExtPkg,Package JavaDoc rootPkg) {
161
162       File f=new File(relativePathToExtPkg);
163       if (!f.isAbsolute()) {
164          f=new File(getParentDirectory(rootPkg)+File.separator+relativePathToExtPkg);
165       }
166       if (f.exists()) {
167          //System.out.println("Pkg for "+relativePathToExtPkg+"->"+f.getAbsolutePath()+" is found");
168
return getPackageByFilename(f.getAbsolutePath());
169       } else {
170          //System.out.println("Pkg for "+relativePathToExtPkg+"->"+f.getAbsolutePath()+" is not found");
171
return null;
172       }
173    }
174
175    public String JavaDoc getAbsoluteFilePath (Package JavaDoc pkg) {
176       Iterator it=xmlFileToPackage.entrySet().iterator();
177       String JavaDoc fullPath=null;
178       while (it.hasNext()) {
179          Map.Entry me=(Map.Entry)it.next();
180          String JavaDoc u=(String JavaDoc)me.getKey();
181          Package JavaDoc p=(Package JavaDoc)me.getValue();
182          if (p.equals(pkg)) {
183             fullPath=u;
184             break;
185          }
186       }
187       return fullPath;
188    }
189
190    public Collection getAllPackages () {
191       return idToPackage.values();
192    }
193
194    public Collection getAllPackageIds () {
195       return idToPackage.keySet();
196    }
197
198    public Collection getAllPackageFilenames () {
199       return xmlFileToPackage.keySet();
200    }
201
202    public boolean doesPackageFileExists (String JavaDoc xmlFile) {
203       if (new File(xmlFile).exists() || getPackageFileContent(xmlFile)!=null) {
204          return true;
205       } else {
206          return false;
207       }
208    }
209
210    public String JavaDoc getParentDirectory (Package JavaDoc pkg) {
211       return (String JavaDoc)packageToParentDirectory.get(pkg);
212    }
213
214    public Package JavaDoc openPackage (String JavaDoc pkgReference,boolean openFromStream) {
215       parsingErrorMessages.clear();
216       if (!openFromStream) {
217          mainPackageReference=pkgReference;
218       }
219       // remember the all packages before opening the given package
220
Set pre=new HashSet(getAllPackages());
221       // this method opens the package and all of it's external packages
222
Package JavaDoc pkg=openDocument(pkgReference,openFromStream);
223       // get all packages after opening the given package
224
Set post=new HashSet(getAllPackages());
225       // extract newly opened packages
226
post.removeAll(pre);
227       //System.out.println("Newly opened packages are: "+post);
228
// append all external packages of each newly added package (this means
229
// the packages referenced by the package's external packages, because
230
// till now, only the first level external packages are added).
231
// (there can be cross-reference, so it must be done this way).
232
Iterator newPackages=post.iterator();
233       while (newPackages.hasNext()) {
234          Package JavaDoc p=(Package JavaDoc)newPackages.next();
235          appendAllExternalPackagesForPackage(p);
236          //System.out.println("Eps for p "+p+" are "+p.getAllExternalPackages());
237
}
238
239       // calling afterImporting method on package and all ext. packages
240
// NOTE: this can't be done within the previous loop
241
newPackages=post.iterator();
242       while (newPackages.hasNext()) {
243          Package JavaDoc p=(Package JavaDoc)newPackages.next();
244          p.afterImporting();
245       }
246       if (pkg!=null && !openFromStream) {
247          System.setProperty("user.dir",getParentDirectory(pkg));
248       }
249       //printDebug();
250
return pkg;
251    }
252
253    public void printDebug () {
254       System.out.println("idToPackage="+idToPackage);
255       System.out.println("xmlFileToPackage="+xmlFileToPackage);
256       System.out.println("pkgIdToFileContent="+pkgIdToFileContent);
257       System.out.println("packageToWorkingDirectory="+packageToParentDirectory);
258       System.out.println("fileLocks="+fileLocks);
259       System.out.println("rndAccessFiles="+rndAccessFiles);
260    }
261
262    // Recursive implementation
263
private Package JavaDoc openDocument (String JavaDoc pkgReference,boolean openFromStream) {
264
265       Package JavaDoc pkg=null;
266       File f=null;
267       String JavaDoc oldP=pkgReference;
268
269       if (!openFromStream) {
270          pkgReference=XMLUtil.getCanonicalPath(pkgReference, false);
271          if (pkgReference==null) {
272             Set fem=new HashSet();
273             fem.add("File does not exist");
274             parsingErrorMessages.put(oldP,fem);
275             return null;
276          } else {
277
278             f=new File(pkgReference);
279             // set the proper user dir
280
try {
281                System.setProperty("user.dir",f.getParentFile().getCanonicalPath());
282             } catch (Exception JavaDoc ex) {
283                System.setProperty("user.dir",f.getParentFile().getAbsolutePath());
284             }
285          }
286       }
287
288       if (xmlFileToPackage.containsKey(pkgReference)) {
289          return getPackageByFilename(pkgReference);
290       }
291
292       if (openFromStream && idToPackage.containsKey(pkgReference)) {
293          return getPackageById(pkgReference);
294       }
295
296       if (!openFromStream) {
297          pkg=parseDocument(pkgReference,true);
298          try {
299             // trying to open main package file as 'rw'
300
// and to lock it exclusivly
301
if (oldP.equals(mainPackageReference)) {
302                RandomAccessFile raf=new RandomAccessFile(f,"rw");
303                rndAccessFiles.put(pkg,raf);
304                if (fileLocking) {
305                   FileLock fl=raf.getChannel().tryLock();
306                   // this happens if the main package is not already locked
307
if (fl!=null) {
308                      fileLocks.put(pkg,fl);
309                      // this happens if the file is already opened as 'rw' and locked
310
// exclusivly, or if it is opened as 'r' and locked as shared
311
} else {
312                      Set errorMessages = new HashSet();
313                      errorMessages.add(XMLUtil.getLanguageDependentString("ErrorTheFileIsLocked"));
314                      parsingErrorMessages.put(pkgReference,errorMessages);
315                      return null;
316                   }
317                }
318                // trying to open external package file as 'rw'
319
// and to lock it exclusivly
320
} else {
321                RandomAccessFile raf=new RandomAccessFile(f,"r");
322                rndAccessFiles.put(pkg,raf);
323                if (fileLocking) {
324                   FileLock fl=raf.getChannel().tryLock(0L,Long.MAX_VALUE,true);
325                   // this happens if the file isn't already opened as
326
// 'rw' and locked exclusivly
327
if (fl!=null) {
328                      fileLocks.put(pkg,fl);
329                      // this happens if the file is opened as 'rw' and locked exclusivly
330
} else {
331                      Set errorMessages = new HashSet();
332                      errorMessages.add(XMLUtil.getLanguageDependentString("ErrorTheFileIsLocked"));
333                      parsingErrorMessages.put(pkgReference,errorMessages);
334                      return null;
335                   }
336                }
337             }
338             // this exception happens if using jdk1.4.0 under Linux
339
} catch (Exception JavaDoc ex) {
340             //ex.printStackTrace();
341
}
342       } else {
343          pkg=parseDocument(getPackageFileContent(pkgReference),false);
344       }
345
346       if (pkg!=null) {
347          String JavaDoc pkgId=pkg.get("Id").toString();
348          // check if package is already imported
349
if (idToPackage.containsKey(pkgId)) {
350             // check if this is the same package, or just the one with the same id
351
if ((!openFromStream && xmlFileToPackage.containsKey(pkgReference)) ||
352                    (openFromStream && getPackageFileContent(pkgReference)!=null)) {
353                return getPackageById(pkgId);
354             } else {
355                return null;
356             }
357          }
358          idToPackage.put(pkgId,pkg);
359          if (!openFromStream) {
360             xmlFileToPackage.put(pkgReference,pkg);
361             try {
362                packageToParentDirectory.put(pkg,f.getParentFile().getCanonicalPath());
363             } catch (Exception JavaDoc ex) {
364                packageToParentDirectory.put(pkg,f.getParentFile().getAbsolutePath());
365             }
366          }
367
368          // open all external packages
369
Iterator eps=((ExternalPackages)pkg.get("ExternalPackages")).
370          toCollection().iterator();
371          while (eps.hasNext()) {
372             String JavaDoc pathToExtPackage=((ExternalPackage)eps.next()).get("href").toString();
373             // setting working dir to be the one of the current package
374
if (!openFromStream) {
375                System.setProperty("user.dir",packageToParentDirectory.get(pkg).toString());
376             }
377             Package JavaDoc extPkg=openDocument(pathToExtPackage,openFromStream);
378             if (extPkg!=null) {
379                pkg.addExternalPackage(extPkg);
380             }
381          }
382       } else {
383          System.err.println("Problems with opening file "+pkgReference);
384       }
385       return pkg;
386    }
387
388    private void appendAllExternalPackagesForPackage(Package JavaDoc m) {
389       Stack s = new Stack();
390       s.addAll(m.getAllExternalPackages());
391       Set result=new HashSet();
392       while (!s.isEmpty()) {
393          Package JavaDoc tmp=(Package JavaDoc)s.pop();
394          Iterator extPkgs=tmp.getAllExternalPackages().iterator();
395          while (extPkgs.hasNext()) {
396             Object JavaDoc nextP=extPkgs.next();
397             if (!m.getAllExternalPackages().contains(nextP) && !s.contains(nextP) && nextP!=m) {
398                s.add(nextP);
399                m.addExternalPackage((Package JavaDoc)nextP);
400             }
401          }
402       }
403    }
404
405    public Package JavaDoc parseDocument (String JavaDoc toParse,boolean isFile) {
406       Package JavaDoc pkg=null;
407       // Create a Xerces DOM Parser
408
DOMParser parser = new DOMParser();
409
410       // Parse the Document and traverse the DOM
411
try {
412          parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error",true);
413          ParsingErrors pErrors=new ParsingErrors();
414          parser.setErrorHandler(pErrors);
415          if (isValidationON) {
416             parser.setEntityResolver(new XPDLEntityResolver());
417             parser.setFeature("http://xml.org/sax/features/validation",true);
418             parser.setFeature("http://apache.org/xml/features/validation/schema",true);
419             //parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true);
420
}
421          if (isFile) {
422             //System.out.println("Parsing from file");
423
File f=new File(toParse);
424             if (!f.exists()) {
425                f=new File(f.getCanonicalPath());
426             }
427             //parser.parse(xmlFile);
428
parser.parse(new InputSource(new FileInputStream(f))); // Fixed by Harald Meister
429
} else {
430             //System.out.println("Parsing from stream");
431
parser.parse(new InputSource(new StringReader(toParse)));
432          }
433          Document document = parser.getDocument();
434          Set errorMessages = pErrors.getErrorMessages();
435          if (errorMessages.size()>0) {
436             //System.err.println("Errors during document parsing");
437
if (isFile) {
438                parsingErrorMessages.put(toParse,errorMessages);
439             } else {
440                parsingErrorMessages.put("",errorMessages);
441             }
442          }
443          if (document!=null) {
444             pkg=new Package JavaDoc(this);
445             pkg.fromXML(document.getDocumentElement());
446             //System.out.println("package "+pkg+" imported");
447
}
448       } catch (Exception JavaDoc ex) {
449          //ex.printStackTrace();
450
System.err.println("Fatal error while parsing document");
451          Set fem=new HashSet();
452          fem.add("Fatal error while parsing document");
453          if (isFile) {
454             parsingErrorMessages.put(toParse,fem);
455          } else {
456             parsingErrorMessages.put("",fem);
457          }
458          return null;
459       }
460       return pkg;
461    }
462
463    /**
464     * This method should be called immediatelly after opening a document,
465     * otherwise, messages could be invalid.
466     * @return The map which keys are opened packages, and values are the sets
467     * of errors for corresponding package.
468     */

469    public Map getParsingErrorMessages () {
470       return parsingErrorMessages;
471    }
472
473    public void closePackage (String JavaDoc pkgId) {
474       Package JavaDoc toRemove=(Package JavaDoc)idToPackage.remove(pkgId);
475       if (toRemove!=null) {
476          // removing file to package mapping
477
Iterator it=xmlFileToPackage.entrySet().iterator();
478          Object JavaDoc keyToRemove=null;
479          while (it.hasNext()) {
480             Map.Entry me=(Map.Entry)it.next();
481             Object JavaDoc key=me.getKey();
482             Object JavaDoc val=me.getValue();
483             if (val.equals(toRemove)) {
484                keyToRemove=key;
485                break;
486             }
487          }
488          if (keyToRemove!=null) {
489             xmlFileToPackage.remove(keyToRemove);
490          }
491
492          packageToParentDirectory.remove(toRemove);
493          // close file
494
RandomAccessFile raf=(RandomAccessFile)rndAccessFiles.remove(toRemove);
495          try {
496             raf.close();
497          } catch (Exception JavaDoc ex) {}
498          // unlock file
499
FileLock fl=(FileLock)fileLocks.remove(toRemove);
500          try {
501             fl.release();
502          } catch (Exception JavaDoc ex) {}
503       }
504
505       pkgIdToFileContent.remove(pkgId);
506    }
507
508    public void closeAllPackages () {
509       idToPackage.clear();
510       xmlFileToPackage.clear();
511       packageToParentDirectory.clear();
512       pkgIdToFileContent.clear();
513       // close all files
514
Iterator it=rndAccessFiles.values().iterator();
515       while (it.hasNext()) {
516          RandomAccessFile raf=(RandomAccessFile)it.next();
517          try {
518             raf.close();
519          } catch (Exception JavaDoc ex) {}
520       }
521       rndAccessFiles.clear();
522       unlockAllFiles();
523    }
524
525    public void unlockAllFiles () {
526       // unlock all files
527
Iterator it=fileLocks.values().iterator();
528       while (it.hasNext()) {
529          FileLock fl=(FileLock)it.next();
530          try {
531             fl.release();
532          } catch (Exception JavaDoc ex) {}
533       }
534       fileLocks.clear();
535    }
536
537    public void lockAllFiles () {
538       if (!fileLocking) return;
539       Iterator it=rndAccessFiles.entrySet().iterator();
540       while (it.hasNext()) {
541          Map.Entry me=(Map.Entry)it.next();
542          Package JavaDoc pkg=(Package JavaDoc)me.getKey();
543          RandomAccessFile raf=(RandomAccessFile)me.getValue();
544
545          try {
546             // lock main package exclusivly
547
if (pkg.equals(mainPackageReference)) {
548                FileLock fl=raf.getChannel().tryLock();
549                // this happens if the main package is not already locked
550
if (fl!=null) {
551                   fileLocks.put(pkg,fl);
552                   // this happens if the file is already opened as 'rw' and locked
553
// exclusivly, or if it is opened as 'r' and locked as shared
554
} else {
555                   continue;
556                }
557                // lock external package exclusivly
558
} else {
559                FileLock fl=raf.getChannel().tryLock(0L,Long.MAX_VALUE,true);
560                // this happens if the file isn't already opened as
561
// 'rw' and locked exclusivly
562
if (fl!=null) {
563                   fileLocks.put(pkg,fl);
564                   // this happens if the file is opened as 'rw' and locked exclusivly
565
} else {
566                   continue;
567                }
568             }
569             // this exception happens if using jdk1.4.0 under Linux
570
} catch (Exception JavaDoc ex) {
571             //ex.printStackTrace();
572
}
573       }
574    }
575
576    public String JavaDoc getIDFromFile (String JavaDoc xmlFile) {
577       try {
578          // Create parser
579
DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
580          factory.setValidating(false);
581          DocumentBuilder JavaDoc parser = factory.newDocumentBuilder();
582          Document document=null;
583
584          // Parse the Document
585
try {
586             File f=new File(xmlFile);
587             if (!f.exists()) {
588                f=new File(f.getCanonicalPath());
589             }
590             //document=parser.parse(xmlFile);
591
document=parser.parse(new InputSource(new FileInputStream(f))); // Fixed by Harald Meister
592
} catch (Exception JavaDoc ex) {
593             document=parser.parse(new InputSource(new StringReader(getPackageFileContent(xmlFile))));
594          }
595          return XMLUtil.getID(document.getDocumentElement());
596       } catch (Exception JavaDoc ex) {
597          return "";
598       }
599    }
600
601 }
602
603
Popular Tags