Source Code Cross Referenced for Response.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » catalina » connector » 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 » Sevlet Container » apache tomcat 6.0.14 » org.apache.catalina.connector 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.catalina.connector;
0019:
0020:        import java.io.IOException;
0021:        import java.io.OutputStream;
0022:        import java.io.PrintWriter;
0023:        import java.net.MalformedURLException;
0024:        import java.security.AccessController;
0025:        import java.security.PrivilegedAction;
0026:        import java.security.PrivilegedActionException;
0027:        import java.security.PrivilegedExceptionAction;
0028:        import java.text.SimpleDateFormat;
0029:        import java.util.ArrayList;
0030:        import java.util.Enumeration;
0031:        import java.util.Locale;
0032:        import java.util.TimeZone;
0033:        import java.util.Vector;
0034:
0035:        import javax.servlet.ServletOutputStream;
0036:        import javax.servlet.http.Cookie;
0037:        import javax.servlet.http.HttpServletResponse;
0038:
0039:        import org.apache.catalina.Context;
0040:        import org.apache.catalina.Globals;
0041:        import org.apache.catalina.Session;
0042:        import org.apache.catalina.Wrapper;
0043:        import org.apache.catalina.security.SecurityUtil;
0044:        import org.apache.catalina.util.CharsetMapper;
0045:        import org.apache.catalina.util.DateTool;
0046:        import org.apache.catalina.util.StringManager;
0047:        import org.apache.tomcat.util.buf.CharChunk;
0048:        import org.apache.tomcat.util.buf.UEncoder;
0049:        import org.apache.tomcat.util.http.FastHttpDateFormat;
0050:        import org.apache.tomcat.util.http.MimeHeaders;
0051:        import org.apache.tomcat.util.http.ServerCookie;
0052:        import org.apache.tomcat.util.net.URL;
0053:
0054:        /**
0055:         * Wrapper object for the Coyote response.
0056:         *
0057:         * @author Remy Maucherat
0058:         * @author Craig R. McClanahan
0059:         * @version $Revision: 555304 $ $Date: 2007-07-11 17:28:52 +0200 (mer., 11 juil. 2007) $
0060:         */
0061:
0062:        public class Response implements  HttpServletResponse {
0063:
0064:            // ----------------------------------------------------------- Constructors
0065:
0066:            static {
0067:                // Ensure that URL is loaded for SM
0068:                URL.isSchemeChar('c');
0069:            }
0070:
0071:            public Response() {
0072:                urlEncoder.addSafeCharacter('/');
0073:            }
0074:
0075:            // ----------------------------------------------------- Class Variables
0076:
0077:            /**
0078:             * Descriptive information about this Response implementation.
0079:             */
0080:            protected static final String info = "org.apache.coyote.tomcat5.CoyoteResponse/1.0";
0081:
0082:            /**
0083:             * The string manager for this package.
0084:             */
0085:            protected static StringManager sm = StringManager
0086:                    .getManager(Constants.Package);
0087:
0088:            // ----------------------------------------------------- Instance Variables
0089:
0090:            /**
0091:             * The date format we will use for creating date headers.
0092:             */
0093:            protected SimpleDateFormat format = null;
0094:
0095:            // ------------------------------------------------------------- Properties
0096:
0097:            /**
0098:             * Associated Catalina connector.
0099:             */
0100:            protected Connector connector;
0101:
0102:            /**
0103:             * Return the Connector through which this Request was received.
0104:             */
0105:            public Connector getConnector() {
0106:                return (this .connector);
0107:            }
0108:
0109:            /**
0110:             * Set the Connector through which this Request was received.
0111:             *
0112:             * @param connector The new connector
0113:             */
0114:            public void setConnector(Connector connector) {
0115:                this .connector = connector;
0116:                if ("AJP/1.3".equals(connector.getProtocol())) {
0117:                    // default size to size of one ajp-packet
0118:                    outputBuffer = new OutputBuffer(8184);
0119:                } else {
0120:                    outputBuffer = new OutputBuffer();
0121:                }
0122:                outputStream = new CoyoteOutputStream(outputBuffer);
0123:                writer = new CoyoteWriter(outputBuffer);
0124:            }
0125:
0126:            /**
0127:             * Coyote response.
0128:             */
0129:            protected org.apache.coyote.Response coyoteResponse;
0130:
0131:            /**
0132:             * Set the Coyote response.
0133:             * 
0134:             * @param coyoteResponse The Coyote response
0135:             */
0136:            public void setCoyoteResponse(
0137:                    org.apache.coyote.Response coyoteResponse) {
0138:                this .coyoteResponse = coyoteResponse;
0139:                outputBuffer.setResponse(coyoteResponse);
0140:            }
0141:
0142:            /**
0143:             * Get the Coyote response.
0144:             */
0145:            public org.apache.coyote.Response getCoyoteResponse() {
0146:                return (coyoteResponse);
0147:            }
0148:
0149:            /**
0150:             * Return the Context within which this Request is being processed.
0151:             */
0152:            public Context getContext() {
0153:                return (request.getContext());
0154:            }
0155:
0156:            /**
0157:             * Set the Context within which this Request is being processed.  This
0158:             * must be called as soon as the appropriate Context is identified, because
0159:             * it identifies the value to be returned by <code>getContextPath()</code>,
0160:             * and thus enables parsing of the request URI.
0161:             *
0162:             * @param context The newly associated Context
0163:             */
0164:            public void setContext(Context context) {
0165:                request.setContext(context);
0166:            }
0167:
0168:            /**
0169:             * The associated output buffer.
0170:             */
0171:            protected OutputBuffer outputBuffer;
0172:
0173:            /**
0174:             * The associated output stream.
0175:             */
0176:            protected CoyoteOutputStream outputStream;
0177:
0178:            /**
0179:             * The associated writer.
0180:             */
0181:            protected CoyoteWriter writer;
0182:
0183:            /**
0184:             * The application commit flag.
0185:             */
0186:            protected boolean appCommitted = false;
0187:
0188:            /**
0189:             * The included flag.
0190:             */
0191:            protected boolean included = false;
0192:
0193:            /**
0194:             * The characterEncoding flag
0195:             */
0196:            private boolean isCharacterEncodingSet = false;
0197:
0198:            /**
0199:             * The error flag.
0200:             */
0201:            protected boolean error = false;
0202:
0203:            /**
0204:             * The set of Cookies associated with this Response.
0205:             */
0206:            protected ArrayList cookies = new ArrayList();
0207:
0208:            /**
0209:             * Using output stream flag.
0210:             */
0211:            protected boolean usingOutputStream = false;
0212:
0213:            /**
0214:             * Using writer flag.
0215:             */
0216:            protected boolean usingWriter = false;
0217:
0218:            /**
0219:             * URL encoder.
0220:             */
0221:            protected UEncoder urlEncoder = new UEncoder();
0222:
0223:            /**
0224:             * Recyclable buffer to hold the redirect URL.
0225:             */
0226:            protected CharChunk redirectURLCC = new CharChunk();
0227:
0228:            // --------------------------------------------------------- Public Methods
0229:
0230:            /**
0231:             * Release all object references, and initialize instance variables, in
0232:             * preparation for reuse of this object.
0233:             */
0234:            public void recycle() {
0235:
0236:                outputBuffer.recycle();
0237:                usingOutputStream = false;
0238:                usingWriter = false;
0239:                appCommitted = false;
0240:                included = false;
0241:                error = false;
0242:                isCharacterEncodingSet = false;
0243:
0244:                cookies.clear();
0245:
0246:                if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
0247:                    if (facade != null) {
0248:                        facade.clear();
0249:                        facade = null;
0250:                    }
0251:                    if (outputStream != null) {
0252:                        outputStream.clear();
0253:                        outputStream = null;
0254:                    }
0255:                    if (writer != null) {
0256:                        writer.clear();
0257:                        writer = null;
0258:                    }
0259:                } else {
0260:                    writer.recycle();
0261:                }
0262:
0263:            }
0264:
0265:            /**
0266:             * Clear cached encoders (to save memory for Comet requests).
0267:             */
0268:            public void clearEncoders() {
0269:                outputBuffer.clearEncoders();
0270:            }
0271:
0272:            // ------------------------------------------------------- Response Methods
0273:
0274:            /**
0275:             * Return the number of bytes actually written to the output stream.
0276:             */
0277:            public int getContentCount() {
0278:                return outputBuffer.getContentWritten();
0279:            }
0280:
0281:            /**
0282:             * Set the application commit flag.
0283:             * 
0284:             * @param appCommitted The new application committed flag value
0285:             */
0286:            public void setAppCommitted(boolean appCommitted) {
0287:                this .appCommitted = appCommitted;
0288:            }
0289:
0290:            /**
0291:             * Application commit flag accessor.
0292:             */
0293:            public boolean isAppCommitted() {
0294:                return (this .appCommitted || isCommitted() || isSuspended() || ((getContentLength() > 0) && (getContentCount() >= getContentLength())));
0295:            }
0296:
0297:            /**
0298:             * Return the "processing inside an include" flag.
0299:             */
0300:            public boolean getIncluded() {
0301:                return included;
0302:            }
0303:
0304:            /**
0305:             * Set the "processing inside an include" flag.
0306:             *
0307:             * @param included <code>true</code> if we are currently inside a
0308:             *  RequestDispatcher.include(), else <code>false</code>
0309:             */
0310:            public void setIncluded(boolean included) {
0311:                this .included = included;
0312:            }
0313:
0314:            /**
0315:             * Return descriptive information about this Response implementation and
0316:             * the corresponding version number, in the format
0317:             * <code>&lt;description&gt;/&lt;version&gt;</code>.
0318:             */
0319:            public String getInfo() {
0320:                return (info);
0321:            }
0322:
0323:            /**
0324:             * The request with which this response is associated.
0325:             */
0326:            protected Request request = null;
0327:
0328:            /**
0329:             * Return the Request with which this Response is associated.
0330:             */
0331:            public org.apache.catalina.connector.Request getRequest() {
0332:                return (this .request);
0333:            }
0334:
0335:            /**
0336:             * Set the Request with which this Response is associated.
0337:             *
0338:             * @param request The new associated request
0339:             */
0340:            public void setRequest(org.apache.catalina.connector.Request request) {
0341:                this .request = (Request) request;
0342:            }
0343:
0344:            /**
0345:             * The facade associated with this response.
0346:             */
0347:            protected ResponseFacade facade = null;
0348:
0349:            /**
0350:             * Return the <code>ServletResponse</code> for which this object
0351:             * is the facade.
0352:             */
0353:            public HttpServletResponse getResponse() {
0354:                if (facade == null) {
0355:                    facade = new ResponseFacade(this );
0356:                }
0357:                return (facade);
0358:            }
0359:
0360:            /**
0361:             * Return the output stream associated with this Response.
0362:             */
0363:            public OutputStream getStream() {
0364:                if (outputStream == null) {
0365:                    outputStream = new CoyoteOutputStream(outputBuffer);
0366:                }
0367:                return outputStream;
0368:            }
0369:
0370:            /**
0371:             * Set the output stream associated with this Response.
0372:             *
0373:             * @param stream The new output stream
0374:             */
0375:            public void setStream(OutputStream stream) {
0376:                // This method is evil
0377:            }
0378:
0379:            /**
0380:             * Set the suspended flag.
0381:             * 
0382:             * @param suspended The new suspended flag value
0383:             */
0384:            public void setSuspended(boolean suspended) {
0385:                outputBuffer.setSuspended(suspended);
0386:            }
0387:
0388:            /**
0389:             * Suspended flag accessor.
0390:             */
0391:            public boolean isSuspended() {
0392:                return outputBuffer.isSuspended();
0393:            }
0394:
0395:            /**
0396:             * Closed flag accessor.
0397:             */
0398:            public boolean isClosed() {
0399:                return outputBuffer.isClosed();
0400:            }
0401:
0402:            /**
0403:             * Set the error flag.
0404:             */
0405:            public void setError() {
0406:                error = true;
0407:            }
0408:
0409:            /**
0410:             * Error flag accessor.
0411:             */
0412:            public boolean isError() {
0413:                return error;
0414:            }
0415:
0416:            /**
0417:             * Create and return a ServletOutputStream to write the content
0418:             * associated with this Response.
0419:             *
0420:             * @exception IOException if an input/output error occurs
0421:             */
0422:            public ServletOutputStream createOutputStream() throws IOException {
0423:                // Probably useless
0424:                if (outputStream == null) {
0425:                    outputStream = new CoyoteOutputStream(outputBuffer);
0426:                }
0427:                return outputStream;
0428:            }
0429:
0430:            /**
0431:             * Perform whatever actions are required to flush and close the output
0432:             * stream or writer, in a single operation.
0433:             *
0434:             * @exception IOException if an input/output error occurs
0435:             */
0436:            public void finishResponse() throws IOException {
0437:                // Writing leftover bytes
0438:                outputBuffer.close();
0439:            }
0440:
0441:            /**
0442:             * Return the content length that was set or calculated for this Response.
0443:             */
0444:            public int getContentLength() {
0445:                return (coyoteResponse.getContentLength());
0446:            }
0447:
0448:            /**
0449:             * Return the content type that was set or calculated for this response,
0450:             * or <code>null</code> if no content type was set.
0451:             */
0452:            public String getContentType() {
0453:                return (coyoteResponse.getContentType());
0454:            }
0455:
0456:            /**
0457:             * Return a PrintWriter that can be used to render error messages,
0458:             * regardless of whether a stream or writer has already been acquired.
0459:             *
0460:             * @return Writer which can be used for error reports. If the response is
0461:             * not an error report returned using sendError or triggered by an
0462:             * unexpected exception thrown during the servlet processing
0463:             * (and only in that case), null will be returned if the response stream
0464:             * has already been used.
0465:             *
0466:             * @exception IOException if an input/output error occurs
0467:             */
0468:            public PrintWriter getReporter() throws IOException {
0469:                if (outputBuffer.isNew()) {
0470:                    outputBuffer.checkConverter();
0471:                    if (writer == null) {
0472:                        writer = new CoyoteWriter(outputBuffer);
0473:                    }
0474:                    return writer;
0475:                } else {
0476:                    return null;
0477:                }
0478:            }
0479:
0480:            // ------------------------------------------------ ServletResponse Methods
0481:
0482:            /**
0483:             * Flush the buffer and commit this response.
0484:             *
0485:             * @exception IOException if an input/output error occurs
0486:             */
0487:            public void flushBuffer() throws IOException {
0488:                outputBuffer.flush();
0489:            }
0490:
0491:            /**
0492:             * Return the actual buffer size used for this Response.
0493:             */
0494:            public int getBufferSize() {
0495:                return outputBuffer.getBufferSize();
0496:            }
0497:
0498:            /**
0499:             * Return the character encoding used for this Response.
0500:             */
0501:            public String getCharacterEncoding() {
0502:                return (coyoteResponse.getCharacterEncoding());
0503:            }
0504:
0505:            /**
0506:             * Return the servlet output stream associated with this Response.
0507:             *
0508:             * @exception IllegalStateException if <code>getWriter</code> has
0509:             *  already been called for this response
0510:             * @exception IOException if an input/output error occurs
0511:             */
0512:            public ServletOutputStream getOutputStream() throws IOException {
0513:
0514:                if (usingWriter)
0515:                    throw new IllegalStateException(sm
0516:                            .getString("coyoteResponse.getOutputStream.ise"));
0517:
0518:                usingOutputStream = true;
0519:                if (outputStream == null) {
0520:                    outputStream = new CoyoteOutputStream(outputBuffer);
0521:                }
0522:                return outputStream;
0523:
0524:            }
0525:
0526:            /**
0527:             * Return the Locale assigned to this response.
0528:             */
0529:            public Locale getLocale() {
0530:                return (coyoteResponse.getLocale());
0531:            }
0532:
0533:            /**
0534:             * Return the writer associated with this Response.
0535:             *
0536:             * @exception IllegalStateException if <code>getOutputStream</code> has
0537:             *  already been called for this response
0538:             * @exception IOException if an input/output error occurs
0539:             */
0540:            public PrintWriter getWriter() throws IOException {
0541:
0542:                if (usingOutputStream)
0543:                    throw new IllegalStateException(sm
0544:                            .getString("coyoteResponse.getWriter.ise"));
0545:
0546:                if (Globals.STRICT_SERVLET_COMPLIANCE) {
0547:                    /*
0548:                     * If the response's character encoding has not been specified as
0549:                     * described in <code>getCharacterEncoding</code> (i.e., the method
0550:                     * just returns the default value <code>ISO-8859-1</code>),
0551:                     * <code>getWriter</code> updates it to <code>ISO-8859-1</code>
0552:                     * (with the effect that a subsequent call to getContentType() will
0553:                     * include a charset=ISO-8859-1 component which will also be
0554:                     * reflected in the Content-Type response header, thereby satisfying
0555:                     * the Servlet spec requirement that containers must communicate the
0556:                     * character encoding used for the servlet response's writer to the
0557:                     * client).
0558:                     */
0559:                    setCharacterEncoding(getCharacterEncoding());
0560:                }
0561:
0562:                usingWriter = true;
0563:                outputBuffer.checkConverter();
0564:                if (writer == null) {
0565:                    writer = new CoyoteWriter(outputBuffer);
0566:                }
0567:                return writer;
0568:
0569:            }
0570:
0571:            /**
0572:             * Has the output of this response already been committed?
0573:             */
0574:            public boolean isCommitted() {
0575:                return (coyoteResponse.isCommitted());
0576:            }
0577:
0578:            /**
0579:             * Clear any content written to the buffer.
0580:             *
0581:             * @exception IllegalStateException if this response has already
0582:             *  been committed
0583:             */
0584:            public void reset() {
0585:
0586:                if (included)
0587:                    return; // Ignore any call from an included servlet
0588:
0589:                coyoteResponse.reset();
0590:                outputBuffer.reset();
0591:            }
0592:
0593:            /**
0594:             * Reset the data buffer but not any status or header information.
0595:             *
0596:             * @exception IllegalStateException if the response has already
0597:             *  been committed
0598:             */
0599:            public void resetBuffer() {
0600:
0601:                if (isCommitted())
0602:                    throw new IllegalStateException(sm
0603:                            .getString("coyoteResponse.resetBuffer.ise"));
0604:
0605:                outputBuffer.reset();
0606:
0607:            }
0608:
0609:            /**
0610:             * Set the buffer size to be used for this Response.
0611:             *
0612:             * @param size The new buffer size
0613:             *
0614:             * @exception IllegalStateException if this method is called after
0615:             *  output has been committed for this response
0616:             */
0617:            public void setBufferSize(int size) {
0618:
0619:                if (isCommitted() || !outputBuffer.isNew())
0620:                    throw new IllegalStateException(sm
0621:                            .getString("coyoteResponse.setBufferSize.ise"));
0622:
0623:                outputBuffer.setBufferSize(size);
0624:
0625:            }
0626:
0627:            /**
0628:             * Set the content length (in bytes) for this Response.
0629:             *
0630:             * @param length The new content length
0631:             */
0632:            public void setContentLength(int length) {
0633:
0634:                if (isCommitted())
0635:                    return;
0636:
0637:                // Ignore any call from an included servlet
0638:                if (included)
0639:                    return;
0640:
0641:                if (usingWriter)
0642:                    return;
0643:
0644:                coyoteResponse.setContentLength(length);
0645:
0646:            }
0647:
0648:            /**
0649:             * Set the content type for this Response.
0650:             *
0651:             * @param type The new content type
0652:             */
0653:            public void setContentType(String type) {
0654:
0655:                if (isCommitted())
0656:                    return;
0657:
0658:                // Ignore any call from an included servlet
0659:                if (included)
0660:                    return;
0661:
0662:                // Ignore charset if getWriter() has already been called
0663:                if (usingWriter) {
0664:                    if (type != null) {
0665:                        int index = type.indexOf(";");
0666:                        if (index != -1) {
0667:                            type = type.substring(0, index);
0668:                        }
0669:                    }
0670:                }
0671:
0672:                coyoteResponse.setContentType(type);
0673:
0674:                // Check to see if content type contains charset
0675:                if (type != null) {
0676:                    int index = type.indexOf(";");
0677:                    if (index != -1) {
0678:                        int len = type.length();
0679:                        index++;
0680:                        while (index < len
0681:                                && Character.isSpace(type.charAt(index))) {
0682:                            index++;
0683:                        }
0684:                        if (index + 7 < len && type.charAt(index) == 'c'
0685:                                && type.charAt(index + 1) == 'h'
0686:                                && type.charAt(index + 2) == 'a'
0687:                                && type.charAt(index + 3) == 'r'
0688:                                && type.charAt(index + 4) == 's'
0689:                                && type.charAt(index + 5) == 'e'
0690:                                && type.charAt(index + 6) == 't'
0691:                                && type.charAt(index + 7) == '=') {
0692:                            isCharacterEncodingSet = true;
0693:                        }
0694:                    }
0695:                }
0696:            }
0697:
0698:            /*
0699:             * Overrides the name of the character encoding used in the body
0700:             * of the request. This method must be called prior to reading
0701:             * request parameters or reading input using getReader().
0702:             *
0703:             * @param charset String containing the name of the chararacter encoding.
0704:             */
0705:            public void setCharacterEncoding(String charset) {
0706:
0707:                if (isCommitted())
0708:                    return;
0709:
0710:                // Ignore any call from an included servlet
0711:                if (included)
0712:                    return;
0713:
0714:                // Ignore any call made after the getWriter has been invoked
0715:                // The default should be used
0716:                if (usingWriter)
0717:                    return;
0718:
0719:                coyoteResponse.setCharacterEncoding(charset);
0720:                isCharacterEncodingSet = true;
0721:            }
0722:
0723:            /**
0724:             * Set the Locale that is appropriate for this response, including
0725:             * setting the appropriate character encoding.
0726:             *
0727:             * @param locale The new locale
0728:             */
0729:            public void setLocale(Locale locale) {
0730:
0731:                if (isCommitted())
0732:                    return;
0733:
0734:                // Ignore any call from an included servlet
0735:                if (included)
0736:                    return;
0737:
0738:                coyoteResponse.setLocale(locale);
0739:
0740:                // Ignore any call made after the getWriter has been invoked.
0741:                // The default should be used
0742:                if (usingWriter)
0743:                    return;
0744:
0745:                if (isCharacterEncodingSet) {
0746:                    return;
0747:                }
0748:
0749:                CharsetMapper cm = getContext().getCharsetMapper();
0750:                String charset = cm.getCharset(locale);
0751:                if (charset != null) {
0752:                    coyoteResponse.setCharacterEncoding(charset);
0753:                }
0754:
0755:            }
0756:
0757:            // --------------------------------------------------- HttpResponse Methods
0758:
0759:            /**
0760:             * Return an array of all cookies set for this response, or
0761:             * a zero-length array if no cookies have been set.
0762:             */
0763:            public Cookie[] getCookies() {
0764:                return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
0765:            }
0766:
0767:            /**
0768:             * Return the value for the specified header, or <code>null</code> if this
0769:             * header has not been set.  If more than one value was added for this
0770:             * name, only the first is returned; use getHeaderValues() to retrieve all
0771:             * of them.
0772:             *
0773:             * @param name Header name to look up
0774:             */
0775:            public String getHeader(String name) {
0776:                return coyoteResponse.getMimeHeaders().getHeader(name);
0777:            }
0778:
0779:            /**
0780:             * Return an array of all the header names set for this response, or
0781:             * a zero-length array if no headers have been set.
0782:             */
0783:            public String[] getHeaderNames() {
0784:
0785:                MimeHeaders headers = coyoteResponse.getMimeHeaders();
0786:                int n = headers.size();
0787:                String[] result = new String[n];
0788:                for (int i = 0; i < n; i++) {
0789:                    result[i] = headers.getName(i).toString();
0790:                }
0791:                return result;
0792:
0793:            }
0794:
0795:            /**
0796:             * Return an array of all the header values associated with the
0797:             * specified header name, or an zero-length array if there are no such
0798:             * header values.
0799:             *
0800:             * @param name Header name to look up
0801:             */
0802:            public String[] getHeaderValues(String name) {
0803:
0804:                Enumeration enumeration = coyoteResponse.getMimeHeaders()
0805:                        .values(name);
0806:                Vector result = new Vector();
0807:                while (enumeration.hasMoreElements()) {
0808:                    result.addElement(enumeration.nextElement());
0809:                }
0810:                String[] resultArray = new String[result.size()];
0811:                result.copyInto(resultArray);
0812:                return resultArray;
0813:
0814:            }
0815:
0816:            /**
0817:             * Return the error message that was set with <code>sendError()</code>
0818:             * for this Response.
0819:             */
0820:            public String getMessage() {
0821:                return coyoteResponse.getMessage();
0822:            }
0823:
0824:            /**
0825:             * Return the HTTP status code associated with this Response.
0826:             */
0827:            public int getStatus() {
0828:                return coyoteResponse.getStatus();
0829:            }
0830:
0831:            /**
0832:             * Reset this response, and specify the values for the HTTP status code
0833:             * and corresponding message.
0834:             *
0835:             * @exception IllegalStateException if this response has already been
0836:             *  committed
0837:             */
0838:            public void reset(int status, String message) {
0839:                reset();
0840:                setStatus(status, message);
0841:            }
0842:
0843:            // -------------------------------------------- HttpServletResponse Methods
0844:
0845:            /**
0846:             * Add the specified Cookie to those that will be included with
0847:             * this Response.
0848:             *
0849:             * @param cookie Cookie to be added
0850:             */
0851:            public void addCookie(final Cookie cookie) {
0852:
0853:                // Ignore any call from an included servlet
0854:                if (included)
0855:                    return;
0856:
0857:                addCookieInternal(cookie);
0858:
0859:            }
0860:
0861:            /**
0862:             * Add the specified Cookie to those that will be included with
0863:             * this Response.
0864:             *
0865:             * @param cookie Cookie to be added
0866:             */
0867:            public void addCookieInternal(final Cookie cookie) {
0868:
0869:                if (isCommitted())
0870:                    return;
0871:
0872:                cookies.add(cookie);
0873:
0874:                final StringBuffer sb = new StringBuffer();
0875:                if (SecurityUtil.isPackageProtectionEnabled()) {
0876:                    AccessController.doPrivileged(new PrivilegedAction() {
0877:                        public Object run() {
0878:                            ServerCookie.appendCookieValue(sb, cookie
0879:                                    .getVersion(), cookie.getName(), cookie
0880:                                    .getValue(), cookie.getPath(), cookie
0881:                                    .getDomain(), cookie.getComment(), cookie
0882:                                    .getMaxAge(), cookie.getSecure());
0883:                            return null;
0884:                        }
0885:                    });
0886:                } else {
0887:                    ServerCookie.appendCookieValue(sb, cookie.getVersion(),
0888:                            cookie.getName(), cookie.getValue(), cookie
0889:                                    .getPath(), cookie.getDomain(), cookie
0890:                                    .getComment(), cookie.getMaxAge(), cookie
0891:                                    .getSecure());
0892:                }
0893:
0894:                // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
0895:                // RFC2965 is not supported by browsers and the Servlet spec
0896:                // asks for 2109.
0897:                addHeader("Set-Cookie", sb.toString());
0898:
0899:            }
0900:
0901:            /**
0902:             * Add the specified date header to the specified value.
0903:             *
0904:             * @param name Name of the header to set
0905:             * @param value Date value to be set
0906:             */
0907:            public void addDateHeader(String name, long value) {
0908:
0909:                if (isCommitted())
0910:                    return;
0911:
0912:                // Ignore any call from an included servlet
0913:                if (included) {
0914:                    return;
0915:                }
0916:
0917:                if (format == null) {
0918:                    format = new SimpleDateFormat(
0919:                            DateTool.HTTP_RESPONSE_DATE_HEADER, Locale.US);
0920:                    format.setTimeZone(TimeZone.getTimeZone("GMT"));
0921:                }
0922:
0923:                addHeader(name, FastHttpDateFormat.formatDate(value, format));
0924:
0925:            }
0926:
0927:            /**
0928:             * Add the specified header to the specified value.
0929:             *
0930:             * @param name Name of the header to set
0931:             * @param value Value to be set
0932:             */
0933:            public void addHeader(String name, String value) {
0934:
0935:                if (isCommitted())
0936:                    return;
0937:
0938:                // Ignore any call from an included servlet
0939:                if (included)
0940:                    return;
0941:
0942:                coyoteResponse.addHeader(name, value);
0943:
0944:            }
0945:
0946:            /**
0947:             * Add the specified integer header to the specified value.
0948:             *
0949:             * @param name Name of the header to set
0950:             * @param value Integer value to be set
0951:             */
0952:            public void addIntHeader(String name, int value) {
0953:
0954:                if (isCommitted())
0955:                    return;
0956:
0957:                // Ignore any call from an included servlet
0958:                if (included)
0959:                    return;
0960:
0961:                addHeader(name, "" + value);
0962:
0963:            }
0964:
0965:            /**
0966:             * Has the specified header been set already in this response?
0967:             *
0968:             * @param name Name of the header to check
0969:             */
0970:            public boolean containsHeader(String name) {
0971:                // Need special handling for Content-Type and Content-Length due to
0972:                // special handling of these in coyoteResponse
0973:                char cc = name.charAt(0);
0974:                if (cc == 'C' || cc == 'c') {
0975:                    if (name.equalsIgnoreCase("Content-Type")) {
0976:                        // Will return null if this has not been set
0977:                        return (coyoteResponse.getContentType() != null);
0978:                    }
0979:                    if (name.equalsIgnoreCase("Content-Length")) {
0980:                        // -1 means not known and is not sent to client
0981:                        return (coyoteResponse.getContentLengthLong() != -1);
0982:                    }
0983:                }
0984:
0985:                return coyoteResponse.containsHeader(name);
0986:            }
0987:
0988:            /**
0989:             * Encode the session identifier associated with this response
0990:             * into the specified redirect URL, if necessary.
0991:             *
0992:             * @param url URL to be encoded
0993:             */
0994:            public String encodeRedirectURL(String url) {
0995:
0996:                if (isEncodeable(toAbsolute(url))) {
0997:                    return (toEncoded(url, request.getSessionInternal()
0998:                            .getIdInternal()));
0999:                } else {
1000:                    return (url);
1001:                }
1002:
1003:            }
1004:
1005:            /**
1006:             * Encode the session identifier associated with this response
1007:             * into the specified redirect URL, if necessary.
1008:             *
1009:             * @param url URL to be encoded
1010:             *
1011:             * @deprecated As of Version 2.1 of the Java Servlet API, use
1012:             *  <code>encodeRedirectURL()</code> instead.
1013:             */
1014:            public String encodeRedirectUrl(String url) {
1015:                return (encodeRedirectURL(url));
1016:            }
1017:
1018:            /**
1019:             * Encode the session identifier associated with this response
1020:             * into the specified URL, if necessary.
1021:             *
1022:             * @param url URL to be encoded
1023:             */
1024:            public String encodeURL(String url) {
1025:
1026:                String absolute = toAbsolute(url);
1027:                if (isEncodeable(absolute)) {
1028:                    // W3c spec clearly said 
1029:                    if (url.equalsIgnoreCase("")) {
1030:                        url = absolute;
1031:                    }
1032:                    return (toEncoded(url, request.getSessionInternal()
1033:                            .getIdInternal()));
1034:                } else {
1035:                    return (url);
1036:                }
1037:
1038:            }
1039:
1040:            /**
1041:             * Encode the session identifier associated with this response
1042:             * into the specified URL, if necessary.
1043:             *
1044:             * @param url URL to be encoded
1045:             *
1046:             * @deprecated As of Version 2.1 of the Java Servlet API, use
1047:             *  <code>encodeURL()</code> instead.
1048:             */
1049:            public String encodeUrl(String url) {
1050:                return (encodeURL(url));
1051:            }
1052:
1053:            /**
1054:             * Send an acknowledgment of a request.
1055:             * 
1056:             * @exception IOException if an input/output error occurs
1057:             */
1058:            public void sendAcknowledgement() throws IOException {
1059:
1060:                if (isCommitted())
1061:                    return;
1062:
1063:                // Ignore any call from an included servlet
1064:                if (included)
1065:                    return;
1066:
1067:                coyoteResponse.acknowledge();
1068:
1069:            }
1070:
1071:            /**
1072:             * Send an error response with the specified status and a
1073:             * default message.
1074:             *
1075:             * @param status HTTP status code to send
1076:             *
1077:             * @exception IllegalStateException if this response has
1078:             *  already been committed
1079:             * @exception IOException if an input/output error occurs
1080:             */
1081:            public void sendError(int status) throws IOException {
1082:                sendError(status, null);
1083:            }
1084:
1085:            /**
1086:             * Send an error response with the specified status and message.
1087:             *
1088:             * @param status HTTP status code to send
1089:             * @param message Corresponding message to send
1090:             *
1091:             * @exception IllegalStateException if this response has
1092:             *  already been committed
1093:             * @exception IOException if an input/output error occurs
1094:             */
1095:            public void sendError(int status, String message)
1096:                    throws IOException {
1097:
1098:                if (isCommitted())
1099:                    throw new IllegalStateException(sm
1100:                            .getString("coyoteResponse.sendError.ise"));
1101:
1102:                // Ignore any call from an included servlet
1103:                if (included)
1104:                    return;
1105:
1106:                Wrapper wrapper = getRequest().getWrapper();
1107:                if (wrapper != null) {
1108:                    wrapper.incrementErrorCount();
1109:                }
1110:
1111:                setError();
1112:
1113:                coyoteResponse.setStatus(status);
1114:                coyoteResponse.setMessage(message);
1115:
1116:                // Clear any data content that has been buffered
1117:                resetBuffer();
1118:
1119:                // Cause the response to be finished (from the application perspective)
1120:                setSuspended(true);
1121:
1122:            }
1123:
1124:            /**
1125:             * Send a temporary redirect to the specified redirect location URL.
1126:             *
1127:             * @param location Location URL to redirect to
1128:             *
1129:             * @exception IllegalStateException if this response has
1130:             *  already been committed
1131:             * @exception IOException if an input/output error occurs
1132:             */
1133:            public void sendRedirect(String location) throws IOException {
1134:
1135:                if (isCommitted())
1136:                    throw new IllegalStateException(sm
1137:                            .getString("coyoteResponse.sendRedirect.ise"));
1138:
1139:                // Ignore any call from an included servlet
1140:                if (included)
1141:                    return;
1142:
1143:                // Clear any data content that has been buffered
1144:                resetBuffer();
1145:
1146:                // Generate a temporary redirect to the specified location
1147:                try {
1148:                    String absolute = toAbsolute(location);
1149:                    setStatus(SC_FOUND);
1150:                    setHeader("Location", absolute);
1151:                } catch (IllegalArgumentException e) {
1152:                    setStatus(SC_NOT_FOUND);
1153:                }
1154:
1155:                // Cause the response to be finished (from the application perspective)
1156:                setSuspended(true);
1157:
1158:            }
1159:
1160:            /**
1161:             * Set the specified date header to the specified value.
1162:             *
1163:             * @param name Name of the header to set
1164:             * @param value Date value to be set
1165:             */
1166:            public void setDateHeader(String name, long value) {
1167:
1168:                if (isCommitted())
1169:                    return;
1170:
1171:                // Ignore any call from an included servlet
1172:                if (included) {
1173:                    return;
1174:                }
1175:
1176:                if (format == null) {
1177:                    format = new SimpleDateFormat(
1178:                            DateTool.HTTP_RESPONSE_DATE_HEADER, Locale.US);
1179:                    format.setTimeZone(TimeZone.getTimeZone("GMT"));
1180:                }
1181:
1182:                setHeader(name, FastHttpDateFormat.formatDate(value, format));
1183:
1184:            }
1185:
1186:            /**
1187:             * Set the specified header to the specified value.
1188:             *
1189:             * @param name Name of the header to set
1190:             * @param value Value to be set
1191:             */
1192:            public void setHeader(String name, String value) {
1193:
1194:                if (isCommitted())
1195:                    return;
1196:
1197:                // Ignore any call from an included servlet
1198:                if (included)
1199:                    return;
1200:
1201:                coyoteResponse.setHeader(name, value);
1202:
1203:            }
1204:
1205:            /**
1206:             * Set the specified integer header to the specified value.
1207:             *
1208:             * @param name Name of the header to set
1209:             * @param value Integer value to be set
1210:             */
1211:            public void setIntHeader(String name, int value) {
1212:
1213:                if (isCommitted())
1214:                    return;
1215:
1216:                // Ignore any call from an included servlet
1217:                if (included)
1218:                    return;
1219:
1220:                setHeader(name, "" + value);
1221:
1222:            }
1223:
1224:            /**
1225:             * Set the HTTP status to be returned with this response.
1226:             *
1227:             * @param status The new HTTP status
1228:             */
1229:            public void setStatus(int status) {
1230:                setStatus(status, null);
1231:            }
1232:
1233:            /**
1234:             * Set the HTTP status and message to be returned with this response.
1235:             *
1236:             * @param status The new HTTP status
1237:             * @param message The associated text message
1238:             *
1239:             * @deprecated As of Version 2.1 of the Java Servlet API, this method
1240:             *  has been deprecated due to the ambiguous meaning of the message
1241:             *  parameter.
1242:             */
1243:            public void setStatus(int status, String message) {
1244:
1245:                if (isCommitted())
1246:                    return;
1247:
1248:                // Ignore any call from an included servlet
1249:                if (included)
1250:                    return;
1251:
1252:                coyoteResponse.setStatus(status);
1253:                coyoteResponse.setMessage(message);
1254:
1255:            }
1256:
1257:            // ------------------------------------------------------ Protected Methods
1258:
1259:            /**
1260:             * Return <code>true</code> if the specified URL should be encoded with
1261:             * a session identifier.  This will be true if all of the following
1262:             * conditions are met:
1263:             * <ul>
1264:             * <li>The request we are responding to asked for a valid session
1265:             * <li>The requested session ID was not received via a cookie
1266:             * <li>The specified URL points back to somewhere within the web
1267:             *     application that is responding to this request
1268:             * </ul>
1269:             *
1270:             * @param location Absolute URL to be validated
1271:             */
1272:            protected boolean isEncodeable(final String location) {
1273:
1274:                if (location == null)
1275:                    return (false);
1276:
1277:                // Is this an intra-document reference?
1278:                if (location.startsWith("#"))
1279:                    return (false);
1280:
1281:                // Are we in a valid session that is not using cookies?
1282:                final Request hreq = request;
1283:                final Session session = hreq.getSessionInternal(false);
1284:                if (session == null)
1285:                    return (false);
1286:                if (hreq.isRequestedSessionIdFromCookie())
1287:                    return (false);
1288:
1289:                if (SecurityUtil.isPackageProtectionEnabled()) {
1290:                    return ((Boolean) AccessController
1291:                            .doPrivileged(new PrivilegedAction() {
1292:
1293:                                public Object run() {
1294:                                    return new Boolean(doIsEncodeable(hreq,
1295:                                            session, location));
1296:                                }
1297:                            })).booleanValue();
1298:                } else {
1299:                    return doIsEncodeable(hreq, session, location);
1300:                }
1301:            }
1302:
1303:            private boolean doIsEncodeable(Request hreq, Session session,
1304:                    String location) {
1305:                // Is this a valid absolute URL?
1306:                URL url = null;
1307:                try {
1308:                    url = new URL(location);
1309:                } catch (MalformedURLException e) {
1310:                    return (false);
1311:                }
1312:
1313:                // Does this URL match down to (and including) the context path?
1314:                if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol()))
1315:                    return (false);
1316:                if (!hreq.getServerName().equalsIgnoreCase(url.getHost()))
1317:                    return (false);
1318:                int serverPort = hreq.getServerPort();
1319:                if (serverPort == -1) {
1320:                    if ("https".equals(hreq.getScheme()))
1321:                        serverPort = 443;
1322:                    else
1323:                        serverPort = 80;
1324:                }
1325:                int urlPort = url.getPort();
1326:                if (urlPort == -1) {
1327:                    if ("https".equals(url.getProtocol()))
1328:                        urlPort = 443;
1329:                    else
1330:                        urlPort = 80;
1331:                }
1332:                if (serverPort != urlPort)
1333:                    return (false);
1334:
1335:                String contextPath = getContext().getPath();
1336:                if (contextPath != null) {
1337:                    String file = url.getFile();
1338:                    if ((file == null) || !file.startsWith(contextPath))
1339:                        return (false);
1340:                    String tok = ";" + Globals.SESSION_PARAMETER_NAME + "="
1341:                            + session.getIdInternal();
1342:                    if (file.indexOf(tok, contextPath.length()) >= 0)
1343:                        return (false);
1344:                }
1345:
1346:                // This URL belongs to our web application, so it is encodeable
1347:                return (true);
1348:
1349:            }
1350:
1351:            /**
1352:             * Convert (if necessary) and return the absolute URL that represents the
1353:             * resource referenced by this possibly relative URL.  If this URL is
1354:             * already absolute, return it unchanged.
1355:             *
1356:             * @param location URL to be (possibly) converted and then returned
1357:             *
1358:             * @exception IllegalArgumentException if a MalformedURLException is
1359:             *  thrown when converting the relative URL to an absolute one
1360:             */
1361:            private String toAbsolute(String location) {
1362:
1363:                if (location == null)
1364:                    return (location);
1365:
1366:                boolean leadingSlash = location.startsWith("/");
1367:
1368:                if (leadingSlash || !hasScheme(location)) {
1369:
1370:                    redirectURLCC.recycle();
1371:
1372:                    String scheme = request.getScheme();
1373:                    String name = request.getServerName();
1374:                    int port = request.getServerPort();
1375:
1376:                    try {
1377:                        redirectURLCC.append(scheme, 0, scheme.length());
1378:                        redirectURLCC.append("://", 0, 3);
1379:                        redirectURLCC.append(name, 0, name.length());
1380:                        if ((scheme.equals("http") && port != 80)
1381:                                || (scheme.equals("https") && port != 443)) {
1382:                            redirectURLCC.append(':');
1383:                            String portS = port + "";
1384:                            redirectURLCC.append(portS, 0, portS.length());
1385:                        }
1386:                        if (!leadingSlash) {
1387:                            String relativePath = request
1388:                                    .getDecodedRequestURI();
1389:                            int pos = relativePath.lastIndexOf('/');
1390:                            relativePath = relativePath.substring(0, pos);
1391:
1392:                            String encodedURI = null;
1393:                            final String frelativePath = relativePath;
1394:                            if (SecurityUtil.isPackageProtectionEnabled()) {
1395:                                try {
1396:                                    encodedURI = (String) AccessController
1397:                                            .doPrivileged(new PrivilegedExceptionAction() {
1398:                                                public Object run()
1399:                                                        throws IOException {
1400:                                                    return urlEncoder
1401:                                                            .encodeURL(frelativePath);
1402:                                                }
1403:                                            });
1404:                                } catch (PrivilegedActionException pae) {
1405:                                    IllegalArgumentException iae = new IllegalArgumentException(
1406:                                            location);
1407:                                    iae.initCause(pae.getException());
1408:                                    throw iae;
1409:                                }
1410:                            } else {
1411:                                encodedURI = urlEncoder.encodeURL(relativePath);
1412:                            }
1413:                            redirectURLCC.append(encodedURI, 0, encodedURI
1414:                                    .length());
1415:                            redirectURLCC.append('/');
1416:                        }
1417:                        redirectURLCC.append(location, 0, location.length());
1418:                    } catch (IOException e) {
1419:                        IllegalArgumentException iae = new IllegalArgumentException(
1420:                                location);
1421:                        iae.initCause(e);
1422:                        throw iae;
1423:                    }
1424:
1425:                    return redirectURLCC.toString();
1426:
1427:                } else {
1428:
1429:                    return (location);
1430:
1431:                }
1432:
1433:            }
1434:
1435:            /**
1436:             * Determine if a URI string has a <code>scheme</code> component.
1437:             */
1438:            private boolean hasScheme(String uri) {
1439:                int len = uri.length();
1440:                for (int i = 0; i < len; i++) {
1441:                    char c = uri.charAt(i);
1442:                    if (c == ':') {
1443:                        return i > 0;
1444:                    } else if (!URL.isSchemeChar(c)) {
1445:                        return false;
1446:                    }
1447:                }
1448:                return false;
1449:            }
1450:
1451:            /**
1452:             * Return the specified URL with the specified session identifier
1453:             * suitably encoded.
1454:             *
1455:             * @param url URL to be encoded with the session id
1456:             * @param sessionId Session id to be included in the encoded URL
1457:             */
1458:            protected String toEncoded(String url, String sessionId) {
1459:
1460:                if ((url == null) || (sessionId == null))
1461:                    return (url);
1462:
1463:                String path = url;
1464:                String query = "";
1465:                String anchor = "";
1466:                int question = url.indexOf('?');
1467:                if (question >= 0) {
1468:                    path = url.substring(0, question);
1469:                    query = url.substring(question);
1470:                }
1471:                int pound = path.indexOf('#');
1472:                if (pound >= 0) {
1473:                    anchor = path.substring(pound);
1474:                    path = path.substring(0, pound);
1475:                }
1476:                StringBuffer sb = new StringBuffer(path);
1477:                if (sb.length() > 0) { // jsessionid can't be first.
1478:                    sb.append(";");
1479:                    sb.append(Globals.SESSION_PARAMETER_NAME);
1480:                    sb.append("=");
1481:                    sb.append(sessionId);
1482:                }
1483:                sb.append(anchor);
1484:                sb.append(query);
1485:                return (sb.toString());
1486:
1487:            }
1488:
1489:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.