Source Code Cross Referenced for ServletManager.java in  » J2EE » Pustefix » de » schlund » pfixxml » 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 » J2EE » Pustefix » de.schlund.pfixxml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file is part of PFIXCORE.
0003:         *
0004:         * PFIXCORE is free software; you can redistribute it and/or modify
0005:         * it under the terms of the GNU Lesser General Public License as published by
0006:         * the Free Software Foundation; either version 2 of the License, or
0007:         * (at your option) any later version.
0008:         *
0009:         * PFIXCORE is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012:         * GNU Lesser General Public License for more details.
0013:         *
0014:         * You should have received a copy of the GNU Lesser General Public License
0015:         * along with PFIXCORE; if not, write to the Free Software
0016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:         *
0018:         */
0019:
0020:        package de.schlund.pfixxml;
0021:
0022:        import java.io.FileNotFoundException;
0023:        import java.io.IOException;
0024:        import java.nio.charset.Charset;
0025:        import java.text.NumberFormat;
0026:        import java.text.SimpleDateFormat;
0027:        import java.util.Date;
0028:        import java.util.Enumeration;
0029:        import java.util.HashMap;
0030:        import java.util.Iterator;
0031:        import java.util.LinkedList;
0032:        import java.util.Map;
0033:        import java.util.Properties;
0034:        import java.util.TreeSet;
0035:        import java.util.concurrent.atomic.AtomicInteger;
0036:
0037:        import javax.servlet.ServletConfig;
0038:        import javax.servlet.ServletContext;
0039:        import javax.servlet.ServletException;
0040:        import javax.servlet.http.Cookie;
0041:        import javax.servlet.http.HttpServlet;
0042:        import javax.servlet.http.HttpServletRequest;
0043:        import javax.servlet.http.HttpServletResponse;
0044:        import javax.servlet.http.HttpSession;
0045:
0046:        import org.apache.log4j.Logger;
0047:        import org.xml.sax.SAXException;
0048:
0049:        import de.schlund.pfixxml.config.ServletManagerConfig;
0050:        import de.schlund.pfixxml.config.XMLPropertiesUtil;
0051:        import de.schlund.pfixxml.exceptionprocessor.ExceptionConfig;
0052:        import de.schlund.pfixxml.exceptionprocessor.ExceptionProcessor;
0053:        import de.schlund.pfixxml.perflogging.PerfEvent;
0054:        import de.schlund.pfixxml.perflogging.PerfEventType;
0055:        import de.schlund.pfixxml.resources.FileResource;
0056:        import de.schlund.pfixxml.resources.ResourceUtil;
0057:        import de.schlund.pfixxml.serverutil.SessionAdmin;
0058:        import de.schlund.pfixxml.serverutil.SessionHelper;
0059:        import de.schlund.pfixxml.serverutil.SessionInfoStruct;
0060:        import de.schlund.pfixxml.serverutil.SessionInfoStruct.TrailElement;
0061:        import de.schlund.pfixxml.util.MD5Utils;
0062:
0063:        /**
0064:         * ServletManager.java
0065:         *
0066:         *
0067:         * Created: Wed May  8 16:39:06 2002
0068:         *
0069:         * @author <a href="mailto:jtl@schlund.de">Jens Lautenbacher</a>
0070:         */
0071:
0072:        public abstract class ServletManager extends HttpServlet {
0073:            public static final String VISIT_ID = "__VISIT_ID__";
0074:            public static final String PROP_LOADINDEX = "__PROPERTIES_LOAD_INDEX";
0075:            private static final String STORED_REQUEST = "__STORED_PFIXSERVLETREQUEST__";
0076:            private static final String SECURE_SESS_COOKIE = "__PFIX_SEC_";
0077:            private static final String TEST_COOKIE = "__PFIX_TST_";
0078:            private static final String SESSION_COOKIES_MARKER = "__COOKIES_USED_DURING_SESSION__";
0079:            private static final String REFUSE_COOKIES = "__REFUSE_COOKIES__";
0080:            private static final String RAND_SESS_COOKIE_VALUE = "__RAND_SESS_COOKIE_VALUE__";
0081:            private static final String CHECK_FOR_RUNNING_SSL_SESSION = "__CHECK_FOR_RUNNING_SSL_SESSION__";
0082:            private static final String PARAM_FORCELOCAL = "__forcelocal";
0083:            public static final String PROP_COOKIE_SEC_NOT_ENFORCED = "servletmanager.cookie_security_not_enforced";
0084:            public static final String PROP_P3PHEADER = "servletmanager.p3p";
0085:            private static final String PROP_EXCEPTION = "exception";
0086:            public static final String PROP_SSL_REDIRECT_PORT = "pfixcore.ssl_redirect_port.for.";
0087:            protected static final String DEF_CONTENT_TYPE = "text/html";
0088:            private static final String DEFAULT_ENCODING = "UTF-8";
0089:            private static final String SERVLET_ENCODING = "servlet.encoding";
0090:            private static final int MAX_PARALLEL_SEC_SESSIONS = 10;
0091:            private static String TIMESTAMP_ID = "";
0092:            private static int INC_ID = 0;
0093:            private boolean cookie_security_not_enforced = false;
0094:            private Logger LOGGER_VISIT = Logger.getLogger("LOGGER_VISIT");
0095:            private Logger LOG = Logger.getLogger(ServletManager.class);
0096:            private Map<Class<? extends Throwable>, ExceptionConfig> exceptionConfigs = new HashMap<Class<? extends Throwable>, ExceptionConfig>();
0097:            private long common_mtime = -2;
0098:            private long servlet_mtime = -2;
0099:            private FileResource commonpropfile;
0100:            private FileResource servletpropfile;
0101:            private String servletEncoding;
0102:            private AtomicInteger configLoadIndex = new AtomicInteger(0);
0103:
0104:            protected abstract ServletManagerConfig getServletManagerConfig();
0105:
0106:            protected abstract void reloadServletConfig(
0107:                    FileResource configFile, Properties globalProperties)
0108:                    throws ServletException;
0109:
0110:            protected boolean runningUnderSSL(HttpServletRequest req) {
0111:                return req.isSecure();
0112:            }
0113:
0114:            protected boolean needsSSL(PfixServletRequest preq)
0115:                    throws ServletException {
0116:                return this .getServletManagerConfig().isSSL();
0117:            }
0118:
0119:            abstract protected boolean needsSession();
0120:
0121:            abstract protected boolean allowSessionCreate();
0122:
0123:            public static String getServerName(HttpServletRequest req) {
0124:                String forward = req.getHeader("X-Forwarded-Server");
0125:                if (forward != null && !forward.equals("")) {
0126:                    return forward;
0127:                } else {
0128:                    return req.getServerName();
0129:                }
0130:            }
0131:
0132:            protected void relocate(HttpServletResponse res, String reloc_url) {
0133:                LOG.debug("\n\n        ======> relocating to " + reloc_url
0134:                        + "\n");
0135:                res.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
0136:                res.setHeader("Pragma", "no-cache");
0137:                res.setHeader("Cache-Control",
0138:                        "no-cache, no-store, private, must-revalidate");
0139:                res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
0140:                res.setHeader("Location", reloc_url);
0141:            }
0142:
0143:            public void doPost(HttpServletRequest req, HttpServletResponse res)
0144:                    throws ServletException, IOException {
0145:                doGet(req, res);
0146:            }
0147:
0148:            public void doGet(HttpServletRequest req, HttpServletResponse res)
0149:                    throws ServletException, IOException {
0150:                req.setCharacterEncoding(servletEncoding);
0151:                res.setCharacterEncoding(servletEncoding);
0152:                if (LOG.isDebugEnabled()) {
0153:                    LOG
0154:                            .debug("\n ------------------- Start of new Request ---------------");
0155:                    LOG.debug("====> Scheme://Server:Port " + req.getScheme()
0156:                            + "://" + getServerName(req) + ":"
0157:                            + req.getServerPort());
0158:                    LOG.debug("====> URI:   " + req.getRequestURI());
0159:                    LOG.debug("====> Query: " + req.getQueryString());
0160:                    LOG.debug("----> needsSession=" + needsSession()
0161:                            + " allowSessionCreate=" + allowSessionCreate());
0162:                    LOG.debug("====> Sessions: "
0163:                            + SessionAdmin.getInstance().toString());
0164:                    LOG.debug("\n");
0165:
0166:                    Enumeration<?> headers = req.getHeaderNames();
0167:
0168:                    while (headers.hasMoreElements()) {
0169:                        String header = (String) headers.nextElement();
0170:                        String headerval = req.getHeader(header);
0171:                        LOG.debug("+++ Header: " + header + " -> " + headerval);
0172:                    }
0173:
0174:                }
0175:
0176:                HttpSession session = null;
0177:                boolean has_session = false;
0178:                boolean has_ssl_session_insecure = false;
0179:                boolean has_ssl_session_secure = false;
0180:                boolean force_jump_back_to_ssl = false;
0181:                boolean force_reuse_visit_id = false;
0182:                String mark_session_as_no_cookies = null;
0183:                boolean does_cookies = false;
0184:                boolean refuse_cookies = false;
0185:
0186:                // Set P3P-Header if needed to make sure it is 
0187:                // set for every response (even redirects).
0188:                String p3pHeader = getServletManagerConfig().getProperties()
0189:                        .getProperty(PROP_P3PHEADER);
0190:                if (p3pHeader != null && p3pHeader.length() > 0) {
0191:                    res.addHeader("P3P", p3pHeader);
0192:                }
0193:
0194:                // Delete JSESSIONID cookie
0195:                // Otherwise a redirect loop will be caused when a request with an
0196:                // invalid JSESSIONID cookie is made
0197:                if (req.getCookies() != null) {
0198:                    Cookie[] cookies = req.getCookies();
0199:                    for (int i = 0; i < cookies.length; i++) {
0200:                        Cookie cookie = cookies[i];
0201:                        if (cookie.getName().equalsIgnoreCase("JSESSIONID")) {
0202:                            cookie.setMaxAge(0);
0203:                            cookie
0204:                                    .setPath((req.getContextPath().equals("")) ? "/"
0205:                                            : req.getContextPath());
0206:                            res.addCookie(cookie);
0207:                        }
0208:                    }
0209:                }
0210:
0211:                if (req.isRequestedSessionIdValid()) {
0212:                    session = req.getSession(false);
0213:                    has_session = true;
0214:                    LOG.debug("*** Found valid session with ID "
0215:                            + session.getId());
0216:
0217:                    // Much of the advanced security depends on having cookies enabled.  We need to make
0218:                    // sure that this isn't defeated by just disabling cookies.  So we mark every session
0219:                    // whenever the client has cookies enabled, and don't allow further uses of this session
0220:                    // without cookies. BUT: having a valid session that has the attribute
0221:                    // __REFUSE_COOKIES__ set, will be considered as not doing cookies at all. See
0222:                    // below where mark_session_as_no_cookies is set for the reason behind this.
0223:                    Boolean refuse_param = (Boolean) session
0224:                            .getAttribute(REFUSE_COOKIES);
0225:                    if (refuse_param != null && refuse_param.booleanValue()) {
0226:                        does_cookies = false;
0227:                        refuse_cookies = true;
0228:                    } else {
0229:                        refuse_cookies = false;
0230:                        does_cookies = doCookieTest(req, res, session);
0231:                    }
0232:                    Boolean secure = (Boolean) session
0233:                            .getAttribute(SessionAdmin.SESSION_IS_SECURE);
0234:
0235:                    if (!does_cookies && !refuse_cookies) {
0236:                        LOG.debug("*** Client doesn't use cookies...");
0237:                        // We still need to check if the session itself thinks differently -
0238:                        // this happens e.g. when cookies are disabled in the middle of the session.
0239:                        Boolean need_cookies = (Boolean) session
0240:                                .getAttribute(SESSION_COOKIES_MARKER);
0241:                        if (need_cookies != null && need_cookies.booleanValue()) {
0242:                            if (cookie_security_not_enforced) {
0243:                                LOG
0244:                                        .debug("    ... during the session cookies were ENABLED, "
0245:                                                + "but will continue because of cookie_security_not_enforced "
0246:                                                + session.getId());
0247:                            } else {
0248:                                LOG
0249:                                        .debug("    ... but during the session cookies were already ENABLED: "
0250:                                                + "Will invalidate the session "
0251:                                                + session.getId());
0252:                                session.invalidate();
0253:                                has_session = false;
0254:                            }
0255:                        } else {
0256:                            LOG
0257:                                    .debug("    ... and during the session cookies were DISABLED, too: Let's hope everything is OK...");
0258:                        }
0259:                    } else if (!does_cookies && refuse_cookies) {
0260:                        LOG.debug("*** Session REFUSES to use cookies!");
0261:                        LOG
0262:                                .debug("    Client may send cookies, but session refuses to handle them.");
0263:                    } else {
0264:                        LOG.debug("*** Client uses cookies.");
0265:                    }
0266:                    if (has_session) {
0267:                        if (runningUnderSSL(req)) {
0268:                            LOG.debug("*** Found running under SSL");
0269:                            if (secure != null && secure.booleanValue()) {
0270:                                LOG.debug("    ... and session is secure.");
0271:                                if (does_cookies) {
0272:                                    LOG
0273:                                            .debug("*** Client does cookies: Double checking SSL cookie for session ID");
0274:                                    String sec_testid = (String) session
0275:                                            .getAttribute(SECURE_SESS_COOKIE
0276:                                                    + MD5Utils.hex_md5(session
0277:                                                            .getId()));
0278:                                    LOG
0279:                                            .debug("*** Session expects to see the cookie value "
0280:                                                    + sec_testid);
0281:                                    Cookie cookie = getSecureSessionCookie(req,
0282:                                            session.getId());
0283:                                    cleanupCookies(req, res, cookie);
0284:                                    if (cookie != null) {
0285:                                        LOG
0286:                                                .debug("*** Found a matching cookie ...");
0287:                                        String tmp = cookie.getValue();
0288:                                        String tmp_sec = tmp.substring(tmp
0289:                                                .indexOf(":") + 1);
0290:                                        if (tmp_sec.equals(sec_testid)) {
0291:                                            LOG
0292:                                                    .debug("   ... and the value is correct! ("
0293:                                                            + tmp_sec + ")");
0294:                                            has_ssl_session_secure = true;
0295:                                            Cookie cookie_new = new Cookie(
0296:                                                    cookie.getName(),
0297:                                                    System.currentTimeMillis()
0298:                                                            + ":" + tmp_sec);
0299:                                            setCookiePath(req, cookie_new);
0300:                                            // FIXME (see comment in cleanupCookies
0301:                                            // cookie_new.setMaxAge(session.getMaxInactiveInterval());
0302:                                            cookie_new.setMaxAge(-1);
0303:                                            cookie_new.setSecure(true);
0304:                                            res.addCookie(cookie_new);
0305:                                        } else {
0306:                                            LOG
0307:                                                    .debug("   ... but the value is WRONG!");
0308:                                            LOG
0309:                                                    .error("*** Wrong Session-ID for running secure session from cookie. "
0310:                                                            + "IP:"
0311:                                                            + req
0312:                                                                    .getRemoteAddr()
0313:                                                            + " Cookie: "
0314:                                                            + cookie.getValue()
0315:                                                            + " SessID: "
0316:                                                            + session.getId());
0317:                                            session.invalidate();
0318:                                            has_session = false;
0319:                                        }
0320:                                    } else {
0321:                                        LOG
0322:                                                .debug("*** Found NO matching cookie at all, but client does cookies: ***");
0323:                                        LOG
0324:                                                .error("*** NOSECSESSIDFROMCOOKIE: "
0325:                                                        + req.getRemoteAddr()
0326:                                                        + "|"
0327:                                                        + session.getId()
0328:                                                        + "|"
0329:                                                        + req
0330:                                                                .getHeader("User-Agent")
0331:                                                        + "|"
0332:                                                        + req
0333:                                                                .getHeader("Cookie"));
0334:                                        // Most time when this happens, we are not under attack, but one of
0335:                                        // two things happened: a) a stupid behaviour (bug?)  of IE or opera
0336:                                        // strikes us bad: With these two browsers, if we accept the
0337:                                        // __PFIX_TST_* cookie, but then deny the __PFIX_SEC_* cookie AND
0338:                                        // also deny for all further cookies from the domain, the stupid
0339:                                        // browser will still continue to send the __PFIX_TST_* cookie, so
0340:                                        // we will continue to come into this branch over and over
0341:                                        // again... or b) We simply have stored too many cookies for the
0342:                                        // secure cookie to be send by the client. So we try to mark the now
0343:                                        // created session to decide in the following requests that this
0344:                                        // session does NOT use cookies at all, despite what ever the
0345:                                        // __PFIX_TST_* cookie says.  Basically we completely switch off
0346:                                        // cookie handling for this new session.
0347:                                        mark_session_as_no_cookies = (String) session
0348:                                                .getAttribute(VISIT_ID);
0349:                                        session.invalidate();
0350:                                        has_session = false;
0351:                                    }
0352:                                } else {
0353:                                    // We don't do cookies, so we simply have to believe it...
0354:                                    has_ssl_session_secure = true;
0355:                                }
0356:                            } else {
0357:                                LOG.debug("    ... but session is insecure!");
0358:                                has_ssl_session_insecure = true;
0359:                            }
0360:                        } else if (secure != null && secure.booleanValue()) {
0361:                            LOG
0362:                                    .debug("*** Found secure session but NOT running under SSL => Destroying session.");
0363:                            session.invalidate();
0364:                            has_session = false;
0365:                        }
0366:                    }
0367:                } else if (req.getRequestedSessionId() != null) {
0368:                    LOG.debug("*** Found old and invalid session in request");
0369:                    // We have no valid session, but the request contained an invalid session id.
0370:                    // case a) This may be an invalid id because we invalidated the session when jumping
0371:                    // into the secure SSL session (see redirectToSecureSSLSession below). by using the back button
0372:                    // of the browser, the user may have come back to a (non-ssl) page (in his browser history) that contains
0373:                    // links with the old "parent" session id embedded. We need to check for this and create a
0374:                    // new session but reuse the visit id of the currently running SSL session.
0375:                    if (!runningUnderSSL(req)
0376:                            && SessionAdmin.getInstance().idWasParentSession(
0377:                                    req.getRequestedSessionId())) {
0378:                        LOG
0379:                                .debug("    ... but this session was the parent of a currently running secure session.");
0380:                        HttpSession secure_session = SessionAdmin.getInstance()
0381:                                .getChildSessionForParentId(
0382:                                        req.getRequestedSessionId());
0383:                        if (secure_session != null) {
0384:                            does_cookies = doCookieTest(req, res,
0385:                                    secure_session);
0386:                        }
0387:                        // We'll try to get back there securely by first jumping back to a new (insecure) SSL session,
0388:                        // and after that the the jump to the secure SSL session will not create a new one, but reuse
0389:                        // the already running secure session instead (but only if a secure cookie can identify the request as
0390:                        // coming from the browser that made the initial jump http->https).
0391:                        if (does_cookies) {
0392:                            LOG
0393:                                    .debug("    ... client handles cookies, so we'll check if we can reuse the parent session.");
0394:                            force_jump_back_to_ssl = true;
0395:                        } else {
0396:                            // OK, it seems as if we will not be able to identify the peer by comparing cookies.
0397:                            // So the only thing we can do is to reuse the VISIT_ID.
0398:                            LOG
0399:                                    .debug("    ... but can't reuse the secure session because the client doesn't handle cookies.");
0400:                            force_reuse_visit_id = true;
0401:                        }
0402:                    } else {
0403:                        // Normally the balancer (or, more accurate: mod_jk) has a chance to choose the right server for a 
0404:                        // new session, but with a session id in the URL it wasn't able to. So we redirect to a "fresh" request 
0405:                        // without _any_ id, giving the balancer the possibility to choose a different server. (this can be 
0406:                        // overridden by supplying the parameter __forcelocal=1 to the request). All this makes only sense of 
0407:                        // course if we are running in a cluster of servers behind a balancer that chooses the right server
0408:                        // based on the session id included in the URL.
0409:                        String forcelocal = req.getParameter(PARAM_FORCELOCAL);
0410:                        if (forcelocal != null
0411:                                && (forcelocal.equals("1")
0412:                                        || forcelocal.equals("true") || forcelocal
0413:                                        .equals("yes"))) {
0414:                            LOG
0415:                                    .debug("    ... but found __forcelocal parameter to be set.");
0416:                        } else {
0417:                            LOG.debug("    ... and __forcelocal is NOT set.");
0418:                            redirectToClearedRequest(req, res);
0419:                            return;
0420:                            // End of request cycle.
0421:                        }
0422:                    }
0423:                }
0424:
0425:                PfixServletRequest preq = null;
0426:                if (has_session) {
0427:                    preq = (PfixServletRequest) session
0428:                            .getAttribute(STORED_REQUEST);
0429:                    if (preq != null) {
0430:                        LOG
0431:                                .debug("*** Found old PfixServletRequest object in session");
0432:                        session.removeAttribute(STORED_REQUEST);
0433:                        preq.updateRequest(req);
0434:                    }
0435:                }
0436:                if (preq == null) {
0437:                    LOG.debug("*** Creating PfixServletRequest object.");
0438:                    preq = new PfixServletRequestImpl(req, this 
0439:                            .getServletManagerConfig().getProperties());
0440:                }
0441:
0442:                FactoryInitServlet.tryReloadLog4j();
0443:                tryReloadProperties(preq);
0444:
0445:                // End of initialization. Now we handle all cases where we need to redirect.
0446:
0447:                if (force_jump_back_to_ssl && allowSessionCreate()) {
0448:                    LOG.debug("=> I");
0449:                    forceRedirectBackToInsecureSSL(preq, req, res);
0450:                    return;
0451:                    // End of request cycle.
0452:                }
0453:                if (force_reuse_visit_id && allowSessionCreate()) {
0454:                    LOG.debug("=> II");
0455:                    forceNewSessionSameVisit(preq, req, res);
0456:                    return;
0457:                    // End of request cycle.
0458:                }
0459:                if (has_ssl_session_insecure) {
0460:                    LOG.debug("=> III");
0461:                    redirectToSecureSSLSession(preq, req, res,
0462:                            mark_session_as_no_cookies);
0463:                    return;
0464:                    // End of request cycle.
0465:                }
0466:                if (needsSession() && allowSessionCreate() && needsSSL(preq)
0467:                        && !has_ssl_session_secure) {
0468:                    LOG.debug("=> IV");
0469:                    redirectToInsecureSSLSession(preq, req, res,
0470:                            mark_session_as_no_cookies);
0471:                    return;
0472:                    // End of request cycle.
0473:                }
0474:                if (!has_session && needsSession() && allowSessionCreate()
0475:                        && !needsSSL(preq)) {
0476:                    LOG.debug("=> V");
0477:                    redirectToSession(preq, req, res,
0478:                            mark_session_as_no_cookies);
0479:                    return;
0480:                    // End of request cycle.
0481:                }
0482:                if (!has_session && !needsSession() && needsSSL(preq)
0483:                        && !runningUnderSSL(req)) {
0484:                    LOG.debug("=> VI");
0485:                    redirectToSSL(req, res);
0486:                    return;
0487:                    // End of request cycle.
0488:                }
0489:
0490:                LOG
0491:                        .debug("*** >>> End of redirection management, handling request now.... <<< ***\n");
0492:
0493:                PerfEvent pe = new PerfEvent(
0494:                        PerfEventType.XMLSERVER_CALLPROCESS, req
0495:                                .getRequestURI());
0496:                pe.start();
0497:                callProcess(preq, req, res);
0498:                pe.save();
0499:            }
0500:
0501:            private void redirectToClearedRequest(HttpServletRequest req,
0502:                    HttpServletResponse res) {
0503:                LOG.debug("===> Redirecting to cleared Request URL");
0504:                String redirect_uri = SessionHelper.getClearedURL(req
0505:                        .getScheme(), getServerName(req), req,
0506:                        getServletManagerConfig().getProperties());
0507:                relocate(res, redirect_uri);
0508:            }
0509:
0510:            private void redirectToSSL(HttpServletRequest req,
0511:                    HttpServletResponse res) {
0512:                LOG
0513:                        .debug("===> Redirecting to session-less request URL under SSL");
0514:                String redirect_uri = SessionHelper.getClearedURL("https",
0515:                        getServerName(req), req, getServletManagerConfig()
0516:                                .getProperties());
0517:                relocate(res, redirect_uri);
0518:            }
0519:
0520:            private void redirectToSecureSSLSession(PfixServletRequest preq,
0521:                    HttpServletRequest req, HttpServletResponse res,
0522:                    String msanc) {
0523:                HttpSession session = req.getSession(false);
0524:                String visit_id = (String) session.getAttribute(VISIT_ID);
0525:                String parentid = (String) session
0526:                        .getAttribute(CHECK_FOR_RUNNING_SSL_SESSION);
0527:                if (parentid != null && !parentid.equals("")) {
0528:                    LOG
0529:                            .debug("*** The current insecure SSL session says to check for a already running SSL session for reuse");
0530:                    HttpSession secure_session = SessionAdmin.getInstance()
0531:                            .getChildSessionForParentId(parentid);
0532:                    if (secure_session != null) {
0533:                        String secure_id = secure_session.getId();
0534:                        String sec_testid = (String) secure_session
0535:                                .getAttribute(SECURE_SESS_COOKIE
0536:                                        + MD5Utils.hex_md5(secure_id));
0537:                        LOG.debug("*** We have found a candidate: SessionId="
0538:                                + secure_id + " now search for cookie...");
0539:                        LOG
0540:                                .debug("*** Session expects to see the cookie value "
0541:                                        + sec_testid);
0542:                        // But we need to make sure that the current request comes
0543:                        // from the same user who created this secure session.
0544:                        // We do this by checking for a (secure) cookie with a corresponding session id.
0545:                        Cookie cookie = getSecureSessionCookie(req, secure_id);
0546:                        if (cookie != null) {
0547:                            LOG.debug("*** Found a matching cookie ...");
0548:                            String tmp = cookie.getValue();
0549:                            String tmp_sec = tmp
0550:                                    .substring(tmp.indexOf(":") + 1);
0551:                            if (tmp_sec.equals(sec_testid)) {
0552:                                LOG.debug("   ... and the value is correct! ("
0553:                                        + tmp_sec + ")");
0554:                                LOG
0555:                                        .debug("==> Redirecting to the secure SSL URL with the already running secure session "
0556:                                                + secure_id);
0557:                                String redirect_uri = SessionHelper.encodeURL(
0558:                                        "https", getServerName(req), req,
0559:                                        secure_id, getServletManagerConfig()
0560:                                                .getProperties());
0561:                                relocate(res, redirect_uri);
0562:                                return;
0563:                            } else {
0564:                                LOG.debug("   ... but the value is WRONG!");
0565:                                // throw new RuntimeException("Wrong Session-ID for running secure session from cookie.");
0566:                                LOG
0567:                                        .error("Wrong Session-ID for running secure session from cookie.");
0568:                            }
0569:                        } else {
0570:                            LOG
0571:                                    .debug("*** NO matching SecureSessionCookie (not even a wrong one...)");
0572:                        }
0573:                    }
0574:                }
0575:
0576:                LOG.debug("*** Saving session data...");
0577:                HashMap<String, Object> map = new HashMap<String, Object>();
0578:                SessionHelper.saveSessionData(map, session);
0579:                // Before we invalidate the current session we save the traillog
0580:                SessionInfoStruct infostruct = SessionAdmin.getInstance()
0581:                        .getInfo(session);
0582:                LinkedList<TrailElement> traillog = new LinkedList<TrailElement>();
0583:                String old_id = session.getId();
0584:                if (infostruct != null) {
0585:                    traillog = SessionAdmin.getInstance().getInfo(session)
0586:                            .getTraillog();
0587:                } else {
0588:                    LOG.warn("*** Infostruct == NULL ***");
0589:                }
0590:
0591:                LOG.debug("*** Invalidation old session (Id: " + old_id + ")");
0592:                session.invalidate();
0593:                session = req.getSession(true);
0594:
0595:                // First of all we put the old session id into the new session (__PARENT_SESSION_ID__)
0596:                session.setAttribute(SessionAdmin.PARENT_SESS_ID, old_id);
0597:                if (visit_id != null) {
0598:                    // Don't call this.registerSession(...) here. We don't want to log this as a different visit.
0599:                    // Now we register the new session with saved traillog
0600:                    SessionAdmin.getInstance().registerSession(session,
0601:                            traillog, infostruct.getData().getServerName(),
0602:                            infostruct.getData().getRemoteAddr());
0603:                } else {
0604:                    // Register a new session now.
0605:                    registerSession(req, session);
0606:                }
0607:                LOG.debug("*** Got new Session (Id: " + session.getId() + ")");
0608:                LOG.debug("*** Copying data back to new session");
0609:                SessionHelper.copySessionData(map, session);
0610:                session.setAttribute(SessionHelper.SESSION_ID_URL,
0611:                        SessionHelper.getURLSessionId(req));
0612:                LOG.debug("*** Setting " + SessionHelper.SESSION_ID_URL
0613:                        + "  to "
0614:                        + session.getAttribute(SessionHelper.SESSION_ID_URL));
0615:                LOG.debug("*** Setting SECURE flag");
0616:                session.setAttribute(SessionAdmin.SESSION_IS_SECURE,
0617:                        Boolean.TRUE);
0618:                session.setAttribute(STORED_REQUEST, preq);
0619:
0620:                if (msanc == null) {
0621:                    Cookie cookie = getSecureSessionCookie(req, session.getId());
0622:                    if (cookie != null) {
0623:                        setCookiePath(req, cookie);
0624:                        cookie.setMaxAge(0);
0625:                        cookie.setSecure(true);
0626:                        res.addCookie(cookie);
0627:                    }
0628:
0629:                    String sec_testid = Long
0630:                            .toHexString((long) (Math.random() * Long.MAX_VALUE));
0631:                    LOG.debug("*** Secure Test-ID used in session and cookie: "
0632:                            + sec_testid);
0633:                    String sec_cookie = MD5Utils.hex_md5(session.getId());
0634:                    session.setAttribute(SECURE_SESS_COOKIE + sec_cookie,
0635:                            sec_testid);
0636:
0637:                    cookie = new Cookie(SECURE_SESS_COOKIE + sec_cookie, System
0638:                            .currentTimeMillis()
0639:                            + ":" + sec_testid);
0640:                    setCookiePath(req, cookie);
0641:                    // FIXME (see comment in cleanupCookies
0642:                    //cookie.setMaxAge(session.getMaxInactiveInterval());
0643:                    cookie.setMaxAge(-1);
0644:                    cookie.setSecure(true);
0645:                    res.addCookie(cookie);
0646:
0647:                    // Make sure a test cookie is created for the new session if needed
0648:                    createTestCookie(req, res);
0649:                }
0650:
0651:                LOG
0652:                        .debug("===> Redirecting to secure SSL URL with session (Id: "
0653:                                + session.getId() + ")");
0654:                String redirect_uri = SessionHelper.encodeURL("https",
0655:                        getServerName(req), req, getServletManagerConfig()
0656:                                .getProperties());
0657:                relocate(res, redirect_uri);
0658:            }
0659:
0660:            private void redirectToInsecureSSLSession(PfixServletRequest preq,
0661:                    HttpServletRequest req, HttpServletResponse res,
0662:                    String msanc) {
0663:                boolean reuse_session = false;
0664:                if (req.isRequestedSessionIdValid()) {
0665:                    reuse_session = true;
0666:                    LOG
0667:                            .debug("*** reusing existing session for jump http=>https");
0668:                }
0669:                HttpSession session = req.getSession(true);
0670:                if (!reuse_session) {
0671:                    if (msanc == null) {
0672:                        registerSession(req, session);
0673:                    } else {
0674:                        session.setAttribute(VISIT_ID, msanc);
0675:                        LOG
0676:                                .debug("*** Setting REFUSE COOKIES flag in session (Id: "
0677:                                        + session.getId() + ")");
0678:                        session.setAttribute(REFUSE_COOKIES, Boolean.TRUE);
0679:                        SessionAdmin.getInstance().registerSession(session,
0680:                                getServerName(req), req.getRemoteAddr());
0681:                    }
0682:                }
0683:
0684:                session.setAttribute(SessionHelper.SESSION_ID_URL,
0685:                        SessionHelper.getURLSessionId(req));
0686:                LOG.debug("*** Setting INSECURE flag in session (Id: "
0687:                        + session.getId() + ")");
0688:                session.setAttribute(SessionAdmin.SESSION_IS_SECURE,
0689:                        Boolean.FALSE);
0690:                session.setAttribute(STORED_REQUEST, preq);
0691:
0692:                // Make sure a test cookie is created if needed
0693:                if (msanc == null) {
0694:                    createTestCookie(req, res);
0695:                }
0696:
0697:                LOG
0698:                        .debug("===> Redirecting to insecure SSL URL with session (Id: "
0699:                                + session.getId() + ")");
0700:                String redirect_uri = SessionHelper.encodeURL("https",
0701:                        getServerName(req), req, getServletManagerConfig()
0702:                                .getProperties());
0703:                relocate(res, redirect_uri);
0704:            }
0705:
0706:            private void forceRedirectBackToInsecureSSL(
0707:                    PfixServletRequest preq, HttpServletRequest req,
0708:                    HttpServletResponse res) {
0709:                // When we come here, we KNOW that there's a secure SSL session already running, so this session here is
0710:                // only used for the jump to SSL so we can get the cookie to check the identity of the caller.
0711:                String parentid = req.getRequestedSessionId();
0712:                HttpSession session = req.getSession(true);
0713:                session.setAttribute(SessionHelper.SESSION_ID_URL,
0714:                        SessionHelper.getURLSessionId(req));
0715:                session.setAttribute(CHECK_FOR_RUNNING_SSL_SESSION, parentid);
0716:                LOG.debug("*** Setting INSECURE flag in session (Id: "
0717:                        + session.getId() + ")");
0718:                session.setAttribute(SessionAdmin.SESSION_IS_SECURE,
0719:                        Boolean.FALSE);
0720:                session.setAttribute(STORED_REQUEST, preq);
0721:
0722:                HttpSession child = SessionAdmin.getInstance()
0723:                        .getChildSessionForParentId(parentid);
0724:                String testrand = (String) child
0725:                        .getAttribute(RAND_SESS_COOKIE_VALUE);
0726:                if (testrand == null || testrand.equals("")) {
0727:                    // Make sure a test cookie is created
0728:                    createTestCookie(req, res);
0729:                } else {
0730:                    session.setAttribute(RAND_SESS_COOKIE_VALUE, testrand);
0731:                }
0732:
0733:                LOG.debug("===> Redirecting to SSL URL with session (Id: "
0734:                        + session.getId() + ")");
0735:                String redirect_uri = SessionHelper.encodeURL("https",
0736:                        getServerName(req), req, getServletManagerConfig()
0737:                                .getProperties());
0738:                relocate(res, redirect_uri);
0739:            }
0740:
0741:            private void forceNewSessionSameVisit(PfixServletRequest preq,
0742:                    HttpServletRequest req, HttpServletResponse res) {
0743:                // When we come here, we KNOW that there's a secure SSL session already running, but unfortunately
0744:                // it seems that the browser doesn't send cookies. So we will not be able to know for sure that the request comes
0745:                // from the legitimate user. The only thing we can do is to copy the VISIT_ID, which helps to keep the
0746:                // statistic clean :-)
0747:                String parentid = req.getRequestedSessionId();
0748:                HttpSession child = SessionAdmin.getInstance()
0749:                        .getChildSessionForParentId(parentid);
0750:                String curr_visit_id = (String) child.getAttribute(VISIT_ID);
0751:                HttpSession session = req.getSession(true);
0752:
0753:                String testrand = (String) child
0754:                        .getAttribute(RAND_SESS_COOKIE_VALUE);
0755:                if (testrand == null || testrand.equals("")) {
0756:                    // Make sure a test cookie is created
0757:                    createTestCookie(req, res);
0758:                } else {
0759:                    session.setAttribute(RAND_SESS_COOKIE_VALUE, testrand);
0760:                }
0761:
0762:                LinkedList<TrailElement> traillog = SessionAdmin.getInstance()
0763:                        .getInfo(child).getTraillog();
0764:                session.setAttribute(SessionHelper.SESSION_ID_URL,
0765:                        SessionHelper.getURLSessionId(req));
0766:                session.setAttribute(VISIT_ID, curr_visit_id);
0767:                SessionAdmin.getInstance().registerSession(session, traillog,
0768:                        getServerName(req), req.getRemoteAddr());
0769:                LOG.debug("===> Redirecting with session (Id: "
0770:                        + session.getId() + ") using OLD VISIT_ID: "
0771:                        + curr_visit_id);
0772:                session.setAttribute(STORED_REQUEST, preq);
0773:                String redirect_uri = SessionHelper.encodeURL(req.getScheme(),
0774:                        getServerName(req), req, getServletManagerConfig()
0775:                                .getProperties());
0776:                relocate(res, redirect_uri);
0777:            }
0778:
0779:            private void redirectToSession(PfixServletRequest preq,
0780:                    HttpServletRequest req, HttpServletResponse res,
0781:                    String msanc) {
0782:                HttpSession session = req.getSession(true);
0783:                session.setAttribute(SessionHelper.SESSION_ID_URL,
0784:                        SessionHelper.getURLSessionId(req));
0785:                if (msanc == null) {
0786:                    registerSession(req, session);
0787:                    createTestCookie(req, res);
0788:                } else {
0789:                    session.setAttribute(VISIT_ID, msanc);
0790:                    LOG
0791:                            .debug("*** Setting REFUSE COOKIES flag in session (Id: "
0792:                                    + session.getId() + ")");
0793:                    session.setAttribute(REFUSE_COOKIES, Boolean.TRUE);
0794:                    SessionAdmin.getInstance().registerSession(session,
0795:                            getServerName(req), req.getRemoteAddr());
0796:                }
0797:
0798:                LOG.debug("===> Redirecting to URL with session (Id: "
0799:                        + session.getId() + ")");
0800:                session.setAttribute(STORED_REQUEST, preq);
0801:                String redirect_uri = SessionHelper.encodeURL(req.getScheme(),
0802:                        getServerName(req), req, getServletManagerConfig()
0803:                                .getProperties());
0804:                relocate(res, redirect_uri);
0805:            }
0806:
0807:            private boolean doCookieTest(HttpServletRequest req,
0808:                    HttpServletResponse res, HttpSession sess) {
0809:                if (sess == null) {
0810:                    sess = req.getSession(false);
0811:                }
0812:                // If in this session the client has been found to do cookies already, don't check the test
0813:                // cookie value again.  We still have to check if there are any cookies at all (a
0814:                // test cookie should be there, but maybe the wrong value because another session is
0815:                // opened in parallel), because we need to guard against clients which supply cookies over
0816:                // the whole redirect chain, but don't supply cookies on the following request, and we want
0817:                // to correctly react on people who turn off cookies during the session.
0818:                if (sess != null) {
0819:                    LOG.debug("*** Testing for marked session...");
0820:                    Cookie[] cookies = req.getCookies();
0821:                    boolean sessionusescookies = false;
0822:                    Boolean doescookies = (Boolean) sess
0823:                            .getAttribute(SESSION_COOKIES_MARKER);
0824:                    if (doescookies != null && doescookies.booleanValue()) {
0825:                        sessionusescookies = true;
0826:                        LOG
0827:                                .debug("    ...session is already marked as using cookies, looking for ANY test cookie...");
0828:                    } else {
0829:                        LOG
0830:                                .debug("    ...session is NOT already marked as using cookies!");
0831:                    }
0832:
0833:                    String rand = (String) sess
0834:                            .getAttribute(RAND_SESS_COOKIE_VALUE);
0835:                    if (rand != null) {
0836:                        LOG.debug("*** Testing for cookie " + TEST_COOKIE
0837:                                + "...");
0838:                        if (cookies != null) {
0839:                            for (int i = 0; i < cookies.length; i++) {
0840:                                Cookie cookie = cookies[i];
0841:                                if (cookie.getName().equals(TEST_COOKIE)) {
0842:                                    if (sessionusescookies) {
0843:                                        // No need to check the value...
0844:                                        LOG
0845:                                                .debug("    ... found it, no need to check the value (because session is marked).");
0846:                                        return true;
0847:                                    } else {
0848:                                        LOG
0849:                                                .debug("    ... found it, checking value "
0850:                                                        + rand);
0851:                                        if (cookie.getValue().equals(rand)) {
0852:                                            LOG
0853:                                                    .debug("    ... value matches! Marking session...");
0854:                                            sess.setAttribute(
0855:                                                    SESSION_COOKIES_MARKER,
0856:                                                    Boolean.TRUE);
0857:                                            return true;
0858:                                        } else {
0859:                                            LOG
0860:                                                    .debug("    ... value is WRONG.");
0861:                                        }
0862:                                    }
0863:                                    break;
0864:                                }
0865:                            }
0866:                            LOG
0867:                                    .debug("*** Client sends cookies, but not our test cookie! ***");
0868:                        }
0869:                    }
0870:                }
0871:                return false;
0872:            }
0873:
0874:            private boolean createTestCookie(HttpServletRequest req,
0875:                    HttpServletResponse res) {
0876:                HttpSession sess = req.getSession(false);
0877:                String rand = null;
0878:                if (sess != null) {
0879:                    rand = (String) sess.getAttribute(RAND_SESS_COOKIE_VALUE);
0880:                    if (rand != null) {
0881:                        LOG
0882:                                .debug("*** Already found a test cookie value in session: "
0883:                                        + rand);
0884:                    } else {
0885:                        rand = Long
0886:                                .toHexString((long) (Math.random() * Long.MAX_VALUE));
0887:                        LOG.debug("*** Creating a random test cookie value: "
0888:                                + rand);
0889:                    }
0890:                    Cookie newprobe = new Cookie(TEST_COOKIE, rand);
0891:                    setCookiePath(req, newprobe);
0892:                    res.addCookie(newprobe);
0893:                    sess.setAttribute(RAND_SESS_COOKIE_VALUE, rand);
0894:                    return true;
0895:                }
0896:                return false;
0897:            }
0898:
0899:            private Cookie getSecureSessionCookie(HttpServletRequest req,
0900:                    String sessionid) {
0901:                Cookie[] cookies = req.getCookies();
0902:                Cookie tmp;
0903:                if (cookies != null) {
0904:                    for (int i = 0; i < cookies.length; i++) {
0905:                        tmp = cookies[i];
0906:                        if (tmp.getName().equals(
0907:                                SECURE_SESS_COOKIE
0908:                                        + MD5Utils.hex_md5(sessionid)))
0909:                            return tmp;
0910:                    }
0911:                }
0912:                return null;
0913:            }
0914:
0915:            private void registerSession(HttpServletRequest req,
0916:                    HttpSession session) {
0917:                if (session != null) {
0918:                    synchronized (TIMESTAMP_ID) {
0919:                        SimpleDateFormat sdf = new SimpleDateFormat(
0920:                                "yyyyMMddHHmmss");
0921:                        String timestamp = sdf.format(new Date());
0922:                        NumberFormat nf = NumberFormat.getInstance();
0923:                        nf.setMinimumIntegerDigits(3);
0924:
0925:                        if (timestamp.equals(TIMESTAMP_ID)) {
0926:                            INC_ID++;
0927:                        } else {
0928:                            TIMESTAMP_ID = timestamp;
0929:                            INC_ID = 0;
0930:                        }
0931:                        if (INC_ID >= 1000) {
0932:                            LOG.warn("*** More than 999 connects/sec! ***");
0933:                        }
0934:                        String sessid = session.getId();
0935:                        String mach = "";
0936:                        if (sessid.lastIndexOf(".") > 0) {
0937:                            mach = sessid.substring(sessid.lastIndexOf("."));
0938:                        }
0939:                        session.setAttribute(VISIT_ID, TIMESTAMP_ID + "-"
0940:                                + nf.format(INC_ID) + mach);
0941:                    }
0942:                    StringBuffer logbuff = new StringBuffer();
0943:                    logbuff.append(session.getAttribute(VISIT_ID) + "|"
0944:                            + session.getId() + "|");
0945:                    logbuff.append(getServerName(req) + "|"
0946:                            + req.getRemoteAddr() + "|"
0947:                            + req.getHeader("user-agent") + "|");
0948:                    if (req.getHeader("referer") != null) {
0949:                        logbuff.append(req.getHeader("referer"));
0950:                    }
0951:                    logbuff.append("|");
0952:                    if (req.getHeader("accept-language") != null) {
0953:                        logbuff.append(req.getHeader("accept-language"));
0954:                    }
0955:                    LOGGER_VISIT.warn(logbuff.toString());
0956:                    SessionAdmin.getInstance().registerSession(session,
0957:                            getServerName(req), req.getRemoteAddr());
0958:                }
0959:            }
0960:
0961:            public void init(ServletConfig config) throws ServletException {
0962:                super .init(config);
0963:
0964:                ServletContext ctx = config.getServletContext();
0965:                LOG.debug("*** Servlet container is '" + ctx.getServerInfo()
0966:                        + "'");
0967:                int major = ctx.getMajorVersion();
0968:                int minor = ctx.getMinorVersion();
0969:                if ((major == 2 && minor >= 3) || (major > 2)) {
0970:                    LOG
0971:                            .warn("*** Servlet container with support for Servlet API "
0972:                                    + major + "." + minor + " detected");
0973:                } else {
0974:                    throw new ServletException(
0975:                            "*** Can't detect servlet container with support for Servlet API 2.3 or higher");
0976:                }
0977:
0978:                Properties properties = new Properties(System.getProperties());
0979:
0980:                String commonpropfilename = config
0981:                        .getInitParameter("servlet.commonpropfile");
0982:                if (commonpropfilename != null) {
0983:                    if (!commonpropfilename.startsWith("/")) {
0984:                        commonpropfile = ResourceUtil
0985:                                .getFileResourceFromDocroot(commonpropfilename);
0986:                    } else {
0987:                        commonpropfile = ResourceUtil.getFileResource("file://"
0988:                                + commonpropfilename);
0989:                    }
0990:                    // Load on first request
0991:                    common_mtime = loadPropertyfile(properties, commonpropfile);
0992:                }
0993:
0994:                String servletpropfilename = config
0995:                        .getInitParameter("servlet.propfile");
0996:                if (servletpropfilename != null) {
0997:                    if (!servletpropfilename.startsWith("/")) {
0998:                        servletpropfile = ResourceUtil
0999:                                .getFileResourceFromDocroot(servletpropfilename);
1000:                    } else {
1001:                        servletpropfile = ResourceUtil
1002:                                .getFileResource("file://"
1003:                                        + servletpropfilename);
1004:                    }
1005:                }
1006:
1007:                // Make sure configuration is available
1008:                this .reloadServletConfig(servletpropfile, properties);
1009:
1010:                initCookieSec();
1011:                initExceptionConfigs();
1012:                initServletEncoding();
1013:            }
1014:
1015:            protected boolean tryReloadProperties(PfixServletRequest preq)
1016:                    throws ServletException {
1017:                if ((commonpropfile != null && commonpropfile.lastModified() > common_mtime)
1018:                        || (servletpropfile != null && servletpropfile
1019:                                .lastModified() > servlet_mtime)
1020:                        || (this .getServletManagerConfig() != null && this 
1021:                                .getServletManagerConfig().needsReload())) {
1022:
1023:                    int currLoadIndex = configLoadIndex.incrementAndGet();
1024:
1025:                    LOG.warn("\n\n##############################\n"
1026:                            + "#### Reloading properties ####\n"
1027:                            + "##############################\n");
1028:                    Properties properties = new Properties(System
1029:                            .getProperties());
1030:
1031:                    if (commonpropfile != null) {
1032:                        common_mtime = loadPropertyfile(properties,
1033:                                commonpropfile);
1034:                    }
1035:                    servlet_mtime = servletpropfile.lastModified();
1036:                    this .reloadServletConfig(servletpropfile, properties);
1037:                    this .getServletManagerConfig().getProperties().setProperty(
1038:                            PROP_LOADINDEX, String.valueOf(currLoadIndex));
1039:
1040:                    initCookieSec();
1041:                    return true;
1042:                } else {
1043:                    return false;
1044:                }
1045:
1046:            }
1047:
1048:            /**
1049:             * This is only for broken clients who suddenly stop supplying cookies in the middle of a
1050:             * session.  Windows XP internet configuration wizard (which speaks http) seems to be an example of a
1051:             * client that remembers the cookies over the first request/relocate/relocate cycle, but never sends a
1052:             * cookie again on the next request.
1053:             * You are strongly advised to NOT set the corresponding property to true, unless you deal with broken software.
1054:             */
1055:            private void initCookieSec() {
1056:                String csec = this .getServletManagerConfig().getProperties()
1057:                        .getProperty(PROP_COOKIE_SEC_NOT_ENFORCED);
1058:                if (csec != null && csec.equals("true")) {
1059:                    cookie_security_not_enforced = true;
1060:                } else {
1061:                    cookie_security_not_enforced = false;
1062:                }
1063:            }
1064:
1065:            private long loadPropertyfile(Properties props,
1066:                    FileResource propfile) throws ServletException {
1067:                long mtime;
1068:                try {
1069:                    mtime = propfile.lastModified();
1070:                    XMLPropertiesUtil
1071:                            .loadPropertiesFromXMLFile(propfile, props);
1072:                } catch (FileNotFoundException e) {
1073:                    throw new ServletException("*** [" + propfile.getName()
1074:                            + "] Not found: " + e.toString());
1075:                } catch (IOException e) {
1076:                    throw new ServletException("*** [" + propfile.getName()
1077:                            + "] IO-error: " + e.toString());
1078:                } catch (SAXException e) {
1079:                    throw new ServletException("*** [" + propfile.getName()
1080:                            + "] Parsing-error: " + e.toString());
1081:                }
1082:                return mtime;
1083:            }
1084:
1085:            private void callProcess(PfixServletRequest preq,
1086:                    HttpServletRequest req, HttpServletResponse res)
1087:                    throws ServletException, IOException {
1088:                try {
1089:                    if (!FactoryInitServlet.isConfigured()
1090:                            && !FactoryInitUtil.isInitialized()) {
1091:                        FactoryInitException initEx = FactoryInitServlet
1092:                                .getInitException();
1093:                        if (initEx != null) {
1094:                            initEx = initEx.copy();
1095:                            initEx.fillInStackTrace();
1096:                            throw initEx;
1097:                        } else
1098:                            throw new IllegalStateException(
1099:                                    "Factories aren't initialized yet.");
1100:                    }
1101:                    res.setContentType(DEF_CONTENT_TYPE);
1102:                    process(preq, res);
1103:                } catch (Throwable e) {
1104:                    LOG.error("Exception in process", e);
1105:                    ExceptionConfig exconf = getExceptionConfigForThrowable(e
1106:                            .getClass());
1107:                    if (exconf != null && exconf.getProcessor() != null) {
1108:                        if (preq.getLastException() == null) {
1109:                            ExceptionProcessor eproc = exconf.getProcessor();
1110:                            eproc.processException(e, exconf, preq,
1111:                                    getServletConfig().getServletContext(),
1112:                                    req, res, this .getServletManagerConfig()
1113:                                            .getProperties());
1114:                        }
1115:                    }
1116:                    if (!res.isCommitted())
1117:                        throw new ServletException("Exception in process.", e);
1118:                }
1119:            }
1120:
1121:            /**
1122:             * 
1123:             * @return null if no processor is responsible for the passed throwable
1124:             * @throws ServletException
1125:             * @throws ClassNotFoundException
1126:             */
1127:            private ExceptionConfig getExceptionConfigForThrowable(
1128:                    Class<? extends Throwable> clazz) throws ServletException {
1129:                ExceptionConfig exConf = null;
1130:                if (clazz != null) {
1131:                    exConf = exceptionConfigs.get(clazz);
1132:                    if (exConf == null)
1133:                        exConf = getExceptionConfigForThrowable(clazz
1134:                                .getSuperclass().asSubclass(Throwable.class));
1135:                }
1136:                return exConf;
1137:            }
1138:
1139:            /**
1140:             * This method uses all properties prefixed with 'exception' to build ExceptionConfig
1141:             * objects, which are then stored in the exConfig-Map, keyed by the type attribute
1142:             * of the ExceptionConfig.
1143:             * Syntax of key: "exception" '.' JAVATYPE '.' ("forward"|"page"|"processor")
1144:             * @exception ServletException if the exception configuration defined in the properties
1145:             * is somehow invalid
1146:             */
1147:            private void initExceptionConfigs() throws ServletException {
1148:                Map<String, ExceptionConfig> tmpExConf = new HashMap<String, ExceptionConfig>();
1149:                Properties properties = this .getServletManagerConfig()
1150:                        .getProperties();
1151:                Enumeration<?> props = properties.propertyNames();
1152:                while (props.hasMoreElements()) {
1153:                    String propName = (String) props.nextElement();
1154:
1155:                    if (propName.startsWith(PROP_EXCEPTION)) {
1156:                        String propValue = properties.getProperty(propName);
1157:
1158:                        String type = null;
1159:                        String attrName = null;
1160:                        IndexOutOfBoundsException ioobex = null;
1161:                        try {
1162:                            int dot1 = propName.indexOf('.');
1163:                            int dot2 = propName.lastIndexOf('.');
1164:                            type = propName.substring(dot1 + 1, dot2);
1165:                            attrName = propName.substring(dot2 + 1);
1166:                        } catch (IndexOutOfBoundsException e) {
1167:                            // logging is done below
1168:                            ioobex = e;
1169:                        }
1170:                        if (type == null || attrName == null || "".equals(type)
1171:                                || "".equals(attrName)) {
1172:                            LOG
1173:                                    .debug(
1174:                                            "Could not parse property key \""
1175:                                                    + propName
1176:                                                    + "\" into three non-empty parts separated by '.'",
1177:                                            ioobex);
1178:                        }
1179:
1180:                        ExceptionConfig exConf = (ExceptionConfig) tmpExConf
1181:                                .get(type);
1182:
1183:                        LOG.debug("Property found for exception processing: "
1184:                                + propName + "=" + propValue);
1185:
1186:                        if (exConf == null) {
1187:                            exConf = new ExceptionConfig();
1188:                            exConf.setType(type);
1189:                            tmpExConf.put(type, exConf);
1190:                        }
1191:
1192:                        try {
1193:                            if ("forward".equals(attrName)) {
1194:                                exConf.setForward(Boolean.valueOf(propValue)
1195:                                        .booleanValue());
1196:                            } else if ("page".equals(attrName)) {
1197:                                exConf.setPage(propValue);
1198:                            } else if ("processor".equals(attrName)) {
1199:                                Class<?> procClass = Class.forName(propValue);
1200:                                ExceptionProcessor exProc = (ExceptionProcessor) procClass
1201:                                        .newInstance();
1202:                                exConf.setProcessor(exProc);
1203:                            }
1204:                        } catch (ClassCastException ex) {
1205:                            throw new ServletException(
1206:                                    "INVALID CONF: Class "
1207:                                            + propValue
1208:                                            + " is not an instance of 'ExceptionProcessor'");
1209:                        } catch (IllegalAccessException ex) {
1210:                            throw new ServletException(
1211:                                    "INVALID CONF: Can't create instance of class "
1212:                                            + propName, ex);
1213:                        } catch (SecurityException ex) {
1214:                            throw new ServletException(
1215:                                    "INVALID CONF: Can't create instance of class "
1216:                                            + propName, ex);
1217:                        } catch (ClassNotFoundException ex) {
1218:                            throw new ServletException(
1219:                                    "INVALID CONF: Can't create instance of class "
1220:                                            + propName, ex);
1221:                        } catch (InstantiationException ex) {
1222:                            throw new ServletException(
1223:                                    "INVALID CONF: Can't create instance of class "
1224:                                            + propName, ex);
1225:                        }
1226:                    }
1227:                }
1228:
1229:                LOG
1230:                        .debug("Finished reading properties for Exception configuration! \n"
1231:                                + tmpExConf);
1232:
1233:                exceptionConfigs.clear();
1234:
1235:                // validate the ExceptionConfig-instances and save them, keyed by their type-attribute
1236:                for (Iterator<ExceptionConfig> values = tmpExConf.values()
1237:                        .iterator(); values.hasNext();) {
1238:                    ExceptionConfig exConfig = values.next();
1239:                    if (exConfig.validate() == false)
1240:                        throw new ServletException(
1241:                                "INVALID ExceptionConfig: \n" + exConfig);
1242:                    else {
1243:                        try {
1244:                            Class<?> clazz = Class.forName(exConfig.getType());
1245:                            exceptionConfigs.put(clazz
1246:                                    .asSubclass(Throwable.class), exConfig);
1247:                        } catch (ClassNotFoundException x) {
1248:                            throw new ServletException(
1249:                                    "Can't find exception class: "
1250:                                            + exConfig.getType());
1251:                        }
1252:                    }
1253:                }
1254:
1255:                if (LOG.isDebugEnabled()) {
1256:                    LOG.debug("Complete ExceptionConfig is:");
1257:                    LOG.debug("\n" + exceptionConfigs);
1258:                }
1259:            }
1260:
1261:            /**
1262:             * Sets the servlet's encoding, which is used as character encoding for decoding/encoding 
1263:             * requests/responses. Be aware that this setting only applies to the appropriate Readers, 
1264:             * Writers and body request parameters. It has no effect on the byte streams. The URI
1265:             * encoding (which is set on Tomcat connector level and can't be changed here) is set always
1266:             * be the same as the body encoding.
1267:             */
1268:            private void initServletEncoding() {
1269:                //Try to get servlet encoding from properties:
1270:                String encoding = this .getServletManagerConfig()
1271:                        .getProperties().getProperty(SERVLET_ENCODING);
1272:                if (encoding == null || encoding.trim().equals(""))
1273:                    LOG.warn("No servlet encoding property set");
1274:                else if (!Charset.isSupported(encoding))
1275:                    LOG.error("Servlet encoding '" + encoding
1276:                            + "' is not supported.");
1277:                else
1278:                    servletEncoding = encoding;
1279:
1280:                //Try to get servlet encoding from init parameters:
1281:                if (servletEncoding == null) {
1282:                    encoding = getServletConfig().getInitParameter(
1283:                            SERVLET_ENCODING);
1284:                    if (encoding == null || encoding.trim().equals(""))
1285:                        LOG.warn("No servlet encoding init parameter set");
1286:                    else if (!Charset.isSupported(encoding))
1287:                        LOG.error("Servlet encoding '" + encoding
1288:                                + "' is not supported.");
1289:                    else
1290:                        servletEncoding = encoding;
1291:                }
1292:                //Use default servlet encoding:
1293:                if (servletEncoding == null) {
1294:                    servletEncoding = DEFAULT_ENCODING;
1295:                    LOG.warn("Using default servlet encoding: "
1296:                            + DEFAULT_ENCODING);
1297:                }
1298:
1299:                LOG.debug("Servlet encoding was set to '" + servletEncoding
1300:                        + "'.");
1301:            }
1302:
1303:            protected abstract void process(PfixServletRequest preq,
1304:                    HttpServletResponse res) throws Exception;
1305:
1306:            public static final int HTTP_PORT = 80;
1307:            public static final int HTTPS_PORT = 443;
1308:
1309:            public static boolean isDefault(String scheme, int port) {
1310:                if (scheme.equals("http") && port == HTTP_PORT) {
1311:                    return true;
1312:                } else if (scheme.equals("https") && port == HTTPS_PORT) {
1313:                    return true;
1314:                } else {
1315:                    return false;
1316:                }
1317:            }
1318:
1319:            private class SortableCookie implements  Comparable<SortableCookie> {
1320:                public final Cookie cookie;
1321:                public final long lasttouch;
1322:
1323:                public final int compareTo(final SortableCookie in) {
1324:                    if (in.lasttouch > lasttouch)
1325:                        return -1;
1326:                    if (in.lasttouch < lasttouch)
1327:                        return 1;
1328:                    else
1329:                        return 0;
1330:                }
1331:
1332:                public SortableCookie(Cookie cookie, long lasttouch) {
1333:                    this .cookie = cookie;
1334:                    this .lasttouch = lasttouch;
1335:                    assert (cookie != null) : "cookie argument must not be null";
1336:                    assert (lasttouch > 0) : "lasttouch argument must be > 0";
1337:                }
1338:            }
1339:
1340:            private void cleanupCookies(HttpServletRequest req,
1341:                    HttpServletResponse res, Cookie cookie) {
1342:                HttpSession session = req.getSession(false);
1343:                assert (session != null) : "session can't be null here...";
1344:
1345:                Long timeout = System.currentTimeMillis()
1346:                        - (1000 * session.getMaxInactiveInterval());
1347:                assert (timeout > 0) : "timeout can't be negative...";
1348:
1349:                Cookie[] cookies = req.getCookies();
1350:                if (cookies != null && cookies.length > 0) {
1351:                    TreeSet<SortableCookie> cset = new TreeSet<SortableCookie>();
1352:
1353:                    for (int i = 0; i < cookies.length; i++) {
1354:                        Cookie tmp = cookies[i];
1355:                        if (tmp.getName().startsWith(SECURE_SESS_COOKIE)
1356:                                && (cookie == null || !tmp.getName().equals(
1357:                                        cookie.getName()))) {
1358:                            String value = tmp.getValue();
1359:                            String stamp = value.substring(0, value
1360:                                    .indexOf(":"));
1361:                            try {
1362:                                long lasttouch = Long.parseLong(stamp);
1363:                                cset.add(new SortableCookie(tmp, lasttouch));
1364:                                LOG.debug("~~~ Adding cookie " + lasttouch
1365:                                        + "->" + tmp.getName());
1366:                            } catch (NumberFormatException e) {
1367:                                setCookiePath(req, tmp);
1368:                                tmp.setMaxAge(0);
1369:                                tmp.setSecure(true);
1370:                                res.addCookie(tmp);
1371:                            }
1372:                        }
1373:                    }
1374:                    int count = 0;
1375:                    int length = cset.size();
1376:                    for (Iterator<SortableCookie> iter = cset.iterator(); iter
1377:                            .hasNext(); count++) {
1378:                        SortableCookie current = iter.next();
1379:                        Cookie curr_cookie = current.cookie;
1380:                        long curr_lasttouch = current.lasttouch;
1381:
1382:                        LOG
1383:                                .debug("--- Checking cookie " + count + "->"
1384:                                        + curr_lasttouch + "->"
1385:                                        + curr_cookie.getName());
1386:
1387:                        if (count <= (length - MAX_PARALLEL_SEC_SESSIONS)) {
1388:                            LOG
1389:                                    .debug("   -> removing cookie because number of secure session cookies too high");
1390:                            curr_cookie.setMaxAge(0);
1391:                            curr_cookie.setSecure(true);
1392:                            setCookiePath(req, curr_cookie);
1393:                            res.addCookie(curr_cookie);
1394:                        } else if (curr_lasttouch < timeout) {
1395:                            // FIXME We shoudln't need to check for "old" cookies here, because the
1396:                            // lifetime of a cookie should ideally be set to the max. inactive time of the
1397:                            // session, so the browser would stop sending old cookies by itself. But I'm not
1398:                            // entirely sure if we can really depend on having the time set right on all
1399:                            // clients... What happens if the client clock is set half an hour too early?
1400:                            // Will the browser stop sending the cookie half an hour before the session is
1401:                            // really invalidated? As we need the timestamp info anyway to sort the cookies,
1402:                            // we can also do the timeout removing here.
1403:                            LOG
1404:                                    .debug("   -> removing cookie because timestamp too old");
1405:                            curr_cookie.setMaxAge(0);
1406:                            curr_cookie.setSecure(true);
1407:                            setCookiePath(req, curr_cookie);
1408:                            res.addCookie(curr_cookie);
1409:                        } else {
1410:                            break;
1411:                        }
1412:                    }
1413:                }
1414:            }
1415:
1416:            private void setCookiePath(HttpServletRequest req, Cookie cookie) {
1417:                if (req.getContextPath().length() > 0) {
1418:                    cookie.setPath(req.getContextPath());
1419:                } else {
1420:                    cookie.setPath("/");
1421:                }
1422:            }
1423:
1424:        }// ServletManager
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.