Source Code Cross Referenced for NegotiatedFrame.java in  » Web-Server » Jigsaw » org » w3c » jigsaw » frames » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Jigsaw » org.w3c.jigsaw.frames 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // NegotiatedFrame.java
0002:        // $Id: NegotiatedFrame.java,v 1.44 2007/03/10 12:28:23 ylafon Exp $
0003:        // (c) COPYRIGHT MIT and INRIA, 1996.
0004:        // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006:        package org.w3c.jigsaw.frames;
0007:
0008:        import java.io.PrintStream;
0009:
0010:        import java.util.Vector;
0011:
0012:        import org.w3c.tools.resources.Attribute;
0013:        import org.w3c.tools.resources.AttributeHolder;
0014:        import org.w3c.tools.resources.AttributeRegistry;
0015:        import org.w3c.tools.resources.BooleanAttribute;
0016:        import org.w3c.tools.resources.DirectoryResource;
0017:        import org.w3c.tools.resources.FramedResource;
0018:        import org.w3c.tools.resources.InvalidResourceException;
0019:        import org.w3c.tools.resources.LookupState;
0020:        import org.w3c.tools.resources.LookupResult;
0021:        import org.w3c.tools.resources.MultipleLockException;
0022:        import org.w3c.tools.resources.ProtocolException;
0023:        import org.w3c.tools.resources.ReplyInterface;
0024:        import org.w3c.tools.resources.RequestInterface;
0025:        import org.w3c.tools.resources.Resource;
0026:        import org.w3c.tools.resources.ResourceException;
0027:        import org.w3c.tools.resources.ResourceFrame;
0028:        import org.w3c.tools.resources.ResourceReference;
0029:        import org.w3c.tools.resources.ServerInterface;
0030:        import org.w3c.tools.resources.StringArrayAttribute;
0031:
0032:        import org.w3c.jigsaw.http.HTTPException;
0033:        import org.w3c.jigsaw.http.Reply;
0034:        import org.w3c.jigsaw.http.Request;
0035:
0036:        import org.w3c.jigsaw.html.HtmlGenerator;
0037:
0038:        import org.w3c.jigsaw.html.HtmlGenerator;
0039:
0040:        import org.w3c.www.mime.LanguageTag;
0041:        import org.w3c.www.mime.MimeType;
0042:
0043:        import org.w3c.www.http.HTTP;
0044:        import org.w3c.www.http.HttpAccept;
0045:        import org.w3c.www.http.HttpAcceptCharset;
0046:        import org.w3c.www.http.HttpAcceptEncoding;
0047:        import org.w3c.www.http.HttpAcceptLanguage;
0048:        import org.w3c.www.http.HttpEntityMessage;
0049:        import org.w3c.www.http.HttpEntityTag;
0050:        import org.w3c.www.http.HttpFactory;
0051:        import org.w3c.www.http.HttpInvalidValueException;
0052:        import org.w3c.www.http.HttpMessage;
0053:        import org.w3c.www.http.HttpReplyMessage;
0054:        import org.w3c.www.http.HttpRequestMessage;
0055:        import org.w3c.www.http.HttpTokenList;
0056:
0057:        import org.w3c.tools.resources.ProtocolException;
0058:        import org.w3c.tools.resources.ResourceException;
0059:
0060:        /**
0061:         * Content negotiation.
0062:         */
0063:        public class NegotiatedFrame extends HTTPFrame {
0064:
0065:            class VariantState {
0066:                ResourceReference variant = null;
0067:                double qs = 0.0; // configured frame quality
0068:                double qe = 0.0; // content encoding quality
0069:                double qc = 0.0; // content charset quality
0070:                double ql = 0.0; // content language quality
0071:                double q = 0.0; // quality (mime type one)
0072:                double Q = 0.0; // the big Q
0073:
0074:                public String toString() {
0075:                    try {
0076:                        Resource res = variant.unsafeLock();
0077:                        String name = (String) res.getIdentifier();
0078:                        if (name == null)
0079:                            name = "<noname>";
0080:                        return "[" + name + " qc=" + qc + " qs=" + qs + " qe="
0081:                                + qe + " ql=" + ql + " q =" + q + " Q ="
0082:                                + getQ() + "]";
0083:                    } catch (InvalidResourceException ex) {
0084:                        return "invalid";
0085:                    } finally {
0086:                        variant.unlock();
0087:                    }
0088:                }
0089:
0090:                void setCharsetQuality(double qc) {
0091:                    this .qc = qc;
0092:                }
0093:
0094:                double getCharsetQuality() {
0095:                    return qc;
0096:                }
0097:
0098:                void setContentEncodingQuality(double qe) {
0099:                    this .qe = qe;
0100:                }
0101:
0102:                void setContentEncodingQuality(HttpAcceptEncoding e) {
0103:                    this .qe = e.getQuality();
0104:                }
0105:
0106:                double getContentEncodingQuality() {
0107:                    return qe;
0108:                }
0109:
0110:                void setQuality(double q) {
0111:                    this .q = q;
0112:                }
0113:
0114:                void setQuality(HttpAccept a) {
0115:                    q = a.getQuality();
0116:                }
0117:
0118:                void setLanguageQuality(double ql) {
0119:                    this .ql = ql;
0120:                }
0121:
0122:                void setLanguageQuality(HttpAcceptLanguage l) {
0123:                    this .ql = l.getQuality();
0124:                }
0125:
0126:                double getLanguageQuality() {
0127:                    return ql;
0128:                }
0129:
0130:                ResourceReference getResource() {
0131:                    return variant;
0132:                }
0133:
0134:                double getQ() {
0135:                    return qe * q * qs * ql * qc;
0136:                }
0137:
0138:                VariantState(ResourceReference variant, double qs) {
0139:                    this .qs = qs;
0140:                    this .variant = variant;
0141:                }
0142:            }
0143:
0144:            private static Class httpFrameClass = null;
0145:            private static Class negotiatedFrameClass = null;
0146:
0147:            static {
0148:                try {
0149:                    httpFrameClass = Class
0150:                            .forName("org.w3c.jigsaw.frames.HTTPFrame");
0151:                } catch (Exception ex) {
0152:                    throw new RuntimeException("No HTTPFrame class found.");
0153:                }
0154:                try {
0155:                    negotiatedFrameClass = Class
0156:                            .forName("org.w3c.jigsaw.frames.NegotiatedFrame");
0157:                } catch (Exception ex) {
0158:                    throw new RuntimeException(
0159:                            "No NegotiatedFrame class found.");
0160:                }
0161:            }
0162:
0163:            /**
0164:             * Our Icon property.
0165:             */
0166:            public static String NEGOTIATED_ICON_P = "org.w3c.jigsaw.frames.negotiated.icon";
0167:            /**
0168:             * Our default Icon
0169:             */
0170:            public static String DEFAULT_NEGOTIATED_ICON = "generic.gif";
0171:
0172:            /**
0173:             * our state
0174:             */
0175:            protected static String STATE_NEG = "org.w3c.jigsaw.frames.Negotiated";
0176:
0177:            /**
0178:             * Turn debugging on/off.
0179:             */
0180:            private static final boolean debug = false;
0181:            /**
0182:             * Minimum quality for a resource to be considered further.
0183:             */
0184:            private static final double REQUIRED_QUALITY = 0.0001;
0185:            /**
0186:             * The Vary header field for this resource
0187:             */
0188:            protected HttpTokenList vary = null;
0189:            private boolean vary_done = false;
0190:            /**
0191:             * Attribute index - The set of names of variants.
0192:             */
0193:            protected static int ATTR_VARIANTS = -1;
0194:            /**
0195:             * Attribute index - Should the PUT needs to be strictly checked?
0196:             */
0197:            protected static int ATTR_PUT_POLICY = -1;
0198:            /**
0199:             * Attribute index - Should the variants to be strictly checked?
0200:             * the variants should NEVER contain negotiated resources!
0201:             */
0202:            protected static int ATTR_PARANOID_VARIANT_CHECK = -1;
0203:
0204:            static {
0205:                Attribute a = null;
0206:                Class cls = null;
0207:                try {
0208:                    cls = Class
0209:                            .forName("org.w3c.jigsaw.frames.NegotiatedFrame");
0210:                } catch (Exception ex) {
0211:                    ex.printStackTrace();
0212:                    System.exit(1);
0213:                }
0214:                // The names of the varint we negotiate
0215:                a = new StringArrayAttribute("variants", null,
0216:                        Attribute.EDITABLE);
0217:                ATTR_VARIANTS = AttributeRegistry.registerAttribute(cls, a);
0218:                a = new BooleanAttribute("strict_put", new Boolean(true),
0219:                        Attribute.EDITABLE);
0220:                ATTR_PUT_POLICY = AttributeRegistry.registerAttribute(cls, a);
0221:                a = new BooleanAttribute("paranoid_variant_check", new Boolean(
0222:                        false), Attribute.EDITABLE);
0223:                ATTR_PARANOID_VARIANT_CHECK = AttributeRegistry
0224:                        .registerAttribute(cls, a);
0225:            }
0226:
0227:            private boolean b_charset = true;
0228:            private boolean b_type = true;
0229:            private boolean b_language = true;
0230:            private boolean b_encoding = true;
0231:
0232:            public synchronized void setValue(int idx, Object value) {
0233:                if (idx == ATTR_VARIANTS) {
0234:                    super .setValue(idx, checkVariants((String[]) value));
0235:                } else {
0236:                    super .setValue(idx, value);
0237:                }
0238:            }
0239:
0240:            private HttpTokenList getVary() {
0241:                if (vary_done) {
0242:                    return vary;
0243:                }
0244:                // ok let's do it!
0245:                vary_done = true;
0246:                b_charset = false;
0247:                b_type = false;
0248:                b_language = false;
0249:                b_encoding = false;
0250:
0251:                ResourceReference variants[] = null;
0252:                try {
0253:                    variants = getVariantResources();
0254:                } catch (ProtocolException ex) {
0255:                }
0256:                ;
0257:                // no vary for so few variants!
0258:
0259:                if ((variants == null) || (variants.length < 2)) {
0260:                    return null;
0261:                }
0262:                synchronized (this ) {
0263:                    int num = 0;
0264:                    HTTPFrame refframe = null;
0265:                    FramedResource resource = null;
0266:                    do {
0267:                        try {
0268:                            resource = (FramedResource) variants[num]
0269:                                    .unsafeLock();
0270:                            refframe = (HTTPFrame) resource
0271:                                    .getFrame(httpFrameClass);
0272:                        } catch (InvalidResourceException ex) {
0273:                            //ex.printStackTrace();
0274:                            //FIXME
0275:                        } catch (Exception fex) {
0276:                            fex.printStackTrace();
0277:                        } finally {
0278:                            variants[num].unlock();
0279:                        }
0280:                        num++;
0281:                    } while ((refframe == null) && (num < variants.length));
0282:                    // not enough variants, abort
0283:                    if (variants.length - num < 1)
0284:                        return null;
0285:
0286:                    String language = refframe.getContentLanguage();
0287:                    String encoding = refframe.getContentEncoding();
0288:                    String charset = refframe.getCharset();
0289:                    MimeType mtype = refframe.getContentType();
0290:
0291:                    HTTPFrame itsframe = null;
0292:                    for (int i = num; i < variants.length; i++) {
0293:                        try {
0294:                            resource = (FramedResource) variants[i]
0295:                                    .unsafeLock();
0296:                            itsframe = (HTTPFrame) resource
0297:                                    .unsafeGetFrame(httpFrameClass);
0298:                            if (language != null) {
0299:                                if (!language.equals(itsframe
0300:                                        .getContentLanguage())) {
0301:                                    b_language = true;
0302:                                }
0303:                            } else {
0304:                                if (itsframe.getContentLanguage() != null) {
0305:                                    b_language = true;
0306:                                }
0307:                            }
0308:                            if (encoding != null) {
0309:                                if (!encoding.equals(itsframe
0310:                                        .getContentEncoding())) {
0311:                                    b_encoding = true;
0312:                                }
0313:                            } else {
0314:                                if (itsframe.getContentEncoding() != null) {
0315:                                    b_encoding = true;
0316:                                }
0317:                            }
0318:                            if (charset != null) {
0319:                                if (!charset.equals(itsframe.getCharset())) {
0320:                                    b_charset = true;
0321:                                }
0322:                            } else {
0323:                                if (itsframe.getCharset() != null) {
0324:                                    b_charset = true;
0325:                                }
0326:                            }
0327:                            if (mtype != null) {
0328:                                MimeType o_type = itsframe.getContentType();
0329:                                if ((o_type != null)
0330:                                        && (mtype.match(o_type) != MimeType.MATCH_SPECIFIC_SUBTYPE)) {
0331:                                    b_type = true;
0332:                                }
0333:                            } else {
0334:                                if (itsframe.getContentType() != null) {
0335:                                    b_type = true;
0336:                                }
0337:                            }
0338:                        } catch (InvalidResourceException ex) {
0339:                            //ex.printStackTrace();
0340:                            //FIXME
0341:                        } finally {
0342:                            variants[i].unlock();
0343:                        }
0344:                    }
0345:                    int vary_size = 0;
0346:                    if (b_language) {
0347:                        vary_size++;
0348:                    }
0349:                    if (b_charset) {
0350:                        vary_size++;
0351:                    }
0352:                    if (b_encoding) {
0353:                        ++vary_size;
0354:                    }
0355:                    if (b_type) {
0356:                        ++vary_size;
0357:                    }
0358:
0359:                    if (vary_size == 0) {
0360:                        return null;
0361:                    }
0362:                    String[] s_vary = new String[vary_size];
0363:                    num = 0;
0364:                    if (b_type) {
0365:                        s_vary[num++] = "Accept";
0366:                    }
0367:                    if (b_encoding) {
0368:                        s_vary[num++] = "Accept-Encoding";
0369:                    }
0370:                    if (b_language) {
0371:                        s_vary[num++] = "Accept-Language";
0372:                    }
0373:                    if (b_charset) {
0374:                        s_vary[num] = "Accept-Charset";
0375:                    }
0376:                    vary = HttpFactory.makeStringList(s_vary);
0377:                }
0378:                return vary;
0379:            }
0380:
0381:            public String getIcon() {
0382:                String icon = super .getIcon();
0383:                if (icon == null) {
0384:                    icon = getServer().getProperties().getString(
0385:                            NEGOTIATED_ICON_P, DEFAULT_NEGOTIATED_ICON);
0386:                    setValue(ATTR_ICON, icon);
0387:                }
0388:                return icon;
0389:            }
0390:
0391:            /**
0392:             * Get the variant names.
0393:             */
0394:            public String[] getVariantNames() {
0395:                return (String[]) getValue(ATTR_VARIANTS, null);
0396:            }
0397:
0398:            protected String[] checkVariants(String variants[]) {
0399:
0400:                Vector checked = new Vector(variants.length);
0401:                ResourceReference tmpres = null;
0402:                ResourceReference r_parent = resource.getParent();
0403:                try {
0404:                    DirectoryResource parent = (DirectoryResource) r_parent
0405:                            .unsafeLock();
0406:                    for (int i = 0; i < variants.length; i++) {
0407:                        tmpres = parent.lookup(variants[i]);
0408:                        if (tmpres != null) {
0409:                            try {
0410:                                FramedResource resource = (FramedResource) tmpres
0411:                                        .unsafeLock();
0412:                                NegotiatedFrame itsframe = (NegotiatedFrame) resource
0413:                                        .getFrame(negotiatedFrameClass);
0414:                                if (itsframe == null) {
0415:                                    checked.addElement(variants[i]);
0416:                                }
0417:                            } catch (InvalidResourceException ex) {
0418:                            } finally {
0419:                                tmpres.unlock();
0420:                            }
0421:                        } else {
0422:                            checked.addElement(variants[i]);
0423:                        }
0424:                    }
0425:                } catch (InvalidResourceException ex) {
0426:                    // throw new HTTPException("invalid parent for negotiation");
0427:                } finally {
0428:                    r_parent.unlock();
0429:                }
0430:
0431:                String[] variants_ok = new String[checked.size()];
0432:                checked.copyInto(variants_ok);
0433:
0434:                return variants_ok;
0435:            }
0436:
0437:            public void setVariants(String variants[]) {
0438:                setValue(ATTR_VARIANTS, variants);
0439:
0440:                // invalidate the Vary header
0441:                vary_done = false;
0442:            }
0443:
0444:            /**
0445:             * get the "strictness" of the PUT checking
0446:             */
0447:            public boolean getPutPolicy() {
0448:                Boolean val = (Boolean) getValue(ATTR_PUT_POLICY, null);
0449:                if (val == null) // strict by default
0450:                    return true;
0451:                return val.booleanValue();
0452:            }
0453:
0454:            public void setPutPolicy(Boolean strict) {
0455:                setValue(ATTR_PUT_POLICY, strict);
0456:            }
0457:
0458:            public void setPutPolicy(boolean strict) {
0459:                setValue(ATTR_PUT_POLICY, new Boolean(strict));
0460:            }
0461:
0462:            /**
0463:             * get the variant checking policy
0464:             */
0465:            public boolean getParanoidVariantCheck() {
0466:                Boolean val = (Boolean) getValue(ATTR_PARANOID_VARIANT_CHECK,
0467:                        Boolean.FALSE);
0468:                return val.booleanValue();
0469:            }
0470:
0471:            public void setParanoidVariantCheck(boolean strict) {
0472:                setValue(ATTR_PARANOID_VARIANT_CHECK, new Boolean(strict));
0473:            }
0474:
0475:            /**
0476:             * Get the variant resources.
0477:             * This is somehow broken, it shouldn't allocate the array of variants
0478:             * on each call. However, don't forget that the list of variants can be
0479:             * dynamically edited, this means that if we are to keep a cache of it 
0480:             * (as would be the case if we kept the array of variants as instance var)
0481:             * we should also take care of editing of attributes (possible, but I
0482:             * just don't have enough lifes).
0483:             * @return An array of ResourceReference, or <strong>null</strong>.
0484:             * @exception ProtocolException If one of the variants doesn't exist.
0485:             */
0486:
0487:            public ResourceReference[] getVariantResources()
0488:                    throws ProtocolException {
0489:
0490:                // Get the variant names:
0491:                String names[] = getVariantNames();
0492:                if (names == null)
0493:                    return null;
0494:
0495:                int oldlength = names.length;
0496:
0497:                if (getParanoidVariantCheck()) {
0498:                    names = checkVariants(names);
0499:                }
0500:
0501:                // Look them up in our parent directory:
0502:                ResourceReference variants[] = new ResourceReference[names.length];
0503:                ResourceReference r_parent = resource.getParent();
0504:                try {
0505:                    DirectoryResource parent = (DirectoryResource) r_parent
0506:                            .unsafeLock();
0507:                    int missing = 0;
0508:                    for (int i = 0; i < names.length; i++) {
0509:                        variants[i] = parent.lookup(names[i]);
0510:                        if (variants[i] == null)
0511:                            missing++;
0512:                    }
0513:                    if (missing > 0) {
0514:                        int kept = names.length - missing;
0515:                        if (kept < 1)
0516:                            return null;
0517:                        String newNames[] = new String[kept];
0518:                        int j = 0;
0519:                        int i = 0;
0520:                        while (i < variants.length) {
0521:                            if (variants[i] != null) {
0522:                                newNames[j++] = names[i++];
0523:                            } else {
0524:                                i++;
0525:                            }
0526:                        }
0527:                        setVariants(newNames);
0528:                        //recompute Variant Resources
0529:                        return getVariantResources();
0530:                    } else if (oldlength > names.length) {
0531:                        setVariants(names);
0532:                    }
0533:
0534:                } catch (InvalidResourceException ex) {
0535:                    throw new HTTPException("invalid parent for negotiation");
0536:                } finally {
0537:                    r_parent.unlock();
0538:                }
0539:                return variants;
0540:            }
0541:
0542:            /**
0543:             * Print the current negotiation state.
0544:             * @param header The header to print first.
0545:             * @param states The current negotiation states.
0546:             */
0547:
0548:            protected void printNegotiationState(String header, Vector states) {
0549:                if (debug) {
0550:                    System.out.println("------" + header);
0551:                    for (int i = 0; i < states.size(); i++) {
0552:                        VariantState state = (VariantState) states.elementAt(i);
0553:                        System.out.println(state);
0554:                    }
0555:                    System.out.println("-----");
0556:                }
0557:            }
0558:
0559:            /**
0560:             * Negotiate among content encodings.
0561:             * <p>BUG: This will work only for single encoded variants.
0562:             * @param states The current negotiation states.
0563:             * @param request The request to handle.
0564:             * @return a boolean.
0565:             * @exception ProtocolException If one of the variants doesn't exist.
0566:             */
0567:
0568:            protected boolean negotiateContentEncoding(Vector states,
0569:                    Request request) throws ProtocolException {
0570:                if (!request.hasAcceptEncoding() || !b_encoding) {
0571:                    // All encodings accepted:
0572:                    for (int i = 0; i < states.size(); i++) {
0573:                        VariantState state = (VariantState) states.elementAt(i);
0574:                        state.setContentEncodingQuality(1.0);
0575:                    }
0576:                } else {
0577:                    HttpAcceptEncoding encodings[] = request
0578:                            .getAcceptEncoding();
0579:                    for (int i = 0; i < states.size(); i++) {
0580:                        VariantState state = (VariantState) states.elementAt(i);
0581:                        ResourceReference rr = state.getResource();
0582:                        try {
0583:                            FramedResource resource = (FramedResource) rr
0584:                                    .unsafeLock();
0585:                            HTTPFrame itsframe = (HTTPFrame) resource
0586:                                    .unsafeGetFrame(httpFrameClass);
0587:                            if (itsframe != null) {
0588:                                String ve;
0589:                                ve = (String) itsframe.unsafeGetValue(
0590:                                        ATTR_CONTENT_ENCODING, null);
0591:                                if (ve == null) {
0592:                                    ve = "identity"; // default encoding
0593:                                    state.setContentEncodingQuality(1.0);
0594:                                } else {
0595:                                    state.setContentEncodingQuality(0.01);
0596:                                }
0597:                                int jidx = -1;
0598:                                for (int j = 0; j < encodings.length; j++) {
0599:                                    if (encodings[j].getEncoding().equals(ve)) {
0600:                                        jidx = j;
0601:                                        break;
0602:                                    }
0603:                                    if (encodings[j].getEncoding().equals("*"))
0604:                                        jidx = j; // default '*' if no better match
0605:                                }
0606:                                if (jidx >= 0)
0607:                                    state
0608:                                            .setContentEncodingQuality(encodings[jidx]
0609:                                                    .getQuality()
0610:                                                    - jidx * 0.001);
0611:                            }
0612:                        } catch (InvalidResourceException ex) {
0613:
0614:                        } finally {
0615:                            rr.unlock();
0616:                        }
0617:                    }
0618:                    // FIXME We should check here against unlegible variants as now
0619:                }
0620:                return false;
0621:            }
0622:
0623:            /**
0624:             * Negotiate on charsets.
0625:             * The algorithm is described in RFC2616 (Obsoletes RFC2068)
0626:             * @param states The current states of negotiation.
0627:             * @param request The request to handle.
0628:             */
0629:
0630:            protected boolean negotiateCharsetQuality(Vector states,
0631:                    Request request) {
0632:                if (!request.hasAcceptCharset() || !b_charset) {
0633:                    // All variants get a quality of 1.0
0634:                    for (int i = 0; i < states.size(); i++) {
0635:                        VariantState state = (VariantState) states.elementAt(i);
0636:                        state.setCharsetQuality(1.0);
0637:                    }
0638:                } else {
0639:                    // The browser has given some preferences:
0640:                    HttpAcceptCharset charsets[] = request.getAcceptCharset();
0641:
0642:                    for (int i = 0; i < states.size(); i++) {
0643:                        VariantState state = (VariantState) states.elementAt(i);
0644:                        // Get the most specific match for this variant:
0645:                        ResourceReference rr = state.getResource();
0646:                        try {
0647:                            FramedResource resource = (FramedResource) rr
0648:                                    .unsafeLock();
0649:                            HTTPFrame itsframe = (HTTPFrame) resource
0650:                                    .unsafeGetFrame(httpFrameClass);
0651:                            if (itsframe != null) {
0652:                                MimeType vt;
0653:                                vt = (MimeType) itsframe.unsafeGetValue(
0654:                                        ATTR_CONTENT_TYPE, null);
0655:                                String fcharset = vt
0656:                                        .getParameterValue("charset");
0657:                                // if not defined in the frame, it must be the default
0658:                                if (fcharset == null) {
0659:                                    fcharset = "ISO-8859-1";
0660:                                }
0661:                                double qual = 0.0;
0662:                                boolean default_done = false;
0663:                                String charset;
0664:                                for (int j = 0; j < charsets.length; j++) {
0665:                                    charset = charsets[j].getCharset();
0666:                                    if (charset.equals("*")) {
0667:                                        default_done = true;
0668:                                        if (qual == 0) {
0669:                                            qual = charsets[j].getQuality()
0670:                                                    - 0.001 * j;
0671:                                        }
0672:                                    } else {
0673:                                        if (charset.equals("ISO-8859-1"))
0674:                                            default_done = true;
0675:                                        if (charset.equals(fcharset))
0676:                                            if (charsets[j].getQuality() > qual) {
0677:                                                qual = charsets[j].getQuality()
0678:                                                        - 0.001 * j;
0679:                                            }
0680:                                    }
0681:                                }
0682:                                if (!default_done
0683:                                        && fcharset.equals("ISO-8859-1"))
0684:                                    qual = 1.0 - 0.001 * charsets.length;
0685:                                state.setCharsetQuality(qual);
0686:                            }
0687:                        } catch (InvalidResourceException ex) {
0688:                            //FIXME
0689:                        } finally {
0690:                            rr.unlock();
0691:                        }
0692:                    }
0693:                }
0694:                return false;
0695:            }
0696:
0697:            /**
0698:             * Negotiate among language qualities.
0699:             * <p>BUG: This will only work for variants that have one language tag.
0700:             * @param states The current states of negotiation.
0701:             * @param request The request to handle.
0702:             * @return a boolean.
0703:             * @exception ProtocolException If one of the variants doesn't exist.
0704:             */
0705:
0706:            protected boolean negotiateLanguageQuality(Vector states,
0707:                    Request request) throws ProtocolException {
0708:                if (!request.hasAcceptLanguage() || !b_language) {
0709:                    for (int i = 0; i < states.size(); i++) {
0710:                        VariantState state = (VariantState) states.elementAt(i);
0711:                        state.setLanguageQuality(1.0);
0712:                    }
0713:                } else {
0714:                    HttpAcceptLanguage languages[] = request
0715:                            .getAcceptLanguage();
0716:                    LanguageTag req_lang[] = new LanguageTag[languages.length];
0717:                    for (int i = 0; i < languages.length; i++) {
0718:                        req_lang[i] = new LanguageTag(languages[i]
0719:                                .getLanguage());
0720:                    }
0721:                    boolean varyLang = false;
0722:                    for (int i = 0; i < states.size(); i++) {
0723:                        VariantState state = (VariantState) states.elementAt(i);
0724:                        ResourceReference rr = state.getResource();
0725:                        try {
0726:                            FramedResource resource = (FramedResource) rr
0727:                                    .unsafeLock();
0728:                            HTTPFrame itsframe = (HTTPFrame) resource
0729:                                    .getFrame(httpFrameClass);
0730:                            if (itsframe != null) {
0731:                                String lang;
0732:                                lang = (String) itsframe.unsafeGetValue(
0733:                                        ATTR_CONTENT_LANGUAGE, null);
0734:                                if (lang == null) {
0735:                                    state.setLanguageQuality(-1.0);
0736:                                } else {
0737:                                    varyLang = true;
0738:                                    LanguageTag ftag = new LanguageTag(lang);
0739:                                    int jmatch = -1;
0740:                                    int jidx = -1;
0741:                                    for (int j = 0; j < languages.length; j++) {
0742:                                        int match = ftag.match(req_lang[j]);
0743:                                        if (match > jmatch) {
0744:                                            jmatch = match;
0745:                                            jidx = j;
0746:                                        }
0747:                                    }
0748:                                    if (jidx < 0)
0749:                                        state.setLanguageQuality(0.01);
0750:                                    else {
0751:                                        // little hack for first
0752:                                        state
0753:                                                .setLanguageQuality(languages[jidx]
0754:                                                        .getQuality()
0755:                                                        - jidx * 0.001);
0756:                                    }
0757:                                }
0758:                            }
0759:                        } catch (InvalidResourceException ex) {
0760:                            //FIXME
0761:                        } finally {
0762:                            rr.unlock();
0763:                        }
0764:                    }
0765:                    if (varyLang) {
0766:                        for (int i = 0; i < states.size(); i++) {
0767:                            VariantState s = (VariantState) states.elementAt(i);
0768:                            if (s.getLanguageQuality() < 0)
0769:                                s.setLanguageQuality(0.5);
0770:                        }
0771:                    } else {
0772:                        for (int i = 0; i < states.size(); i++) {
0773:                            VariantState s = (VariantState) states.elementAt(i);
0774:                            s.setLanguageQuality(1.0);
0775:                        }
0776:                    }
0777:                }
0778:                return false;
0779:            }
0780:
0781:            /**
0782:             * Negotiate among content types.
0783:             * @param states The current states of negotiation.
0784:             * @param request The request to handle.
0785:             * @return a boolean.
0786:             * @exception ProtocolException If one of the variants doesn't exist.
0787:             */
0788:
0789:            protected boolean negotiateContentType(Vector states,
0790:                    Request request) throws ProtocolException {
0791:                if (!request.hasAccept() || !b_type) {
0792:                    // All variants get a quality of 1.0
0793:                    for (int i = 0; i < states.size(); i++) {
0794:                        VariantState state = (VariantState) states.elementAt(i);
0795:                        state.setQuality(1.0);
0796:                    }
0797:                } else {
0798:                    // The browser has given some preferences:
0799:                    HttpAccept accepts[] = request.getAccept();
0800:
0801:                    for (int i = 0; i < states.size(); i++) {
0802:                        VariantState state = (VariantState) states.elementAt(i);
0803:                        // Get the most specific match for this variant:
0804:                        ResourceReference rr = state.getResource();
0805:                        try {
0806:                            FramedResource resource = (FramedResource) rr
0807:                                    .unsafeLock();
0808:                            HTTPFrame itsframe = (HTTPFrame) resource
0809:                                    .unsafeGetFrame(httpFrameClass);
0810:                            if (itsframe != null) {
0811:                                MimeType vt;
0812:                                vt = (MimeType) itsframe.unsafeGetValue(
0813:                                        ATTR_CONTENT_TYPE, null);
0814:                                int jmatch = -1;
0815:                                int jidx = -1;
0816:                                for (int j = 0; j < accepts.length; j++) {
0817:                                    try {
0818:                                        int match = vt.match(accepts[j]
0819:                                                .getMimeType());
0820:                                        if (match > jmatch) {
0821:                                            jmatch = match;
0822:                                            jidx = j;
0823:                                        }
0824:                                    } catch (HttpInvalidValueException ivex) {
0825:                                        // There is a bad acept header here
0826:                                        // let's be cool and ignore it
0827:                                        // FIXME we should answer with a Bad Request
0828:                                    }
0829:                                }
0830:                                if (jidx < 0)
0831:                                    state.setQuality(0.0);
0832:                                else
0833:                                    state.setQuality(accepts[jidx].getQuality()
0834:                                            - jidx * 0.001);
0835:                            }
0836:                        } catch (InvalidResourceException ex) {
0837:                            //FIXME
0838:                        } finally {
0839:                            rr.unlock();
0840:                        }
0841:                    }
0842:                }
0843:                return false;
0844:            }
0845:
0846:            /**
0847:             * Negotiate among the various variants for the Resource.
0848:             * We made our best efforts to be as compliant as possible to the HTTP/1.0
0849:             * content negotiation algorithm.
0850:             * @param request the incomming request.
0851:             * @return a RefourceReference instance.
0852:             * @exception ProtocolException If one of the variants doesn't exist.
0853:             */
0854:            protected ResourceReference negotiate(Request request)
0855:                    throws ProtocolException {
0856:                // Check for zero or one variant:
0857:                ResourceReference variants[] = getVariantResources();
0858:                if (variants == null) {
0859:                    try {
0860:                        getResource().delete();
0861:                    } catch (MultipleLockException ex) {
0862:                        //will be deleted later...
0863:                    } finally {
0864:                        Reply reply = request.makeReply(HTTP.NOT_FOUND);
0865:                        reply.setContent("<h1>Document not found</h1>"
0866:                                + "<p>The document " + request.getURL()
0867:                                + " has no acceptable variants "
0868:                                + "(probably deleted).");
0869:                        throw new HTTPException(reply);
0870:                    }
0871:                }
0872:                if (variants.length < 2) {
0873:                    if (variants.length == 0) {
0874:                        try {
0875:                            getResource().delete();
0876:                        } catch (MultipleLockException ex) {
0877:                            //will be deleted later...
0878:                        } finally {
0879:                            Reply reply = request.makeReply(HTTP.NOT_FOUND);
0880:                            reply.setContent("<h1>Document not found</h1>"
0881:                                    + "<p>The document " + request.getURL()
0882:                                    + " has no acceptable variants "
0883:                                    + "(probably deleted).");
0884:                            throw new HTTPException(reply);
0885:                        }
0886:                    } else {
0887:                        return variants[0];
0888:                    }
0889:                }
0890:                // Build a vector of variant negociation states, one per variants:
0891:                Vector states = new Vector(variants.length);
0892:                for (int i = 0; i < variants.length; i++) {
0893:                    double qs = 1.0;
0894:                    try {
0895:                        FramedResource resource = (FramedResource) variants[i]
0896:                                .unsafeLock();
0897:                        HTTPFrame itsframe = (HTTPFrame) resource
0898:                                .unsafeGetFrame(httpFrameClass);
0899:                        if (itsframe != null) {
0900:                            if (itsframe.unsafeDefinesAttribute(ATTR_QUALITY))
0901:                                qs = itsframe.unsafeGetQuality();
0902:                            if (qs > REQUIRED_QUALITY)
0903:                                states.addElement(new VariantState(variants[i],
0904:                                        qs));
0905:                        }
0906:                    } catch (InvalidResourceException ex) {
0907:                        //FIXME
0908:                    } finally {
0909:                        variants[i].unlock();
0910:                    }
0911:                }
0912:                // Content-encoding negociation:
0913:                if (debug) {
0914:                    printNegotiationState("init:", states);
0915:                }
0916:                if (negotiateContentEncoding(states, request)) {
0917:                    // Remains a single acceptable variant:
0918:                    return ((VariantState) states.elementAt(0)).getResource();
0919:                }
0920:                if (debug) {
0921:                    printNegotiationState("encoding:", states);
0922:                }
0923:                // Charset quality negociation:
0924:                if (negotiateCharsetQuality(states, request)) {
0925:                    // Remains a single acceptable variant:
0926:                    return ((VariantState) states.elementAt(0)).getResource();
0927:                }
0928:                if (debug) {
0929:                    printNegotiationState("charset:", states);
0930:                }
0931:                // Language quality negociation:
0932:                if (negotiateLanguageQuality(states, request)) {
0933:                    // Remains a single acceptable variant:
0934:                    return ((VariantState) states.elementAt(0)).getResource();
0935:                }
0936:                if (debug) {
0937:                    printNegotiationState("language:", states);
0938:                }
0939:                // Content-type negociation:
0940:                if (negotiateContentType(states, request)) {
0941:                    // Remains a single acceptable variant:
0942:                    return ((VariantState) states.elementAt(0)).getResource();
0943:                }
0944:                if (debug) {
0945:                    printNegotiationState("type:", states);
0946:                }
0947:                // If we reached this point, this means that multiple variants are 
0948:                // acceptable at this point. Keep the ones that have the best quality.
0949:                if (debug) {
0950:                    printNegotiationState("before Q selection:", states);
0951:                }
0952:                double qmax = REQUIRED_QUALITY;
0953:
0954:                for (int i = 0; i < states.size();) {
0955:                    VariantState state = (VariantState) states.elementAt(i);
0956:                    if (state.getQ() > qmax) {
0957:                        for (int j = i; j > 0; j--)
0958:                            states.removeElementAt(0);
0959:                        qmax = state.getQ();
0960:                        i = 1;
0961:                    } else {
0962:                        if (state.getQ() < qmax)
0963:                            states.removeElementAt(i);
0964:                        else
0965:                            i++;
0966:                    }
0967:                }
0968:                if (debug)
0969:                    printNegotiationState("After Q selection:", states);
0970:                if (qmax == REQUIRED_QUALITY) {
0971:
0972:                    Reply reply = request.makeReply(HTTP.NOT_ACCEPTABLE);
0973:                    HtmlGenerator g = new HtmlGenerator("No acceptable");
0974:                    g
0975:                            .append("<P>The resource cannot be served according to the "
0976:                                    + "headers sent</P>");
0977:                    reply.setStream(g);
0978:                    throw new HTTPException(reply);
0979:                } else if (states.size() == 1) {
0980:                    return ((VariantState) states.elementAt(0)).getResource();
0981:                } else {
0982:                    // Respond with multiple choice (for the time being, there should
0983:                    // be a parameter to decide what to do.
0984:                    Reply reply = request.makeReply(HTTP.MULTIPLE_CHOICE);
0985:                    HtmlGenerator g = new HtmlGenerator("Multiple choice for "
0986:                            + resource.getIdentifier());
0987:                    g.append("<ul>");
0988:                    for (int i = 0; i < states.size(); i++) {
0989:                        VariantState state = (VariantState) states.elementAt(i);
0990:                        String name = null;
0991:                        ResourceReference rr = state.getResource();
0992:                        try {
0993:                            name = rr.unsafeLock().getIdentifier();
0994:                            g.append("<li>" + "<a href=\"" + name + "\">"
0995:                                    + name + "</a>" + " Q= " + state.getQ());
0996:                        } catch (InvalidResourceException ex) {
0997:                            //FIXME
0998:                        } finally {
0999:                            rr.unlock();
1000:                        }
1001:                    }
1002:                    reply.setStream(g);
1003:                    reply.setHeaderValue(reply.H_VARY, getVary());
1004:                    throw new HTTPException(reply);
1005:                }
1006:            }
1007:
1008:            /**
1009:             * "negotiate" for a PUT, the negotiation of a PUT should be 
1010:             * different as we just want to match the desciption of the entity
1011:             * and the available variants
1012:             * @param request, the request to handle
1013:             * @return a ResourceReference instance
1014:             * @exception ProtocolException If negotiating among the resource variants 
1015:             * failed.
1016:             * @exception ResourceException If the resource got a fatal error.
1017:             */
1018:
1019:            protected ResourceReference negotiatePut(Request request)
1020:                    throws ProtocolException, ResourceException {
1021:                // Check for zero or one variant:
1022:                ResourceReference variants[] = getVariantResources();
1023:                HTTPFrame itsframe;
1024:                int nb_v;
1025:                // zero, don't PUT on a negotiable resource! 
1026:                if (variants == null || variants.length == 0) {
1027:                    try {
1028:                        getResource().delete();
1029:                    } catch (MultipleLockException ex) {
1030:                        //will be deleted later...
1031:                    } finally {
1032:                        Reply reply = request.makeReply(HTTP.NOT_FOUND);
1033:                        reply.setContent("<h1>Document not found</h1>"
1034:                                + "<p>The document " + request.getURL()
1035:                                + " has no acceptable variants "
1036:                                + "(probably deleted).");
1037:                        throw new HTTPException(reply);
1038:                    }
1039:                }
1040:                // negotiate etag
1041:                HttpEntityTag etag = request.getETag();
1042:                HttpEntityTag etags[] = request.getIfMatch();
1043:                // gather the etags
1044:                if (etags == null && etag != null) {
1045:                    etags = new HttpEntityTag[1];
1046:                    etags[0] = etag;
1047:                } else if (etag != null) {
1048:                    HttpEntityTag t_etags[] = new HttpEntityTag[etags.length + 1];
1049:                    System.arraycopy(etags, 0, t_etags, 0, etags.length);
1050:                    t_etags[etags.length] = etag;
1051:                    etags = t_etags;
1052:                }
1053:
1054:                if (etags != null) {
1055:                    // yeah go for it!
1056:                    FramedResource resource;
1057:                    HttpEntityTag frametag;
1058:                    for (int i = 0; i < variants.length; i++) {
1059:                        try {
1060:                            resource = (FramedResource) variants[i]
1061:                                    .unsafeLock();
1062:                            itsframe = (HTTPFrame) resource
1063:                                    .getFrame(httpFrameClass);
1064:                            if (itsframe != null) {
1065:                                frametag = itsframe.getETag();
1066:                                if (frametag == null) {
1067:                                    continue;
1068:                                }
1069:                                // Do we have a winner?
1070:                                try {
1071:                                    for (int j = 0; j < etags.length; j++)
1072:                                        if (frametag.getTag().equals(
1073:                                                etags[j].getTag()))
1074:                                            return variants[i];
1075:                                } catch (NullPointerException ex) {
1076:                                    // if the list of etag contains a null
1077:                                    // it should never happen and the try doesn't cost
1078:                                }
1079:                            }
1080:                        } catch (InvalidResourceException ex) {
1081:                            //FIXME
1082:                        } finally {
1083:                            variants[i].unlock();
1084:                        }
1085:                    }
1086:                    // no matching variants...
1087:                    Reply reply = request.makeReply(HTTP.NOT_FOUND);
1088:                    reply.setContent("<h1>Document not found</h1>"
1089:                            + "<p>The document " + request.getURL()
1090:                            + " has no acceptable variants "
1091:                            + "according to the ETag sent");
1092:                    throw new HTTPException(reply);
1093:                }
1094:                // if we are strict, don't go any further, etags
1095:                // is the mandatory thing, otherwise PUT on the direct version
1096:                if (getPutPolicy()) {
1097:                    Reply reply = request.makeReply(HTTP.NOT_FOUND);
1098:                    reply.setContent("<h1>Document not found</h1>"
1099:                            + "<p>The document " + request.getURL()
1100:                            + " has no acceptable variants "
1101:                            + " for a PUT, as no ETags were sent");
1102:                    throw new HTTPException(reply);
1103:                }
1104:                // now filter out variants
1105:                nb_v = variants.length;
1106:                MimeType type = request.getContentType();
1107:                String encodings[] = request.getContentEncoding();
1108:                String languages[] = request.getContentLanguage();
1109:                ResourceReference rr;
1110:
1111:                if (type != null || encodings != null || languages != null) {
1112:                    // the request is not too bad ;)
1113:                    for (int i = 0; i < variants.length; i++) {
1114:                        if (variants[i] == null)
1115:                            continue;
1116:                        rr = variants[i];
1117:                        try {
1118:                            resource = (FramedResource) rr.unsafeLock();
1119:                            itsframe = (HTTPFrame) resource
1120:                                    .getFrame(httpFrameClass);
1121:                            if (itsframe == null) {
1122:                                nb_v--;
1123:                                variants[i] = null;
1124:                                continue;
1125:                            }
1126:                            // remove the non matching mime types
1127:                            if (type != null) {
1128:                                MimeType fmt = itsframe.getContentType();
1129:                                if (fmt == null
1130:                                        || (fmt.match(type) != MimeType.MATCH_SPECIFIC_SUBTYPE)) {
1131:                                    nb_v--;
1132:                                    variants[i] = null;
1133:                                    continue;
1134:                                }
1135:                            }
1136:                            // remove the non matching languages
1137:                            if (languages != null) {
1138:                                String language = itsframe.getContentLanguage();
1139:                                nb_v--;
1140:                                variants[i] = null;
1141:                                if (language == null) {
1142:                                    continue;
1143:                                }
1144:                                for (int j = 0; j < languages.length; j++) {
1145:                                    if (language.equals(languages[j])) {
1146:                                        nb_v++;
1147:                                        variants[i] = rr;
1148:                                        break;
1149:                                    }
1150:                                }
1151:                            }
1152:                            // remove the non matching encodings		    
1153:                            if (encodings != null) {
1154:                                String encoding = itsframe.getContentEncoding();
1155:                                nb_v--;
1156:                                variants[i] = null;
1157:                                if (encoding == null) {
1158:                                    continue;
1159:                                }
1160:                                for (int j = 0; j < encodings.length; j++) {
1161:                                    if (encoding.equals(languages[j])) {
1162:                                        nb_v++;
1163:                                        variants[i] = rr;
1164:                                        break;
1165:                                    }
1166:                                }
1167:                            }
1168:                        } catch (InvalidResourceException ex) {
1169:                            //FIXME
1170:                        } finally {
1171:                            rr.unlock();
1172:                        }
1173:                    }
1174:                    // a winner!
1175:                    if (nb_v == 1) {
1176:                        for (int i = 0; i < variants.length; i++) {
1177:                            if (variants[i] != null)
1178:                                return variants[i];
1179:                        }
1180:                    }
1181:                    // no document matching
1182:                    if (nb_v <= 0) {
1183:                        Reply reply = request.makeReply(HTTP.NOT_FOUND);
1184:                        reply
1185:                                .setContent("<h1>Document not found</h1>"
1186:                                        + "<p>The document " + request.getURL()
1187:                                        + " has no acceptable variants "
1188:                                        + " for a PUT");
1189:                        throw new HTTPException(reply);
1190:                    }
1191:                }
1192:                // now we have multiple choice :(
1193:                String name;
1194:                Reply reply = request.makeReply(HTTP.MULTIPLE_CHOICE);
1195:                HtmlGenerator g = new HtmlGenerator("Multiple choice for "
1196:                        + resource.getIdentifier());
1197:                g.append("<ul>");
1198:                for (int i = 0; i < variants.length; i++) {
1199:                    if (variants[i] != null) {
1200:                        try {
1201:                            name = variants[i].unsafeLock().getIdentifier();
1202:                            g.append("<li>" + "<a href=\"" + name + "\">"
1203:                                    + name + "</a>");
1204:                        } catch (InvalidResourceException ex) {
1205:                            //FIXME (this should NOT happen :) )
1206:                        } finally {
1207:                            variants[i].unlock();
1208:                        }
1209:                    }
1210:                }
1211:                reply.setStream(g);
1212:                reply.setHeaderValue(reply.H_VARY, getVary());
1213:                throw new HTTPException(reply);
1214:            }
1215:
1216:            public void registerResource(FramedResource resource) {
1217:                super .registerOtherResource(resource);
1218:            }
1219:
1220:            /**
1221:             * Lookup the target resource.
1222:             * @param ls The current lookup state
1223:             * @param lr The result
1224:             * @return true if lookup is done.
1225:             * @exception ProtocolException If an error relative to the protocol occurs
1226:             */
1227:            public boolean lookup(LookupState ls, LookupResult lr)
1228:                    throws ProtocolException {
1229:                if (ls.isDirectory()) { // we are not a directory, bail out
1230:                    Request req = (Request) ls.getRequest();
1231:                    String locstate = (String) req
1232:                            .getState(STATE_CONTENT_LOCATION);
1233:                    if (locstate == null) {
1234:                        lr.setTarget(null);
1235:                        return true;
1236:                    }
1237:                }
1238:                ResourceFrame frames[] = getFrames();
1239:                if (frames != null) {
1240:                    for (int i = 0; i < frames.length; i++) {
1241:                        if (frames[i] == null) {
1242:                            continue;
1243:                        }
1244:                        if (frames[i].lookup(ls, lr)) {
1245:                            return true;
1246:                        }
1247:                    }
1248:                }
1249:                if (ls.hasMoreComponents()) {
1250:                    // We are not a container resource, and we don't have children:
1251:                    lr.setTarget(null);
1252:                    return false;
1253:                } else {
1254:                    //we are done! try to find the negotiated one...
1255:                    RequestInterface reqi = ls.getRequest();
1256:                    ResourceReference selected;
1257:                    Request request = (Request) reqi;
1258:                    // Run content negotiation now:
1259:                    // The PUT is special, we negotiate with ETag (if present) or
1260:                    // using the metainformation about the PUT entity.
1261:                    String method = request.getMethod();
1262:                    try {
1263:                        if (method.equals("PUT")) {
1264:                            selected = negotiatePut(request);
1265:                        } else {
1266:                            selected = negotiate(request);
1267:                        }
1268:                    } catch (ResourceException ex) {
1269:                        // the failure will be processed in perform
1270:                        return false;
1271:                    }
1272:                    if (selected != null) {
1273:                        try {
1274:                            FramedResource resource = (FramedResource) selected
1275:                                    .unsafeLock();
1276:                            resource.lookup(ls, lr);
1277:                        } catch (InvalidResourceException ex) {
1278:                            // the failure will be processed in perform
1279:                        } finally {
1280:                            selected.unlock();
1281:                        }
1282:                    }
1283:                    request.setState(STATE_NEG, selected);
1284:                    // fake now, we handle the process to have a two-level processing
1285:                    // just to add the Vary: header
1286:                    lr.setTarget(getResourceReference());
1287:                    return true;
1288:                }
1289:            }
1290:
1291:            /**
1292:             * Perform an HTTP request.
1293:             * Negotiate among the variants, the best variant according to the request
1294:             * fields, and make this elected variant serve the request.
1295:             * @param request The request to handle.
1296:             * @exception ProtocolException If negotiating among the resource variants 
1297:             * failed.
1298:             * @exception ResourceException If the resource got a fatal error.
1299:             */
1300:
1301:            public ReplyInterface perform(RequestInterface req)
1302:                    throws ProtocolException, ResourceException {
1303:                ReplyInterface repi = performFrames(req);
1304:                if (repi != null)
1305:                    return repi;
1306:
1307:                if (!checkRequest(req))
1308:                    return null;
1309:
1310:                Request request = (Request) req;
1311:                ResourceReference selected;
1312:                // get the right resources
1313:                if (request.hasState(STATE_NEG)) {
1314:                    selected = (ResourceReference) request.getState(STATE_NEG);
1315:                } else {
1316:                    String method = request.getMethod();
1317:                    if (method.equals("PUT")) {
1318:                        selected = negotiatePut(request);
1319:                    } else {
1320:                        selected = negotiate(request);
1321:                    }
1322:                }
1323:
1324:                // This should never happen: either the negotiation succeed, or the
1325:                // negotiate method should return an error.
1326:                if (selected == null) {
1327:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
1328:                    error
1329:                            .setContent("Error negotiating among resource's variants.");
1330:                    throw new HTTPException(error);
1331:                }
1332:
1333:                try {
1334:                    FramedResource resource = (FramedResource) selected
1335:                            .unsafeLock();
1336:                    Reply reply = (Reply) resource.perform(request);
1337:                    reply.setHeaderValue(reply.H_VARY, getVary());
1338:                    HTTPFrame itsframe = (HTTPFrame) resource
1339:                            .unsafeGetFrame(httpFrameClass);
1340:                    if (itsframe != null) {
1341:                        reply.setContentLocation(itsframe.getURL(request)
1342:                                .toExternalForm());
1343:                        return reply;
1344:                    }
1345:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
1346:                    error.setContent("Error negotiating : "
1347:                            + "selected resource has no HTTPFrame");
1348:                    throw new HTTPException(error);
1349:                } catch (InvalidResourceException ex) {
1350:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
1351:                    error
1352:                            .setContent("Error negotiating : Invalid selected resource");
1353:                    throw new HTTPException(error);
1354:                } finally {
1355:                    selected.unlock();
1356:                }
1357:            }
1358:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.