Source Code Cross Referenced for httpHeader.java in  » Search-Engine » yacy » de » anomic » http » 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 » Search Engine » yacy » de.anomic.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // httpHeader.java 
0002:        // -----------------------
0003:        // (C) by Michael Peter Christen; mc@anomic.de
0004:        // first published on http://www.anomic.de
0005:        // Frankfurt, Germany, 2004
0006:        //
0007:        // last major change: $LastChangedDate: 2008-01-29 10:12:48 +0000 (Di, 29 Jan 2008) $ by $LastChangedBy: orbiter $
0008:        // Revision: $LastChangedRevision: 4414 $
0009:        //
0010:        // This program is free software; you can redistribute it and/or modify
0011:        // it under the terms of the GNU General Public License as published by
0012:        // the Free Software Foundation; either version 2 of the License, or
0013:        // (at your option) any later version.
0014:        //
0015:        // This program is distributed in the hope that it will be useful,
0016:        // but WITHOUT ANY WARRANTY; without even the implied warranty of
0017:        // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018:        // GNU General Public License for more details.
0019:        //
0020:        // You should have received a copy of the GNU General Public License
0021:        // along with this program; if not, write to the Free Software
0022:        // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0023:        //
0024:        // Using this software in any meaning (reading, learning, copying, compiling,
0025:        // running) means that you agree that the Author(s) is (are) not responsible
0026:        // for cost, loss of data or any harm that may be caused directly or indirectly
0027:        // by usage of this softare or this documentation. The usage of this software
0028:        // is on your own risk. The installation and usage (starting/running) of this
0029:        // software may allow other people or application to access your computer and
0030:        // any attached devices and is highly dependent on the configuration of the
0031:        // software which must be done by the user of the software; the author(s) is
0032:        // (are) also not responsible for proper configuration and usage of the
0033:        // software, even if provoked by documentation provided together with
0034:        // the software.
0035:        //
0036:        // Any changes to this file according to the GPL as documented in the file
0037:        // gpl.txt aside this file in the shipment you received can be done to the
0038:        // lines that follows this copyright notice here, but changes must not be
0039:        // done inside the copyright notive above. A re-distribution must contain
0040:        // the intact and unchanged copyright notice.
0041:        // Contributions and changes to the program code must be marked as such.
0042:
0043:        /*
0044:         Documentation:
0045:         this class implements a key-value mapping, as a hashtable
0046:         The difference to ordinary hashtable implementations is that the
0047:         keys are not compared by the equal() method, but are always
0048:         treated as string and compared as
0049:         key.uppercase().equal(.uppercase(comparator))
0050:         You use this class by first creation of a static HashMap
0051:         that then is used a the reverse mapping cache for every new
0052:         instance of this class.
0053:         */
0054:
0055:        package de.anomic.http;
0056:
0057:        import java.io.BufferedReader;
0058:        import java.io.File;
0059:        import java.io.FileOutputStream;
0060:        import java.io.FileReader;
0061:        import java.io.IOException;
0062:        import java.net.MalformedURLException;
0063:        import java.text.Collator;
0064:        import java.util.Date;
0065:        import java.util.HashMap;
0066:        import java.util.Iterator;
0067:        import java.util.Locale;
0068:        import java.util.Map;
0069:        import java.util.Properties;
0070:        import java.util.TreeMap;
0071:        import java.util.Vector;
0072:
0073:        import de.anomic.server.serverCore;
0074:        import de.anomic.server.serverDate;
0075:        import de.anomic.yacy.yacyURL;
0076:
0077:        public final class httpHeader extends TreeMap<String, String> implements 
0078:                Map<String, String> {
0079:
0080:            private static final long serialVersionUID = 17L;
0081:
0082:            public static final String DEFAULT_CHARSET = "ISO-8859-1";
0083:
0084:            /* =============================================================
0085:             * Constants defining http versions
0086:             * ============================================================= */
0087:            public static final String HTTP_VERSION_0_9 = "HTTP/0.9";
0088:            public static final String HTTP_VERSION_1_0 = "HTTP/1.0";
0089:            public static final String HTTP_VERSION_1_1 = "HTTP/1.1";
0090:
0091:            /* =============================================================
0092:             * Constants defining http header names
0093:             * ============================================================= */
0094:            public static final String ACCEPT = "Accept";
0095:            public static final String ACCEPT_CHARSET = "Accept-Charset";
0096:            public static final String ACCEPT_LANGUAGE = "Accept-Language";
0097:
0098:            public static final String HOST = "Host";
0099:
0100:            public static final String CONNECTION = "Connection";
0101:            public static final String PROXY_CONNECTION = "Proxy-Connection";
0102:            public static final String KEEP_ALIVE = "Keep-Alive";
0103:
0104:            public static final String REFERER = "Referer";
0105:            public static final String USER_AGENT = "User-Agent";
0106:
0107:            public static final String AUTHORIZATION = "Authorization";
0108:            public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
0109:            public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
0110:            public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
0111:
0112:            public static final String DATE = "Date";
0113:            public static final String SERVER = "Server";
0114:
0115:            public static final String CONTENT_LENGTH = "Content-Length";
0116:            public static final String CONTENT_TYPE = "Content-Type";
0117:            public static final String CONTENT_MD5 = "Content-MD5";
0118:            public static final String CONTENT_LOCATION = "Content-Location";
0119:
0120:            public static final String SET_COOKIE = "Set-Cookie";
0121:            public static final String SET_COOKIE2 = "Set-Cookie2";
0122:            public static final String COOKIE = "Cookie";
0123:            public static final String EXPIRES = "Expires";
0124:
0125:            public static final String ACCEPT_ENCODING = "Accept-Encoding";
0126:            public static final String CONTENT_ENCODING = "Content-Encoding";
0127:            public static final String TRANSFER_ENCODING = "Transfer-Encoding";
0128:
0129:            public static final String ACCEPT_RANGES = "Accept-Ranges";
0130:            public static final String CONTENT_RANGE = "Content-Range";
0131:            public static final String RANGE = "Range";
0132:            public static final String IF_RANGE = "If-Range";
0133:
0134:            public static final String PRAGMA = "Pragma";
0135:            public static final String CACHE_CONTROL = "Cache-Control";
0136:            public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
0137:            public static final String LAST_MODIFIED = "Last-modified";
0138:
0139:            public static final String LOCATION = "Location";
0140:            public static final String ETAG = "ETag";
0141:            public static final String VIA = "Via";
0142:
0143:            public static final String X_CACHE = "X-Cache";
0144:            public static final String X_CACHE_LOOKUP = "X-Cache-Lookup";
0145:            public static final String X_FORWARDED_FOR = "X-Forwarded-For";
0146:
0147:            public static final String X_YACY_KEEP_ALIVE_REQUEST_COUNT = "X-Keep-Alive-Request-Count";
0148:            public static final String X_YACY_ORIGINAL_REQUEST_LINE = "X-Original-Request-Line";
0149:            public static final String X_YACY_PREVIOUS_REQUEST_LINE = "X-Previous-Request-Line";
0150:
0151:            public static final String X_YACY_INDEX_CONTROL = "X-YACY-Index-Control";
0152:
0153:            public static final String UPGRADE = "Upgrade";
0154:            public static final String TE = "TE";
0155:
0156:            /* =============================================================
0157:             * Constants for content-encodings
0158:             * ============================================================= */
0159:            public static final String CONTENT_ENCODING_GZIP = "gzip";
0160:
0161:            /* =============================================================
0162:             * Constants defining http methods
0163:             * ============================================================= */
0164:            public static final String METHOD_GET = "GET";
0165:            public static final String METHOD_HEAD = "HEAD";
0166:            public static final String METHOD_POST = "POST";
0167:            public static final String METHOD_CONNECT = "CONNECT";
0168:
0169:            /* =============================================================
0170:             * defining default http status messages
0171:             * ============================================================= */
0172:            public static final HashMap<String, String> http0_9 = new HashMap<String, String>();
0173:            public static final HashMap<String, String> http1_0 = new HashMap<String, String>();
0174:            static {
0175:                http1_0.putAll(http0_9);
0176:                http1_0.put("200", "OK");
0177:                http1_0.put("201", "Created");
0178:                http1_0.put("202", "Accepted");
0179:                http1_0.put("204", "No Content");
0180:                http1_0.put("300", "Multiple Choices");
0181:                http1_0.put("301", "Moved Permanently");
0182:                http1_0.put("302", "Moved Temporarily");
0183:                http1_0.put("304", "Not Modified");
0184:                http1_0.put("400", "Bad Request");
0185:                http1_0.put("401", "Unauthorized");
0186:                http1_0.put("403", "Forbidden");
0187:                http1_0.put("404", "Not Found");
0188:                http1_0.put("500", "Internal Server Error");
0189:                http1_0.put("501", "Not Implemented");
0190:                http1_0.put("502", "Bad Gateway");
0191:                http1_0.put("503", "Service Unavailable");
0192:            }
0193:            public static final HashMap<String, String> http1_1 = new HashMap<String, String>();
0194:            static {
0195:                http1_1.putAll(http1_0);
0196:                http1_1.put("100", "Continue");
0197:                http1_1.put("101", "Switching Protocols");
0198:                http1_1.put("203", "Non-Authoritative Information");
0199:                http1_1.put("205", "Reset Content");
0200:                http1_1.put("206", "Partial Content");
0201:                http1_1.put("300", "Multiple Choices");
0202:                http1_1.put("303", "See Other");
0203:                http1_1.put("305", "Use Proxy");
0204:                http1_1.put("307", "Temporary Redirect");
0205:                http1_1.put("402", "Payment Required");
0206:                http1_1.put("405", "Method Not Allowed");
0207:                http1_1.put("406", "Not Acceptable");
0208:                http1_1.put("407", "Proxy Authentication Required");
0209:                http1_1.put("408", "Request Time-out");
0210:                http1_1.put("409", "Conflict");
0211:                http1_1.put("410", "Gone");
0212:                http1_1.put("411", "Length Required");
0213:                http1_1.put("412", "Precondition Failed");
0214:                http1_1.put("413", "Request Entity Too Large");
0215:                http1_1.put("414", "Request-URI Too Large");
0216:                http1_1.put("415", "Unsupported Media Type");
0217:                http1_1.put("416", "Requested range not satisfiable");
0218:                http1_1.put("417", "Expectation Failed");
0219:                http1_1.put("504", "Gateway Time-out");
0220:                http1_1.put("505", "HTTP Version not supported");
0221:            }
0222:
0223:            /* PROPERTIES: General properties */
0224:            public static final String CONNECTION_PROP_HTTP_VER = "HTTP";
0225:            public static final String CONNECTION_PROP_HOST = "HOST";
0226:            public static final String CONNECTION_PROP_USER = "USER";
0227:            public static final String CONNECTION_PROP_METHOD = "METHOD";
0228:            public static final String CONNECTION_PROP_PATH = "PATH";
0229:            public static final String CONNECTION_PROP_EXT = "EXT";
0230:            public static final String CONNECTION_PROP_URL = "URL";
0231:            public static final String CONNECTION_PROP_ARGS = "ARGS";
0232:            public static final String CONNECTION_PROP_CLIENTIP = "CLIENTIP";
0233:            public static final String CONNECTION_PROP_PERSISTENT = "PERSISTENT";
0234:            public static final String CONNECTION_PROP_KEEP_ALIVE_COUNT = "KEEP-ALIVE_COUNT";
0235:            public static final String CONNECTION_PROP_REQUESTLINE = "REQUESTLINE";
0236:            public static final String CONNECTION_PROP_PREV_REQUESTLINE = "PREVREQUESTLINE";
0237:            public static final String CONNECTION_PROP_REQUEST_START = "REQUEST_START";
0238:            public static final String CONNECTION_PROP_REQUEST_END = "REQUEST_END";
0239:            //public static final String CONNECTION_PROP_INPUTSTREAM = "INPUTSTREAM";
0240:            //public static final String CONNECTION_PROP_OUTPUTSTREAM = "OUTPUTSTREAM";
0241:
0242:            /* PROPERTIES: Client -> Proxy */
0243:            public static final String CONNECTION_PROP_CLIENT_REQUEST_HEADER = "CLIENT_REQUEST_HEADER";
0244:
0245:            /* PROPERTIES: Proxy -> Client */
0246:            public static final String CONNECTION_PROP_PROXY_RESPOND_CODE = "PROXY_RESPOND_CODE";
0247:            public static final String CONNECTION_PROP_PROXY_RESPOND_STATUS = "PROXY_RESPOND_STATUS";
0248:            public static final String CONNECTION_PROP_PROXY_RESPOND_HEADER = "PROXY_RESPOND_HEADER";
0249:            public static final String CONNECTION_PROP_PROXY_RESPOND_SIZE = "PROXY_REQUEST_SIZE";
0250:
0251:            private final HashMap<String, String> reverseMappingCache;
0252:
0253:            private static final Collator insensitiveCollator = Collator
0254:                    .getInstance(Locale.US);
0255:            static {
0256:                insensitiveCollator.setStrength(Collator.SECONDARY);
0257:                insensitiveCollator.setDecomposition(Collator.NO_DECOMPOSITION);
0258:            }
0259:
0260:            public httpHeader() {
0261:                this (null);
0262:            }
0263:
0264:            public httpHeader(HashMap<String, String> reverseMappingCache) {
0265:                // this creates a new TreeMap with a case insensitive mapping
0266:                // to provide a put-method that translates given keys into their
0267:                // 'proper' appearance, a translation cache is needed.
0268:                // upon instantiation, such a mapping cache can be handed over
0269:                // If the reverseMappingCache is null, none is used
0270:                super ((Collator) insensitiveCollator.clone());
0271:                this .reverseMappingCache = reverseMappingCache;
0272:            }
0273:
0274:            public httpHeader(HashMap<String, String> reverseMappingCache,
0275:                    File f) throws IOException {
0276:                // creates also a case insensitive map and loads it initially
0277:                // with some values
0278:                super ((Collator) insensitiveCollator.clone());
0279:                this .reverseMappingCache = reverseMappingCache;
0280:
0281:                // load with data
0282:                BufferedReader br = new BufferedReader(new FileReader(f));
0283:                String line;
0284:                int pos;
0285:                while ((line = br.readLine()) != null) {
0286:                    pos = line.indexOf("=");
0287:                    if (pos >= 0)
0288:                        put(line.substring(0, pos), line.substring(pos + 1));
0289:                }
0290:                br.close();
0291:            }
0292:
0293:            public httpHeader(HashMap<String, String> reverseMappingCache,
0294:                    Map<String, String> othermap) {
0295:                // creates a case insensitive map from another map
0296:                super ((Collator) insensitiveCollator.clone());
0297:                this .reverseMappingCache = reverseMappingCache;
0298:
0299:                // load with data
0300:                if (othermap != null)
0301:                    this .putAll(othermap);
0302:            }
0303:
0304:            // we override the put method to make use of the reverseMappingCache
0305:            public String put(String key, String value) {
0306:                String upperK = key.toUpperCase();
0307:
0308:                if (reverseMappingCache == null) {
0309:                    return super .put(key, value);
0310:                }
0311:
0312:                if (reverseMappingCache.containsKey(upperK)) {
0313:                    // we put in the value using the reverse mapping
0314:                    return super .put(reverseMappingCache.get(upperK), value);
0315:                }
0316:
0317:                // we put in without a cached key and store the key afterwards
0318:                String r = super .put(key, value);
0319:                reverseMappingCache.put(upperK, key);
0320:                return r;
0321:            }
0322:
0323:            // to make the occurrence of multiple keys possible, we add them using a counter
0324:            public String add(String key, String value) {
0325:                int c = keyCount(key);
0326:                if (c == 0)
0327:                    return put(key, value);
0328:                return put("*" + key + "-" + c, value);
0329:            }
0330:
0331:            public int keyCount(String key) {
0332:                if (!(containsKey(key)))
0333:                    return 0;
0334:                int c = 1;
0335:                while (containsKey("*" + key + "-" + c))
0336:                    c++;
0337:                return c;
0338:            }
0339:
0340:            // a convenience method to access the map with fail-over defaults
0341:            public Object get(Object key, Object dflt) {
0342:                Object result = get(key);
0343:                if (result == null)
0344:                    return dflt;
0345:                return result;
0346:            }
0347:
0348:            // return multiple results
0349:            public Object getSingle(Object key, int count) {
0350:                if (count == 0)
0351:                    return get(key, null);
0352:                return get("*" + key + "-" + count, null);
0353:            }
0354:
0355:            public Object[] getMultiple(String key) {
0356:                int count = keyCount(key);
0357:                Object[] result = new Object[count];
0358:                for (int i = 0; i < count; i++)
0359:                    result[i] = getSingle(key, i);
0360:                return result;
0361:            }
0362:
0363:            // convenience methods for storing and loading to a file system
0364:            public void store(File f) throws IOException {
0365:                FileOutputStream fos = null;
0366:                try {
0367:                    fos = new FileOutputStream(f);
0368:                    Iterator<String> i = keySet().iterator();
0369:                    String key, value;
0370:                    while (i.hasNext()) {
0371:                        key = i.next();
0372:                        value = (String) get(key);
0373:                        fos.write((key + "=" + value + "\r\n").getBytes());
0374:                    }
0375:                    fos.flush();
0376:                } finally {
0377:                    if (fos != null)
0378:                        try {
0379:                            fos.close();
0380:                        } catch (Exception e) {
0381:                        }
0382:                }
0383:            }
0384:
0385:            public String toString() {
0386:                return super .toString();
0387:            }
0388:
0389:            /*
0390:             * example header
0391:              Connection=close
0392:              Content-Encoding=gzip
0393:              Content-Length=7281
0394:              Content-Type=text/html
0395:              Date=Mon, 05 Jan 2004 11:55:10 GMT
0396:              Server=Apache/1.3.26
0397:             */
0398:
0399:            private Date headerDate(String kind) {
0400:                if (containsKey(kind)) {
0401:                    Date parsedDate = serverDate
0402:                            .parseHTTPDate((String) get(kind));
0403:                    if (parsedDate == null)
0404:                        parsedDate = new Date();
0405:                    return parsedDate;
0406:                }
0407:                return null;
0408:            }
0409:
0410:            public String mime() {
0411:                return (String) get(httpHeader.CONTENT_TYPE,
0412:                        "application/octet-stream");
0413:            }
0414:
0415:            public String getCharacterEncoding() {
0416:                String mimeType = mime();
0417:                return extractCharsetFromMimetyeHeader(mimeType);
0418:            }
0419:
0420:            public static String extractCharsetFromMimetyeHeader(String mimeType) {
0421:                if (mimeType == null)
0422:                    return null;
0423:
0424:                String[] parts = mimeType.split(";");
0425:                if (parts == null || parts.length <= 1)
0426:                    return null;
0427:
0428:                for (int i = 1; i < parts.length; i++) {
0429:                    String param = parts[i].trim();
0430:                    if (param.startsWith("charset=")) {
0431:                        String charset = param.substring("charset=".length())
0432:                                .trim();
0433:                        if (charset.startsWith("\"") || charset.startsWith("'"))
0434:                            charset = charset.substring(1);
0435:                        if (charset.endsWith("\"") || charset.endsWith("'"))
0436:                            charset = charset
0437:                                    .substring(0, charset.length() - 1);
0438:                        return charset.trim();
0439:                    }
0440:                }
0441:
0442:                return null;
0443:            }
0444:
0445:            public Date date() {
0446:                return headerDate(httpHeader.DATE);
0447:            }
0448:
0449:            public Date expires() {
0450:                return headerDate(httpHeader.EXPIRES);
0451:            }
0452:
0453:            public Date lastModified() {
0454:                return headerDate(httpHeader.LAST_MODIFIED);
0455:            }
0456:
0457:            public Date ifModifiedSince() {
0458:                return headerDate(httpHeader.IF_MODIFIED_SINCE);
0459:            }
0460:
0461:            public Object ifRange() {
0462:                if (containsKey(httpHeader.IF_RANGE)) {
0463:                    Date rangeDate = serverDate
0464:                            .parseHTTPDate((String) get(httpHeader.IF_RANGE));
0465:                    if (rangeDate != null)
0466:                        return rangeDate;
0467:
0468:                    return get(httpHeader.IF_RANGE);
0469:                }
0470:                return null;
0471:            }
0472:
0473:            public String userAgent() {
0474:                return (String) get(USER_AGENT, "");
0475:            }
0476:
0477:            public long age() {
0478:                Date lm = lastModified();
0479:                Date sd = date();
0480:                if (lm == null)
0481:                    return Long.MAX_VALUE;
0482:                return ((sd == null) ? new Date() : sd).getTime()
0483:                        - lm.getTime();
0484:            }
0485:
0486:            public long contentLength() {
0487:                if (containsKey(httpHeader.CONTENT_LENGTH)) {
0488:                    try {
0489:                        return Long
0490:                                .parseLong((String) get(httpHeader.CONTENT_LENGTH));
0491:                    } catch (NumberFormatException e) {
0492:                        return -1;
0493:                    }
0494:                }
0495:                return -1;
0496:            }
0497:
0498:            public boolean acceptGzip() {
0499:                return ((containsKey(httpHeader.ACCEPT_ENCODING)) && (((String) get(httpHeader.ACCEPT_ENCODING))
0500:                        .toUpperCase().indexOf("GZIP")) != -1);
0501:            }
0502:
0503:            public boolean gzip() {
0504:                return ((containsKey(httpHeader.CONTENT_ENCODING)) && (((String) get(httpHeader.CONTENT_ENCODING))
0505:                        .toUpperCase().startsWith("GZIP")));
0506:            }
0507:
0508:            public static Object[] parseResponseLine(String respLine) {
0509:
0510:                if ((respLine == null) || (respLine.length() == 0)) {
0511:                    return new Object[] { "HTTP/1.0", new Integer(500),
0512:                            "status line parse error" };
0513:                }
0514:
0515:                int p = respLine.indexOf(" ");
0516:                if (p < 0) {
0517:                    return new Object[] { "HTTP/1.0", new Integer(500),
0518:                            "status line parse error" };
0519:                }
0520:
0521:                String httpVer, status, statusText;
0522:                Integer statusCode;
0523:
0524:                // the http version reported by the server
0525:                httpVer = respLine.substring(0, p);
0526:
0527:                // Status of the request, e.g. "200 OK"
0528:                status = respLine.substring(p + 1).trim(); // the status code plus reason-phrase
0529:
0530:                // splitting the status into statuscode and statustext
0531:                p = status.indexOf(" ");
0532:                try {
0533:                    statusCode = Integer.valueOf((p < 0) ? status.trim()
0534:                            : status.substring(0, p).trim());
0535:                    statusText = (p < 0) ? "" : status.substring(p + 1).trim();
0536:                } catch (Exception e) {
0537:                    statusCode = new Integer(500);
0538:                    statusText = status;
0539:                }
0540:
0541:                return new Object[] { httpVer, statusCode, statusText };
0542:            }
0543:
0544:            public static Properties parseRequestLine(String s,
0545:                    Properties prop, String virtualHost) {
0546:                int p = s.indexOf(" ");
0547:                if (p >= 0) {
0548:                    String cmd = s.substring(0, p);
0549:                    String args = s.substring(p + 1);
0550:                    return parseRequestLine(cmd, args, prop, virtualHost);
0551:                }
0552:                return prop;
0553:            }
0554:
0555:            public static Properties parseRequestLine(String cmd, String args,
0556:                    Properties prop, String virtualHost) {
0557:
0558:                // getting the last request line for debugging purposes
0559:                String prevRequestLine = prop
0560:                        .containsKey(CONNECTION_PROP_REQUESTLINE) ? prop
0561:                        .getProperty(CONNECTION_PROP_REQUESTLINE) : "";
0562:
0563:                // reset property from previous run   
0564:                prop.clear();
0565:
0566:                // storing informations about the request
0567:                prop.setProperty(CONNECTION_PROP_METHOD, cmd);
0568:                prop.setProperty(CONNECTION_PROP_REQUESTLINE, cmd + " " + args);
0569:                prop.setProperty(CONNECTION_PROP_PREV_REQUESTLINE,
0570:                        prevRequestLine);
0571:
0572:                // this parses a whole URL
0573:                if (args.length() == 0) {
0574:                    prop.setProperty(CONNECTION_PROP_HOST, virtualHost);
0575:                    prop.setProperty(CONNECTION_PROP_PATH, "/");
0576:                    prop
0577:                            .setProperty(CONNECTION_PROP_HTTP_VER,
0578:                                    HTTP_VERSION_0_9);
0579:                    prop.setProperty(CONNECTION_PROP_EXT, "");
0580:                    return prop;
0581:                }
0582:
0583:                // store the version propery "HTTP" and cut the query at both ends
0584:                int sep = args.lastIndexOf(" ");
0585:                if ((sep >= 0)
0586:                        && (args.substring(sep + 1).toLowerCase()
0587:                                .startsWith("http/"))) {
0588:                    // HTTP version is given
0589:                    prop.setProperty(CONNECTION_PROP_HTTP_VER, args.substring(
0590:                            sep + 1).trim());
0591:                    args = args.substring(0, sep).trim(); // cut off HTTP version mark
0592:                } else {
0593:                    // HTTP version is not given, it will be treated as ver 0.9
0594:                    prop
0595:                            .setProperty(CONNECTION_PROP_HTTP_VER,
0596:                                    HTTP_VERSION_0_9);
0597:                }
0598:
0599:                // replacing spaces in the url string correctly
0600:                args = args.replaceAll(" ", "%20");
0601:
0602:                // properties of the query are stored with the prefix "&"
0603:                // additionally, the values URL and ARGC are computed
0604:
0605:                String argsString = "";
0606:                sep = args.indexOf("?");
0607:                if (sep >= 0) {
0608:                    // there are values attached to the query string
0609:                    argsString = args.substring(sep + 1); // cut head from tail of query
0610:                    args = args.substring(0, sep);
0611:                }
0612:                prop.setProperty(CONNECTION_PROP_URL, args); // store URL
0613:                //System.out.println("HTTPD: ARGS=" + argsString);
0614:                if (argsString.length() != 0)
0615:                    prop.setProperty(CONNECTION_PROP_ARGS, argsString); // store arguments in original form
0616:
0617:                // finally find host string
0618:                String path;
0619:                if (args.toUpperCase().startsWith("HTTP://")) {
0620:                    // a host was given. extract it and set path
0621:                    args = args.substring(7);
0622:                    sep = args.indexOf("/");
0623:                    if (sep < 0) {
0624:                        // this is a malformed url, something like
0625:                        // http://index.html
0626:                        // we are lazy and guess that it means
0627:                        // /index.html
0628:                        // which is a localhost access to the file servlet
0629:                        prop.setProperty(CONNECTION_PROP_HOST, args);
0630:                        path = "/";
0631:                    } else {
0632:                        // THIS IS THE "GOOD" CASE
0633:                        // a perfect formulated url
0634:                        String dstHostSocket = args.substring(0, sep);
0635:                        prop.setProperty(CONNECTION_PROP_HOST, (httpd
0636:                                .isThisHostName(dstHostSocket) ? virtualHost
0637:                                : dstHostSocket));
0638:                        path = args.substring(sep); // yes, including beginning "/"
0639:                    }
0640:                } else {
0641:                    // no host in url. set path
0642:                    if (args.startsWith("/")) {
0643:                        // thats also fine, its a perfect localhost access
0644:                        // in this case, we simulate a
0645:                        // http://localhost/s
0646:                        // access by setting a virtual host
0647:                        prop.setProperty(CONNECTION_PROP_HOST, virtualHost);
0648:                        path = args;
0649:                    } else {
0650:                        // the client 'forgot' to set a leading '/'
0651:                        // this is the same case as above, with some lazyness
0652:                        prop.setProperty(CONNECTION_PROP_HOST, virtualHost);
0653:                        path = "/" + args;
0654:                    }
0655:                }
0656:                prop.setProperty(CONNECTION_PROP_PATH, path);
0657:
0658:                // find out file extension (we already stripped ?-parameters from args)
0659:                String ext = ""; // default when no file extension
0660:                sep = path.lastIndexOf(".");
0661:                if (sep >= 0) {
0662:                    int ancpos = path.indexOf("#", sep + 1);
0663:                    if (ancpos >= sep) {
0664:                        // ex: /foo/bar.html#xy => html
0665:                        ext = path.substring(sep + 1, ancpos).toLowerCase();
0666:                    } else {
0667:                        // ex: /foo/bar.php => php
0668:                        ext = path.substring(sep + 1).toLowerCase();
0669:                    }
0670:                }
0671:                prop.setProperty(CONNECTION_PROP_EXT, ext);
0672:
0673:                return prop;
0674:            }
0675:
0676:            public static boolean supportChunkedEncoding(Properties conProp) {
0677:                // getting the http version of the client
0678:                String httpVer = conProp.getProperty(CONNECTION_PROP_HTTP_VER);
0679:
0680:                // only clients with http version 1.1 supports chunk
0681:                return !(httpVer.equals(HTTP_VERSION_0_9) || httpVer
0682:                        .equals(HTTP_VERSION_1_0));
0683:            }
0684:
0685:            /**
0686:             * Reading http headers from a reader class and building up a httpHeader object
0687:             * @param reader the {@link BufferedReader} that is used to read the http header lines
0688:             * @return a {@link httpHeader}-Object containing all parsed headers
0689:             * @throws IOException
0690:             */
0691:            public static httpHeader readHttpHeader(BufferedReader reader)
0692:                    throws IOException {
0693:                // reading all request headers
0694:                httpHeader httpHeader = new httpHeader(
0695:                        httpd.reverseMappingCache);
0696:                int p;
0697:                String line;
0698:                while ((line = reader.readLine()) != null) {
0699:                    if (line.length() == 0)
0700:                        break;
0701:                    if ((p = line.indexOf(":")) >= 0) {
0702:                        // store a property
0703:                        httpHeader.add(line.substring(0, p).trim(), line
0704:                                .substring(p + 1).trim());
0705:                    }
0706:                }
0707:                return httpHeader;
0708:            }
0709:
0710:            public static httpHeader readHeader(Properties prop,
0711:                    serverCore.Session theSession) throws IOException {
0712:
0713:                // reading all headers
0714:                httpHeader header = new httpHeader(httpd.reverseMappingCache);
0715:                int p;
0716:                String line;
0717:                while ((line = theSession.readLineAsString()) != null) {
0718:                    if (line.length() == 0)
0719:                        break; // this seperates the header of the HTTP request from the body
0720:                    // parse the header line: a property seperated with the ':' sign
0721:                    if ((p = line.indexOf(":")) >= 0) {
0722:                        // store a property
0723:                        header.add(line.substring(0, p).trim(), line.substring(
0724:                                p + 1).trim());
0725:                    }
0726:                }
0727:
0728:                /* 
0729:                 * doing some header validation here ...
0730:                 */
0731:                String httpVersion = prop.getProperty(
0732:                        httpHeader.CONNECTION_PROP_HTTP_VER, "HTTP/0.9");
0733:                if (httpVersion.equals("HTTP/1.1")
0734:                        && !header.containsKey(httpHeader.HOST)) {
0735:                    // the HTTP/1.1 specification requires that an HTTP/1.1 server must reject any  
0736:                    // HTTP/1.1 message that does not contain a Host header.            
0737:                    httpd.sendRespondError(prop, theSession.out, 0, 400, null,
0738:                            null, null);
0739:                    throw new IOException("400 Bad request");
0740:                }
0741:
0742:                return header;
0743:            }
0744:
0745:            public StringBuffer toHeaderString(String httpVersion,
0746:                    int httpStatusCode, String httpStatusText) {
0747:                // creating a new buffer to store the header as string
0748:                StringBuffer theHeader = new StringBuffer();
0749:
0750:                // generating the header string
0751:                this .toHeaderString(httpVersion, httpStatusCode,
0752:                        httpStatusText, theHeader);
0753:
0754:                // returning the result
0755:                return theHeader;
0756:            }
0757:
0758:            public void toHeaderString(String httpVersion, int httpStatusCode,
0759:                    String httpStatusText, StringBuffer theHeader) {
0760:
0761:                if (theHeader == null)
0762:                    throw new IllegalArgumentException();
0763:
0764:                // setting the http version if it was not already set
0765:                if (httpVersion == null)
0766:                    httpVersion = "HTTP/1.0";
0767:
0768:                // setting the status text if it was not already set
0769:                if ((httpStatusText == null) || (httpStatusText.length() == 0)) {
0770:                    if (httpVersion.equals("HTTP/1.0")
0771:                            && httpHeader.http1_0.containsKey(Integer
0772:                                    .toString(httpStatusCode)))
0773:                        httpStatusText = httpHeader.http1_0.get(Integer
0774:                                .toString(httpStatusCode));
0775:                    else if (httpVersion.equals("HTTP/1.1")
0776:                            && httpHeader.http1_1.containsKey(Integer
0777:                                    .toString(httpStatusCode)))
0778:                        httpStatusText = httpHeader.http1_1.get(Integer
0779:                                .toString(httpStatusCode));
0780:                    else
0781:                        httpStatusText = "Unknown";
0782:                }
0783:
0784:                // write status line
0785:                theHeader.append(httpVersion).append(" ").append(
0786:                        Integer.toString(httpStatusCode)).append(" ").append(
0787:                        httpStatusText).append("\r\n");
0788:
0789:                // write header
0790:                Iterator<String> i = keySet().iterator();
0791:                String key;
0792:                char tag;
0793:                int count;
0794:                while (i.hasNext()) {
0795:                    key = i.next();
0796:                    tag = key.charAt(0);
0797:                    if ((tag != '*') && (tag != '#')) { // '#' in key is reserved for proxy attributes as artificial header values
0798:                        count = keyCount(key);
0799:                        for (int j = 0; j < count; j++) {
0800:                            theHeader.append(key).append(": ").append(
0801:                                    (String) getSingle(key, j)).append("\r\n");
0802:                        }
0803:                    }
0804:                }
0805:                // end header
0806:                theHeader.append("\r\n");
0807:            }
0808:
0809:            public static yacyURL getRequestURL(Properties conProp)
0810:                    throws MalformedURLException {
0811:                String host = conProp
0812:                        .getProperty(httpHeader.CONNECTION_PROP_HOST);
0813:                String path = conProp
0814:                        .getProperty(httpHeader.CONNECTION_PROP_PATH); // always starts with leading '/'
0815:                String args = conProp
0816:                        .getProperty(httpHeader.CONNECTION_PROP_ARGS); // may be null if no args were given
0817:                //String ip =      conProp.getProperty(httpHeader.CONNECTION_PROP_CLIENTIP); // the ip from the connecting peer
0818:
0819:                int port, pos;
0820:                if ((pos = host.indexOf(":")) < 0) {
0821:                    port = 80;
0822:                } else {
0823:                    port = Integer.parseInt(host.substring(pos + 1));
0824:                    host = host.substring(0, pos);
0825:                }
0826:
0827:                yacyURL url = new yacyURL("http", host, port,
0828:                        (args == null) ? path : path + "?" + args);
0829:                return url;
0830:            }
0831:
0832:            public static void handleTransparentProxySupport(httpHeader header,
0833:                    Properties prop, String virtualHost,
0834:                    boolean isTransparentProxy) {
0835:                // transparent proxy support is only available for http 1.0 and above connections
0836:                if (prop.getProperty(CONNECTION_PROP_HTTP_VER, "HTTP/0.9")
0837:                        .equals("HTTP/0.9"))
0838:                    return;
0839:
0840:                // if the transparent proxy support was disabled, we have nothing todo here ...
0841:                if (!(isTransparentProxy && header.containsKey(HOST)))
0842:                    return;
0843:
0844:                // we only need to do the transparent proxy support if the request URL didn't contain the hostname
0845:                // and therefor was set to virtualHost by function parseQuery()
0846:                if (!prop.getProperty(CONNECTION_PROP_HOST).equals(virtualHost))
0847:                    return;
0848:
0849:                // TODO: we could have problems with connections from extern here ...
0850:                String dstHostSocket = (String) header.get(httpHeader.HOST);
0851:                prop.setProperty(CONNECTION_PROP_HOST, (httpd
0852:                        .isThisHostName(dstHostSocket) ? virtualHost
0853:                        : dstHostSocket));
0854:            }
0855:
0856:            /*
0857:             * Patch BEGIN:
0858:             * Name: Header Property Patch
0859:             * Date: Fri. 13.01.2006
0860:             * Description: Makes possible to send header properties such as cookies back to the client.
0861:             * Part 1 of 5
0862:             * Questions: sergej.z@list.ru
0863:             */
0864:            /**
0865:             * Holds header properties
0866:             */
0867:            //Since properties such as cookies can be multiple, we cannot use HashMap here. We have to use Vector.
0868:            private Vector<Entry> cookies = new Vector<Entry>();
0869:
0870:            /**
0871:             * Implementation of Map.Entry. Structure that hold two values - exactly what we need!
0872:             */
0873:            class Entry implements  Map.Entry<String, Object> {
0874:                private String k;
0875:                private Object v;
0876:
0877:                Entry(String k, Object v) {
0878:                    this .k = k;
0879:                    this .v = v;
0880:                }
0881:
0882:                public String getKey() {
0883:                    return k;
0884:                }
0885:
0886:                public Object getValue() {
0887:                    return v;
0888:                }
0889:
0890:                public Object setValue(Object v) {
0891:                    Object r = this .v;
0892:                    this .v = v;
0893:                    return r;
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Sets Cookie on the client machine.
0899:             *
0900:             * @param name Cookie name
0901:             * @param value Cookie value
0902:             * @param expires when should this cookie be autmatically deleted. If <b>null</b> - cookie will stay forever
0903:             * @param path Path the cookie belongs to. Default - "/". Can be <b>null</b>.
0904:             * @param domain Domain this cookie belongs to. Default - domain name. Can be <b>null</b>.
0905:             * @param secure If true cookie will be send only over safe connection such as https
0906:             * @see further documentation: <a href="http://docs.sun.com/source/816-6408-10/cookies.htm">docs.sun.com</a>
0907:             */
0908:            public void setCookie(String name, String value, String expires,
0909:                    String path, String domain, boolean secure) {
0910:                /*
0911:                 * TODO:Here every value can be validated for correctness if needed
0912:                 * For example semicolon should be not in any of the values
0913:                 * However an exception in this case would be an overhead IMHO.
0914:                 */
0915:                String cookieString = name + "=" + value + ";";
0916:                if (expires != null)
0917:                    cookieString += " expires=" + expires + ";";
0918:                if (path != null)
0919:                    cookieString += " path=" + path + ";";
0920:                if (domain != null)
0921:                    cookieString += " domain=" + domain + ";";
0922:                if (secure)
0923:                    cookieString += " secure;";
0924:                cookies.add(new Entry("Set-Cookie", cookieString));
0925:            }
0926:
0927:            /**
0928:             * Sets Cookie on the client machine.
0929:             *
0930:             * @param name Cookie name
0931:             * @param value Cookie value
0932:             * @param expires when should this cookie be autmatically deleted. If <b>null</b> - cookie will stay forever
0933:             * @param path Path the cookie belongs to. Default - "/". Can be <b>null</b>.
0934:             * @param domain Domain this cookie belongs to. Default - domain name. Can be <b>null</b>.
0935:             *
0936:             * Note: this cookie will be sent over each connection independend if it is safe connection or not.
0937:             * @see further documentation: <a href="http://docs.sun.com/source/816-6408-10/cookies.htm">docs.sun.com</a>
0938:             */
0939:            public void setCookie(String name, String value, String expires,
0940:                    String path, String domain) {
0941:                setCookie(name, value, expires, path, domain, false);
0942:            }
0943:
0944:            /**
0945:             * Sets Cookie on the client machine.
0946:             *
0947:             * @param name Cookie name
0948:             * @param value Cookie value
0949:             * @param expires when should this cookie be autmatically deleted. If <b>null</b> - cookie will stay forever
0950:             * @param path Path the cookie belongs to. Default - "/". Can be <b>null</b>.
0951:             *
0952:             * Note: this cookie will be sent over each connection independend if it is safe connection or not.
0953:             * @see further documentation: <a href="http://docs.sun.com/source/816-6408-10/cookies.htm">docs.sun.com</a>
0954:             */
0955:            public void setCookie(String name, String value, String expires,
0956:                    String path) {
0957:                setCookie(name, value, expires, path, null, false);
0958:            }
0959:
0960:            /**
0961:             * Sets Cookie on the client machine.
0962:             *
0963:             * @param name Cookie name
0964:             * @param value Cookie value
0965:             * @param expires when should this cookie be autmatically deleted. If <b>null</b> - cookie will stay forever
0966:             *
0967:             * Note: this cookie will be sent over each connection independend if it is safe connection or not.
0968:             * @see further documentation: <a href="http://docs.sun.com/source/816-6408-10/cookies.htm">docs.sun.com</a>
0969:             */
0970:            public void setCookie(String name, String value, String expires) {
0971:                setCookie(name, value, expires, null, null, false);
0972:            }
0973:
0974:            /**
0975:             * Sets Cookie on the client machine.
0976:             *
0977:             * @param name Cookie name
0978:             * @param value Cookie value
0979:             *
0980:             * Note: this cookie will be sent over each connection independend if it is safe connection or not. This cookie never expires
0981:             * @see further documentation: <a href="http://docs.sun.com/source/816-6408-10/cookies.htm">docs.sun.com</a>
0982:             */
0983:            public void setCookie(String name, String value) {
0984:                setCookie(name, value, null, null, null, false);
0985:            }
0986:
0987:            public String getHeaderCookies() {
0988:                Iterator<Map.Entry<String, String>> it = this .entrySet()
0989:                        .iterator();
0990:                while (it.hasNext()) {
0991:                    Map.Entry<String, String> e = it.next();
0992:                    //System.out.println(""+e.getKey()+" : "+e.getValue());
0993:                    if (e.getKey().equals("Cookie")) {
0994:                        return e.getValue().toString();
0995:                    }
0996:                }
0997:                return "";
0998:            }
0999:
1000:            public Vector<Entry> getCookieVector() {
1001:                return cookies;
1002:            }
1003:
1004:            public void setCookieVector(Vector<Entry> mycookies) {
1005:                cookies = mycookies;
1006:            }
1007:
1008:            /**
1009:             * Returns an iterator within all properties can be reached.
1010:             * Is used mainly by httpd.
1011:             *
1012:             * <p>Example:</p>
1013:             * <pre>
1014:             * Iterator it=serverObjects.getRequestProperties();
1015:             * while(it.hasNext())
1016:             * {
1017:             *  java.util.Map.Entry e=(java.util.Map.Entry)it.next();
1018:             *  String propertyName=e.getKey();
1019:             *  String propertyValue=e.getValue();
1020:             * }</pre>
1021:             * @return iterator to read all request properties.
1022:             */
1023:            public Iterator<Entry> getCookies() {
1024:                return cookies.iterator();
1025:            }
1026:            /*
1027:             * Patch END:
1028:             * Name: Header Property Patch
1029:             */
1030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.