001: // DirectoryResource.java
002: // $Id: DirectoryResource.java,v 1.52 2002/06/26 17:55:05 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.jigsaw.resources;
007:
008: import java.util.Hashtable;
009:
010: import java.io.File;
011:
012: import org.w3c.tools.resources.Attribute;
013: import org.w3c.tools.resources.AttributeHolder;
014: import org.w3c.tools.resources.AttributeRegistry;
015: import org.w3c.tools.resources.BooleanAttribute;
016: import org.w3c.tools.resources.ContainerResource;
017: import org.w3c.tools.resources.FramedResource;
018: import org.w3c.tools.resources.InvalidResourceException;
019: import org.w3c.tools.resources.LookupResult;
020: import org.w3c.tools.resources.LookupState;
021: import org.w3c.tools.resources.ProtocolException;
022: import org.w3c.tools.resources.RequestInterface;
023: import org.w3c.tools.resources.Resource;
024: import org.w3c.tools.resources.ResourceContext;
025: import org.w3c.tools.resources.ResourceReference;
026:
027: import org.w3c.jigsaw.frames.NegotiatedFrame;
028:
029: public class DirectoryResource extends
030: org.w3c.tools.resources.DirectoryResource {
031:
032: /**
033: * Attribute index - Should this directory support content negotiation.
034: */
035: protected static int ATTR_NEGOTIABLE = -1;
036:
037: static {
038: Attribute a = null;
039: Class cls = null;
040: // Get a pointer to our class.
041: try {
042: cls = Class
043: .forName("org.w3c.jigsaw.resources.DirectoryResource");
044: } catch (Exception ex) {
045: ex.printStackTrace();
046: System.exit(1);
047: }
048: // The negotiate flag
049: a = new BooleanAttribute("negotiable", Boolean.FALSE,
050: Attribute.EDITABLE);
051: ATTR_NEGOTIABLE = AttributeRegistry.registerAttribute(cls, a);
052: }
053:
054: /**
055: * Get the negotiable flag for this directory.
056: * When turned to <strong>true</strong>, this flag indicates to the
057: * directory resource that it should automatically build negotiated
058: * resources ont op of all existing resources.
059: * <p>You should know, at least, that turning this flag on has some
060: * not so small cost in terms of the size of the index files, and some
061: * not so small costs in CPU time when detecting not found documents.
062: * Otherwise, in all other situations its cost is probably negligible.
063: * @return A boolean, <strong>true</strong> if the directory is extensible
064: * <strong>false</strong> otherwise.
065: */
066: public boolean getNegotiableFlag() {
067: return getBoolean(ATTR_NEGOTIABLE, false);
068: }
069:
070: private String getUnextendedName(String name) {
071: int strlen = name.length();
072: for (int i = 0; i < strlen; i++) {
073: // FIXME: Should use the system props to get the right sep
074: if (name.charAt(i) == '.') {
075: if (i == 0)
076: return null;
077: return name.substring(0, i);
078: }
079: }
080: return null;
081: }
082:
083: /**
084: * Update a negotiable resource.
085: * Given the name of a resource that exists, create or update the
086: * attributes of a resource that allows to negotiate its content.
087: * <p>I hate this part here: it has nothing to do within the directory
088: * resource itself, and the indexer shouldn't know that much about
089: * directory resource, so I am stuck.
090: * @param name The name of the newly created resource.
091: */
092: public synchronized void updateNegotiableResource(String name) {
093: // Does the maintainer really wants us to perform this ugly hack ?
094: if (!getNegotiableFlag())
095: return;
096: // Check for the corresponding negotiable resource:
097: String noext = getUnextendedName(name);
098: if (noext == null) {
099: return;
100: } else {
101: ResourceReference rr = lookup(noext);
102: ResourceReference rr_neg_frame = null;
103:
104: if (rr != null) {
105: try {
106: FramedResource r = (FramedResource) rr.lock();
107: Class nClass = Class
108: .forName("org.w3c.jigsaw.frames.NegotiatedFrame");
109: rr_neg_frame = r.getFrameReference(nClass);
110: if (rr_neg_frame == null)
111: return;
112: } catch (ClassNotFoundException cex) {
113: return;
114: } catch (InvalidResourceException ex) {
115: return;
116: } finally {
117: rr.unlock();
118: }
119: }
120:
121: if (rr_neg_frame == null) {
122: // we can't add a NegotiatedFrame to an existing resource.
123: if (rr == null) {
124: // create the resource.
125: FramedResource resource = new FramedResource();
126: Hashtable defs = new Hashtable(5);
127: defs.put(id, noext);
128: ResourceContext context = updateDefaultChildAttributes(defs);
129: resource.initialize(defs);
130: addResource(resource, defs);
131: // add a NegotiatedFrame.
132: String variants[] = new String[1];
133: variants[0] = name;
134: NegotiatedFrame negotiated = new NegotiatedFrame();
135: Hashtable f_defs = new Hashtable(5);
136: f_defs.put("variants".intern(), variants);
137: resource.registerFrame(negotiated, f_defs);
138: }
139: } else {
140: try {
141: NegotiatedFrame negotiated = (NegotiatedFrame) rr_neg_frame
142: .lock();
143: String variants[] = negotiated.getVariantNames();
144: boolean exists = false;
145: for (int i = 0; i < variants.length; i++) {
146: if (variants[i].equals(name))
147: exists = true;
148: }
149: if (!exists) {
150: String nvariants[] = new String[variants.length + 1];
151: System.arraycopy(variants, 0, nvariants, 0,
152: variants.length);
153: nvariants[variants.length] = name;
154: negotiated.setVariants(nvariants);
155: }
156: } catch (InvalidResourceException ex) {
157: //FIXME
158: } finally {
159: rr_neg_frame.unlock();
160: }
161: }
162: }
163: }
164:
165: /**
166: * Lookup the next component of this lookup state in here.
167: * @param ls The current lookup state.
168: * @param lr The lookup result under construction.
169: * @exception ProtocolException If an error occurs.
170: * @return A boolean, <strong>true</strong> if lookup has completed,
171: * <strong>false</strong> if it should be continued by the caller.
172: */
173: public boolean lookup(LookupState ls, LookupResult lr)
174: throws ProtocolException {
175: int remain = ls.countRemainingComponents();
176: String name = null;
177: // save the name if it is the last
178: if (remain == 1) {
179: name = ls.peekNextComponent();
180: }
181: // if it is ok, great!
182: if (super .lookup(ls, lr)) {
183: return true;
184: }
185: // fails: check if we can create a negotiated resource
186: if ((name != null) && getNegotiableFlag()
187: && getExtensibleFlag()) {
188: // try to create the right negotiated resource
189: String rname = name + '.';
190: File directory = getDirectory();
191: if (directory != null) {
192: synchronized (this ) {
193: long dirstamp = directory.lastModified();
194: String lst[] = directory.list();
195: // FIXME we should perhaps get also the children
196: // FIXME in case specific config has been done
197: if (lst != null) {
198: for (int i = 0; i < lst.length; i++) {
199: if (lst[i].equals(".")
200: || lst[i].equals(".."))
201: continue;
202: // if it is not matching the name, abort
203: if (!lst[i].startsWith(rname))
204: continue;
205: if (lookup(lst[i]) == null) {
206: String indexed = getIndexedName(lst[i]);
207: if (indexed.equals(lst[i])) {
208: createDefaultResource(lst[i]);
209: } else if (super .lookup(indexed) == null) {
210: createDefaultResource(lst[i]);
211: }
212: }
213: updateNegotiableResource(lst[i]);
214: }
215: }
216: setLong(ATTR_DIRSTAMP, dirstamp);
217: }
218: }
219: ResourceReference rr = null;
220: rr = lookup(name);
221: if (rr == null) {
222: lr.setTarget(null);
223: return false;
224: }
225: try {
226: lr.setTarget(rr);
227: FramedResource resource = (FramedResource) rr.lock();
228: return (resource != null) ? resource.lookup(ls, lr)
229: : false;
230: } catch (InvalidResourceException ex) {
231: return false;
232: } finally {
233: rr.unlock();
234: }
235: }
236: return false;
237: }
238: }
|