001: // PropertyManager.java
002: // $Id: PropertyManager.java,v 1.8 2000/08/16 21:37:28 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1997.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigadmin;
007:
008: import java.util.Enumeration;
009: import java.util.Hashtable;
010: import java.util.Properties;
011: import java.util.StringTokenizer;
012: import java.util.Vector;
013:
014: import java.util.zip.ZipEntry;
015: import java.util.zip.ZipFile;
016:
017: import java.io.BufferedInputStream;
018: import java.io.File;
019: import java.io.InputStream;
020: import java.io.PrintStream;
021:
022: import org.w3c.jigsaw.admin.RemoteAccessException;
023: import org.w3c.jigsaw.admin.RemoteResource;
024:
025: import org.w3c.tools.resources.Attribute;
026:
027: class ResourceClassProperties {
028:
029: // The class we're handling the configuration for
030: String entryPath = null;
031: // The zip file this classes configuration is at
032: ZipFile zip = null;
033: // The class editor properties
034: Properties editorProperties = null;
035: // The set of registered helpers for that editor's class
036: String helperClasses[] = new String[0];
037: // The helpers properties (map help classes to properties)
038: Hashtable helperProperties = null;
039: // The attribute properties
040: Hashtable attributeProperties = null;
041:
042: /**
043: * Parse | separated property value into a String array.
044: * @param p Properties to look into.
045: * @param name The property to look for and parse.
046: * @return A non-null but potentially zero-length string array.
047: */
048:
049: static String[] getStringArray(Properties p, String name) {
050: String v = (String) p.get(name);
051: if (v == null)
052: return new String[0];
053: // Parse the property value:
054: StringTokenizer st = new StringTokenizer(v, "|");
055: int len = st.countTokens();
056: String ret[] = new String[len];
057: for (int i = 0; i < ret.length; i++) {
058: ret[i] = st.nextToken();
059: }
060: return ret;
061:
062: }
063:
064: /**
065: * Does this class config allows for helper aggregation.
066: * If <strong>true</strong> this means that the GUI should instantiate
067: * all inherited helpers to construct the resource editor.
068: * @return A boolean.
069: */
070:
071: boolean aggregateHelpers() {
072: if (editorProperties == null)
073: return true;
074: String s = (String) editorProperties.get("aggregateHelpers");
075: return (s != null) && s.equalsIgnoreCase("true");
076: }
077:
078: /**
079: * Does this class config allows for attribute aggregation.
080: * If <strong>true</strong> this means that the GUI should instantiate
081: * an editor for all inherited attributes.
082: * @return A boolean.
083: */
084:
085: boolean aggregateAttributes() {
086: if (editorProperties == null)
087: return true;
088: String s = (String) editorProperties.get("aggregateAttributes");
089: return (s != null) && s.equalsIgnoreCase("true");
090: }
091:
092: /**
093: * Should the config aggregate specific attribute editor properties.
094: * @return A boolean.
095: */
096:
097: boolean aggregateAttributeProperties() {
098: return false;
099: }
100:
101: /**
102: * Utility - Load a directory of prop files into given hashtable.
103: * @param into Hashtable to fill in with Properties instance.
104: * @param dir Directory to load.
105: */
106:
107: void loadPropertyDirectory(Hashtable into, ZipFile zip, String dir) {
108: try {
109: Enumeration entries = zip.entries();
110: while (entries.hasMoreElements()) {
111: ZipEntry entry = (ZipEntry) entries.nextElement();
112: String name = entry.getName();
113: if (name.startsWith(dir) && name.endsWith(".p")) {
114: Properties p = new Properties();
115: InputStream in = (new BufferedInputStream(zip
116: .getInputStream(entry)));
117: p.load(in);
118: in.close();
119: // Register them into the hashtable:
120: into.put(name.substring(dir.length() + 1, name
121: .length() - 2), p);
122: }
123: }
124: } catch (Exception ex) {
125: ex.printStackTrace();
126: }
127: }
128:
129: /**
130: * Initialize that class config.
131: * This method will load the resource editor properties, than the helper
132: * specific properties, and finally the attribute properties.
133: */
134:
135: void initialize() {
136: // Load the editor properties:
137: try {
138: ZipEntry propentry = zip.getEntry(entryPath + "properties");
139: if (propentry != null) {
140: InputStream in = (new BufferedInputStream(zip
141: .getInputStream(propentry)));
142: editorProperties = new Properties();
143: editorProperties.load(in);
144: in.close();
145: }
146: } catch (Exception ex) {
147: ex.printStackTrace();
148: }
149: // From the editor properties, get the set of helpers:
150: if (editorProperties != null)
151: helperClasses = getStringArray(editorProperties, "helpers");
152: // Load the helpers specific properties:
153: helperProperties = new Hashtable(11);
154: loadPropertyDirectory(helperProperties, zip, entryPath
155: + "helpers");
156: // Load the specific attribute editor properties:
157: attributeProperties = new Hashtable(11);
158: loadPropertyDirectory(attributeProperties, zip, entryPath
159: + "attrs");
160: }
161:
162: String[] getHelperClasses() {
163: return helperClasses;
164: }
165:
166: Properties getHelperProperties(String clsname) {
167: Properties p = (Properties) helperProperties.get(clsname);
168: return p;
169: }
170:
171: Properties getAttributeProperties(String name) {
172: Properties p = (Properties) attributeProperties.get(name);
173: return p;
174: }
175:
176: Properties getEditorProperties() {
177: return editorProperties;
178: }
179:
180: String getEditorClass() {
181: if (editorProperties == null)
182: return null;
183: return (String) editorProperties.get("class");
184: }
185:
186: boolean isEditable() {
187: if (editorProperties == null)
188: return true;
189: String editable = (String) editorProperties.get("editable");
190: if (editable == null)
191: return true;
192: return (!editable.equalsIgnoreCase("false"));
193: }
194:
195: boolean isExtensible() {
196: if (editorProperties == null)
197: return true;
198: String extensible = (String) editorProperties.get("extensible");
199: if (extensible == null)
200: return true;
201: return (!extensible.equalsIgnoreCase("false"));
202: }
203:
204: ResourceClassProperties(String entryPath, ZipFile zip) {
205: this .entryPath = entryPath;
206: this .zip = zip;
207: initialize();
208: }
209: }
210:
211: /**
212: * The PropertyManager
213: * @version $Revision: 1.8 $
214: * @author Benoît Mahé (bmahe@w3.org)
215: */
216: public class PropertyManager {
217:
218: /**
219: * The root for the property files.
220: */
221: protected File root = null;
222: protected File zipfile = null;
223: /**
224: * The set of resource classes we know about.
225: * Maps class names to ResourceClassProperty
226: */
227: protected Hashtable classProperties = null;
228:
229: /**
230: * the mapping of icon names to icon locations
231: */
232: protected Properties iconProperties = null;
233:
234: /**
235: * the hashtable of mime types
236: */
237: protected Hashtable mimeTypes = null;
238: /**
239: * the hashtable of resources
240: */
241: protected Properties resources = null;
242: /**
243: * the hashtable of frames
244: */
245: protected Properties frames = null;
246: /**
247: * the hashtable of indexers
248: */
249: protected Properties indexers = null;
250:
251: private boolean inited = false;
252:
253: protected static Properties merge(Properties into,
254: Properties source, boolean overide) {
255: Properties p = (Properties) into.clone();
256: Enumeration e = source.keys();
257: while (e.hasMoreElements()) {
258: Object key = e.nextElement();
259: if ((!overide) && into.get(key) != null)
260: continue;
261: Object val = source.get(key);
262: p.put(key, val);
263: }
264: return p;
265: }
266:
267: protected static Properties merge(Properties into, Properties source) {
268: return merge(into, source, true);
269: }
270:
271: /**
272: * Load the properties from the root directory.
273: */
274:
275: protected void initialize() {
276: ZipFile zip = null;
277: try {
278: zip = new ZipFile(this .zipfile);
279: } catch (Exception ex) {
280: ex.printStackTrace();
281: return;
282: }
283: Enumeration entries = zip.entries();
284: classProperties = new Hashtable(11);
285:
286: while (entries.hasMoreElements()) {
287: ZipEntry entry = (ZipEntry) entries.nextElement();
288: String entry_name = entry.getName();
289: if (entry_name.equals("icons" + File.separator)) //reserved
290: continue;
291: // Skip non directory entries
292: if (!entry.isDirectory())
293: continue;
294: // only first level sub directories
295: if (entry_name.indexOf(File.separator) == entry_name
296: .lastIndexOf(File.separator)) {
297: ResourceClassProperties rcp = null;
298: rcp = new ResourceClassProperties(entry_name, zip);
299: String name = entry_name.substring(0, entry_name
300: .length() - 1);
301: classProperties.put(name, rcp);
302: }
303: }
304: // and now the icons mapping
305: try {
306: ZipEntry icons = zip.getEntry("icons.p");
307: InputStream in = (new BufferedInputStream(zip
308: .getInputStream(icons)));
309: iconProperties = new Properties();
310: iconProperties.load(in);
311: in.close();
312: } catch (Exception ex) {
313: ex.printStackTrace();
314: }
315: // and now the mime types
316: mimeTypes = new Hashtable(11);
317: try {
318: ZipEntry mime = zip.getEntry("mimetypes.p");
319: InputStream in = (new BufferedInputStream(zip
320: .getInputStream(mime)));
321: Properties p = new Properties();
322: p.load(in);
323: in.close();
324: String[] major = ResourceClassProperties.getStringArray(p,
325: "Types");
326: String[] minor;
327: for (int i = 0; i < major.length; i++) {
328: minor = ResourceClassProperties.getStringArray(p,
329: major[i]);
330: mimeTypes.put(major[i], minor);
331: }
332: } catch (Exception ex) {
333: ex.printStackTrace();
334: }
335: //resources list
336: try {
337: ZipEntry res = zip.getEntry("resources.p");
338: InputStream in = (new BufferedInputStream(zip
339: .getInputStream(res)));
340: resources = new Properties();
341: resources.load(in);
342: in.close();
343: } catch (Exception ex) {
344: ex.printStackTrace();
345: }
346: //frames list
347: try {
348: ZipEntry fr = zip.getEntry("frames.p");
349: InputStream in = (new BufferedInputStream(zip
350: .getInputStream(fr)));
351: frames = new Properties();
352: frames.load(in);
353: in.close();
354: } catch (Exception ex) {
355: ex.printStackTrace();
356: }
357: //indexers list
358: try {
359: ZipEntry idx = zip.getEntry("indexers.p");
360: InputStream in = (new BufferedInputStream(zip
361: .getInputStream(idx)));
362: indexers = new Properties();
363: indexers.load(in);
364: in.close();
365: } catch (Exception ex) {
366: ex.printStackTrace();
367: }
368: //close
369: try {
370: zip.close(); //FIXME: sure?
371: } catch (Exception ex) {
372: ex.printStackTrace();
373: }
374: inited = true;
375: }
376:
377: /**
378: * Get the best matching resource class properties for given class.
379: * @param classes The class names we're looking a macth for.
380: * @return A ResourceClassProperties instance.
381: */
382:
383: protected ResourceClassProperties getResourceClassProperties(
384: String names[], int from) {
385: // Look along the hierarchy for a class editor:
386: ResourceClassProperties rcp = null;
387: for (int i = from; i < names.length; i++) {
388: rcp = (ResourceClassProperties) classProperties
389: .get(names[i]);
390: if (rcp != null)
391: break;
392: }
393: if (rcp == null)
394: throw new RuntimeException(
395: "configuration error, no editor for: " + names[0]);
396: return rcp;
397: }
398:
399: protected ResourceClassProperties getResourceClassProperties(
400: String names[]) {
401: return getResourceClassProperties(names, 0);
402: }
403:
404: protected int findResourceClassProperties(String classes[],
405: int offset) {
406: // Look along the hierarchy for a class editor:
407: ResourceClassProperties rcp = null;
408: for (int i = offset; i < classes.length; i++) {
409: rcp = (ResourceClassProperties) classProperties
410: .get(classes[i]);
411: if (rcp != null)
412: return i;
413: }
414: return -1;
415: }
416:
417: protected int findResourceClassProperties(String classes[]) {
418: return findResourceClassProperties(classes, 0);
419: }
420:
421: protected String[] getClassHierarchy(RemoteResourceWrapper rrw) {
422: try {
423: String classes[] = rrw.getResource().getClassHierarchy();
424: return classes;
425: } catch (RemoteAccessException ex) {
426: ex.printStackTrace();
427: }
428: return new String[0];
429: }
430:
431: protected Properties getDefaultHelperProperties(String clsname) {
432: ResourceClassProperties rcp = null;
433: rcp = (ResourceClassProperties) classProperties.get("defaults");
434: if (rcp != null)
435: return rcp.getHelperProperties(clsname);
436: return null;
437: }
438:
439: protected Properties getDefaultAttributeProperties(String clsname) {
440: ResourceClassProperties rcp = null;
441: rcp = (ResourceClassProperties) classProperties.get("defaults");
442: if (rcp != null)
443: return rcp.getAttributeProperties(clsname);
444: return null;
445: }
446:
447: /**
448: * Get any properties for the editor of the given remote resource instance.
449: * @return A Properties instance.
450: */
451:
452: public Properties getEditorProperties(RemoteResourceWrapper rrw) {
453: String classes[] = getClassHierarchy(rrw);
454: return getResourceClassProperties(classes)
455: .getEditorProperties();
456: }
457:
458: /**
459: * Get any properties for the editor of the given remote resource instance.
460: * @return A Properties instance.
461: */
462:
463: public String getEditorClass(RemoteResourceWrapper rrw) {
464: String classes[] = getClassHierarchy(rrw);
465: return getResourceClassProperties(classes).getEditorClass();
466: }
467:
468: /**
469: * Is the resource editable via JigAdmin?
470: * @param rrw the RemoteResourceWrapper
471: * @return true is the resoure is editable
472: */
473:
474: public boolean isEditable(RemoteResourceWrapper rrw) {
475: String classes[] = getClassHierarchy(rrw);
476: return getResourceClassProperties(classes).isEditable();
477: }
478:
479: /**
480: * Is the resource extensible?
481: * @param rrw the RemoteResourceWrapper
482: * @return true is the resoure is extensible
483: */
484:
485: public boolean isExtensible(RemoteResourceWrapper rrw) {
486: String classes[] = getClassHierarchy(rrw);
487: return getResourceClassProperties(classes).isExtensible();
488: }
489:
490: /**
491: * Get the list of helpers to be created for the given remote resource.
492: * @return A set of helper class names (as an array).
493: */
494:
495: public String[] getHelperClasses(RemoteResourceWrapper rrw) {
496: String classes[] = getClassHierarchy(rrw);
497: // Load in the most specific helpers:
498: int slot = findResourceClassProperties(classes);
499: if (slot < 0)
500: return new String[0];
501: ResourceClassProperties rcp = getResourceClassProperties(classes);
502: Vector vhelpers = new Vector();
503: vhelpers.addElement(rcp.getHelperClasses());
504: // Look up the hierarchy, while allowed:
505: while (rcp.aggregateHelpers()) {
506: if (++slot >= classes.length)
507: break;
508: if ((slot = findResourceClassProperties(classes, slot)) < 0)
509: break;
510: rcp = getResourceClassProperties(classes, slot);
511: vhelpers.addElement(rcp.getHelperClasses());
512: }
513: // Convert the vector of String arrays into a single String array:
514: if (vhelpers.size() == 1)
515: return (String[]) vhelpers.elementAt(0);
516: int sz = 0;
517: int n = 0;
518: for (int i = 0; i < vhelpers.size(); i++)
519: sz += ((String[]) vhelpers.elementAt(i)).length;
520: String helpers[] = new String[sz];
521: for (int i = 0; i < vhelpers.size(); i++) {
522: String s[] = (String[]) vhelpers.elementAt(i);
523: for (int j = 0; j < s.length; j++)
524: helpers[n++] = s[j];
525: }
526: return helpers;
527: }
528:
529: /**
530: * Get the properties for the helper of a given remote resource.
531: * @param rr The remote resource being edited.
532: * @param helperClass Class of the helper about to be created.
533: * @return An instance of Properties.
534: */
535:
536: public Properties getHelperProperties(RemoteResourceWrapper rrw,
537: String helperClass) {
538: String classes[] = getClassHierarchy(rrw);
539: int slot = findResourceClassProperties(classes);
540: if (slot < 0)
541: return new Properties();
542: ResourceClassProperties rcp = getResourceClassProperties(classes);
543: // Properties p = getDefaultProperties(helperClass);
544: Properties p = rcp.getHelperProperties(helperClass);
545: while (rcp.aggregateHelpers()) {
546: if (++slot >= classes.length)
547: break;
548: if ((slot = findResourceClassProperties(classes, slot)) < 0)
549: break;
550: rcp = getResourceClassProperties(classes, slot);
551: Properties more = rcp.getHelperProperties(helperClass);
552: if (more != null)
553: p = (p != null) ? merge(p, more, false) : more;
554: }
555: return (p == null) ? new Properties() : p;
556: }
557:
558: /**
559: * Get the properties for the attribute editor of a given remote resource.
560: * @param rr The remote resource being edited.
561: * @param attr The attribute being edited.
562: */
563:
564: public Properties getAttributeProperties(RemoteResourceWrapper rrw,
565: Attribute attr) {
566: String classes[] = getClassHierarchy(rrw);
567: String attrClass = attr.getClass().getName();
568: int slot = findResourceClassProperties(classes);
569: if (slot < 0)
570: return new Properties();
571: ResourceClassProperties rcp = getResourceClassProperties(classes);
572: Properties p = rcp.getAttributeProperties(attr.getName());
573: if (p == null)
574: p = new Properties();
575: Properties defs = getDefaultAttributeProperties(attrClass);
576: if (defs != null)
577: p = merge(defs, p);
578: while (rcp.aggregateAttributeProperties()) {
579: if (++slot >= classes.length)
580: break;
581: if ((slot = findResourceClassProperties(classes, slot)) < 0)
582: break;
583: rcp = getResourceClassProperties(classes, slot);
584: Properties more = rcp
585: .getAttributeProperties(attr.getName());
586: if (more != null)
587: p = merge(more, p);
588: }
589: return p;
590: }
591:
592: /**
593: * get the icon name resolved from its description
594: * @param name a String
595: */
596:
597: public String getIconLocation(String name) {
598: String rname = iconProperties.getProperty(name);
599: if (rname != null) {
600: boolean rel;
601: rel = iconProperties.getProperty("relative").equals("true");
602: return (rel) ? root.getAbsolutePath() + File.separator
603: + "icons" + File.separator + rname : rname;
604: }
605: return null;
606: }
607:
608: /**
609: * get the hashtable of mimetypes
610: */
611:
612: public Hashtable getMimeTypes() {
613: return mimeTypes;
614: }
615:
616: /**
617: * get the hashtable of resources
618: */
619:
620: public Hashtable getResources() {
621: return resources;
622: }
623:
624: /**
625: * get the hashtable of indexers
626: */
627:
628: public Hashtable getIndexers() {
629: return indexers;
630: }
631:
632: /**
633: * get the hashtable of frames
634: */
635:
636: public Hashtable getFrames() {
637: return frames;
638: }
639:
640: public static String ROOT_P = "jigadmRoot";
641:
642: public static PropertyManager propertyManager = null;
643:
644: public static PropertyManager getPropertyManager() {
645: if (propertyManager == null) {
646: Properties p = System.getProperties();
647: String base = p.getProperty(ROOT_P);
648: if (base == null) {
649: propertyManager = new PropertyManager(new File(p
650: .getProperty("user.dir")
651: + File.separator
652: + "config"
653: + File.separator
654: + "jigadmin.zip"), new File(p
655: .getProperty("user.dir")
656: + File.separator + "config"));
657: } else
658: propertyManager = new PropertyManager(new File(base
659: + File.separator + "config" + File.separator
660: + "jigadmin.zip"), new File(base
661: + File.separator + "config"));
662: }
663: return propertyManager;
664: }
665:
666: public PropertyManager(File zipfile, File root) {
667: this .root = root;
668: this .zipfile = zipfile;
669: initialize();
670: if (!this .inited) {
671: // The one who wrote that code has already booked a special
672: // place in hell
673: System.out
674: .println("PropertyManager: unable to initialize.");
675: System.out
676: .println("\tCouldn't find mandatory properties in \""
677: + root
678: + "\" use the \"-root\" option or run "
679: + "jigadmin from Jigsaw root directory.");
680: System.exit(1);
681: }
682: }
683: }
|