JAL-3060 entry points for createFeatures, amendFeatures
[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 /**
35  * 
36  * @author gmcarstairs
37  *
38  */
39 public abstract class AbstractRequestHandler extends AbstractHandler
40 {
41
42   /*
43    * The relative path (below context root) of this handler (without /
44    * separators)
45    */
46   private String path;
47
48   /*
49    * The full URI on which this handler listens
50    */
51   private String uri;
52
53   /**
54    * Handle an incoming Http request.
55    */
56   @Override
57   public void handle(String target, Request baseRequest,
58           HttpServletRequest request, HttpServletResponse response)
59           throws IOException, ServletException
60   {
61     try
62     {
63       // dumpRequest(request); // debug
64       processRequest(request, response);
65     } catch (Throwable t)
66     {
67       /*
68        * Set server error status on response
69        */
70       System.err.println("Exception handling request "
71               + request.getRequestURI() + " : " + t.getMessage());
72       if (response.isCommitted())
73       {
74         /*
75          * Can't write an HTTP header once any response content has been written
76          */
77         System.err.println(
78                 "Unable to return HTTP 500 as response already committed");
79       }
80       else
81       {
82         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
83       }
84     } finally
85     {
86       response.getWriter().flush();
87       baseRequest.setHandled(true);
88     }
89   }
90
91   /**
92    * Subclasses should override this method to perform request processing
93    * 
94    * @param request
95    * @param response
96    * @throws IOException
97    */
98   protected abstract void processRequest(HttpServletRequest request,
99           HttpServletResponse response) throws IOException;
100
101   /**
102    * For debug - writes HTTP request details to stdout
103    * 
104    * @param request
105    */
106   protected void dumpRequest(HttpServletRequest request)
107   {
108     System.out.println(request.getMethod());
109     System.out.println(request.getRequestURL());
110     for (String hdr : Collections.list(request.getHeaderNames()))
111     {
112       for (String val : Collections.list(request.getHeaders(hdr)))
113       {
114         System.out.println(hdr + ": " + val);
115       }
116     }
117     for (String param : Collections.list(request.getParameterNames()))
118     {
119       for (String val : request.getParameterValues(param))
120       {
121         System.out.println(param + "=" + val);
122       }
123     }
124   }
125
126   /**
127    * Returns a display name for the handler
128    * 
129    * @return
130    */
131   public abstract String getName();
132
133   /**
134    * Deregister this listener and close it down
135    * 
136    * @throws Exception
137    */
138   public void shutdown()
139   {
140     try
141     {
142       HttpServer.getInstance().removeHandler(this);
143       stop();
144     } catch (Exception e)
145     {
146       System.err.println(
147               "Error stopping " + getName() + ": " + e.getMessage());
148     }
149   }
150
151   /**
152    * Returns the URI on which we are listening
153    * 
154    * @return
155    */
156   public String getUri()
157   {
158     return this.uri;
159   }
160
161   /**
162    * Set the URI to this handler
163    * 
164    * @param u
165    */
166   protected void setUri(String u)
167   {
168     this.uri = u;
169   }
170
171   /**
172    * Sets the relative path to this handler - do this before registering the
173    * handler.
174    * 
175    * @param p
176    */
177   protected void setPath(String p)
178   {
179     this.path = p;
180   }
181
182   /**
183    * Returns the relative path to this handler below the context root (without /
184    * separators)
185    * 
186    * @return
187    */
188   public String getPath()
189   {
190     return this.path;
191   }
192
193   /**
194    * Registers the handler with the HttpServer and reports its URI on stdout
195    * 
196    * @throws BindException
197    *           if no port could be allocated
198    * @throws IllegalStateException
199    *           if this method is called before {@link #setPath}
200    */
201   protected void registerHandler() throws BindException
202   {
203     HttpServer.getInstance().registerHandler(this);
204   }
205 }