1 package jalview.ext.ensembl;
3 import jalview.io.FileParse;
5 import java.io.BufferedReader;
6 import java.io.DataOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.net.HttpURLConnection;
11 import java.net.MalformedURLException;
13 import java.util.List;
15 import javax.ws.rs.HttpMethod;
18 * Base class for Ensembl REST service clients
22 abstract class EnsemblRestClient extends EnsemblSequenceFetcher
24 protected final static String ENSEMBL_REST = "http://rest.ensembl.org";
26 protected static final String SEQUENCE_ID_URL = ENSEMBL_REST
29 // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
30 private static final String PING_URL = "http://rest.ensembl.org/info/ping.json";
32 private final static long RETEST_INTERVAL = 10000L; // 10 seconds
34 private static boolean ensemblRestAvailable = false;
36 private static long lastCheck = -1;
38 protected volatile boolean inProgress = false;
41 public boolean queryInProgress()
47 public StringBuffer getRawRecords()
53 * Returns the URL for the client http request
57 * @throws MalformedURLException
59 protected abstract URL getUrl(List<String> ids)
60 throws MalformedURLException;
63 * Returns true if client uses GET method, false if it uses POST
67 protected abstract boolean useGetRequest();
70 * Return the desired value for the Content-Type request header
75 * @see https://github.com/Ensembl/ensembl-rest/wiki/HTTP-Headers
77 protected abstract String getRequestMimeType(boolean multipleIds);
80 * Return the desired value for the Accept request header
83 * @see https://github.com/Ensembl/ensembl-rest/wiki/HTTP-Headers
85 protected abstract String getResponseMimeType();
88 * Tries to connect to Ensembl's REST 'ping' endpoint, and returns true if
89 * successful, else false
93 private boolean checkEnsembl()
97 URL ping = new URL(PING_URL);
98 HttpURLConnection conn = (HttpURLConnection) ping.openConnection();
99 int rc = conn.getResponseCode();
101 if (rc >= 200 && rc < 300)
105 } catch (Throwable t)
107 System.err.println("Error connecting to " + PING_URL + ": "
114 * returns a reader to a Fasta response from the Ensembl sequence endpoint
118 * @throws IOException
120 protected FileParse getSequenceReader(List<String> ids)
123 URL url = getUrl(ids);
125 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
128 * POST method allows multiple queries in one request; it is supported for
129 * sequence queries, but not for overlap
131 boolean multipleIds = ids.size() > 1;// useGetRequest();
132 connection.setRequestMethod(multipleIds ? HttpMethod.POST
134 connection.setRequestProperty("Content-Type",
135 getRequestMimeType(multipleIds));
136 connection.setRequestProperty("Accept", getResponseMimeType());
138 connection.setUseCaches(false);
139 connection.setDoInput(true);
140 connection.setDoOutput(multipleIds);
144 writePostBody(connection, ids);
147 InputStream response = connection.getInputStream();
148 int responseCode = connection.getResponseCode();
150 if (responseCode != 200)
153 * note: a GET request for an invalid id returns an error code e.g. 415
154 * but POST request returns 200 and an empty Fasta response
156 throw new RuntimeException(
157 "Response code was not 200. Detected response was "
161 BufferedReader reader = null;
162 reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
163 FileParse fp = new FileParse(reader, url.toString(), "HTTP_POST");
168 * Rechecks if Ensembl is responding, unless the last check was successful and
169 * the retest interval has not yet elapsed. Returns true if Ensembl is up,
174 protected boolean isEnsemblAvailable()
176 long now = System.currentTimeMillis();
177 boolean retest = now - lastCheck > RETEST_INTERVAL;
178 if (ensemblRestAvailable && !retest)
182 ensemblRestAvailable = checkEnsembl();
184 return ensemblRestAvailable;
188 * Constructs, writes and flushes the POST body of the request, containing the
189 * query ids in JSON format
193 * @throws IOException
195 protected void writePostBody(HttpURLConnection connection,
196 List<String> ids) throws IOException
199 StringBuilder postBody = new StringBuilder(64);
200 postBody.append("{\"ids\":[");
202 for (String id : ids)
206 postBody.append(",");
209 postBody.append("\"");
210 postBody.append(id.trim());
211 postBody.append("\"");
213 postBody.append("]}");
214 byte[] thepostbody = postBody.toString().getBytes();
215 connection.setRequestProperty("Content-Length",
216 Integer.toString(thepostbody.length));
217 DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
218 wr.write(thepostbody);