- From: Roland Mainz <Roland.Mainz@informatik.med.uni-giessen.de>
- Date: Sat, 17 Apr 1999 01:07:19 +0200
- To: W3 Jigsaw Mailinglist <www-jigsaw@w3.org>, "jigsaw@w3.org" <jigsaw@w3.org>
- Message-Id: <3717C2A7.64576ECC@informatik.med.uni-giessen.de>
Hi ! ---- Today I figured out a problem as I tried to use a NegotiatedFrame for switching between text/xml and text/html. Problem is that Netscape V4.51 adds */* at the end of the "accept"-header line, and text/html is completely missing in the "accept"-header line. Therefore, I wrote a V1.22 of NegotiatedFrame.java, which fixes the problem in a hack way (but it works now). I've added the source as an attachment. ---- I've started some "cosmetics" in the Multiple-Choice output of NegotiatedFrame, but it is not finished yet, sorry (1:02h Saturday now), maybe someone else has time to finish this... ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) Roland Mainz C programmer \__\/\/__/ Roland.Mainz@informatik.med.uni-giessen.de MPEG specialist /O /==\ O\ gisburn@w-specht.rhein-ruhr.de Sun&&Amiga programmer (;O/ \/ \O;) TEL +49 (0) 2426901568 FAX +49 (0) 2426901569
// NegotiatedFrame.java // $Id: NegotiatedFrame.java,v 1.22 1999/02/09 23:11:39 gisburn Exp $ // (c) COPYRIGHT MIT and INRIA, 1996. // Please first read the full copyright statement in file COPYRIGHT.html // new for V1.22: // - */* in "Accept"-header is now replaced by text/html to solve a problem... // - multiple choice page now gets a style sheed added; // // note to Yves/Benoit: I'm too tired (0:54h Saturday) to to the rest, but it would be nice // if the multiple-choice page looks like the "normal" directory listing. package org.w3c.jigsaw.frames; import java.io.*; import java.util.*; import org.w3c.tools.resources.*; import org.w3c.jigsaw.http.* ; import org.w3c.jigsaw.html.*; import org.w3c.jigsaw.html.HtmlGenerator ; import org.w3c.www.mime.* ; import org.w3c.www.http.*; import org.w3c.tools.resources.ProtocolException; import org.w3c.tools.resources.ResourceException; /** * Content negotiation frame. * Selects between variants of the same "thing" in different formats based * on information from the requesting client and variant attributes like language, * content-type or content-encoding. * @author Yves Lafon <ylafon@w3.org> * @author Benoît Mahé <bmahe@w3.org> * @author Roland Mainz <Roland.Mainz@informatik.med.uni-giessen.de> */ public class NegotiatedFrame extends HTTPFrame { class VariantState { ResourceReference variant = null ; double qs = 0.0 ; double qe = 0.0 ; double qc = 0.0 ; double ql = 0.0 ; double q = 0.0 ; // quality (mime type one) double Q = 0.0 ; // the big Q public String toString() { try { Resource res = variant.lock(); String name = (String) res.getIdentifier() ; if ( name == null ) name = "<noname>" ; return "[" + name + " qs=" + qs + " qe=" + qe + " ql=" + ql + " q =" + q + " Q =" + getQ() +"]" ; } catch (InvalidResourceException ex) { return "invalid"; } finally { variant.unlock(); } } void setContentEncodingQuality (double qe) { this.qe = qe ; } void setContentEncodingQuality (HttpAcceptEncoding e) { this.qe = e.getQuality(); } double getContentEncodingQuality () { return qe ; } void setQuality (double q) { this.q = q ; } void setQuality (HttpAccept a) { q = a.getQuality() ; } void setLanguageQuality (double ql) { this.ql = ql ; } void setLanguageQuality (HttpAcceptLanguage l) { this.ql = l.getQuality() ; } double getLanguageQuality () { return ql ; } ResourceReference getResource () { return variant ; } double getQ() { return qe * q * qs * ql ; } VariantState (ResourceReference variant, double qs) { this.qs = qs ; this.variant = variant ; } } private static Class httpFrameClass = null; static { try { httpFrameClass = Class.forName("org.w3c.jigsaw.frames.HTTPFrame") ; } catch (Exception ex) { throw new RuntimeException("No HTTPFrame class found."); } } /** * Our Icon property. */ public static String NEGOTIATED_ICON_P = "org.w3c.jigsaw.frames.negotiated.icon"; /** * Our default Icon */ public static String DEFAULT_NEGOTIATED_ICON = "generic.gif"; /** * Turn debugging on/off. */ private static final boolean debug = false; /** * Minimum quality for a resource to be considered further. */ private static final double REQUIRED_QUALITY = 0.0001 ; /** * The Vary header field for this resource is always the same. */ protected static HttpTokenList VARY = null; /** * Attribute index - The set of names of variants. */ protected static int ATTR_VARIANTS = -1 ; /** * Attribute index - Should the PUT needs to be strictly checked? */ protected static int ATTR_PUT_POLICY = -1; static { // Compute and initialize the Vary header once and for all String vary[] = { "Accept", "Accept-Charset", "Accept-Language", "Accept-Encoding" }; VARY = HttpFactory.makeStringList(vary); } static { Attribute a = null ; Class cls = null ; try { cls = Class.forName("org.w3c.jigsaw.frames.NegotiatedFrame") ; } catch (Exception ex) { ex.printStackTrace() ; System.exit(1) ; } // The names of the varint we negotiate a = new StringArrayAttribute("variants" , null , Attribute.EDITABLE) ; ATTR_VARIANTS = AttributeRegistry.registerAttribute(cls, a) ; a = new BooleanAttribute("strict_put" , new Boolean(true) , Attribute.EDITABLE); ATTR_PUT_POLICY = AttributeRegistry.registerAttribute(cls, a) ; } public String getIcon() { String icon = super.getIcon(); if (icon == null) { icon = getServer().getProperties().getString(NEGOTIATED_ICON_P, DEFAULT_NEGOTIATED_ICON); setValue(ATTR_ICON, icon); } return icon; } /** * Get the variant names. */ public String[] getVariantNames() { return (String[]) getValue(ATTR_VARIANTS, null) ; } public void setVariants(String variants[]) { setValue(ATTR_VARIANTS, variants); } /** * get the "strictness" of the PUT checking */ public boolean getPutPolicy() { Boolean val = (Boolean) getValue(ATTR_PUT_POLICY, null); if (val == null) // strict by default return true; return val.booleanValue(); } public void setPutPolicy(Boolean strict) { setValue(ATTR_PUT_POLICY, strict); } public void setPutPolicy(boolean strict) { setValue(ATTR_PUT_POLICY, new Boolean(strict)); } /** * Get the variant resources. * This is somehow broken, it shouldn't allocate the array of variants * on each call. However, don't forget that the list of variants can be * dynamically edited, this means that if we are to keep a cache of it * (as would be the case if we kept the array of variants as instance var) * we should also take care of editing of attributes (possible, but I * just don't have enough lifes). * @return An array of ResourceReference, or <strong>null</strong>. * @exception ProtocolException If one of the variants doesn't exist. */ public ResourceReference[] getVariantResources() throws ProtocolException { // Get the variant names: String names[] = getVariantNames() ; if ( names == null ) return null ; // Look them up in our parent directory: ResourceReference variants[] = new ResourceReference[names.length] ; ResourceReference r_parent = resource.getParent() ; try { DirectoryResource parent = (DirectoryResource) r_parent.lock(); int missing = 0; for (int i = 0 ; i < names.length ; i++) { variants[i] = parent.lookup(names[i]) ; if (variants[i] == null) missing++; } if (missing > 0) { int kept = names.length - missing; if (kept < 1) return null; String newNames[] = new String[kept]; int j = 0; int i = 0; while (i < variants.length) { if (variants[i] != null) { newNames[j++] = names[i++]; } else { i++; } } setVariants(newNames); //recompute Variant Resources return getVariantResources(); } } catch (InvalidResourceException ex) { throw new HTTPException("invalid parent for negotiation"); } finally { r_parent.unlock(); } return variants ; } /** * Print the current negotiation state. * @param header The header to print first. * @param states The current negotiation states. */ protected void printNegotiationState (String header, Vector states) { if ( debug ) { System.out.println ("------" + header) ; for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; System.out.println (state) ; } System.out.println ("-----") ; } } /** * Negotiate among content encodings. * <p>BUG: This will work only for single encoded variants. * @param states The current negotiation states. * @param request The request to handle. * @return a boolean. * @exception ProtocolException If one of the variants doesn't exist. */ protected boolean negotiateContentEncoding (Vector states, Request request) throws ProtocolException { if ( ! request.hasAcceptEncoding() ) { // All encodings accepted: for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; state.setContentEncodingQuality(1.0) ; } } else { HttpAcceptEncoding encodings[] = request.getAcceptEncoding() ; for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; ResourceReference rr = state.getResource(); try { FramedResource resource = (FramedResource)rr.lock() ; HTTPFrame itsframe = (HTTPFrame) resource.getFrame(httpFrameClass); if (itsframe != null) { String ve; if ( !itsframe.definesAttribute("content-encoding") ) { ve = "identity"; // default encoding state.setContentEncodingQuality (1.0) ; } else { ve = itsframe.getContentEncoding() ; state.setContentEncodingQuality (0.001) ; } int jidx = -1 ; for (int j = 0 ; j < encodings.length ; j++) { if (encodings[j].getEncoding().equals(ve)) { jidx = j; break; } if (encodings[j].getEncoding().equals("*")) jidx = j; // default '*' if no better match } if ( jidx >= 0 ) state.setContentEncodingQuality (encodings[jidx]) ; } } catch (InvalidResourceException ex) { } finally { rr.unlock(); } } // FIXME We should check here against unlegible variants as now } return false ; } /** * Negotiate on charsets. * <p>BUG: Not implemented yet. * @param states The current states of negotiation. * @param request The request to handle. */ protected boolean negotiateCharsetQuality (Vector states , Request request) { return false ; } /** * Negotiate among language qualities. * <p>BUG: This will only work for variants that have one language tag. * @param states The current states of negotiation. * @param request The request to handle. * @return a boolean. * @exception ProtocolException If one of the variants doesn't exist. */ protected boolean negotiateLanguageQuality (Vector states , Request request) throws ProtocolException { if ( ! request.hasAcceptLanguage() ) { for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; state.setLanguageQuality (1.0) ; } } else { HttpAcceptLanguage languages[] = request.getAcceptLanguage() ; boolean varyLang = false ; for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; ResourceReference rr = state.getResource(); try { FramedResource resource = (FramedResource)rr.lock() ; HTTPFrame itsframe = (HTTPFrame) resource.getFrame(httpFrameClass); if (itsframe != null) { if ( !itsframe.definesAttribute("content-language") ) { state.setLanguageQuality (-1.0) ; } else { varyLang = true ; String lang = itsframe.getContentLanguage() ; int jidx = -1 ; for (int j = 0 ; j < languages.length ; j++) { if ( languages[j].getLanguage().equals(lang) ) jidx = j ; } if ( jidx < 0 ) state.setLanguageQuality(0.001) ; else state.setLanguageQuality (languages[jidx]) ; } } } catch (InvalidResourceException ex) { //FIXME } finally { rr.unlock(); } } if ( varyLang ) { for (int i = 0 ; i < states.size() ; i++) { VariantState s = (VariantState) states.elementAt(i); if ( s.getLanguageQuality() < 0 ) s.setLanguageQuality (0.5) ; } } else { for (int i = 0 ; i < states.size() ; i++) { VariantState s = (VariantState) states.elementAt(i) ; s.setLanguageQuality (1.0) ; } } } return false ; } /** * Negotiate among content types. * @param states The current states of negotiation. * @param request The request to handle. * @return a boolean. * @exception ProtocolException If one of the variants doesn't exist. */ protected boolean negotiateContentType (Vector states, Request request) throws ProtocolException { if ( ! request.hasAccept() ) { // All variants get a quality of 1.0 for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; state.setQuality (1.0) ; } } else { // The browser has given some preferences: HttpAccept accepts[] = request.getAccept() ; // added by gisburn 16.4.1999: // some browsers like Netscape 4.51 adding */* in their accept header // which confuses this negotiation algorithm :-( // the */* is replaced here (hack method, there should be a better way) // with text/html - assuming that */ is (one of) the last entry(ies) // in the accept line and that there is only ONE */* // this fixed my problems with browsers "accepting" both text/xml and text/html try { for( int z = 0 ; z < accepts.length ; z++ ) { MimeType m = accepts[ z ].getMimeType(); // replace */* with text/html if( m.toString().startsWith( "*/*" ) ) { accepts[ z ].setMimeType( new MimeType( "text/html" ) ); break; } } } catch( Exception exc ) { // bah, should not occur, but... exc.printStackTrace(); } for (int i = 0 ; i < states.size() ; i++ ) { VariantState state = (VariantState) states.elementAt(i) ; // Get the most specific match for this variant: ResourceReference rr = state.getResource(); try { FramedResource resource = (FramedResource)rr.lock() ; HTTPFrame itsframe = (HTTPFrame) resource.getFrame(httpFrameClass); if (itsframe != null) { MimeType vt = itsframe.getContentType(); int jmatch = -1 ; int jidx = -1 ; for (int j = 0 ; j < accepts.length ; j++) { int match = vt.match (accepts[j].getMimeType()) ; if ( match > jmatch ) { jmatch = match ; jidx = j ; } } if ( jidx < 0 ) state.setQuality (0.0) ; else state.setQuality(accepts[jidx]) ; } } catch (InvalidResourceException ex) { //FIXME } finally { rr.unlock(); } } } return false ; } /** * Negotiate among the various variants for the Resource. * We made our best efforts to be as compliant as possible to the HTTP/1.0 * content negotiation algorithm. * @param request the incomming request. * @return a RefourceReference instance. * @exception ProtocolException If one of the variants doesn't exist. */ protected ResourceReference negotiate (Request request) throws ProtocolException { // Check for zero or one variant: ResourceReference variants[] = getVariantResources() ; if (variants == null) { try { getResource().delete(); } catch (MultipleLockException ex) { //will be deleted later... } finally { Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ "(probably deleted)."); throw new HTTPException (reply); } } if ( variants.length < 2 ) { if ( variants.length == 0 ) { try { getResource().delete(); } catch (MultipleLockException ex) { //will be deleted later... } finally { Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ "(probably deleted)."); throw new HTTPException (reply); } } else { return variants[0] ; } } // Build a vector of variant negociation states, one per variants: Vector states = new Vector (variants.length) ; for (int i = 0 ; i < variants.length ; i++) { double qs = 1.0 ; try { FramedResource resource = (FramedResource)variants[i].lock() ; HTTPFrame itsframe = (HTTPFrame) resource.getFrame(httpFrameClass); if (itsframe != null) { if ( itsframe.definesAttribute ("quality") ) qs = itsframe.getQuality() ; if ( qs > REQUIRED_QUALITY ) states.addElement(new VariantState (variants[i], qs)) ; } } catch (InvalidResourceException ex) { //FIXME } finally { variants[i].unlock(); } } // Content-encoding negociation: if ( debug ) printNegotiationState ("init:", states) ; if ( negotiateContentEncoding (states, request) ) // Remains a single acceptable variant: return ((VariantState) states.elementAt(0)).getResource() ; if ( debug ) printNegotiationState ("encoding:", states) ; // Charset quality negociation: if ( negotiateCharsetQuality (states, request) ) // Remains a single acceptable variant: return ((VariantState) states.elementAt(0)).getResource() ; if ( debug ) printNegotiationState ("charset:", states) ; // Language quality negociation: if ( negotiateLanguageQuality (states, request) ) // Remains a single acceptable variant: return ((VariantState) states.elementAt(0)).getResource() ; if ( debug ) printNegotiationState ("language:", states) ; // Content-type negociation: if ( negotiateContentType (states, request) ) // Remains a single acceptable variant: return ((VariantState) states.elementAt(0)).getResource() ; if ( debug ) printNegotiationState ("type:", states) ; // If we reached this point, this means that multiple variants are // acceptable at this point. Keep the ones that have the best quality. if ( debug ) printNegotiationState ("before Q selection:", states) ; double qmax = REQUIRED_QUALITY ; for (int i=0; i< states.size() ; ) { VariantState state = (VariantState) states.elementAt(i) ; if ( state.getQ() > qmax ) { for (int j = i ; j > 0 ; j--) states.removeElementAt(0) ; qmax = state.getQ() ; i = 1 ; } else { if ( state.getQ() < qmax) states.removeElementAt(i) ; else i++; } } if ( debug ) printNegotiationState ("After Q selection:", states) ; if ( qmax == REQUIRED_QUALITY ) { Reply reply = request.makeReply(HTTP.NOT_ACCEPTABLE) ; HtmlGenerator g = new HtmlGenerator("No acceptable"); g.append("<P>The resource cannot be served according to the " + "headers sent</P>"); reply.setStream (g) ; throw new HTTPException (reply) ; } else if ( states.size() == 1 ) { return ((VariantState) states.elementAt(0)).getResource() ; } else { // Respond with multiple choice (for the time being, there should // be a parameter to decide what to do. Reply reply = request.makeReply(HTTP.MULTIPLE_CHOICE) ; HtmlGenerator g = new HtmlGenerator ("Multiple choice for "+ resource.getIdentifier()) ; g.append ("<ul>") ; for (int i = 0 ; i < states.size() ; i++) { VariantState state = (VariantState) states.elementAt(i) ; String name = null; ResourceReference rr = state.getResource(); try { name = rr.lock().getIdentifier(); g.append ("<li>" + "<a href=\"" + name + "\">" + name + "</a>" + " Q= " + state.getQ()) ; } catch (InvalidResourceException ex) { //FIXME } finally { rr.unlock(); } } reply.setStream (g) ; reply.setHeaderValue(reply.H_VARY, VARY); throw new HTTPException (reply) ; } } /** * "negotiate" for a PUT, the negotiation of a PUT should be * different as we just want to match the desciption of the entity * and the available variants * @param request, the request to handle * @return a ResourceReference instance * @exception ProtocolException If negotiating among the resource variants * failed. * @exception ResourceException If the resource got a fatal error. */ protected ResourceReference negotiatePut(Request request) throws ProtocolException, ResourceException { // Check for zero or one variant: ResourceReference variants[] = getVariantResources() ; HTTPFrame itsframe; int nb_v; // zero, don't PUT on a negotiable resource! if (variants == null || variants.length == 0) { try { getResource().delete(); } catch (MultipleLockException ex) { //will be deleted later... } finally { Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ "(probably deleted)."); throw new HTTPException (reply); } } // negotiate etag HttpEntityTag etag = request.getETag(); HttpEntityTag etags[] = request.getIfMatch(); // gather the etags if (etags == null && etag != null) { etags = new HttpEntityTag[1]; etags[0] = etag; } else if (etag != null) { HttpEntityTag t_etags[] = new HttpEntityTag[etags.length+1]; System.arraycopy(etags, 0, t_etags, 0, etags.length); t_etags[etags.length] = etag; etags = t_etags; } if (etags != null) { // yeah go for it! FramedResource resource; HttpEntityTag frametag; for (int i = 0 ; i < variants.length ; i++) { try { resource = (FramedResource)variants[i].lock() ; itsframe = (HTTPFrame)resource.getFrame(httpFrameClass); if (itsframe != null) { frametag = itsframe.getETag(); // Do we have a winner? for (int j=0; j<etags.length; j++) if (frametag.getTag().equals(etags[j].getTag())) return variants[i]; } } catch (InvalidResourceException ex) { //FIXME } finally { variants[i].unlock(); } } // no matching variants... Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ "according to the ETag sent"); throw new HTTPException (reply); } // if we are strict, don't go any further, etags // is the mandatory thing, otherwise PUT on the direct version if (getPutPolicy()) { Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ " for a PUT, as no ETags were sent"); throw new HTTPException (reply); } // now filter out variants nb_v = variants.length; MimeType type = request.getContentType(); String encodings[] = request.getContentEncoding(); String languages[] = request.getContentLanguage(); ResourceReference rr; if (type != null || encodings != null || languages != null) { // the request is not too bad ;) for (int i = 0 ; i < variants.length ; i++) { if (variants[i] == null) continue; rr = variants[i]; try { resource = (FramedResource)rr.lock() ; itsframe = (HTTPFrame)resource.getFrame(httpFrameClass); if (itsframe == null) { nb_v--; variants[i] = null; continue; } // remove the non matching mime types if (type != null) { MimeType fmt = itsframe.getContentType(); if (fmt == null || (fmt.match(type) != MimeType.MATCH_SPECIFIC_SUBTYPE)) { nb_v--; variants[i] = null; continue; } } // remove the non matching languages if (languages != null) { String language = itsframe.getContentLanguage(); nb_v--; variants[i] = null; if (language == null) { continue; } for (int j=0; j<languages.length; j++) { if (language.equals(languages[j])) { nb_v++; variants[i] = rr; break; } } } // remove the non matching encodings if (encodings != null) { String encoding = itsframe.getContentEncoding(); nb_v--; variants[i] = null; if (encoding == null) { continue; } for (int j=0; j<encodings.length; j++) { if (encoding.equals(languages[j])) { nb_v++; variants[i] = rr; break; } } } } catch (InvalidResourceException ex) { //FIXME } finally { rr.unlock(); } } // a winner! if (nb_v == 1) { for (int i=0; i< variants.length; i++) { if (variants[i] != null) return variants[i]; } } // no document matching if (nb_v <= 0 ) { Reply reply = request.makeReply(HTTP.NOT_FOUND); reply.setContent ("<h1>Document not found</h1>"+ "<p>The document "+request.getURL()+ " has no acceptable variants "+ " for a PUT"); throw new HTTPException (reply); } } // now we have multiple choice :( String name; Reply reply = request.makeReply(HTTP.MULTIPLE_CHOICE) ; HtmlGenerator g = new HtmlGenerator ("Multiple choice for "+ resource.getIdentifier()) ; addStyleSheet( g ); g.append ("<ul>") ; for (int i = 0 ; i < variants.length ; i++) { if (variants[i] != null) { try { name = variants[i].lock().getIdentifier(); g.append ("<li>" + "<a href=\"" + name + "\">" +name+ "</a>"); } catch (InvalidResourceException ex) { //FIXME (this should NOT happen :) ) } finally { variants[i].unlock(); } } } reply.setStream (g) ; reply.setHeaderValue(reply.H_VARY, VARY); throw new HTTPException (reply) ; } public void registerResource(FramedResource resource) { super.registerOtherResource(resource); } /** * Perform an HTTP request. * Negotiate among the variants, the best variant according to the request * fields, and make this elected variant serve the request. * @param request The request to handle. * @exception ProtocolException If negotiating among the resource variants * failed. * @exception ResourceException If the resource got a fatal error. */ public ReplyInterface perform(RequestInterface req) throws ProtocolException, ResourceException { ReplyInterface repi = performFrames(req); if (repi != null) return repi; if (! checkRequest(req)) return null; Request request = (Request) req; ResourceReference selected; // Run content negotiation now: // The PUT is special, we negotiate with ETag (if present) or // using the metainformation about the PUT entity. String method = request.getMethod (); if (method.equals("PUT")) selected = negotiatePut(request); else selected = negotiate(request); // This should never happen: either the negotiation succeed, or the // negotiate method should return an error. if ( selected == null ) { Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR) ; error.setContent("Error negotiating among resource's variants."); throw new HTTPException(error) ; } // FIXME content neg should be done at lookup time // FIXME enhencing the reply should be done at outgoingfilter // Get the original variant reply, and add its location as a header: try { FramedResource resource = (FramedResource) selected.lock(); Reply reply = (Reply)resource.perform(request) ; reply.setHeaderValue(reply.H_VARY, VARY); HTTPFrame itsframe = (HTTPFrame) resource.getFrame(httpFrameClass); if (itsframe != null) { reply.setContentLocation( itsframe.getURL(request).toExternalForm()) ; return reply; } Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR) ; error.setContent("Error negotiating : "+ "selected resource has no HTTPFrame"); throw new HTTPException(error) ; } catch (InvalidResourceException ex) { Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR) ; error.setContent("Error negotiating : Invalid selected resource"); throw new HTTPException(error) ; } finally { selected.unlock(); } } }
Received on Friday, 16 April 1999 19:06:33 UTC