JAL-3851 changed error response status codes to 201 for jetty reasons. Some example...
[jalview.git] / src / jalview / httpserver / AbstractRequestHandler.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.httpserver;
22
23 import java.io.IOException;
24 import java.net.BindException;
25 import java.util.Collections;
26
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 import org.eclipse.jetty.server.Request;
32 import org.eclipse.jetty.server.handler.AbstractHandler;
33
34 import jalview.bin.Cache;
35
36 /**
37  * 
38  * @author gmcarstairs
39  *
40  */
41 public abstract class AbstractRequestHandler extends AbstractHandler
42 {
43
44   /*
45    * The relative path (below context root) of this handler (without /
46    * separators)
47    */
48   private String path;
49
50   /*
51    * The full URI on which this handler listens
52    */
53   private String uri;
54
55   /**
56    * Handle an incoming Http request.
57    */
58   @Override
59   public void handle(String target, Request baseRequest,
60           HttpServletRequest request, HttpServletResponse response)
61           throws IOException, ServletException
62   {
63     try
64     {
65       // dumpRequest(request); // debug
66       processRequest(request, response);
67     } catch (Throwable t)
68     {
69       /*
70        * Set server error status on response
71        */
72       System.err.println("Exception handling request "
73               + request.getRequestURI() + " : " + t.getMessage());
74       Cache.error(t);
75       if (response.isCommitted())
76       {
77         /*
78          * Can't write an HTTP header once any response content has been written
79          */
80         System.err.println(
81                 "Unable to return HTTP 500 as response already committed");
82       }
83       else
84       {
85         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
86       }
87     } finally
88     {
89       response.getWriter().flush();
90       baseRequest.setHandled(true);
91     }
92   }
93
94   /**
95    * Subclasses should override this method to perform request processing
96    * 
97    * @param request
98    * @param response
99    * @throws IOException
100    */
101   protected abstract void processRequest(HttpServletRequest request,
102           HttpServletResponse response) throws IOException;
103
104   /**
105    * For debug - writes HTTP request details to stdout
106    * 
107    * @param request
108    */
109   protected void dumpRequest(HttpServletRequest request)
110   {
111     System.out.println(request.getMethod());
112     System.out.println(request.getRequestURL());
113     for (String hdr : Collections.list(request.getHeaderNames()))
114     {
115       for (String val : Collections.list(request.getHeaders(hdr)))
116       {
117         System.out.println(hdr + ": " + val);
118       }
119     }
120     for (String param : Collections.list(request.getParameterNames()))
121     {
122       for (String val : request.getParameterValues(param))
123       {
124         System.out.println(param + "=" + val);
125       }
126     }
127   }
128
129   /**
130    * Returns a display name for the handler
131    * 
132    * @return
133    */
134   public abstract String getName();
135
136   /**
137    * Deregister this listener and close it down
138    * 
139    * @throws Exception
140    */
141   public void shutdown()
142   {
143     try
144     {
145       HttpServer.getInstance().removeHandler(this);
146       stop();
147     } catch (Exception e)
148     {
149       System.err.println(
150               "Error stopping " + getName() + ": " + e.getMessage());
151     }
152   }
153
154   /**
155    * Returns the URI on which we are listening
156    * 
157    * @return
158    */
159   public String getUri()
160   {
161     return this.uri;
162   }
163
164   /**
165    * Set the URI to this handler
166    * 
167    * @param u
168    */
169   protected void setUri(String u)
170   {
171     this.uri = u;
172   }
173
174   /**
175    * Sets the relative path to this handler - do this before registering the
176    * handler.
177    * 
178    * @param p
179    */
180   protected void setPath(String p)
181   {
182     this.path = p;
183   }
184
185   /**
186    * Returns the relative path to this handler below the context root (without /
187    * separators)
188    * 
189    * @return
190    */
191   public String getPath()
192   {
193     return this.path;
194   }
195
196   /**
197    * Registers the handler with the HttpServer and reports its URI on stdout
198    * 
199    * @throws BindException
200    *           if no port could be allocated
201    * @throws IllegalStateException
202    *           if this method is called before {@link #setPath}
203    */
204   protected void registerHandler() throws BindException
205   {
206     HttpServer.getInstance().registerHandler(this);
207   }
208 }