001: // FramedResource.java
002: // $Id: FramedResource.java,v 1.30 2004/07/20 15:54:30 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1996.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.tools.resources;
007:
008: import java.util.EventObject;
009: import java.util.Hashtable;
010:
011: import java.io.PrintStream;
012:
013: import org.w3c.tools.resources.event.AttributeChangedEvent;
014: import org.w3c.tools.resources.event.AttributeChangedListener;
015: import org.w3c.tools.resources.event.Events;
016: import org.w3c.tools.resources.event.FrameEvent;
017: import org.w3c.tools.resources.event.FrameEventListener;
018: import org.w3c.tools.resources.event.ResourceEvent;
019: import org.w3c.tools.resources.event.ResourceEventMulticaster;
020: import org.w3c.tools.resources.event.ResourceEventQueue;
021: import org.w3c.tools.resources.event.StructureChangedEvent;
022: import org.w3c.tools.resources.event.StructureChangedListener;
023:
024: /**
025: * A FramedResource manage frames which are called during the
026: * lookup and the perform.
027: */
028: public class FramedResource extends Resource implements
029: FrameEventListener {
030:
031: /**
032: * The ResourceReference of frames.
033: */
034: class FrameReference implements ResourceReference {
035:
036: Class frameClass = null;
037: String identifier = null;
038: ResourceReference framedr = null;
039:
040: int lockCount = 0;
041:
042: public void updateContext(ResourceContext ctxt) {
043: //nothing to do
044: }
045:
046: public int nbLock() {
047: return lockCount;
048: }
049:
050: /**
051: * Lock the refered resource in memory.
052: * @return A real pointer to the resource.
053: */
054:
055: public Resource lock() throws InvalidResourceException {
056: FramedResource res = (FramedResource) framedr.lock();
057: lockCount++;
058: return res.getFrame(frameClass, identifier);
059: }
060:
061: /**
062: * Lock the refered resource in memory.
063: * @return A real pointer to the resource.
064: */
065:
066: public Resource unsafeLock() throws InvalidResourceException {
067: FramedResource res = (FramedResource) framedr.lock();
068: lockCount++;
069: return res.unsafeGetFrame(frameClass, identifier);
070: }
071:
072: /**
073: * Unlock that resource from memory.
074: */
075:
076: public void unlock() {
077: framedr.unlock();
078: lockCount--;
079: }
080:
081: /**
082: * Is that resource reference locked ?
083: */
084:
085: public boolean isLocked() {
086: return lockCount != 0;
087: }
088:
089: FrameReference(ResourceFrame rframe, ResourceReference framedr) {
090: this .frameClass = rframe.getClass();
091: this .framedr = framedr;
092: this .identifier = rframe.getIdentifier();
093: }
094: }
095:
096: /**
097: * Debug flag
098: */
099: protected final boolean debugEvent = false;
100:
101: /**
102: * Do we handle events?
103: */
104: protected boolean event_disabled = false;
105:
106: /**
107: * Our frames references.
108: */
109: protected Hashtable framesRef = null; //<ResourceFrame, Reference>
110:
111: /**
112: * Our AttributeChangedListener.
113: */
114: protected AttributeChangedListener attrListener = null;
115:
116: /**
117: * Our StructureChangedListener.
118: */
119: protected StructureChangedListener structListener = null;
120:
121: protected void disableEvent() {
122: event_disabled = true;
123: }
124:
125: protected void enableEvent() {
126: event_disabled = false;
127: }
128:
129: protected boolean eventDisabled() {
130: return event_disabled;
131: }
132:
133: /**
134: * Attribute index - The object identifier.
135: */
136: protected static int ATTR_OID = -1;
137:
138: static {
139: Attribute a = null;
140: Class cls = null;
141: // Get a pointer to our class:
142: try {
143: cls = Class
144: .forName("org.w3c.tools.resources.FramedResource");
145: } catch (Exception ex) {
146: ex.printStackTrace();
147: System.exit(1);
148: }
149: // The object identifier, *should* be uniq (see below)
150: a = new IntegerAttribute("oid", null, Attribute.COMPUTED);
151: ATTR_OID = AttributeRegistry.registerAttribute(cls, a);
152: }
153:
154: public Object getClone(Object values[]) {
155: FramedResource clone = (FramedResource) super .getClone(values);
156: clone.framesRef = new Hashtable(3);
157: return clone;
158: }
159:
160: /**
161: * Get this resource's object identifier.
162: * An object identifier is to be used specifically in etags. It's purpose
163: * is to uniquify the etag of a resource. It's computed as a random number
164: *, on demand only.
165: * @return A uniq object identifier for that resource, as an inteeger.
166: */
167: public int getOid() {
168: int oid = getInt(ATTR_OID, -1);
169: if (oid == -1) {
170: double d = Math.random() * ((double) Integer.MAX_VALUE);
171: setInt(ATTR_OID, oid = (int) d);
172: }
173: return oid;
174: }
175:
176: protected void displayEvent(FramedResource fr, EventObject evt) {
177: System.out.println(">>> [" + fr.getIdentifier()
178: + "] has receive " + evt);
179: }
180:
181: /**
182: * This handles the <code>FRAME_ADDED</code> kind of events.
183: * @param evt The FrameEvent.
184: */
185:
186: public void frameAdded(FrameEvent evt) {
187: if (debugEvent)
188: displayEvent(this , evt);
189: if (!isUnloaded())
190: markModified();
191: }
192:
193: /**
194: * This handles the <code>FRAME_MODIFIED</code> kind of events.
195: * @param evt The event describing the change.
196: */
197:
198: public void frameModified(FrameEvent evt) {
199: if (debugEvent)
200: displayEvent(this , evt);
201: if (!isUnloaded())
202: markModified();
203: }
204:
205: /**
206: * A frame is about to be removed
207: * This handles the <code>FRAME_REMOVED</code> kind of events.
208: * @param evt The event describing the change.
209: */
210:
211: public void frameRemoved(FrameEvent evt) {
212: if (debugEvent)
213: displayEvent(this , evt);
214: if (!isUnloaded())
215: markModified();
216: }
217:
218: /**
219: * Initialize and attach a new ResourceFrame to that resource.
220: * @param frame An uninitialized ResourceFrame instance.
221: * @param defs A default set of attribute values.
222: */
223:
224: public void registerFrame(ResourceFrame frame, Hashtable defs) {
225: super .registerFrame(frame, defs);
226: frame.addFrameEventListener(this );
227: addAttributeChangedListener(frame);
228: frame.registerResource(this );
229: }
230:
231: /**
232: * Register a new ResourceFrame if none (from the same class) has been
233: * registered.
234: * @param classname The ResourceFrame class
235: * @param identifier The ResourceFrame identifier
236: * @exception ClassNotFoundException if the class can't be found
237: * @exception IllegalAccessException if the class or initializer is not
238: * accessible
239: * @exception InstantiationException if the class can't be instanciated
240: * @exception ClassCastException if the class is not a ResourceFrame
241: */
242: protected void registerFrameIfNone(String classname,
243: String identifier) throws ClassNotFoundException,
244: IllegalAccessException, InstantiationException,
245: ClassCastException {
246: Class frameclass = Class.forName(classname);
247: ResourceFrame frame = getFrame(frameclass);
248: if (frame == null) {
249: Hashtable defs = new Hashtable(3);
250: defs.put(id, identifier);
251: registerFrame((ResourceFrame) frameclass.newInstance(),
252: defs);
253: }
254: }
255:
256: /**
257: * Unregister a resource frame from the given resource.
258: * @param frame The frame to unregister from the resource.
259: */
260:
261: public synchronized void unregisterFrame(ResourceFrame frame) {
262: super .unregisterFrame(frame);
263: frame.unregisterResource(this );
264: frame.removeFrameEventListener(this );
265: removeAttributeChangedListener(frame);
266: }
267:
268: private ResourceReference[] getReferenceArray(ResourceFrame[] frames) {
269: if (frames == null)
270: return null;
271: ResourceReference[] refs = new ResourceReference[frames.length];
272: ResourceReference rr = null;
273: for (int i = 0; i < frames.length; i++) {
274: rr = (ResourceReference) framesRef.get(frames[i]);
275: if (rr == null) {
276: rr = (ResourceReference) new FrameReference(frames[i],
277: getResourceReference());
278: framesRef.put(frames[i], rr);
279: }
280: refs[i] = rr;
281: }
282: return refs;
283: }
284:
285: /**
286: * Collect all frames references.
287: * @return An array of ResourceReference, containing a set of
288: * FrameReference instances or <strong>null</strong> if no resource
289: * frame is available.
290: */
291: public synchronized ResourceReference[] getFramesReference() {
292: return getReferenceArray(getFrames());
293: }
294:
295: /**
296: * Collect any frame reference pointing to an instance of the given class.
297: * @param cls The class of frames we are looking for.
298: * @return An array of ResourceReference, containing a set of
299: * FrameReference pointing to instances of the given class, or
300: * <strong>null</strong> if no resource frame is available.
301: */
302: public synchronized ResourceReference[] collectFramesReference(
303: Class c) {
304: return getReferenceArray(collectFrames(c));
305: }
306:
307: /**
308: * Get the first occurence of a frame of the given class.
309: * @param cls The class of te frame to look for.
310: * @return A ResourceReference instance, or <strong>null</strong>.
311: */
312: public synchronized ResourceReference getFrameReference(Class c) {
313: ResourceFrame frame = getFrame(c);
314: if (frame == null)
315: return null;
316: ResourceReference rr = (ResourceReference) framesRef.get(frame);
317: if (rr == null) {
318: rr = (ResourceReference) new FrameReference(frame,
319: getResourceReference());
320: framesRef.put(frame, rr);
321: }
322: return rr;
323: }
324:
325: /**
326: * Get The FrameReference of the given frame, or <strong>null</strong>
327: * if the frame is not registered.
328: * @param frame The ResourceFrame.
329: * @return A ResourceReference instance.
330: */
331: public synchronized ResourceReference getFrameReference(
332: ResourceFrame frame) {
333: ResourceReference rr = (ResourceReference) framesRef.get(frame);
334: if (rr == null) {
335: rr = (ResourceReference) new FrameReference(frame,
336: getResourceReference());
337: framesRef.put(frame, rr);
338: }
339: return rr;
340: }
341:
342: /**
343: * Get the frame of the given class and identifier.
344: * @param cls The class of frames we are looking for.
345: * @param identifier the frame identifier
346: * @return a ResourceFrame instance of <strong>null</strong>
347: */
348: public synchronized ResourceFrame getFrame(Class c,
349: String identifier) {
350: ResourceFrame frames[] = collectFrames(c);
351: if (frames != null) {
352: for (int i = 0; i < frames.length; i++) {
353: ResourceFrame fr = frames[i];
354: if (fr.getIdentifier().equals(identifier))
355: return fr;
356: }
357: }
358: return null;
359: }
360:
361: /**
362: * Get the frame of the given class and identifier.
363: * @param cls The class of frames we are looking for.
364: * @param identifier the frame identifier
365: * @return a ResourceFrame instance of <strong>null</strong>
366: */
367: ResourceFrame unsafeGetFrame(Class c, String identifier) {
368: ResourceFrame frames[] = collectFrames(c);
369: if (frames != null) {
370: for (int i = 0; i < frames.length; i++) {
371: ResourceFrame fr = frames[i];
372: if (fr.getIdentifier().equals(identifier))
373: return fr;
374: }
375: }
376: return null;
377: }
378:
379: /**
380: * Get the frame of the given class.
381: * @param classname the class name
382: * @return a ResourceFrame instance of null.
383: */
384: public synchronized ResourceFrame getFrame(String classname) {
385: try {
386: Class c = Class.forName(classname);
387: return getFrame(c);
388: } catch (Exception ex) {
389: return null;
390: }
391: }
392:
393: /**
394: * (AWT Like), dspatch the Event to all our listeners.
395: * @param evt The resourceEvent to dispatch.
396: */
397: public void processEvent(ResourceEvent evt) {
398: if (evt instanceof StructureChangedEvent) {
399: fireStructureChangedEvent((StructureChangedEvent) evt);
400: } else if (evt instanceof AttributeChangedEvent) {
401: fireAttributeChangeEvent((AttributeChangedEvent) evt);
402: }
403: }
404:
405: /**
406: * Post an Event in the Event Queue.
407: * @param evt The Event to post.
408: */
409: public void postEvent(ResourceEvent evt) {
410: if (eventDisabled())
411: return;
412: ResourceSpace space = getSpace();
413: if (space != null)
414: space.getEventQueue().sendEvent(evt);
415: }
416:
417: /**
418: * Add an attribute change listener.
419: * @param l The new attribute change listener.
420: */
421:
422: public void addAttributeChangedListener(AttributeChangedListener l) {
423: attrListener = ResourceEventMulticaster.add(attrListener, l);
424: }
425:
426: /**
427: * Remove an attribute change listener.
428: * @param l The listener to remove.
429: */
430:
431: public void removeAttributeChangedListener(
432: AttributeChangedListener l) {
433: attrListener = ResourceEventMulticaster.remove(attrListener, l);
434: }
435:
436: /**
437: * post an attribute change event. Actually this kind of event should
438: * not be posted. So fire them!
439: * @param idx The index of the attribute that has changed.
440: * @param newvalue The new value for that attribute.
441: */
442:
443: protected void postAttributeChangeEvent(int idx, Object newvalue) {
444: if (eventDisabled())
445: return;
446: if ((attrListener != null) && (getResourceReference() != null)) {
447: AttributeChangedEvent evt = new AttributeChangedEvent(
448: getResourceReference(), attributes[idx], newvalue);
449: fireAttributeChangeEvent(evt);
450: }
451: }
452:
453: /**
454: * Fire an attribute change event.
455: * @param evt the AttributeChangedEvent to fire.
456: */
457: protected void fireAttributeChangeEvent(AttributeChangedEvent evt) {
458: if (attrListener != null)
459: attrListener.attributeChanged(evt);
460: }
461:
462: /**
463: * Add a structure change listener.
464: * @param l The new structure change listener.
465: */
466:
467: public void addStructureChangedListener(StructureChangedListener l) {
468: structListener = ResourceEventMulticaster
469: .add(structListener, l);
470: }
471:
472: /**
473: * Remove a structure change listener.
474: * @param l The listener to remove.
475: */
476:
477: public void removeStructureChangedListener(
478: StructureChangedListener l) {
479: structListener = ResourceEventMulticaster.remove(
480: structListener, l);
481: }
482:
483: /**
484: * post an structure change event.
485: * @param rr the ResourceReference of the source.
486: * @param type The type of the event.
487: */
488: protected void postStructureChangedEvent(ResourceReference rr,
489: int type) {
490: if ((structListener != null) && (rr != null)) {
491: StructureChangedEvent evt = new StructureChangedEvent(rr,
492: type);
493: postEvent(evt);
494: }
495: }
496:
497: /**
498: * post an structure change event.
499: * @param type The type of the event.
500: */
501: protected void postStructureChangedEvent(int type) {
502: if ((structListener != null)
503: && (getResourceReference() != null)) {
504: StructureChangedEvent evt = new StructureChangedEvent(
505: getResourceReference(), type);
506: postEvent(evt);
507: }
508: }
509:
510: /**
511: * Fire an structure change event.
512: * @param type The type of the event.
513: */
514: protected void fireStructureChangedEvent(int type) {
515: if (structListener != null) {
516: ResourceReference resref = unsafeGetResourceReference();
517: if (resref != null) {
518: StructureChangedEvent evt = new StructureChangedEvent(
519: resref, type);
520: fireStructureChangedEvent(evt);
521: }
522: }
523: }
524:
525: /**
526: * Fire an structure change event.
527: * @param evt the StructureChangedEvent to fire.
528: */
529: protected void fireStructureChangedEvent(StructureChangedEvent evt) {
530: if (structListener != null) {
531: int type = evt.getID();
532: switch (type) {
533: case Events.RESOURCE_MODIFIED:
534: structListener.resourceModified(evt);
535: break;
536: case Events.RESOURCE_CREATED:
537: structListener.resourceCreated(evt);
538: break;
539: case Events.RESOURCE_REMOVED:
540: structListener.resourceRemoved(evt);
541: break;
542: case Events.RESOURCE_UNLOADED:
543: structListener.resourceUnloaded(evt);
544: break;
545: }
546: }
547: }
548:
549: /**
550: * This resource is being unloaded.
551: * The resource is being unloaded from memory, perform any additional
552: * cleanup required.
553: */
554: public void notifyUnload() {
555: //
556: // direct notification
557: //
558: ResourceFrame frames[] = unsafeGetFrames();
559: if (frames != null) {
560: for (int i = 0; i < frames.length; i++) {
561: if (frames[i] == null)
562: continue;
563: frames[i].notifyUnload();
564: }
565: }
566: fireStructureChangedEvent(Events.RESOURCE_UNLOADED);
567: super .notifyUnload();
568: }
569:
570: /**
571: * Delete this Resource instance, and remove it from its store.
572: * This method will erase definitely this resource, for ever, by removing
573: * it from its resource store (when doable).
574: * @exception MultipleLockException if someone has locked this resource.
575: */
576: public synchronized void delete() throws MultipleLockException {
577: disableEvent();
578: // fire and not post because we don't want this resource
579: // to be locked() during the delete.
580: fireStructureChangedEvent(Events.RESOURCE_REMOVED);
581: ResourceFrame frames[] = getFrames();
582: if (frames != null) {
583: for (int i = 0; i < frames.length; i++) {
584: if (frames[i] == null)
585: continue;
586: frames[i].removeFrameEventListener(this );
587: this .removeAttributeChangedListener(frames[i]);
588: frames[i].unregisterResource(this );
589: }
590: }
591: try {
592: super .delete();
593: } catch (MultipleLockException ex) {
594: enableEvent();
595: throw ex;
596: }
597: }
598:
599: /**
600: * Mark this resource as having been modified.
601: */
602: public void markModified() {
603: super .markModified();
604: postStructureChangedEvent(Events.RESOURCE_MODIFIED);
605: }
606:
607: /**
608: * Set some of this resource attribute. We overide setValue to post
609: * events.
610: */
611: public synchronized void setValue(int idx, Object value) {
612: super .setValue(idx, value);
613: if (idx != ATTR_LAST_MODIFIED) {
614: postAttributeChangeEvent(idx, value);
615: postStructureChangedEvent(Events.RESOURCE_MODIFIED);
616: }
617: }
618:
619: /**
620: * Set a value, without posting event.
621: * @param idx The attribute index, in the list of attributes advertized by
622: * the resource.
623: * @param value The new value for this attribute.
624: */
625: public synchronized void setSilentValue(int idx, Object value) {
626: disableEvent();
627: super .setValue(idx, value);
628: enableEvent();
629: }
630:
631: /**
632: * Set a value, without posting event.
633: * @param name The attribute name.
634: * @param value The new value for the attribute.
635: */
636: public synchronized void setSilentValue(String name, Object value) {
637: disableEvent();
638: super .setValue(name, value);
639: enableEvent();
640: }
641:
642: /**
643: * Lookup the target resource.
644: * @param ls The current lookup state
645: * @param lr The result
646: * @return true if lookup is done.
647: * @exception ProtocolException If an error relative to the protocol occurs
648: */
649: public boolean lookup(LookupState ls, LookupResult lr)
650: throws ProtocolException {
651: ResourceFrame frames[] = getFrames();
652: if (frames != null) {
653: for (int i = 0; i < frames.length; i++) {
654: if (frames[i] == null)
655: continue;
656: if (frames[i].lookup(ls, lr))
657: return true;
658: }
659: }
660: if (ls.hasMoreComponents()) {
661: // We are not a container resource, and we don't have children:
662: lr.setTarget(null);
663: return false;
664: } else {
665: //we are done!
666: lr.setTarget(getResourceReference());
667: return true;
668: }
669: }
670:
671: /**
672: * Perform the request on all the frames of that resource. The
673: * Reply returned is the first non-null reply.
674: * @param request A RequestInterface instance.
675: * @return A ReplyInterface instance.
676: * @exception ProtocolException If an error relative to the protocol occurs
677: * @exception ResourceException If an error not relative to the
678: * protocol occurs
679: */
680: protected ReplyInterface performFrames(RequestInterface request)
681: throws ProtocolException, ResourceException {
682: ResourceFrame frames[] = getFrames();
683: if (frames != null) {
684: for (int i = 0; i < frames.length; i++) {
685: if (frames[i] == null)
686: continue;
687: ReplyInterface reply = frames[i].perform(request);
688: if (reply != null)
689: return reply;
690: }
691: }
692: return null;
693: }
694:
695: /**
696: * Perform the request.
697: * @return a ReplyInterface instance
698: * @exception ProtocolException If an error relative to the protocol occurs
699: * @exception ResourceException If an error not relative to the
700: * protocol occurs
701: */
702: public ReplyInterface perform(RequestInterface request)
703: throws ProtocolException, ResourceException {
704: return performFrames(request);
705: }
706:
707: /**
708: * Initialize the frames of that framed resource.
709: * @param values Default attribute values.
710: */
711:
712: public void initialize(Object values[]) {
713: this .attrListener = null;
714: this .structListener = null;
715: disableEvent();
716: super .initialize(values);
717: // Initialize the frames if any.
718: ResourceFrame frames[] = getFrames();
719: if (frames != null) {
720: this .framesRef = new Hashtable(Math.max(frames.length, 1));
721: Hashtable defs = new Hashtable(3);
722: for (int i = 0; i < frames.length; i++) {
723: if (frames[i] == null)
724: continue;
725: frames[i].registerResource(this );
726: frames[i].initialize(defs);
727: frames[i].addFrameEventListener(this );
728: this .addAttributeChangedListener(frames[i]);
729: }
730: } else {
731: this .framesRef = new Hashtable(3);
732: }
733: enableEvent();
734: }
735:
736: }
|