JAL-2662 Updated README
[jalview.git] / src / jalview / ws / rest / HttpResultSet.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.ws.rest;
22
23 import jalview.bin.Cache;
24 import jalview.io.FileParse;
25 import jalview.io.packed.DataProvider;
26 import jalview.io.packed.DataProvider.JvDataType;
27 import jalview.io.packed.ParsePackedSet;
28 import jalview.io.packed.SimpleDataProvider;
29 import jalview.util.MessageManager;
30 import jalview.ws.io.mime.JalviewMimeContentHandler;
31
32 import java.io.BufferedReader;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.io.UnsupportedEncodingException;
36 import java.util.ArrayList;
37 import java.util.List;
38
39 import org.apache.http.HttpEntity;
40 import org.apache.http.HttpResponse;
41 import org.apache.http.client.methods.HttpRequestBase;
42 import org.apache.http.entity.mime.MultipartEntity;
43 import org.apache.james.mime4j.MimeException;
44 import org.apache.james.mime4j.parser.MimeStreamParser;
45
46 /**
47  * data source instantiated from the response of an httpclient request.
48  * 
49  * @author JimP
50  * 
51  */
52
53 public class HttpResultSet extends FileParse
54 {
55
56   private HttpRequestBase cachedRequest;
57
58   /**
59    * when set, indicates that en can be recreated by repeating the HttpRequest
60    * in cachedRequest
61    */
62   boolean repeatable = false;
63
64   /**
65    * response that is to be parsed as jalview input data
66    */
67   private HttpEntity en = null;
68
69   /**
70    * (sub)job that produced this result set.
71    */
72   private RestJob restJob;
73
74   public HttpResultSet(RestJob rj, HttpResponse con, HttpRequestBase req)
75           throws IOException
76   {
77     super();
78     setDataName(rj.getJobId() + " Part " + rj.getJobnum());
79     restJob = rj;
80     cachedRequest = req;
81     initDataSource(con);
82   }
83
84   /**
85    * construct a set of dataproviders to parse a result set from this service
86    * 
87    * @param resSet
88    * @return
89    */
90   public List<DataProvider> createResultDataProviders()
91   {
92     List<DataProvider> dp = new ArrayList<DataProvider>();
93     for (JvDataType type : restJob.rsd.getResultDataTypes())
94     {
95       dp.add(new SimpleDataProvider(type, this, null));
96     }
97     return dp;
98   }
99
100   /**
101    * parses the results of the service output.
102    * 
103    * @return the result of ParsePackedSet.getAlignment()
104    * @throws Exception
105    * @throws Error
106    */
107   public Object[] parseResultSet() throws Exception, Error
108   {
109     List<DataProvider> dp = new ArrayList<DataProvider>();
110     Object[] results = null;
111
112     if (en == null)
113     {
114       throw new Error(
115               MessageManager
116                       .getString("error.implementation_error_need_to_have_httpresponse"));
117     }
118     jalview.io.packed.JalviewDataset ds = restJob.newJalviewDataset();
119     // Decide how we deal with content.
120     if (en instanceof MultipartEntity)
121     {
122       // Multipart messages should be properly typed, so we parse them as we go.
123       MultipartEntity mpe = (MultipartEntity) en;
124       // multipart
125       JalviewMimeContentHandler handler = new JalviewMimeContentHandler(ds);
126       MimeStreamParser parser = new MimeStreamParser();
127       parser.setContentHandler(handler);
128       try
129       {
130         parser.parse(mpe.getContent());
131       } catch (MimeException me)
132       {
133         error = true;
134         errormessage = "Couldn't parse message from web service.";
135         Cache.log.warn("Failed to parse MIME multipart content", me);
136         en.consumeContent();
137       }
138       return new ParsePackedSet().getAlignment(ds,
139               handler.getJalviewDataProviders());
140     }
141     else
142     {
143       // Need to use hints from rest service description.
144       dp = createResultDataProviders();
145       ParsePackedSet pps = new ParsePackedSet();
146       return pps.getAlignment(ds, dp);
147     }
148   }
149
150   private void initDataSource(HttpResponse con) throws IOException
151   {
152     en = con.getEntity();
153     repeatable = en.isRepeatable();
154
155     if (!(en instanceof MultipartEntity))
156     {
157       // assume content is simple text stream that can be read from
158       String enc = (en.getContentEncoding() == null) ? null : en
159               .getContentEncoding().getValue();
160       if (en.getContentType() != null)
161       {
162         Cache.log.debug("Result Type: " + en.getContentType().toString());
163       }
164       else
165       {
166         Cache.log.debug("No Result Type Specified.");
167       }
168       if (enc == null || enc.length() < 1)
169       {
170         Cache.log.debug("Assuming 'Default' Result Encoding.");
171       }
172       else
173       {
174         Cache.log.debug("Result Encoded as : " + enc);
175       }
176       // attempt to identify file and construct an appropriate DataSource
177       // identifier for it.
178       // try to parse
179       // Mime-Multipart or single content type will be expected.
180       // if (enc.equals(org.apache.http.client.utils.)))
181       InputStreamReader br = null;
182       try
183       {
184         br = (enc != null) ? new InputStreamReader(en.getContent(), enc)
185                 : new InputStreamReader(en.getContent());
186       } catch (UnsupportedEncodingException e)
187       {
188         Cache.log.error("Can't handle encoding '" + enc
189                 + "' for response from webservice.", e);
190         en.consumeContent();
191         error = true;
192         errormessage = "Can't handle encoding for response from webservice";
193         return;
194       }
195       if (br != null)
196       {
197         dataIn = new BufferedReader(br);
198         error = false;
199       }
200     }
201   }
202
203   @Override
204   protected void finalize() throws Throwable
205   {
206     dataIn = null;
207     cachedRequest = null;
208     try
209     {
210       if (en != null)
211       {
212         en.consumeContent();
213       }
214     } catch (Exception e)
215     {
216     } catch (Error ex)
217     {
218     }
219     super.finalize();
220   }
221
222   /**
223    * 
224    * @return the URL that this result set read data from.
225    */
226   public String getUrl()
227   {
228     try
229     {
230       return cachedRequest.getURI().toURL().toString();
231     } catch (Exception x)
232     {
233       x.printStackTrace();
234       return null;
235     }
236   }
237
238 }