001: package org.enhydra.jawe.base.xpdlhandler;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.io.RandomAccessFile;
006: import java.nio.channels.FileLock;
007: import java.util.ArrayList;
008: import java.util.HashMap;
009: import java.util.HashSet;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.Map;
013: import java.util.Set;
014:
015: import org.enhydra.jawe.JaWEComponent;
016: import org.enhydra.jawe.ResourceManager;
017: import org.enhydra.shark.xpdl.XMLInterface;
018: import org.enhydra.shark.xpdl.XMLInterfaceForJDK13;
019: import org.enhydra.shark.xpdl.XMLUtil;
020: import org.enhydra.shark.xpdl.elements.ExternalPackage;
021: import org.enhydra.shark.xpdl.elements.Package;
022:
023: /**
024: * Class which purpose is to provide methods which are
025: * used by classes that represents program apstraction of
026: * XML elements. These methods offers support for reading or
027: * writting an XML document and for generating the tooltips for
028: * for the classes that needs it.
029: */
030: public class XPDLHandler extends XMLInterfaceForJDK13 {
031:
032: protected XPDLHandlerSettings settings;
033:
034: private Map fileLocks = new HashMap();
035: private Map rndAccessFiles = new HashMap();
036:
037: public XPDLHandler() {
038: settings = new XPDLHandlerSettings();
039: settings.init((JaWEComponent) null);
040: }
041:
042: public XPDLHandler(XPDLHandlerSettings settings) throws Exception {
043: this .settings = settings;
044: this .settings.init((JaWEComponent) null);
045: }
046:
047: public Package getMainPackage() {
048: return (Package) xmlFileToPackage.get(mainPackageReference);
049: }
050:
051: public String getMainPackageId() {
052: Package mainPackage = getMainPackage();
053: if (mainPackage != null) {
054: return mainPackage.getId();
055: }
056:
057: return null;
058: }
059:
060: public String getMainPackageFilename() {
061: return mainPackageReference;
062: }
063:
064: /**
065: * This method has to be called when new package is created.
066: * @param pkg
067: */
068: public void registerPackage(Package pkg) {
069: ArrayList l = (ArrayList) idToPackages.get(pkg.getId());
070: if (l == null) {
071: l = new ArrayList();
072: }
073: l.add(pkg);
074: idToPackages.put(pkg.getId(), l);
075: }
076:
077: /**
078: * This method has to be called from the newly created package after its
079: * Id is entered.
080: * @param pkg
081: */
082: public void changePackageId(Package pkg, String oldId, String newId) {
083: ArrayList l = (ArrayList) idToPackages.remove(oldId);
084: // if (l!=null) {
085: //
086: // }
087: l = (ArrayList) idToPackages.get(newId);
088: if (l == null) {
089: l = new ArrayList();
090: }
091: l.add(pkg);
092: idToPackages.put(newId, l);
093:
094: }
095:
096: /**
097: * This method is called when first saving new package, or when saving it with
098: * a different name.
099: * @param filename
100: * @param pkg
101: */
102: public void registerPackageFilename(String filename, Package pkg) {
103: String uToRem = getAbsoluteFilePath(pkg);
104: boolean isMainPackage = false;
105: if (uToRem != null) {
106: if (uToRem.equals(mainPackageReference)) {
107: isMainPackage = true;
108: }
109: xmlFileToPackage.remove(uToRem);
110: }
111: // release lock
112: try {
113: FileLock fl = (FileLock) fileLocks.remove(pkg);
114: fl.release();
115: } catch (Exception ex) {
116: }
117: // close the file stream
118: try {
119: RandomAccessFile raf = (RandomAccessFile) rndAccessFiles
120: .remove(pkg);
121: raf.close();
122: } catch (Exception ex) {
123: }
124:
125: String cp = XMLUtil.getCanonicalPath(filename, false);
126: xmlFileToPackage.put(cp, pkg);
127: if (isMainPackage || mainPackageReference == null) {
128: mainPackageReference = cp;
129: }
130:
131: File f = new File(cp);
132:
133: try {
134: RandomAccessFile raf = new RandomAccessFile(f, "rw");
135: rndAccessFiles.put(pkg, raf);
136: if (settings.isFileLockingEnabled()) {
137: FileLock fl = raf.getChannel().tryLock();
138: if (fl != null) {
139: fileLocks.put(pkg, fl);
140: // this should never happend
141: } else {
142: System.out.println("Can't lock");
143: }
144: }
145: // this happens when using jdk1.4.0 under Linux, where
146: // the locking is not supported
147: } catch (IOException ex) {
148: } catch (Exception ex) {
149: }
150:
151: // register parent directory with the package
152: try {
153: packageToParentDirectory.put(pkg, f.getParentFile()
154: .getCanonicalPath());
155: } catch (Exception ex) {
156: packageToParentDirectory.put(pkg, f.getParentFile()
157: .getAbsolutePath());
158: }
159: }
160:
161: public RandomAccessFile getRaf(Package pkg) {
162: return (RandomAccessFile) rndAccessFiles.get(pkg);
163: }
164:
165: // In this implementation, if handleExternalPackages is set to false, it is assumed
166: // that JaWE is opening transient Package
167: public Package openPackage(String pkgReference,
168: boolean handleExternalPackages) {
169: parsingErrorMessages.clear();
170: if (mainPackageReference == null && handleExternalPackages) {
171: mainPackageReference = pkgReference;
172: }
173:
174: // this method opens the package. It also opens all of it's external packages
175: // if handleExternalPackages is set to true
176: Package pkg = openPackageRecursively(pkgReference,
177: handleExternalPackages);
178: if (pkg != null) {
179: pkg.setTransient(!handleExternalPackages);
180: System.setProperty("user.dir", getParentDirectory(pkg));
181: }
182:
183: return pkg;
184: }
185:
186: public void printDebug() {
187: super .printDebug();
188: System.out.println("fileLocks=" + fileLocks);
189: System.out.println("rndAccessFiles=" + rndAccessFiles);
190: System.out.println("main package reference="
191: + mainPackageReference);
192: }
193:
194: // Recursive implementation
195: protected Package openPackageRecursively(String pkgReference,
196: boolean handleExternalPackages) {
197:
198: Package pkg = null;
199: File f = null;
200: String oldP = pkgReference;
201:
202: String baseDirectory = null;
203: pkgReference = XMLUtil
204: .getCanonicalPath(pkgReference, "", false);
205: if (pkgReference == null) {
206: Set fem = new HashSet();
207: fem.add("File does not exist");
208: parsingErrorMessages.put(oldP, fem);
209: return null;
210: }
211:
212: f = new File(pkgReference);
213: try {
214: baseDirectory = f.getParentFile().getCanonicalPath();
215: } catch (Exception ex) {
216: baseDirectory = f.getParentFile().getAbsolutePath();
217: }
218:
219: if (xmlFileToPackage.containsKey(pkgReference)) {
220: return getPackageByFilename(pkgReference);
221: }
222:
223: pkg = parseDocument(pkgReference, true);
224: try {
225: // trying to open main package file as 'rw'
226: // and to lock it exclusivly
227: if (oldP.equals(mainPackageReference)) {
228: RandomAccessFile raf = null;
229: try {
230: raf = new RandomAccessFile(f, "rw");
231: } catch (Exception ex) {
232: raf = new RandomAccessFile(f, "r");
233: }
234: rndAccessFiles.put(pkg, raf);
235: if (settings.isFileLockingEnabled()) {
236: FileLock fl = raf.getChannel().tryLock();
237: // this happens if the main package is not already locked
238: if (fl != null) {
239: fileLocks.put(pkg, fl);
240: // this happens if the file is already opened as 'rw' and locked
241: // exclusivly, or if it is opened as 'r' and locked as shared
242: } else {
243: Set errorMessages = new HashSet();
244: errorMessages
245: .add(ResourceManager
246: .getLanguageDependentString("ErrorTheFileIsLocked"));
247: parsingErrorMessages.put(pkgReference,
248: errorMessages);
249: return null;
250: }
251: }
252: // trying to open external package file as 'rw'
253: // and to lock it exclusivly
254: } else {
255: RandomAccessFile raf = null;
256: try {
257: raf = new RandomAccessFile(f, "rw");
258: } catch (Exception ex) {
259: raf = new RandomAccessFile(f, "r");
260: }
261: rndAccessFiles.put(pkg, raf);
262: if (settings.isFileLockingEnabled()) {
263: FileLock fl = raf.getChannel().tryLock();
264: //FileLock fl=raf.getChannel().tryLock(0L,Long.MAX_VALUE,true);
265: // this happens if the file isn't already opened as
266: // 'rw' and locked exclusivly
267: if (fl != null) {
268: fileLocks.put(pkg, fl);
269: // this happens if the file is opened as 'rw' and locked exclusivly
270: } else {
271: Set errorMessages = new HashSet();
272: errorMessages
273: .add(ResourceManager
274: .getLanguageDependentString("ErrorTheFileIsLocked"));
275: parsingErrorMessages.put(pkgReference,
276: errorMessages);
277: return null;
278: }
279: }
280: }
281: // this exception happens if using jdk1.4.0 under Linux
282: } catch (Exception ex) {
283: //ex.printStackTrace();
284: }
285:
286: if (pkg != null) {
287: String pkgId = pkg.getId();
288: // check if package is already imported
289: if (idToPackages.containsKey(pkgId)) {
290: // check if this is the same package, or just the one with the same id
291: if (xmlFileToPackage.containsKey(pkgReference)) {
292: return getPackageById(pkgId);
293: }
294:
295: throw new RuntimeException(
296: "Can't open two packages with the same Id");
297: }
298: ArrayList l = (ArrayList) idToPackages.get(pkgId);
299: if (l == null) {
300: l = new ArrayList();
301: }
302: l.add(pkg);
303: idToPackages.put(pkgId, l);
304: xmlFileToPackage.put(pkgReference, pkg);
305: try {
306: packageToParentDirectory.put(pkg, f.getParentFile()
307: .getCanonicalPath());
308: } catch (Exception ex) {
309: packageToParentDirectory.put(pkg, f.getParentFile()
310: .getAbsolutePath());
311: }
312: // open all external packages if handleExternalPackages is set to true,
313: // otherwise, it assumes that if there are external packages, the
314: // href element is similar to their Ids
315: Iterator eps = pkg.getExternalPackages().toElements()
316: .iterator();
317: while (eps.hasNext()) {
318: String pathToExtPackage = ((ExternalPackage) eps.next())
319: .getHref();
320: String extPkgId = null;
321: if (handleExternalPackages) {
322: // setting working dir to be the one of the current package
323: String ptep = XMLUtil.getCanonicalPath(
324: pathToExtPackage, baseDirectory, false);
325: if (ptep == null) {
326: Set fem = new HashSet();
327: fem.add("File does not exist");
328: parsingErrorMessages.put(pathToExtPackage, fem);
329: continue;
330: }
331:
332: //System.setProperty("user.dir",packageToParentDirectory.get(pkg).toString());
333: Package extPkg = openPackageRecursively(ptep,
334: handleExternalPackages);
335: extPkgId = extPkg.getId();
336: } else {
337: extPkgId = XMLUtil
338: .getExternalPackageId(pathToExtPackage);
339: }
340: pkg.addExternalPackageMapping(pathToExtPackage,
341: extPkgId);
342: }
343: } else {
344: System.err.println("Problems with opening file "
345: + pkgReference);
346: }
347: return pkg;
348: }
349:
350: public synchronized List closePackages(String pkgId) {
351: Package main = getMainPackage();
352: List l = super .closePackages(pkgId);
353: if (l != null) {
354: // removing file to package mapping
355: Iterator itr = l.iterator();
356: while (itr.hasNext()) {
357: Package toRemove = (Package) itr.next();
358: if (toRemove == main) {
359: mainPackageReference = null;
360: }
361: // close file
362: RandomAccessFile raf = (RandomAccessFile) rndAccessFiles
363: .remove(toRemove);
364: try {
365: raf.close();
366: } catch (Exception ex) {
367: }
368: // unlock file
369: FileLock fl = (FileLock) fileLocks.remove(toRemove);
370: try {
371: fl.release();
372: } catch (Exception ex) {
373: }
374: }
375: }
376: return l;
377: }
378:
379: public synchronized Package closePackageVersion(String pkgId,
380: String pkgVer) {
381: Package main = getMainPackage();
382: ArrayList l = (ArrayList) idToPackages.get(pkgId);
383: if (l.size() == 1) {
384: return (Package) this .closePackages(pkgId).get(0);
385: }
386:
387: Package toRemove = super .closePackageVersion(pkgId, pkgVer);
388: // System.out.println("TRID="+toRemove.getId());
389: if (toRemove != null) {
390: if (toRemove == main) {
391: mainPackageReference = null;
392: }
393: // close file
394: RandomAccessFile raf = (RandomAccessFile) rndAccessFiles
395: .remove(toRemove);
396: try {
397: raf.close();
398: } catch (Exception ex) {
399: }
400: // unlock file
401: FileLock fl = (FileLock) fileLocks.remove(toRemove);
402: try {
403: fl.release();
404: } catch (Exception ex) {
405: }
406: }
407: return toRemove;
408: }
409:
410: public void closeAllPackages() {
411: // close all files
412: super .closeAllPackages();
413: Iterator it = rndAccessFiles.values().iterator();
414: while (it.hasNext()) {
415: RandomAccessFile raf = (RandomAccessFile) it.next();
416: try {
417: raf.close();
418: } catch (Exception ex) {
419: }
420: }
421: rndAccessFiles.clear();
422: unlockAllFiles();
423: mainPackageReference = null;
424: }
425:
426: public void unlockAllFiles() {
427: // unlock all files
428: Iterator it = fileLocks.values().iterator();
429: while (it.hasNext()) {
430: FileLock fl = (FileLock) it.next();
431: try {
432: fl.release();
433: } catch (Exception ex) {
434: }
435: }
436: fileLocks.clear();
437: }
438:
439: public void lockAllFiles() throws Exception {
440: if (!settings.isFileLockingEnabled())
441: return;
442: Iterator it = rndAccessFiles.entrySet().iterator();
443: Package main = (Package) xmlFileToPackage
444: .get(mainPackageReference);
445: while (it.hasNext()) {
446: Map.Entry me = (Map.Entry) it.next();
447: Package pkg = (Package) me.getKey();
448: RandomAccessFile raf = (RandomAccessFile) me.getValue();
449:
450: // try {
451: // lock main package exclusivly
452: if (pkg.equals(main)) {
453: FileLock fl = raf.getChannel().tryLock();
454: // this happens if the main package is not already locked
455: if (fl != null) {
456: fileLocks.put(pkg, fl);
457: // this happens if the file is already opened as 'rw' and locked
458: // exclusivly, or if it is opened as 'r' and locked as shared
459: } else {
460: continue;
461: }
462: // lock external package exclusivly
463: } else {
464: FileLock fl = raf.getChannel().tryLock(0L,
465: Long.MAX_VALUE, true);
466: // this happens if the file isn't already opened as
467: // 'rw' and locked exclusivly
468: if (fl != null) {
469: fileLocks.put(pkg, fl);
470: // this happens if the file is opened as 'rw' and locked exclusivly
471: } else {
472: continue;
473: }
474: }
475: // this exception happens if using jdk1.4.0 under Linux
476: // } catch (Exception ex) {
477: // //ex.printStackTrace();
478: // }
479: }
480: }
481:
482: public synchronized void synchronizePackages(
483: XMLInterface xmlInterface) {
484: Iterator it = xmlInterface.getAllPackages().iterator();
485: while (it.hasNext()) {
486: Package pkg = (Package) it.next();
487: String pkgId = pkg.getId();
488: ArrayList l = (ArrayList) idToPackages.get(pkgId);
489: if (l == null) {
490: l = new ArrayList();
491: } else {
492: continue;
493: }
494: l.add(pkg);
495: idToPackages.put(pkgId, l);
496: String fp = xmlInterface.getAbsoluteFilePath(pkg);
497: if (fp != null) {
498: xmlFileToPackage.put(fp, pkg);
499: }
500: String pd = xmlInterface.getParentDirectory(pkg);
501: if (pd != null) {
502: packageToParentDirectory.put(pkg, pd);
503: }
504:
505: XPDLHandler xpdlh = (XPDLHandler) xmlInterface;
506: RandomAccessFile raf = xpdlh.getRaf(pkg);
507: if (raf != null) {
508: this .rndAccessFiles.put(pkg, raf);
509: }
510: FileLock fl = (FileLock) xpdlh.fileLocks.get(pkg);
511: if (fl != null) {
512: if (xpdlh.getMainPackage() == pkg) {
513: try {
514: fl.release();
515: } catch (Exception ex) {
516: System.err
517: .println("Failed to release file lock for package "
518: + pkg.getId());
519: }
520: fl = null;
521: try {
522: fl = raf.getChannel().tryLock();
523: } catch (Exception ex) {
524: }
525: }
526: if (fl != null) {
527: this.fileLocks.put(pkg, fl);
528: }
529: }
530: }
531: }
532:
533: }
|