📄 negotiatedframe.java
字号:
} 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.unsafeLock().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, getVary()); 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].unsafeLock() ; itsframe = (HTTPFrame)resource.getFrame(httpFrameClass); if (itsframe != null) { frametag = itsframe.getETag(); if (frametag == null) { continue; } // Do we have a winner? try { for (int j=0; j<etags.length; j++) if(frametag.getTag().equals(etags[j].getTag())) return variants[i]; } catch (NullPointerException ex) { // if the list of etag contains a null // it should never happen and the try doesn't cost } } } 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.unsafeLock() ; 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()) ; g.append ("<ul>") ; for (int i = 0 ; i < variants.length ; i++) { if (variants[i] != null) { try { name = variants[i].unsafeLock().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, getVary()); throw new HTTPException (reply) ; } public void registerResource(FramedResource resource) { super.registerOtherResource(resource); } /** * Lookup the target resource. * @param ls The current lookup state * @param lr The result * @return true if lookup is done. * @exception ProtocolException If an error relative to the protocol occurs */ public boolean lookup(LookupState ls, LookupResult lr) throws ProtocolException { if ( ls.isDirectory() ) { // we are not a directory, bail out Request req = (Request)ls.getRequest(); String locstate = (String)req.getState(STATE_CONTENT_LOCATION); if (locstate == null) { lr.setTarget(null); return true; } } ResourceFrame frames[] = getFrames(); if (frames != null) { for (int i = 0 ; i < frames.length ; i++) { if (frames[i] == null) { continue; } if (frames[i].lookup(ls,lr)) { return true; } } } if ( ls.hasMoreComponents() ) { // We are not a container resource, and we don't have children: lr.setTarget(null); return false; } else { //we are done! try to find the negotiated one... RequestInterface reqi = ls.getRequest(); ResourceReference selected; Request request = (Request) reqi; // 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 (); try { if (method.equals("PUT")) { selected = negotiatePut(request); } else { selected = negotiate(request); } } catch (ResourceException ex) { // the failure will be processed in perform return false; } if (selected != null) { try { FramedResource resource = (FramedResource) selected.unsafeLock(); resource.lookup(ls, lr); } catch (InvalidResourceException ex) { // the failure will be processed in perform } finally { selected.unlock(); } } request.setState(STATE_NEG, selected); // fake now, we handle the process to have a two-level processing // just to add the Vary: header lr.setTarget(getResourceReference()); return true; } } /** * 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; // get the right resources if (request.hasState(STATE_NEG)) { selected = (ResourceReference) request.getState(STATE_NEG); } else { 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) ; } try { FramedResource resource = (FramedResource) selected.unsafeLock(); Reply reply = (Reply)resource.perform(request) ; reply.setHeaderValue(reply.H_VARY, getVary()); 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(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -