View Javadoc

1   /*
2    * $Id: ServletHelper.java,v 1.2 2005/03/21 18:45:55 mch Exp $
3    *
4    * (C) Copyright Astrogrid...
5    */
6   
7   package org.astrogrid.dataservice.service;
8   
9   import java.io.IOException;
10  import java.io.PrintWriter;
11  import java.io.StringWriter;
12  import java.net.MalformedURLException;
13  import java.net.URISyntaxException;
14  import java.net.URL;
15  import java.security.Principal;
16  import javax.servlet.http.HttpServletRequest;
17  import org.apache.commons.logging.Log;
18  import org.apache.commons.logging.LogFactory;
19  import org.astrogrid.account.LoginAccount;
20  import org.astrogrid.cfg.ConfigFactory;
21  import org.astrogrid.query.condition.CircleCondition;
22  import org.astrogrid.query.returns.ReturnImage;
23  import org.astrogrid.query.returns.ReturnSpec;
24  import org.astrogrid.query.returns.ReturnTable;
25  import org.astrogrid.slinger.mime.MimeNames;
26  import org.astrogrid.slinger.targets.TargetMaker;
27  
28  /***
29   * A set of dataserver methods for helping serving data in HTML form, eg for servlets
30   * or JSPs
31   * <p>
32   * @author M Hill
33   */
34  
35  public class ServletHelper
36  {
37     
38     protected static Log log = LogFactory.getLog(ServletHelper.class);
39  
40     private static String urlStem = null;
41     
42     public static void setUrlStem(String aStem) {
43        if (!aStem.endsWith("/")) {
44           aStem = aStem+"/";
45        }
46        //check it's a valid URL and should be able to open a stream to it.
47        try {
48           new URL(aStem).openStream();
49        }
50        catch (IOException e) {
51           log.error("URL stem "+aStem+" is invalid or unreachable ("+e+")");
52           return; //don't set it
53        }
54        
55        log.info("Service Stem set to '"+aStem+"'");
56        if (urlStem == null) {
57           urlStem = aStem;
58        }
59        else if (!urlStem.equals(aStem)) {
60           log.error("Trying to set service URL stem to "+aStem+" when already "+urlStem+"; ignoring new stem");
61        }
62     }
63  
64     /*** Provides static access to the url stem (eg http://grendel12.roe.ac.uk/pal-6df)" target="alexandria_uri">http://grendel12.roe.ac.uk/pal-6df)  */
65     public static String getUrlStem() {
66        if (urlStem != null) {
67           return urlStem;
68        }
69        //see if we can get it from axis stuff
70        if (AxisDataServer.getMessageContextUrlStem() != null) {
71           setUrlStem(AxisDataServer.getMessageContextUrlStem());
72           return urlStem;
73        }
74        //see if we can get it from servlet stuff
75        if (getRequestUrlStem() != null) {
76           setUrlStem(getRequestUrlStem());
77           return urlStem;
78        }
79        
80        //if not, get it we can get it from config
81        String configStem = ConfigFactory.getCommonConfig().getString("datacenter.url");
82        if (configStem != null) {
83           if (!configStem.endsWith("/")) {
84              configStem = configStem+"/";
85           }
86        }
87        return configStem;
88     }
89  
90     public static String getRequestUrlStem() {
91        return null;
92     }
93     
94     public static String getUrlStem(HttpServletRequest request) {
95        return request.getScheme()+"://"+request.getServerName() +":" + request.getServerPort()+request.getContextPath();
96     }
97  
98     /***
99      * Gets the user details from the request */
100    public static Principal getUser(HttpServletRequest request)  {
101       if (request.getParameter("UserName") != null) {
102          //for information only
103          return new LoginAccount(request.getParameter("UserName"), "Unknown");
104       }
105       else {
106          return LoginAccount.ANONYMOUS;
107       }
108    }
109 
110    /***
111     * Convenience routine for JSPs; decides where target should be from
112     * the parameters in the given request.  The parameter names should match
113     * those assigned in resultsForm.xml */
114    public static ReturnSpec makeReturnSpec(HttpServletRequest request)  {
115       
116       ReturnSpec returnSpec = null;
117       
118       String format = request.getParameter("Format");
119       if ( (format != null) && (format.trim().length()>0)) {
120          if (ReturnImage.isImageFormat(new String[] { format })) {
121             returnSpec = new ReturnImage(null);
122          }
123       }
124       
125       if (returnSpec == null) {
126          returnSpec = new ReturnTable(null);
127       }
128 
129       fillReturnSpec(returnSpec, request);
130       
131       return returnSpec;
132    }
133 
134    /***
135     * Convenience routine for JSPs; returns true if this is an 'ask count' request
136     *  from the resultsForm.xml */
137    public static boolean isCountReq(HttpServletRequest request)  {
138       String format = request.getParameter("Format");
139       if ( (format != null) && (format.trim().length()>0) && (format.trim().toLowerCase().equals("count"))) {
140          return true;
141       }
142       else {
143          return false;
144       }
145    }
146 
147       /***
148     * Convenience routine for JSPs; decides where target should be from
149     * the parameters in the given request.  The parameter names should match
150     * those assigned in resultsForm.xml */
151    public static void fillReturnSpec(ReturnSpec returnSpec, HttpServletRequest request)  {
152 
153       String targetResponse = request.getParameter("TargetResponse");
154       if ((targetResponse != null) && targetResponse.trim().toLowerCase().equals("true")) {
155          //target is the http response
156          returnSpec.setTarget(null);
157       }
158       else {
159          String targetUri = request.getParameter("TargetURI");   //direction - eg URI
160          if ((targetUri != null) && (targetUri.trim().length()>0)) {
161                
162             try {
163                returnSpec.setTarget(TargetMaker.makeTarget(targetUri));
164             }
165             catch (URISyntaxException e) {
166                throw new IllegalArgumentException("Invalid target: "+targetUri+" ("+e+")");
167             }
168             catch (IOException e) {
169                throw new IllegalArgumentException("Invalid target: "+targetUri+" ("+e+")");
170             }
171          }
172          else {
173             //throw new IllegalArgumentException("Bad Target; TargetResponse not 'true' and TargetURI not set");
174             //assume targetresponse true (for things like cone searches)
175             returnSpec.setTarget(null);
176          }
177       }
178       
179       String format = request.getParameter("Format");
180       if ( (format != null) && (format.trim().length()>0)) {
181          returnSpec.setFormat(format);
182       }
183       
184       String compression = request.getParameter("Compression");
185       if ( (compression != null) && (compression.trim().length()>0)) {
186          returnSpec.setCompression(compression);
187       }
188 
189       String limit = request.getParameter("Limit");
190       if ( (limit != null) && (limit.trim().length()>0)) {
191          returnSpec.setLimit(Integer.parseInt(limit));
192       }
193 
194    }
195    
196    /*** Creates a Circle function condition from parameters in the given request.
197     * Accepts POS=(ra,dec) and RA=ra&DEC=dec, and SIZE and SR for search radius.
198     * Accepts all-lower case as well as all-upper case
199     */
200    public static CircleCondition makeCircleCondition(HttpServletRequest request) {
201       
202       String radiusparam = request.getParameter("SIZE");
203       if (radiusparam == null) { radiusparam = request.getParameter("size"); }
204       if (radiusparam == null) { radiusparam = request.getParameter("SR"); }
205       if (radiusparam == null) { radiusparam = request.getParameter("sr"); }
206       if (radiusparam == null) { radiusparam = request.getParameter("RADIUS"); }
207       if (radiusparam == null) { radiusparam = request.getParameter("radius"); }
208       if (radiusparam == null) {
209          throw new IllegalArgumentException("No Radius given as SIZE or SR or RADIUS");
210       }
211       double radius = Double.parseDouble(radiusparam);
212       
213       double ra;
214       double dec;
215 
216       String pos = request.getParameter("POS");
217       if (pos == null)     {  request.getParameter("pos"); }
218       if (pos != null) {
219          int comma = pos.indexOf(",");
220          ra = Double.parseDouble(pos.substring(0,comma));
221          dec = Double.parseDouble(pos.substring(comma+1));
222          return new CircleCondition(ra, dec, radius);
223       }
224 
225       String raparam = request.getParameter("RA");
226       if (raparam == null) {  raparam = request.getParameter("ra"); }
227       if (raparam == null) {  raparam = request.getParameter("Ra"); }
228       if (raparam == null) {
229          throw new IllegalArgumentException("No RA given");
230       }
231       
232       String decparam = request.getParameter("DEC");
233       if (decparam == null) { decparam = request.getParameter("dec"); }
234       if (decparam == null) { decparam = request.getParameter("Dec"); }
235       if (raparam == null) {
236          throw new IllegalArgumentException("No DEC given");
237       }
238       
239       ra = Double.parseDouble(raparam);
240       dec = Double.parseDouble(decparam);
241       
242       return new CircleCondition(ra, dec, radius);
243    }
244    
245    
246    /*** Convenience routine for returning the correct 'HTML' snippet that
247     * refreshes the page given by the URL - which should point to the same page
248     * that contains the snippet */
249    public static String makeRefreshSnippet(int secs, String url) {
250          return("(Refreshes every "+secs+" seconds)"+
251                 "<META HTTP-EQUIV='Refresh' CONTENT='"+secs+";URL="+url+"'>");
252    }
253 
254    /*** Returns the stylesheet to be used for the center's html pages in the form
255     * of a 'link' element.  Returns an empty string if none configured */
256    public static String getCssLink() {
257       String cssName = ConfigFactory.getCommonConfig().getString("datacenter.stylesheet",  "default.css");
258       if (cssName.length() == 0) {
259          return "";
260       }
261       else {
262          return "<LINK href='"+cssName+"' rel='stylesheet' type='text/css'>";
263       }
264    }
265 
266    /*** Convenience routine that returns the complete <HEAD> element for the
267     * standard datacenter page */
268    public static String getHeadElement(String title) {
269       return "<HEAD>\n"+
270              "  <TITLE>"+title+" ("+DataServer.getDatacenterName()+")</TITLE>\n"+
271              "  "+getCssLink()+"\n"+
272              "</HEAD>\n";
273    }
274 
275    
276    /*** Retruns the available formats as a list of <option>format</option>
277     * in a single string */
278    public static String getFormatOptions() throws IOException {
279       String f[] = DataServer.getFormats();
280       
281       String ops = "";
282       for (int i = 0; i < f.length; i++) {
283          ops = ops + "<option>"+MimeNames.humanFriendly(f[i])+"</option>";
284       }
285       return ops;
286    }
287    
288    /***
289     * Returns an error as string suitable for display in a browser as an html
290     * page
291     */
292    public static String exceptionAsHtmlPage(String title, Throwable th, String details) {
293       return
294          "<html>\n"+
295          "<head><title>ERROR: "+makeSafeForHtml(title)+"</title></head>\n"+
296          "<body>\n"+
297          exceptionAsHtml(title, th, details)+
298          "</body>\n"+
299          "</html>\n";
300    }
301 
302    /*** Returns exception suitable for a paragraph in an hmtl page */
303    public static String exceptionAsHtml(String title, Throwable th, String details) {
304 
305       String s =
306          "<h1>ERROR REPORT</h1>\n";
307       
308       if (th != null) {
309          s=s+
310             "<h2>"+makeSafeForHtml(th.getMessage())+"</h2>\n";
311       }
312       s =s + "<p>"+title+"</p>\n";
313 
314       if (th != null) {
315          StringWriter sw = new StringWriter();
316          th.printStackTrace(new PrintWriter(sw));
317          String stack = sw.toString();
318 
319          s = s +
320          "<p><b>"+makeSafeForHtml(th.toString())+"</b></p>\n"+
321          "<p>\n"+
322          "<pre>"+makeSafeForHtml(stack)+"</pre>\n"+
323          "</p>\n"+
324          "<p>\n";
325       }
326       
327       s=s+
328          "<pre>"+makeSafeForHtml(details)+"</pre>\n"+
329          "</p>\n";
330 
331       return s;
332    }
333 
334    /***
335     * Deals with special characters */
336    public static String makeSafeForHtml(String s) {
337       if (s==null) {
338          return "";
339       }
340       s = s.replaceAll(">", "&gt;").replaceAll("<", "&lt;");
341       return s.replaceAll("\n","<br/>");
342    }
343    
344    /*** Convenience routine for exceptionAsHtml(String, Exception, String)   */
345    public static String exceptionAsHtmlPage(String title, Throwable th) {
346       return exceptionAsHtmlPage(title, th, "");
347    }
348    
349    /*** For quick tests/debugging */
350    public static void main(String[] args) throws IOException
351    {
352       String t = getFormatOptions();
353       System.out.println(t);
354    }
355 }
356 
357 
358 
359 
360 
361 
362 
363 
364 
365 
366 
367