JAL-1620 version bump and release notes
[jalview.git] / src / jalview / ws / rest / HttpResultSet.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
3  * Copyright (C) 2014 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.ParsePackedSet;
27 import jalview.io.packed.SimpleDataProvider;
28 import jalview.io.packed.DataProvider.JvDataType;
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(MessageManager.getString("error.implementation_error_need_to_have_httpresponse"));
115     }
116     jalview.io.packed.JalviewDataset ds = restJob.newJalviewDataset();
117     // Decide how we deal with content.
118     if (en instanceof MultipartEntity)
119     {
120       // Multipart messages should be properly typed, so we parse them as we go.
121       MultipartEntity mpe = (MultipartEntity) en;
122       // multipart
123       JalviewMimeContentHandler handler = new JalviewMimeContentHandler(ds);
124       MimeStreamParser parser = new MimeStreamParser();
125       parser.setContentHandler(handler);
126       try
127       {
128         parser.parse(mpe.getContent());
129       } catch (MimeException me)
130       {
131         error = true;
132         errormessage = "Couldn't parse message from web service.";
133         Cache.log.warn("Failed to parse MIME multipart content", me);
134         en.consumeContent();
135       }
136       return new ParsePackedSet().getAlignment(ds,
137               handler.getJalviewDataProviders());
138     }
139     else
140     {
141       // Need to use hints from rest service description.
142       dp = createResultDataProviders();
143       ParsePackedSet pps = new ParsePackedSet();
144       return pps.getAlignment(ds, dp);
145     }
146   }
147
148   private void initDataSource(HttpResponse con) throws IOException
149   {
150     en = con.getEntity();
151     repeatable = en.isRepeatable();
152
153     if (!(en instanceof MultipartEntity))
154     {
155       // assume content is simple text stream that can be read from
156       String enc = (en.getContentEncoding() == null) ? null : en
157               .getContentEncoding().getValue();
158       if (en.getContentType() != null)
159       {
160         Cache.log.debug("Result Type: " + en.getContentType().toString());
161       }
162       else
163       {
164         Cache.log.debug("No Result Type Specified.");
165       }
166       if (enc == null || enc.length() < 1)
167       {
168         Cache.log.debug("Assuming 'Default' Result Encoding.");
169       }
170       else
171       {
172         Cache.log.debug("Result Encoded as : " + enc);
173       }
174       // attempt to identify file and construct an appropriate DataSource
175       // identifier for it.
176       // try to parse
177       // Mime-Multipart or single content type will be expected.
178       // if (enc.equals(org.apache.http.client.utils.)))
179       InputStreamReader br = null;
180       try
181       {
182         br = (enc != null) ? new InputStreamReader(en.getContent(), enc)
183                 : new InputStreamReader(en.getContent());
184       } catch (UnsupportedEncodingException e)
185       {
186         Cache.log.error("Can't handle encoding '" + enc
187                 + "' for response from webservice.", e);
188         en.consumeContent();
189         error = true;
190         errormessage = "Can't handle encoding for response from webservice";
191         return;
192       }
193       if (br != null)
194       {
195         dataIn = new BufferedReader(br);
196         error = false;
197       }
198     }
199   }
200
201   @Override
202   protected void finalize() throws Throwable
203   {
204     dataIn = null;
205     cachedRequest = null;
206     try
207     {
208       if (en != null)
209       {
210         en.consumeContent();
211       }
212     } catch (Exception e)
213     {
214     } catch (Error ex)
215     {
216     }
217     super.finalize();
218   }
219
220   /**
221    * 
222    * @return the URL that this result set read data from.
223    */
224   public String getUrl()
225   {
226     try
227     {
228       return cachedRequest.getURI().toURL().toString();
229     } catch (Exception x)
230     {
231       x.printStackTrace();
232       return null;
233     }
234   }
235
236 }