Source Code Cross Referenced for AbstractService.java in  » GIS » GeoServer » org » vfny » geoserver » servlets » 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 » GIS » GeoServer » org.vfny.geoserver.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
0002:         * This code is licensed under the GPL 2.0 license, availible at the root
0003:         * application directory.
0004:         */
0005:        package org.vfny.geoserver.servlets;
0006:
0007:        import org.geoserver.ows.ServiceStrategy;
0008:        import org.geoserver.ows.util.XmlCharsetDetector;
0009:        import org.springframework.beans.BeansException;
0010:        import org.springframework.context.ApplicationContext;
0011:        import org.springframework.context.ApplicationContextAware;
0012:        import org.springframework.web.context.WebApplicationContext;
0013:        import org.vfny.geoserver.ExceptionHandler;
0014:        import org.vfny.geoserver.Request;
0015:        import org.vfny.geoserver.Response;
0016:        import org.vfny.geoserver.ServiceException;
0017:        import org.vfny.geoserver.global.Data;
0018:        import org.vfny.geoserver.global.GeoServer;
0019:        import org.vfny.geoserver.global.Service;
0020:        import org.vfny.geoserver.util.PartialBufferedOutputStream2;
0021:        import org.vfny.geoserver.util.requests.readers.KvpRequestReader;
0022:        import org.vfny.geoserver.util.requests.readers.XmlRequestReader;
0023:        import java.io.BufferedOutputStream;
0024:        import java.io.BufferedReader;
0025:        import java.io.IOException;
0026:        import java.io.OutputStream;
0027:        import java.io.Reader;
0028:        import java.net.SocketException;
0029:        import java.nio.charset.Charset;
0030:        import java.util.Enumeration;
0031:        import java.util.HashMap;
0032:        import java.util.Iterator;
0033:        import java.util.Map;
0034:        import java.util.logging.Level;
0035:        import java.util.logging.Logger;
0036:        import javax.servlet.ServletContext;
0037:        import javax.servlet.ServletException;
0038:        import javax.servlet.http.HttpServlet;
0039:        import javax.servlet.http.HttpServletRequest;
0040:        import javax.servlet.http.HttpServletResponse;
0041:
0042:        /**
0043:         * Represents a service that all others extend from.  Subclasses should provide
0044:         * response and exception handlers as appropriate.
0045:         *
0046:         * <p>
0047:         * It is <b>really</b> important to adhere to the following workflow:
0048:         *
0049:         * <ol>
0050:         * <li>
0051:         * get a Request reader
0052:         * </li>
0053:         * <li>
0054:         * ask the Request Reader for the Request object
0055:         * </li>
0056:         * <li>
0057:         * Provide the resulting Request with the ServletRequest that generated it
0058:         * </li>
0059:         * <li>
0060:         * get the appropiate ResponseHandler
0061:         * </li>
0062:         * <li>
0063:         * ask it to execute the Request
0064:         * </li>
0065:         * <li>
0066:         * set the response content type
0067:         * </li>
0068:         * <li>
0069:         * write to the http response's output stream
0070:         * </li>
0071:         * <li>
0072:         * pending - call Response cleanup
0073:         * </li>
0074:         * </ol>
0075:         * </p>
0076:         *
0077:         * <p>
0078:         * If anything goes wrong a ServiceException can be thrown and will be written
0079:         * to the output stream instead.
0080:         * </p>
0081:         *
0082:         * <p>
0083:         * This is because we have to be sure that no exception have been produced
0084:         * before setting the response's content type, so we can set the exception
0085:         * specific content type; and that Response.getContentType is called AFTER
0086:         * Response.execute, since the MIME type can depend on any request parameter
0087:         * or another kind of desission making during the execute process. (i.e.
0088:         * FORMAT in WMS GetMap)
0089:         * </p>
0090:         *
0091:         * <p>
0092:         * TODO: We need to call Response.abort() if anything goes wrong to allow the
0093:         * Response a chance to cleanup after itself.
0094:         * </p>
0095:         *
0096:         * @author Gabriel Rold?n
0097:         * @author Chris Holmes
0098:         * @author Jody Garnett, Refractions Research
0099:         * @version $Id: AbstractService.java 8443 2008-02-25 13:18:59Z groldan $
0100:         */
0101:        public abstract class AbstractService extends HttpServlet implements 
0102:                ApplicationContextAware {
0103:            /** Class logger */
0104:            protected static Logger LOGGER = org.geotools.util.logging.Logging
0105:                    .getLogger("org.vfny.geoserver.servlets");
0106:
0107:            /**
0108:             * Servivce group (maps to 'SERVICE' parameter in OGC service urls)
0109:             */
0110:            String service;
0111:
0112:            /**
0113:             * Request type (maps to 'REQUEST' parameter in OGC service urls)
0114:             */
0115:            String request;
0116:
0117:            /**
0118:             * Application context used to look up "Services"
0119:             */
0120:            WebApplicationContext context;
0121:
0122:            /**
0123:             * Reference to the global geoserver instnace.
0124:             */
0125:            GeoServer geoServer;
0126:
0127:            /**
0128:             * Reference to the catalog.
0129:             */
0130:            Data catalog;
0131:
0132:            /**
0133:             * Id of the service strategy to use.
0134:             */
0135:            String serviceStrategy;
0136:
0137:            /**
0138:             * buffer size to use when PARTIAL-BUFFER is being used
0139:             */
0140:            int partialBufferSize;
0141:
0142:            /**
0143:             * Cached service strategy object
0144:             */
0145:
0146:            //    ServiceStrategy strategy;
0147:            /**
0148:             * Reference to the service
0149:             */
0150:            Service serviceRef;
0151:            private String kvpString;
0152:
0153:            //    /** DOCUMENT ME!  */
0154:            //    protected HttpServletRequest curRequest;
0155:
0156:            /**
0157:             * Constructor for abstract service.
0158:             *
0159:             * @param service The service group the service falls into (WFS,WMS,...)
0160:             * @param request The service being requested (GetCapabilities, GetMap, ...)
0161:             * @param serviceRef The global service this "servlet" falls into
0162:             */
0163:            public AbstractService(String service, String request,
0164:                    Service serviceRef) {
0165:                this .service = service;
0166:                this .request = request;
0167:                this .serviceRef = serviceRef;
0168:            }
0169:
0170:            /**
0171:             * @return Returns the "service group" that this service falls into.
0172:             */
0173:            public String getService() {
0174:                return service;
0175:            }
0176:
0177:            /**
0178:             * @return Returns the "request" this service maps to.
0179:             */
0180:            public String getRequest() {
0181:                return request;
0182:            }
0183:
0184:            /**
0185:             * Sets a refeference to the global service instance.
0186:             */
0187:            public void setServiceRef(Service serviceRef) {
0188:                this .serviceRef = serviceRef;
0189:            }
0190:
0191:            /**
0192:             * @return The reference to the global service instance.
0193:             */
0194:            public Service getServiceRef() {
0195:                return serviceRef;
0196:            }
0197:
0198:            /**
0199:             * Sets the application context.
0200:             * <p>
0201:             * Used to process the {@link Service} extension point.
0202:             * </p>
0203:             */
0204:            public void setApplicationContext(ApplicationContext context)
0205:                    throws BeansException {
0206:                this .context = (WebApplicationContext) context;
0207:            }
0208:
0209:            /**
0210:             * @return The application context.
0211:             */
0212:            public WebApplicationContext getApplicationContext() {
0213:                return context;
0214:            }
0215:
0216:            /**
0217:             * Sets the reference to the global geoserver instance.
0218:             */
0219:            public void setGeoServer(GeoServer geoServer) {
0220:                this .geoServer = geoServer;
0221:            }
0222:
0223:            /**
0224:             * @return the reference to the global geoserver instance.
0225:             */
0226:            public GeoServer getGeoServer() {
0227:                return geoServer;
0228:            }
0229:
0230:            /**
0231:             * @return The reference to the global catalog instance.
0232:             */
0233:            public Data getCatalog() {
0234:                return catalog;
0235:            }
0236:
0237:            /**
0238:             * Sets the reference to the global catalog instance.
0239:             *
0240:             */
0241:            public void setCatalog(Data catalog) {
0242:                this .catalog = catalog;
0243:            }
0244:
0245:            /**
0246:             * @return The id used to identify the service strategy to be used.
0247:             * @see ServiceStrategy#getId()
0248:             */
0249:            public String getServiceStrategy() {
0250:                return serviceStrategy;
0251:            }
0252:
0253:            /**
0254:             * Sets the id used to identify the service strategy to be used.
0255:             */
0256:            public void setServiceStrategy(String serviceStrategy) {
0257:                this .serviceStrategy = serviceStrategy;
0258:            }
0259:
0260:            /**
0261:             * Determines if the service is enabled.
0262:             * <p>
0263:             * Subclass should override this method if the service can be turned on/off.
0264:             * This implementation returns <code>true</code>
0265:             * </p>
0266:             */
0267:            protected boolean isServiceEnabled(HttpServletRequest req) {
0268:                return true;
0269:            }
0270:
0271:            /**
0272:             * Override and use spring set servlet context.
0273:             */
0274:            public ServletContext getServletContext() {
0275:                //override and use spring 
0276:                return ((WebApplicationContext) context).getServletContext();
0277:            }
0278:
0279:            /**
0280:             * DOCUMENT ME!
0281:             *
0282:             * @param request DOCUMENT ME!
0283:             * @param response DOCUMENT ME!
0284:             *
0285:             * @throws ServletException DOCUMENT ME!
0286:             * @throws IOException DOCUMENT ME!
0287:             */
0288:            public void doGet(HttpServletRequest request,
0289:                    HttpServletResponse response) throws ServletException,
0290:                    IOException {
0291:                // implements the main request/response logic
0292:                // this.curRequest = request;
0293:                Request serviceRequest = null;
0294:
0295:                if (!isServiceEnabled(request)) {
0296:                    sendDisabledServiceError(response);
0297:
0298:                    return;
0299:                }
0300:
0301:                try {
0302:                    Map requestParams = new HashMap();
0303:                    String qString = ((this .kvpString != null) ? this .kvpString
0304:                            : request.getQueryString());
0305:                    LOGGER.fine("reading request: " + qString);
0306:
0307:                    if (this .kvpString != null) {
0308:                        requestParams = KvpRequestReader.parseKvpSet(qString);
0309:                    } else {
0310:                        String paramName;
0311:                        String paramValue;
0312:
0313:                        for (Enumeration pnames = request.getParameterNames(); pnames
0314:                                .hasMoreElements();) {
0315:                            paramName = (String) pnames.nextElement();
0316:                            paramValue = request.getParameter(paramName);
0317:                            requestParams.put(paramName.toUpperCase(),
0318:                                    paramValue);
0319:                        }
0320:                    }
0321:
0322:                    KvpRequestReader requestReader = getKvpReader(requestParams);
0323:
0324:                    serviceRequest = requestReader.getRequest(request);
0325:                    LOGGER
0326:                            .finer("serviceRequest provided with HttpServletRequest: "
0327:                                    + request);
0328:
0329:                    //serviceRequest.setHttpServletRequest(request);
0330:                } catch (ServiceException se) {
0331:                    sendError(request, response, se);
0332:
0333:                    return;
0334:                } catch (Throwable e) {
0335:                    sendError(request, response, e);
0336:
0337:                    return;
0338:                } finally {
0339:                    this .kvpString = null;
0340:                }
0341:
0342:                doService(request, response, serviceRequest);
0343:            }
0344:
0345:            /**
0346:             * Sends the standard disabled service error message (a 503 error followed by an english description).
0347:             * @param response
0348:             * @throws IOException
0349:             */
0350:            protected void sendDisabledServiceError(HttpServletResponse response)
0351:                    throws IOException {
0352:                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
0353:                        getService() + " service is not enabled. "
0354:                                + "You can enable it in the web admin tool.");
0355:            }
0356:
0357:            /**
0358:             * Performs the post method.  Simply passes itself on to the three argument
0359:             * doPost method, with null for the reader, because the
0360:             * request.getReader() will not have been used if this servlet is called
0361:             * directly.
0362:             *
0363:             * @param request DOCUMENT ME!
0364:             * @param response DOCUMENT ME!
0365:             *
0366:             * @throws ServletException DOCUMENT ME!
0367:             * @throws IOException DOCUMENT ME!
0368:             */
0369:            public void doPost(HttpServletRequest request,
0370:                    HttpServletResponse response) throws ServletException,
0371:                    IOException {
0372:                doPost(request, response, null);
0373:            }
0374:
0375:            /**
0376:             * Performs the post method.  Gets the appropriate xml reader and
0377:             * determines the request from that, and then passes the request on to
0378:             * doService.
0379:             *
0380:             * @param request The request made.
0381:             * @param response The response to be returned.
0382:             * @param requestXml A reader of the xml to be read.  This is only used by
0383:             *        the dispatcher, everyone else should just pass in null.  This is
0384:             *        needed because afaik HttpServletRequest.getReader() can not be
0385:             *        used twice.  So in a dispatched case we write it to a temp file,
0386:             *        which we can then read in twice.
0387:             *
0388:             * @throws ServletException DOCUMENT ME!
0389:             * @throws IOException DOCUMENT ME!
0390:             */
0391:            public void doPost(HttpServletRequest request,
0392:                    HttpServletResponse response, Reader requestXml)
0393:                    throws ServletException, IOException {
0394:                //        this.curRequest = request;
0395:                Request serviceRequest = null;
0396:
0397:                //TODO: This isn't a proper ogc service response.
0398:                if (!isServiceEnabled(request)) {
0399:                    sendDisabledServiceError(response);
0400:
0401:                    return;
0402:                }
0403:
0404:                // implements the main request/response logic
0405:                try {
0406:                    XmlRequestReader requestReader = getXmlRequestReader();
0407:
0408:                    //JD: GEOS-323, adding support for character encoding detection
0409:                    // Reader xml = (requestXml != null) ? requestXml : request.getReader();
0410:                    Reader xml;
0411:
0412:                    if (null != requestXml) {
0413:                        xml = requestXml;
0414:                    } else {
0415:                        /*
0416:                         * `getCharsetAwareReader` returns a reader which not support
0417:                         * mark/reset. So it is a good idea to wrap it into BufferedReader.
0418:                         * In this case the below debug output will work.
0419:                         */
0420:                        xml = new BufferedReader(
0421:                                XmlCharsetDetector
0422:                                        .getCharsetAwareReader(request
0423:                                                .getInputStream()));
0424:                    }
0425:
0426:                    //JD: GEOS-323
0427:
0428:                    //DJB: add support for POST loggin
0429:                    if (LOGGER.isLoggable(Level.FINE)) {
0430:                        if (xml.markSupported()) {
0431:                            // a little protection for large POSTs (ie. updates)
0432:                            // for FINE, I assume people just want to see the "normal" ones - not the big ones
0433:                            // for FINER, I assume they would want to see a bit more
0434:                            // for FINEST, I assume they would want to see even more
0435:                            int maxChars = 16000;
0436:
0437:                            if (LOGGER.isLoggable(Level.FINER)) {
0438:                                maxChars = 64000;
0439:                            }
0440:
0441:                            if (LOGGER.isLoggable(Level.FINEST)) {
0442:                                maxChars = 640000; // Bill gates says 640k is good enough for anyone
0443:                            }
0444:
0445:                            xml.mark(maxChars + 1); // +1 so if you read the whole thing you can still reset()
0446:
0447:                            char[] buffer = new char[maxChars];
0448:                            int actualRead = xml.read(buffer);
0449:                            xml.reset();
0450:                            LOGGER
0451:                                    .fine("------------XML POST START-----------\n"
0452:                                            + new String(buffer, 0, actualRead)
0453:                                            + "\n------------XML POST END-----------");
0454:
0455:                            if (actualRead == maxChars) {
0456:                                LOGGER
0457:                                        .fine("------------XML POST REPORT WAS TRUNCATED AT "
0458:                                                + maxChars
0459:                                                + " CHARACTERS.  RUN WITH HIGHER LOGGING LEVEL TO SEE MORE");
0460:                            }
0461:                        } else {
0462:                            LOGGER
0463:                                    .fine("ATTEMPTED TO LOG POST XML, BUT WAS PREVENTED BECAUSE markSupported() IS FALSE");
0464:                        }
0465:                    }
0466:
0467:                    serviceRequest = requestReader.read(xml, request);
0468:                    serviceRequest.setHttpServletRequest(request);
0469:                } catch (ServiceException se) {
0470:                    sendError(request, response, se);
0471:
0472:                    return;
0473:                } catch (Throwable e) {
0474:                    sendError(request, response, e);
0475:
0476:                    return;
0477:                }
0478:
0479:                doService(request, response, serviceRequest);
0480:            }
0481:
0482:            /**
0483:             * Peforms service according to ServiceStrategy.
0484:             *
0485:             * <p>
0486:             * This method has very strict requirements, please see the class
0487:             * description for the specifics.
0488:             * </p>
0489:             *
0490:             * <p>
0491:             * It has a lot of try/catch blocks, but they are fairly necessary to
0492:             * handle things correctly and to avoid as many ugly servlet responses, so
0493:             * that everything is wrapped correctly.
0494:             * </p>
0495:             *
0496:             * @param request The httpServlet of the request.
0497:             * @param response The response to be returned.
0498:             * @param serviceRequest The OGC request to service.
0499:             *
0500:             * @throws ServletException if the strategy can't be instantiated
0501:             */
0502:            protected void doService(HttpServletRequest request,
0503:                    HttpServletResponse response, Request serviceRequest)
0504:                    throws ServletException {
0505:                LOGGER.info("handling request: " + serviceRequest);
0506:
0507:                if (!isServiceEnabled(request)) {
0508:                    try {
0509:                        sendDisabledServiceError(response);
0510:                    } catch (IOException e) {
0511:                        LOGGER
0512:                                .log(
0513:                                        Level.WARNING,
0514:                                        "Error writing service unavailable response",
0515:                                        e);
0516:                    }
0517:
0518:                    return;
0519:                }
0520:
0521:                ServiceStrategy strategy = null;
0522:                Response serviceResponse = null;
0523:
0524:                try {
0525:                    strategy = createServiceStrategy();
0526:                    LOGGER.fine("strategy is: " + strategy.getId());
0527:                    serviceResponse = getResponseHandler();
0528:                } catch (Throwable t) {
0529:                    sendError(request, response, t);
0530:
0531:                    return;
0532:                }
0533:
0534:                Map services = context.getBeansOfType(Service.class);
0535:                Service s = null;
0536:
0537:                for (Iterator itr = services.entrySet().iterator(); itr
0538:                        .hasNext();) {
0539:                    Map.Entry entry = (Map.Entry) itr.next();
0540:                    String id = (String) entry.getKey();
0541:                    Service service = (Service) entry.getValue();
0542:
0543:                    if (id.toLowerCase().startsWith(
0544:                            serviceRequest.getService().toLowerCase().trim())) {
0545:                        s = service;
0546:
0547:                        break;
0548:                    }
0549:                }
0550:
0551:                if (s == null) {
0552:                    String msg = "No service found matching: "
0553:                            + serviceRequest.getService();
0554:                    sendError(request, response, new ServiceException(msg));
0555:
0556:                    return;
0557:                }
0558:
0559:                try {
0560:                    // execute request
0561:                    LOGGER.finer("executing request");
0562:                    serviceResponse.execute(serviceRequest);
0563:                    LOGGER.finer("execution succeed");
0564:                } catch (ServiceException serviceException) {
0565:                    LOGGER
0566:                            .warning("service exception while executing request: "
0567:                                    + serviceRequest
0568:                                    + "\ncause: "
0569:                                    + serviceException.getMessage());
0570:                    serviceResponse.abort(s);
0571:                    sendError(request, response, serviceException);
0572:
0573:                    return;
0574:                } catch (Throwable t) {
0575:                    //we can safelly send errors here, since we have not touched response yet
0576:                    serviceResponse.abort(s);
0577:                    sendError(request, response, t);
0578:
0579:                    return;
0580:                }
0581:
0582:                OutputStream strategyOuput = null;
0583:
0584:                //obtain the strategy output stream
0585:                try {
0586:                    LOGGER.finest("getting strategy output");
0587:                    strategyOuput = strategy.getDestination(response);
0588:                    LOGGER.finer("strategy output is: "
0589:                            + strategyOuput.getClass().getName());
0590:
0591:                    String mimeType = serviceResponse.getContentType(s
0592:                            .getGeoServer());
0593:                    LOGGER.fine("mime type is: " + mimeType);
0594:                    response.setContentType(mimeType);
0595:
0596:                    String encoding = serviceResponse.getContentEncoding();
0597:
0598:                    if (encoding != null) {
0599:                        LOGGER.fine("content encoding is: " + encoding);
0600:                        response.setHeader("Content-Encoding", encoding);
0601:                    }
0602:
0603:                    String disposition = serviceResponse
0604:                            .getContentDisposition();
0605:
0606:                    if (disposition != null) {
0607:                        LOGGER.fine("content encoding is: " + encoding);
0608:                        response.setHeader("Content-Disposition", disposition);
0609:                    }
0610:                } catch (SocketException socketException) {
0611:                    LOGGER
0612:                            .fine("it seems that the user has closed the request stream: "
0613:                                    + socketException.getMessage());
0614:
0615:                    // It seems the user has closed the request stream
0616:                    // Apparently this is a "cancel" and will quietly go away
0617:                    //
0618:                    // I will still give strategy and serviceResponse
0619:                    // a chance to clean up
0620:                    //
0621:                    serviceResponse.abort(s);
0622:                    strategy.abort();
0623:
0624:                    return;
0625:                } catch (IOException ex) {
0626:                    serviceResponse.abort(s);
0627:                    strategy.abort();
0628:                    sendError(request, response, ex);
0629:
0630:                    return;
0631:                }
0632:
0633:                try {
0634:                    // gather response
0635:                    serviceResponse.writeTo(strategyOuput);
0636:                    strategyOuput.flush();
0637:                    strategy.flush(response);
0638:                } catch (java.net.SocketException sockEx) { // user cancel
0639:                    LOGGER
0640:                            .info("Stream abruptly closed by client, response aborted");
0641:                    serviceResponse.abort(s);
0642:                    strategy.abort();
0643:
0644:                    return;
0645:                } catch (IOException ioException) { // strategyOutput error
0646:                    response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
0647:                    LOGGER
0648:                            .info("Stream abruptly closed by client, response aborted");
0649:                    LOGGER.log(Level.FINE, "Error writing out "
0650:                            + ioException.getMessage(), ioException);
0651:                    serviceResponse.abort(s);
0652:                    strategy.abort();
0653:
0654:                    return;
0655:                } catch (ServiceException writeToFailure) { // writeTo Failure
0656:                    response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
0657:                    serviceResponse.abort(s);
0658:                    strategy.abort();
0659:                    sendError(request, response, writeToFailure);
0660:
0661:                    return;
0662:                } catch (Throwable help) { // This is an unexpected error(!)
0663:                    response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
0664:                    help.printStackTrace();
0665:                    serviceResponse.abort(s);
0666:                    strategy.abort();
0667:                    sendError(request, response, help);
0668:
0669:                    return;
0670:                }
0671:
0672:                // Finish Response
0673:                // I have moved closing the output stream out here, it was being
0674:                // done by a few of the ServiceStrategy
0675:                //
0676:                // By this time serviceResponse has finished successfully
0677:                // and strategy is also finished
0678:                //
0679:                try {
0680:                    response.getOutputStream().flush();
0681:                    response.getOutputStream().close();
0682:                } catch (SocketException sockEx) { // user cancel
0683:                    LOGGER.warning("Could not send completed response to user:"
0684:                            + sockEx);
0685:
0686:                    return;
0687:                } catch (IOException ioException) {
0688:                    // This is bad, the user did not get the completed response
0689:                    LOGGER.warning("Could not send completed response to user:"
0690:                            + ioException);
0691:
0692:                    return;
0693:                }
0694:
0695:                LOGGER.info("Service handled");
0696:            }
0697:
0698:            /**
0699:             * Gets the response class that should handle the request of this service.
0700:             * All subclasses must implement.
0701:             * <p>
0702:             * This method is not abstract to support subclasses that use the
0703:             * request-response mechanism.
0704:             * </p>
0705:             *
0706:             * @return The response that the request read by this servlet should be
0707:             *         passed to.
0708:             */
0709:            protected Response getResponseHandler() {
0710:                return null;
0711:            }
0712:
0713:            /**
0714:             * This method was added in order to adapt the old style servlet services
0715:             * to the new ows dispatching interface, without having to modify the
0716:             * services themselves.
0717:             *
0718:             * @return A call to {@link #getResponseHandler()}.
0719:             */
0720:            public final Response getResponse() {
0721:                return getResponseHandler();
0722:            }
0723:
0724:            /**
0725:             * Gets a reader that will figure out the correct Key Vaule Pairs for this
0726:             * service.
0727:             * <p>
0728:             * Subclasses should override to supply a specific kvp reader. Default
0729:             * implementation returns <code>null</code>
0730:             * </p>
0731:             * @param params A map of the kvp pairs.
0732:             *
0733:             * @return An initialized KVP reader to decode the request.
0734:             */
0735:            protected KvpRequestReader getKvpReader(Map params) {
0736:                return null;
0737:            }
0738:
0739:            /**
0740:             * Gets a reader that will handle a posted xml request for this servlet.
0741:             * <p>
0742:             * Subclasses should override to supply a specific xml reader. Default
0743:             * implementation returns <code>null</code>
0744:             * </p>
0745:             * @return An XmlRequestReader appropriate to this service.
0746:             */
0747:            protected XmlRequestReader getXmlRequestReader() {
0748:                return null;
0749:            }
0750:
0751:            /**
0752:             * Gets the exception handler for this service.
0753:             *
0754:             * @return The correct ExceptionHandler
0755:             */
0756:            protected abstract ExceptionHandler getExceptionHandler();
0757:
0758:            /**
0759:             * Gets the strategy for outputting the response.  This method gets the
0760:             * strategy from the serviceStrategy param in the web.xml file.  This is
0761:             * sort of odd behavior, as all other such parameters are set in the
0762:             * services and catalog xml files, and this param may move there.  But as
0763:             * it is much  more of a programmer configuration than a user
0764:             * configuration there is  no rush to move it.
0765:             *
0766:             * <p>
0767:             * Subclasses may choose to override this method in order to get a strategy
0768:             * more suited to their response.  Currently only Transaction will do
0769:             * this, since the commit is only called after writeTo, and it often
0770:             * messes up, so we want to be able to see the error message (SPEED writes
0771:             * the output directly, so errors in writeTo do not show up.)
0772:             * </p>
0773:             *
0774:             * <p>
0775:             * Most subclasses should not override, this method will most always return
0776:             * the SPEED  strategy, since it is the fastest response and should work
0777:             * fine if everything is well tested.  FILE and BUFFER should be used when
0778:             * there  are errors in writeTo methods of child classes, set by the
0779:             * programmer in the web.xml file.
0780:             * </p>
0781:             *
0782:             * @return The service strategy found in the web.xml serviceStrategy
0783:             *         parameter.   The code that finds this is in the init method
0784:             *
0785:             * @throws ServiceException If the service strategy set in #init() is not
0786:             *         valid.
0787:             *
0788:             * @see #init() for the code that sets the serviceStrategy.
0789:             */
0790:            protected ServiceStrategy createServiceStrategy()
0791:                    throws ServiceException {
0792:                // If verbose exceptions is on then lets make sure they actually get the
0793:                // exception by using the file strategy.
0794:                ServiceStrategy theStrategy = null;
0795:
0796:                if (geoServer.isVerboseExceptions()) {
0797:                    theStrategy = (ServiceStrategy) context
0798:                            .getBean("fileServiceStrategy");
0799:                } else {
0800:                    if (serviceStrategy == null) {
0801:                        // none set, look up in web applicatino context
0802:                        serviceStrategy = getServletContext().getInitParameter(
0803:                                "serviceStrategy");
0804:                    }
0805:
0806:                    // do a lookup
0807:                    if (serviceStrategy != null) {
0808:                        Map strategies = context
0809:                                .getBeansOfType(ServiceStrategy.class);
0810:
0811:                        for (Iterator itr = strategies.values().iterator(); itr
0812:                                .hasNext();) {
0813:                            ServiceStrategy bean = (ServiceStrategy) itr.next();
0814:
0815:                            if (bean.getId().equals(serviceStrategy)) {
0816:                                theStrategy = bean;
0817:
0818:                                break;
0819:                            }
0820:                        }
0821:                    }
0822:                }
0823:
0824:                if (theStrategy == null) {
0825:                    // default to buffer
0826:                    theStrategy = (ServiceStrategy) context
0827:                            .getBean("bufferServiceStrategy");
0828:                }
0829:
0830:                // clone the strategy since at the moment the strategies are marked as singletons
0831:                // in the web.xml file.
0832:                try {
0833:                    theStrategy = (ServiceStrategy) theStrategy.clone();
0834:                } catch (CloneNotSupportedException e) {
0835:                    LOGGER.log(Level.SEVERE,
0836:                            "Programming error found, service strategies should be cloneable, "
0837:                                    + e, e);
0838:                    throw new RuntimeException(
0839:                            "Found a strategy that does not support cloning...",
0840:                            e);
0841:                }
0842:
0843:                // TODO: this hack should be removed once modules have their own config
0844:                if (theStrategy instanceof  PartialBufferStrategy2) {
0845:                    if (partialBufferSize == 0) {
0846:                        String size = getServletContext().getInitParameter(
0847:                                "PARTIAL_BUFFER_STRATEGY_SIZE");
0848:
0849:                        if (size != null) {
0850:                            try {
0851:                                partialBufferSize = Integer.valueOf(size)
0852:                                        .intValue();
0853:
0854:                                if (partialBufferSize <= 0) {
0855:                                    LOGGER
0856:                                            .warning("Invalid partial buffer size, defaulting to "
0857:                                                    + PartialBufferedOutputStream2.DEFAULT_BUFFER_SIZE
0858:                                                    + " (was "
0859:                                                    + partialBufferSize + ")");
0860:                                    partialBufferSize = 0;
0861:                                }
0862:                            } catch (NumberFormatException nfe) {
0863:                                LOGGER
0864:                                        .warning("Invalid partial buffer size, defaulting to "
0865:                                                + PartialBufferedOutputStream2.DEFAULT_BUFFER_SIZE
0866:                                                + " (was "
0867:                                                + partialBufferSize
0868:                                                + ")");
0869:                                partialBufferSize = 0;
0870:                            }
0871:                        }
0872:                    }
0873:
0874:                    ((PartialBufferStrategy2) theStrategy)
0875:                            .setBufferSize(partialBufferSize);
0876:                }
0877:
0878:                return theStrategy;
0879:            }
0880:
0881:            /**
0882:             * DOCUMENT ME!
0883:             *
0884:             * @return DOCUMENT ME!
0885:             */
0886:            protected String getMimeType() {
0887:                ServletContext servContext = getServletContext();
0888:
0889:                try {
0890:                    return ((GeoServer) servContext.getAttribute("GeoServer"))
0891:                            .getMimeType();
0892:                } catch (NullPointerException e) {
0893:                    return "text/xml; charset="
0894:                            + Charset.forName("UTF-8").name();
0895:                }
0896:            }
0897:
0898:            /**
0899:             * DOCUMENT ME!
0900:             *
0901:             * @param response DOCUMENT ME!
0902:             * @param content DOCUMENT ME!
0903:             */
0904:            protected void send(HttpServletResponse response,
0905:                    CharSequence content) {
0906:                send(response, content, getMimeType());
0907:            }
0908:
0909:            /**
0910:             * DOCUMENT ME!
0911:             *
0912:             * @param response DOCUMENT ME!
0913:             * @param content DOCUMENT ME!
0914:             * @param mimeType DOCUMENT ME!
0915:             */
0916:            protected void send(HttpServletResponse response,
0917:                    CharSequence content, String mimeType) {
0918:                try {
0919:                    response.setContentType(mimeType);
0920:                    response.getWriter().write(content.toString());
0921:                } catch (IOException ex) { //stream closed by client, do nothing
0922:                    LOGGER
0923:                            .info("Stream abruptly closed by client, response aborted");
0924:                    LOGGER.fine(ex.getMessage());
0925:                } catch (IllegalStateException ex) { //stream closed by client, do nothing
0926:                    LOGGER
0927:                            .info("Stream abruptly closed by client, response aborted");
0928:                    LOGGER.fine(ex.getMessage());
0929:                }
0930:            }
0931:
0932:            /**
0933:             * Send error produced during getService opperation.
0934:             *
0935:             * <p>
0936:             * Some errors know how to write themselves out WfsTransactionException for
0937:             * instance. It looks like this might be is handled by
0938:             * getExceptionHandler().newServiceException( t, pre, null ). I still
0939:             * would not mind seeing a check for ServiceConfig Exception here.
0940:             * </p>
0941:             *
0942:             * <p>
0943:             * This code says that it deals with UNCAUGHT EXCEPTIONS, so I think it
0944:             * would be wise to explicitly catch ServiceExceptions.
0945:             * </p>
0946:             *
0947:             * @param response DOCUMENT ME!
0948:             * @param t DOCUMENT ME!
0949:             */
0950:            protected void sendError(HttpServletRequest request,
0951:                    HttpServletResponse response, Throwable t) {
0952:                if (t instanceof  ServiceException) {
0953:                    sendError(request, response, (ServiceException) t);
0954:
0955:                    return;
0956:                }
0957:
0958:                LOGGER.info("Had an undefined error: " + t.getMessage());
0959:
0960:                //TODO: put the stack trace in the logger.
0961:                //t.printStackTrace();
0962:                //String pre = "UNCAUGHT EXCEPTION";
0963:                ExceptionHandler exHandler = getExceptionHandler();
0964:                ServiceException se = exHandler.newServiceException(t);
0965:
0966:                sendError(request, response, se);
0967:
0968:                //GeoServer geoServer = (GeoServer) this.getServletConfig()
0969:                //                                      .getServletContext().getAttribute(GeoServer.WEB_CONTAINER_KEY);
0970:                //send(response, se.getXmlResponse(geoServer.isVerboseExceptions()));
0971:            }
0972:
0973:            /**
0974:             * Send a serviceException produced during getService opperation.
0975:             *
0976:             * @param response DOCUMENT ME!
0977:             * @param se DOCUMENT ME!
0978:             */
0979:            protected void sendError(HttpServletRequest request,
0980:                    HttpServletResponse response, ServiceException se) {
0981:                // first log the exception
0982:                LOGGER.log(Level.SEVERE, "Service exception occurred", se);
0983:
0984:                String mimeType = se.getMimeType(geoServer);
0985:
0986:                send(response, se.getXmlResponse(geoServer
0987:                        .isVerboseExceptions(), request, geoServer), mimeType);
0988:            }
0989:
0990:            /**
0991:             * DOCUMENT ME!
0992:             *
0993:             * @param response DOCUMENT ME!
0994:             * @param result DOCUMENT ME!
0995:             */
0996:            protected void send(HttpServletRequest httpRequest,
0997:                    HttpServletResponse response, Response result) {
0998:                OutputStream responseOut = null;
0999:
1000:                try {
1001:                    responseOut = response.getOutputStream();
1002:                } catch (IOException ex) { //stream closed, do nothing.
1003:                    LOGGER.info("apparently client has closed stream: "
1004:                            + ex.getMessage());
1005:                }
1006:
1007:                OutputStream out = new BufferedOutputStream(responseOut);
1008:                ServletContext servContext = getServletContext();
1009:                response.setContentType(result
1010:                        .getContentType((GeoServer) servContext
1011:                                .getAttribute("GeoServer")));
1012:
1013:                try {
1014:                    result.writeTo(out);
1015:                    out.flush();
1016:                    responseOut.flush();
1017:                } catch (IOException ioe) {
1018:                    //user just closed the socket stream, do nothing
1019:                    LOGGER.fine("connection closed by user: "
1020:                            + ioe.getMessage());
1021:                } catch (ServiceException ex) {
1022:                    sendError(httpRequest, response, ex);
1023:                }
1024:            }
1025:
1026:            /**
1027:             * Checks if the client requests supports gzipped responses by quering it's
1028:             * 'accept-encoding' header.
1029:             *
1030:             * @param request the request to query the HTTP header from
1031:             *
1032:             * @return true if 'gzip' if one of the supported content encodings of
1033:             *         <code>request</code>, false otherwise.
1034:             */
1035:            protected boolean requestSupportsGzip(HttpServletRequest request) {
1036:                boolean supportsGzip = false;
1037:                String header = request.getHeader("accept-encoding");
1038:
1039:                if ((header != null) && (header.indexOf("gzip") > -1)) {
1040:                    supportsGzip = true;
1041:                }
1042:
1043:                if (LOGGER.isLoggable(Level.CONFIG)) {
1044:                    LOGGER.config("user-agent="
1045:                            + request.getHeader("user-agent"));
1046:                    LOGGER.config("accept=" + request.getHeader("accept"));
1047:                    LOGGER.config("accept-encoding="
1048:                            + request.getHeader("accept-encoding"));
1049:                }
1050:
1051:                return supportsGzip;
1052:            }
1053:
1054:            public String getKvpString() {
1055:                return kvpString;
1056:            }
1057:
1058:            public void setKvpString(String kvpString) {
1059:                this.kvpString = kvpString;
1060:            }
1061:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.