Source Code Cross Referenced for MessAdminResponseWrapper.java in  » Profiler » MessAdmin » clime » messadmin » filter » 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 » Profiler » MessAdmin » clime.messadmin.filter 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * 
003:         */package clime.messadmin.filter;
004:
005:        import java.io.IOException;
006:        import java.io.PrintWriter;
007:        import java.io.Writer;
008:        import java.lang.reflect.InvocationTargetException;
009:        import java.lang.reflect.Method;
010:        import java.net.InetAddress;
011:        import java.net.UnknownHostException;
012:
013:        import javax.servlet.ServletOutputStream;
014:        import javax.servlet.ServletResponse;
015:        import javax.servlet.http.HttpServletResponse;
016:        import javax.servlet.http.HttpServletResponseWrapper;
017:
018:        import clime.messadmin.core.MessAdmin;
019:
020:        /**
021:         * Pass-trough response wrapper, looking up for message injection.
022:         * IMPLEMENTATION NOTE: do not buffer response here: it can be quite large...
023:         * @author Cédrik LIME
024:         * TODO: for version 2, try to put the script at an even more suitable location (immediatly after <body> or immediatly before </body> or </head>)
025:         */
026:        public class MessAdminResponseWrapper extends
027:                HttpServletResponseWrapper {
028:            private static final boolean DEBUG = false;
029:            private static transient Method getContentType = null;
030:
031:            private static String[] SCRIPT_BEGIN = new String[] {
032:                    "<script language='JavaScript' type='text/javascript'>",
033:                    "<!--",
034:                    "	var width = 600; // screen.availWidth - 10",
035:                    "	var height = 400; // screen.availHeight - 20",
036:                    "	var screenX = Math.floor((screen.width)/2) - Math.floor(width/2);",
037:                    "	var screenY = Math.floor((screen.height)/2) - Math.floor(height/2) - 20;",
038:                    "",
039:                    "	var features =",
040:                    "		'toolbar=no,' +",
041:                    "		'scrollbars=yes,' +",
042:                    "		'status=no,' +",
043:                    "		'location=no,' +",
044:                    "		'directories=no,' +",
045:                    "		'menubar=no,' +",
046:                    "		'resizable=yes,' +",
047:                    "		'width=' + width + ',' +",
048:                    "		'height=' + height + ',' +",
049:                    "		'top=' + screenY + ',' +",
050:                    "		'left=' + screenX + ',' +",
051:                    "",
052:                    "		// NS only",
053:                    "		'screenX=' + screenX + ',' +",
054:                    "		'screenY=' + screenY + ',' +",
055:                    "		'alwaysRaised=yes,' +",
056:                    "		'dependent=yes,' +",
057:                    "		'hotkeys=no,' +",
058:                    "		'modal=yes';",
059:                    "",
060:                    "		// IE only",
061:                    "	var ieFeatures =",
062:                    "		'center=yes,' +",
063:                    "		'dialogHeight=' + height + ',' +",
064:                    "		'dialogWidth=' + width + ',' +",
065:                    "		'dialogTop=' + screenY + ',' +",
066:                    "		'dialogLeft=' + screenX + ',' +",
067:                    "		'resizable=yes,' +",
068:                    "		'help=no';",
069:                    "",
070:                    //		"	//URL - string containing the URL of the document to open in the new window. If no URL is specified, an empty window will be created.",
071:                    //		"	//name - string containing the name of the new window. This can be used as the 'target' attribute of a <form> or <a> tag to point to the new window.",
072:                    //		"	//features - optional string that contains details of which of the standard window features are to be used with the new window.",
073:                    "	var messadminpopup;",
074:                    "	//if (document.all && window.print) { // IE5",
075:                    // Do not confuse Modeless windows (showModelessWindow) of IE5 with Modal Windows (showModalDialog) of IE4.
076:                    // While both remain the active window until closed, the later is somewhat a "pest" in that the rest of the
077:                    // page is "hung up" until the window is dismissed. We like modeless windows better.
078:                    // Note that links inside modeless windows are always launched in a new page.
079:                    "	//	messadminpopup = window.showModelessWindow('', 'MessAdminPopUpPage', ieFeatures);",
080:                    "	//} else {",
081:                    "		messadminpopup = window.open('', 'MessAdminPopUpPage', features);",
082:                    "		if (!messadminpopup.closed) { messadminpopup.close(); }",
083:                    "		messadminpopup = window.open('', 'MessAdminPopUpPage', features);",
084:                    "	//}",
085:                    "	if (!messadminpopup.opener) { messadminpopup.opener = self; }",
086:                    "	messadminpopup.document.writeln('<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">');",
087:                    "	messadminpopup.document.writeln('<html>');",
088:                    "	messadminpopup.document.writeln('<head><title>Administrative message</title></head>');",
089:                    "	messadminpopup.document.writeln('<body onload=\"window.focus()\" onblur=\"self.focus()\">');",
090:                    "	messadminpopup.document.writeln('" };
091:            private static final String[] SCRIPT_END = new String[] { "');",
092:                    "	messadminpopup.document.writeln('</body></html>');",
093:                    "	//self.blur();",
094:                    "	setTimeout('messadminpopup.focus()', 500);",
095:                    "	messadminpopup.focus();",
096:                    //"	document.body.getAttributeNode('onunload').value = 'messadminpopup.close();' + document.body.getAttributeNode('onunload').value;",
097:                    "// -->", "</script>" };
098:
099:            private static final short JS_SCRIPT_SIZE;//bytes
100:
101:            static {
102:                short scriptSize = 0;
103:                for (int i = 0; i < SCRIPT_BEGIN.length; ++i) {
104:                    String line = SCRIPT_BEGIN[i];
105:                    scriptSize += 1 + line.length();//FIXME: depends on encoding!
106:                }
107:                for (int i = 0; i < SCRIPT_END.length; ++i) {
108:                    String line = SCRIPT_END[i];
109:                    scriptSize += 1 + line.length();//FIXME: depends on encoding!
110:                }
111:                JS_SCRIPT_SIZE = scriptSize;
112:
113:                // @since 2.4
114:                try {
115:                    getContentType = ServletResponse.class.getMethod(
116:                            "getContentType", null);//$NON-NLS-1$
117:                } catch (SecurityException e) {
118:                } catch (NoSuchMethodException e) {
119:                }
120:            }
121:
122:            protected String injectedMessageHTML = null;
123:            protected boolean shouldInject = false;
124:            protected boolean messageInjected = false;
125:            private HttpServletResponse httpResponse;
126:            private int contentLength = -1;
127:            private String contentType = null;
128:            private PrintWriter writer = null;
129:            private ServletOutputStream stream = null;
130:            protected long responseLength = -1;
131:            protected int status;
132:
133:            /**
134:             * @param response
135:             */
136:            public MessAdminResponseWrapper(HttpServletResponse response) {
137:                super (response);
138:                this .httpResponse = response;
139:                if (getContentType != null) {
140:                    //contentType = response.getContentType();
141:                    try {
142:                        contentType = (String) getContentType.invoke(response,
143:                                null);
144:                        setShouldInject();
145:                    } catch (IllegalArgumentException iae) {
146:                    } catch (IllegalAccessException iae) {
147:                    } catch (InvocationTargetException ite) {
148:                    }
149:                }
150:            }
151:
152:            public int getContentLength() {
153:                return contentLength;
154:            }
155:
156:            /** {@inheritDoc} */
157:            //  @Override
158:            public void setContentLength(int len) {
159:                int realLength = len;
160:                if (shouldInject) {
161:                    realLength += JS_SCRIPT_SIZE + injectedMessageHTML.length();//FIXME: depends on encoding!
162:                }
163:                super .setContentLength(realLength);
164:                contentLength = realLength;
165:            }
166:
167:            /**
168:             * Will only be valid at end of response cycle, when reponse is flush'ed.
169:             * @return byte count of response
170:             */
171:            public long getResponseLength() {
172:                return (responseLength == -1) ? responseLength
173:                        : responseLength + 1;
174:            }
175:
176:            /** {@inheritDoc} */
177:            //  @Override
178:            public void setContentType(String type) {
179:                super .setContentType(type);
180:                contentType = type;
181:                setShouldInject();
182:            }
183:
184:            /** {@inheritDoc} */
185:            public void setStatus(int sc) {
186:                super .setStatus(sc);
187:                status = sc;
188:            }
189:
190:            public int getStatus() {
191:                return status;
192:            }
193:
194:            protected void setWarning() {
195:                setShouldInject();
196:                if (shouldInject && !httpResponse.isCommitted()) {
197:                    String warnAgent = null;
198:                    try {
199:                        warnAgent = InetAddress.getLocalHost().toString();
200:                    } catch (Exception e) {
201:                        warnAgent = "MessAdmin/" + MessAdmin.getVersion();
202:                    }
203:                    httpResponse
204:                            .addHeader(
205:                                    "Warning",
206:                                    "199 "
207:                                            + warnAgent
208:                                            + " MessAdmin injected a popup message in this message.");
209:                    // 199 Miscellaneous warning The warning text MAY include arbitrary information to be presented to a human user, or logged.
210:                    // A system receiving this warning MUST NOT take any automated action, besides presenting the warning to the user.
211:                }
212:            }
213:
214:            //  @Override
215:            public synchronized PrintWriter getWriter() throws IOException {
216:                setWarning();
217:                if (writer == null) {
218:                    writer = new CountingInjectorPrintWriter(super .getWriter());
219:                }
220:                return writer;
221:            }
222:
223:            /** BUG: if <head> has attributes, it won't be catched. FIXME! Look for </head> instead (more difficult: buffering) or knowledge of spaces+attributes */
224:            protected class CountingInjectorPrintWriter extends PrintWriter {
225:                private final char[] search = new char[] { '<', 'h', 'e', 'a',
226:                        'd', '>' };
227:                private byte pos = 0;
228:
229:                public CountingInjectorPrintWriter(PrintWriter outWriter) {
230:                    super (outWriter);
231:                }
232:
233:                /** {@inheritDoc} */
234:                public void write(int c) {
235:                    if (shouldInject) {
236:                        // look for <head> and inject
237:                        if (Character.toLowerCase((char) c) == search[pos]) {
238:                            ++pos;
239:                        } else {
240:                            pos = 0;
241:                        }
242:                        if (pos >= search.length) {
243:                            try {
244:                                super .write(c);
245:                                ++responseLength;
246:                                // inject message immediatly after '<head>'
247:                                injectMessage((PrintWriter) out);
248:                            } catch (IOException e) {
249:                                setError();
250:                            }
251:                            shouldInject = false;//should not be required, but more prudent...
252:                            pos = 0;
253:                            return;
254:                        }
255:                    }
256:                    super .write(c);
257:                    ++responseLength;
258:                }
259:
260:                /** {@inheritDoc} */
261:                public void write(char[] cbuf, int off, int len) {
262:                    if (shouldInject) {
263:                        // look for <head> and inject
264:                        for (int i = off; i < off + len; ++i) {
265:                            if (Character.toLowerCase(cbuf[i]) == search[pos]) {
266:                                ++pos;
267:                            } else {
268:                                pos = 0;
269:                            }
270:                            if (pos >= search.length) {
271:                                try {
272:                                    ++i;//we can because of return at end
273:                                    super .write(cbuf, off, i - off);
274:                                    // inject message immediatly after '<head>'
275:                                    injectMessage((PrintWriter) out);
276:                                    super .write(cbuf, off + i, len - (i - off));
277:                                    responseLength += len - off;
278:                                } catch (IOException e) {
279:                                    setError();
280:                                }
281:                                shouldInject = false;//should not be required, but more prudent...
282:                                pos = 0;
283:                                return;
284:                            }
285:                        }
286:                    }
287:                    super .write(cbuf, off, len);
288:                    responseLength += len - off;
289:                }
290:
291:                /** {@inheritDoc} */
292:                public void write(String s, int off, int len) {
293:                    if (shouldInject) {
294:                        // look for <head> and inject
295:                        for (int i = off; i < off + len; ++i) {
296:                            if (Character.toLowerCase(s.charAt(i)) == search[pos]) {
297:                                ++pos;
298:                            } else {
299:                                pos = 0;
300:                            }
301:                            if (pos >= search.length) {
302:                                try {
303:                                    ++i;//we can because of return at end
304:                                    super .write(s, off, i - off);
305:                                    // inject message immediatly after '<head>'
306:                                    injectMessage((PrintWriter) out);
307:                                    super .write(s, off + i, len - (i - off));
308:                                    responseLength += len - off;//FIXME: depends on encoding!
309:                                } catch (IOException e) {
310:                                    setError();
311:                                }
312:                                shouldInject = false;//should not be required, but more prudent...
313:                                pos = 0;
314:                                return;
315:                            }
316:                        }
317:                    }
318:                    super .write(s, off, len);
319:                    responseLength += len - off;//FIXME: depends on encoding!
320:                }
321:
322:            }
323:
324:            /** {@inheritDoc} */
325:            //  @Override
326:            public synchronized ServletOutputStream getOutputStream()
327:                    throws IOException {
328:                setWarning();
329:                if (stream == null) {
330:                    stream = new CountingServletOutputStream(super 
331:                            .getOutputStream());
332:                }
333:                return stream;
334:            }
335:
336:            protected class CountingServletOutputStream extends
337:                    ServletOutputStream {
338:                protected ServletOutputStream out;
339:
340:                public CountingServletOutputStream(ServletOutputStream out) {
341:                    this .out = out;
342:                }
343:
344:                /** {@inheritDoc} */
345:                public void write(int b) throws IOException {
346:                    out.write(b);
347:                    ++responseLength;
348:                }
349:            }
350:
351:            /**
352:             * Injects code in output stream
353:             * mess up with response encoding (convert message from UTF to XYZ)? No: handled by the PrintWriter
354:             * @return true if message was injected, false otherwise
355:             * @throws IOException 
356:             */
357:            public boolean finish() throws IOException {
358:                try {
359:                    PrintWriter out = httpResponse.getWriter();
360:                    return injectMessage(out);
361:                } catch (IllegalStateException ise) {
362:                    // abort, don't do anything: getOutputStream() was previously called
363:                    if (DEBUG) {
364:                        System.err
365:                                .println(this .getClass().getName()
366:                                        + ": can't inject: " + ise.getLocalizedMessage());//$NON-NLS-1$
367:                    }
368:                }
369:                return false;
370:            }
371:
372:            protected boolean injectMessage(PrintWriter out) throws IOException {
373:                setShouldInject();
374:                if (!shouldInject) {
375:                    // no message to inject
376:                    return false;
377:                }
378:                out.println();
379:                for (int i = 0; i < SCRIPT_BEGIN.length - 1; ++i) {
380:                    String line = SCRIPT_BEGIN[i];
381:                    out.println(line);
382:                }
383:                out.print(SCRIPT_BEGIN[SCRIPT_BEGIN.length - 1]);
384:                escapeJavaStyleString(out, injectedMessageHTML, true);
385:                for (int i = 0; i < SCRIPT_END.length; ++i) {
386:                    String line = SCRIPT_END[i];
387:                    out.println(line);
388:                }
389:                if (DEBUG) {
390:                    System.out.println(this .getClass().getName()
391:                            + ": injected message");//$NON-NLS-1$
392:                }
393:                responseLength += JS_SCRIPT_SIZE + injectedMessageHTML.length();//FIXME: depends on encoding!
394:                shouldInject = false;
395:                injectedMessageHTML = null; // message is gone; information used by MessAdminFilter
396:                messageInjected = true;
397:                return true;
398:            }
399:
400:            public String getInjectedMessageHTML() {
401:                return injectedMessageHTML;
402:            }
403:
404:            public void setInjectedMessageHTML(String in_injectedMessage) {
405:                injectedMessageHTML = in_injectedMessage;
406:                setShouldInject();
407:            }
408:
409:            private void setShouldInject() {
410:                // is there a message to inject?
411:                shouldInject = (injectedMessageHTML != null
412:                        && injectedMessageHTML.length() != 0 && !"".equals(injectedMessageHTML.trim()));//$NON-NLS-1$
413:                // does the contentType allow HTML injection?
414:                final String l_contentType = (contentType != null) ? contentType
415:                        .toLowerCase()
416:                        : "";//$NON-NLS-1$
417:                if (shouldInject
418:                        && (l_contentType.indexOf("text/html") == -1) && (l_contentType.indexOf("application/xhtml+xml") == -1)) {//$NON-NLS-1$ //$NON-NLS-2$
419:                    // don't inject anything in non-html stuff or if no message to inject!
420:                    shouldInject = false;
421:                    if (DEBUG) {
422:                        System.out.println(this .getClass().getName()
423:                                + ": no injection (not html)");//$NON-NLS-1$
424:                    }
425:                }
426:            }
427:
428:            public boolean isMessageInjected() {
429:                return messageInjected;
430:            }
431:
432:            /**
433:             * COPIED FROM COMMONS-LANG 2.1 org.apache.commons.lang.StringEscapeUtils
434:             * 
435:             * <p>Escapes the characters in a <code>String</code> using JavaScript String rules
436:             * to a <code>Writer</code>.</p>
437:             * 
438:             * <p>Escapes any values it finds into their JavaScript String form.
439:             * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
440:             *
441:             * <p>So a tab becomes the characters <code>'\\'</code> and
442:             * <code>'t'</code>.</p>
443:             *
444:             * <p>The only difference between Java strings and JavaScript strings
445:             * is that in JavaScript, a single quote must be escaped.</p>
446:             *
447:             * <p>Example:
448:             * <pre>
449:             * input string: He didn't say, "Stop!"
450:             * output string: He didn\'t say, \"Stop!\"
451:             * </pre>
452:             * </p>
453:             *
454:             * <p>A <code>null</code> string input has no effect.</p>
455:             * 
456:             * @param out  Writer to write escaped string into
457:             * @param str  String to escape values in, may be null
458:             * @throws IllegalArgumentException if the Writer is <code>null</code>
459:             * @throws IOException if error occurs on undelying Writer
460:             **/
461:            private static void escapeJavaStyleString(Writer out, String str,
462:                    boolean escapeSingleQuote) throws IOException {
463:                if (out == null) {
464:                    throw new IllegalArgumentException(
465:                            "The Writer must not be null");//$NON-NLS-1$
466:                }
467:                if (str == null) {
468:                    return;
469:                }
470:                int sz;
471:                sz = str.length();
472:                for (int i = 0; i < sz; ++i) {
473:                    char ch = str.charAt(i);
474:
475:                    // handle unicode
476:                    if (ch > 0xfff) {
477:                        out.write("\\u" + hex(ch));//$NON-NLS-1$
478:                    } else if (ch > 0xff) {
479:                        out.write("\\u0" + hex(ch));//$NON-NLS-1$
480:                    } else if (ch > 0x7f) {
481:                        out.write("\\u00" + hex(ch));//$NON-NLS-1$
482:                    } else if (ch < 32) {
483:                        switch (ch) {
484:                        case '\b':
485:                            out.write('\\');
486:                            out.write('b');
487:                            break;
488:                        case '\n':
489:                            out.write('\\');
490:                            out.write('n');
491:                            break;
492:                        case '\t':
493:                            out.write('\\');
494:                            out.write('t');
495:                            break;
496:                        case '\f':
497:                            out.write('\\');
498:                            out.write('f');
499:                            break;
500:                        case '\r':
501:                            out.write('\\');
502:                            out.write('r');
503:                            break;
504:                        default:
505:                            if (ch > 0xf) {
506:                                out.write("\\u00" + hex(ch));//$NON-NLS-1$
507:                            } else {
508:                                out.write("\\u000" + hex(ch));//$NON-NLS-1$
509:                            }
510:                            break;
511:                        }
512:                    } else {
513:                        switch (ch) {
514:                        case '\'':
515:                            if (escapeSingleQuote) {
516:                                out.write('\\');
517:                            }
518:                            out.write('\'');
519:                            break;
520:                        case '"':
521:                            out.write('\\');
522:                            out.write('"');
523:                            break;
524:                        case '\\':
525:                            out.write('\\');
526:                            out.write('\\');
527:                            break;
528:                        default:
529:                            out.write(ch);
530:                            break;
531:                        }
532:                    }
533:                }
534:            }
535:
536:            /**
537:             * COPIED FROM COMMONS-LANG 2.1 org.apache.commons.lang.StringEscapeUtils
538:             * 
539:             * <p>Returns an upper case hexadecimal <code>String</code> for the given
540:             * character.</p>
541:             * 
542:             * @param ch The character to convert.
543:             * @return An upper case hexadecimal <code>String</code>
544:             */
545:            private static String hex(char ch) {
546:                return Integer.toHexString(ch).toUpperCase();
547:            }
548:
549:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.