001: // PropertyManager.java
002: // $Id: PropertyManager.java,v 1.15 2000/08/16 21:37:26 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.jigadm;
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: ResourceClassProperties(String entryPath, ZipFile zip) {
181: this .entryPath = entryPath;
182: this .zip = zip;
183: initialize();
184: }
185: }
186:
187: public class PropertyManager {
188:
189: /**
190: * The root for the property files.
191: */
192: protected File root = null;
193: protected File zipfile = null;
194: /**
195: * The set of resource classes we know about.
196: * Maps class names to ResourceClassProperty
197: */
198: protected Hashtable classProperties = null;
199: /**
200: /**
201: * the mapping of icon names to icon locations
202: */
203: protected Properties iconProperties = null;
204:
205: /**
206: * the hashtable of mime types
207: */
208: protected Hashtable mimeTypes = null;
209:
210: private boolean inited = false;
211:
212: protected static Properties merge(Properties into,
213: Properties source, boolean overide) {
214: Properties p = (Properties) into.clone();
215: Enumeration e = source.keys();
216: while (e.hasMoreElements()) {
217: Object key = e.nextElement();
218: if ((!overide) && into.get(key) != null)
219: continue;
220: Object val = source.get(key);
221: p.put(key, val);
222: }
223: return p;
224: }
225:
226: protected static Properties merge(Properties into, Properties source) {
227: return merge(into, source, true);
228: }
229:
230: /**
231: * Load the properties from the root directory.
232: */
233:
234: protected void initialize() {
235: ZipFile zip = null;
236: try {
237: zip = new ZipFile(this .zipfile);
238: } catch (Exception ex) {
239: ex.printStackTrace();
240: return;
241: }
242: Enumeration entries = zip.entries();
243: classProperties = new Hashtable(11);
244:
245: while (entries.hasMoreElements()) {
246: ZipEntry entry = (ZipEntry) entries.nextElement();
247: String entry_name = entry.getName();
248: if (entry_name.equals("icons" + File.separator)) //reserved
249: continue;
250: // Skip non directory entries
251: if (!entry.isDirectory())
252: continue;
253: // only first level sub directories
254: if (entry_name.indexOf(File.separator) == entry_name
255: .lastIndexOf(File.separator)) {
256: ResourceClassProperties rcp = null;
257: rcp = new ResourceClassProperties(entry_name, zip);
258: classProperties.put(entry_name.substring(0, entry_name
259: .length() - 1), rcp);
260: }
261: }
262: // and now the icons mapping
263: try {
264: ZipEntry icons = zip.getEntry("icons.p");
265: InputStream in = (new BufferedInputStream(zip
266: .getInputStream(icons)));
267: iconProperties = new Properties();
268: iconProperties.load(in);
269: in.close();
270: } catch (Exception ex) {
271: ex.printStackTrace();
272: }
273: // and now the mime types
274: mimeTypes = new Hashtable(11);
275: try {
276: ZipEntry mime = zip.getEntry("mimetypes.p");
277: InputStream in = (new BufferedInputStream(zip
278: .getInputStream(mime)));
279: Properties p = new Properties();
280: p.load(in);
281: in.close();
282: String[] major = ResourceClassProperties.getStringArray(p,
283: "Types");
284: String[] minor;
285: for (int i = 0; i < major.length; i++) {
286: minor = ResourceClassProperties.getStringArray(p,
287: major[i]);
288: mimeTypes.put(major[i], minor);
289: }
290: } catch (Exception ex) {
291: ex.printStackTrace();
292: }
293: try {
294: zip.close(); //FIXME: sure?
295: } catch (Exception ex) {
296: ex.printStackTrace();
297: }
298: inited = true;
299: }
300:
301: /**
302: * Get the best matching resource class properties for given class.
303: * @param classes The class names we're looking a macth for.
304: * @return A ResourceClassProperties instance.
305: */
306:
307: protected ResourceClassProperties getResourceClassProperties(
308: String names[], int from) {
309: // Look along the hierarchy for a class editor:
310: ResourceClassProperties rcp = null;
311: for (int i = from; i < names.length; i++) {
312: rcp = (ResourceClassProperties) classProperties
313: .get(names[i]);
314: if (rcp != null)
315: break;
316: }
317: if (rcp == null)
318: throw new RuntimeException(
319: "configuration error, no editor for: " + names[0]);
320: return rcp;
321: }
322:
323: protected ResourceClassProperties getResourceClassProperties(
324: String names[]) {
325: return getResourceClassProperties(names, 0);
326: }
327:
328: protected int findResourceClassProperties(String classes[],
329: int offset) {
330: // Look along the hierarchy for a class editor:
331: ResourceClassProperties rcp = null;
332: for (int i = offset; i < classes.length; i++) {
333: rcp = (ResourceClassProperties) classProperties
334: .get(classes[i]);
335: if (rcp != null)
336: return i;
337: }
338: return -1;
339: }
340:
341: protected int findResourceClassProperties(String classes[]) {
342: return findResourceClassProperties(classes, 0);
343: }
344:
345: protected String[] getClassHierarchy(RemoteResourceWrapper rrw) {
346: try {
347: String classes[] = rrw.getResource().getClassHierarchy();
348: return classes;
349: } catch (RemoteAccessException ex) {
350: ex.printStackTrace();
351: }
352: return new String[0];
353: }
354:
355: protected Properties getDefaultHelperProperties(String clsname) {
356: ResourceClassProperties rcp = null;
357: rcp = (ResourceClassProperties) classProperties.get("defaults");
358: if (rcp != null)
359: return rcp.getHelperProperties(clsname);
360: return null;
361: }
362:
363: protected Properties getDefaultAttributeProperties(String clsname) {
364: ResourceClassProperties rcp = null;
365: rcp = (ResourceClassProperties) classProperties.get("defaults");
366: if (rcp != null)
367: return rcp.getAttributeProperties(clsname);
368: return null;
369: }
370:
371: /**
372: * Get any properties for the editor of the given remote resource instance.
373: * @return A Properties instance.
374: */
375:
376: public Properties getEditorProperties(RemoteResourceWrapper rrw) {
377: String classes[] = getClassHierarchy(rrw);
378: return getResourceClassProperties(classes)
379: .getEditorProperties();
380: }
381:
382: /**
383: * Get the list of helpers to be created for the given remote resource.
384: * @return A set of helper class names (as an array).
385: */
386:
387: public String[] getHelperClasses(RemoteResourceWrapper rrw) {
388: String classes[] = getClassHierarchy(rrw);
389: // Load in the most specific helpers:
390: int slot = findResourceClassProperties(classes);
391: if (slot < 0)
392: return new String[0];
393: ResourceClassProperties rcp = getResourceClassProperties(classes);
394: Vector vhelpers = new Vector();
395: vhelpers.addElement(rcp.getHelperClasses());
396: // Look up the hierarchy, while allowed:
397: while (rcp.aggregateHelpers()) {
398: if (++slot >= classes.length)
399: break;
400: if ((slot = findResourceClassProperties(classes, slot)) < 0)
401: break;
402: rcp = getResourceClassProperties(classes, slot);
403: vhelpers.addElement(rcp.getHelperClasses());
404: }
405: // Convert the vector of String arrays into a single String array:
406: if (vhelpers.size() == 1)
407: return (String[]) vhelpers.elementAt(0);
408: int sz = 0;
409: int n = 0;
410: for (int i = 0; i < vhelpers.size(); i++)
411: sz += ((String[]) vhelpers.elementAt(i)).length;
412: String helpers[] = new String[sz];
413: for (int i = 0; i < vhelpers.size(); i++) {
414: String s[] = (String[]) vhelpers.elementAt(i);
415: for (int j = 0; j < s.length; j++)
416: helpers[n++] = s[j];
417: }
418: return helpers;
419: }
420:
421: /**
422: * Get the properties for the helper of a given remote resource.
423: * @param rr The remote resource being edited.
424: * @param helperClass Class of the helper about to be created.
425: * @return An instance of Properties.
426: */
427:
428: public Properties getHelperProperties(RemoteResourceWrapper rrw,
429: String helperClass) {
430: String classes[] = getClassHierarchy(rrw);
431: int slot = findResourceClassProperties(classes);
432: if (slot < 0)
433: return new Properties();
434: ResourceClassProperties rcp = getResourceClassProperties(classes);
435: // Properties p = getDefaultProperties(helperClass);
436: Properties p = rcp.getHelperProperties(helperClass);
437: while (rcp.aggregateHelpers()) {
438: if (++slot >= classes.length)
439: break;
440: if ((slot = findResourceClassProperties(classes, slot)) < 0)
441: break;
442: rcp = getResourceClassProperties(classes, slot);
443: Properties more = rcp.getHelperProperties(helperClass);
444: if (more != null)
445: p = (p != null) ? merge(p, more, false) : more;
446: }
447: return (p == null) ? new Properties() : p;
448: }
449:
450: /**
451: * Get the properties for the attribute editor of a given remote resource.
452: * @param rr The remote resource being edited.
453: * @param attr The attribute being edited.
454: */
455:
456: public Properties getAttributeProperties(RemoteResourceWrapper rrw,
457: Attribute attr) {
458: String classes[] = getClassHierarchy(rrw);
459: String attrClass = attr.getClass().getName();
460: int slot = findResourceClassProperties(classes);
461: if (slot < 0)
462: return new Properties();
463: ResourceClassProperties rcp = getResourceClassProperties(classes);
464: Properties p = rcp.getAttributeProperties(attr.getName());
465: if (p == null)
466: p = new Properties();
467: Properties defs = getDefaultAttributeProperties(attrClass);
468: if (defs != null)
469: p = merge(defs, p);
470: while (rcp.aggregateAttributeProperties()) {
471: if (++slot >= classes.length)
472: break;
473: if ((slot = findResourceClassProperties(classes, slot)) < 0)
474: break;
475: rcp = getResourceClassProperties(classes, slot);
476: Properties more = rcp
477: .getAttributeProperties(attr.getName());
478: if (more != null)
479: p = merge(more, p);
480: }
481: return p;
482: }
483:
484: /**
485: * get the icon name resolved from its description
486: * @param name a String
487: */
488:
489: public String getIconLocation(String name) {
490: String rname = iconProperties.getProperty(name);
491: if (rname != null) {
492: boolean rel;
493: rel = iconProperties.getProperty("relative").equals("true");
494: return (rel) ? root.getAbsolutePath() + File.separator
495: + "icons" + File.separator + rname : rname;
496: }
497: return null;
498: }
499:
500: /**
501: * get the hashtable of mimetypes
502: */
503:
504: public Hashtable getMimeTypes() {
505: return mimeTypes;
506: }
507:
508: public static String ROOT_P = "jigadmRoot";
509:
510: public static PropertyManager propertyManager = null;
511:
512: public static PropertyManager getPropertyManager() {
513: if (propertyManager == null) {
514: Properties p = System.getProperties();
515: String base = p.getProperty(ROOT_P);
516: if (base == null) {
517: propertyManager = new PropertyManager(new File(p
518: .getProperty("user.dir")
519: + File.separator
520: + "config"
521: + File.separator
522: + "jigadm.zip"), new File(p
523: .getProperty("user.dir")
524: + File.separator + "config"));
525: } else
526: propertyManager = new PropertyManager(new File(base
527: + File.separator + "config" + File.separator
528: + "jigadm.zip"), new File(base + File.separator
529: + "config"));
530: }
531: return propertyManager;
532: }
533:
534: public PropertyManager(File zipfile, File root) {
535: this .root = root;
536: this .zipfile = zipfile;
537: initialize();
538: if (!this .inited) {
539: // The one who wrote that code has already booked a special
540: // place in hell
541: System.out
542: .println("PropertyManager: unable to initialize.");
543: System.out
544: .println("\tCouldn't find mandatory properties in \""
545: + root
546: + "\" use the \"-root\" option or run "
547: + "jigadmin from Jigsaw root directory.");
548: System.exit(1);
549: }
550: }
551: }
|