merge from 2_4_Release branch
[jalview.git] / src / org / biojava / dasobert / das / DAS_FeatureRetrieve.java
1 /**
2  *                    BioJava development code
3  *
4  * This code may be freely distributed and modified under the
5  * terms of the GNU Lesser General Public Licence.  This should
6  * be distributed with the code.  If you do not have a copy,
7  * see:
8  *
9  *      http://www.gnu.org/copyleft/lesser.html
10  *
11  * Copyright for this code is held jointly by the individual
12  * authors.  These should be listed in @author doc comments.
13  *
14  * For more information on the BioJava project and its aims,
15  * or to join the biojava-l mailing list, visit the home page
16  * at:
17  *
18  *      http://www.biojava.org/
19  *
20  * Created on 19.03.2004
21  * @author Andreas Prlic
22  *
23  */
24 package org.biojava.dasobert.das;
25
26 import java.io.*;
27 import java.lang.reflect.*;
28 import java.net.*;
29 import java.util.*;
30 import java.util.logging.*;
31 import javax.xml.parsers.*;
32
33 import org.xml.sax.*;
34
35 /**
36  * A class to perform a DAS features request
37  * 
38  * @author Andreas Prlic Adapted for jalview use.
39  * @author Andrew Waterhouse Updated to Das 1.53e feature spec.
40  * @author Jim Procter
41  */
42 public class DAS_FeatureRetrieve
43 {
44   String version;
45
46   List features;
47
48   Logger logger;
49
50   int comeBackLater;
51
52   URL url;
53
54   /**
55    * @param url
56    *                the URL the features should be downloaded from
57    * 
58    */
59   public DAS_FeatureRetrieve(URL url)
60   {
61     super();
62
63     logger = Logger.getLogger("org.biojava.spice");
64     features = new ArrayList();
65     comeBackLater = -1;
66     this.url = url;
67     reload();
68   }
69
70   /**
71    * contact the DAS-feature server again. Usually it is not necessary to call
72    * this again, because the constructor already does, but if comeBackLater > -1
73    * this should be called again.
74    * 
75    */
76   public void reload()
77   {
78
79     try
80     {
81
82       InputStream dasInStream = null;
83       try
84       {
85         dasInStream = open(url);
86       } catch (Exception e)
87       {
88         comeBackLater = -1;
89         System.out.println("NO RESPONSE FROM " + url);
90         logger.log(Level.FINE, "could not open connection to " + url, e);
91         return;
92       }
93
94       SAXParserFactory spfactory = SAXParserFactory.newInstance();
95
96       spfactory.setValidating(false);
97
98       SAXParser saxParser = null;
99
100       try
101       {
102         saxParser = spfactory.newSAXParser();
103       } catch (ParserConfigurationException e)
104       {
105         e.printStackTrace();
106       }
107
108       String vali = System.getProperty("XMLVALIDATION");
109
110       boolean validation = false;
111       if (vali != null)
112       {
113         if (vali.equals("true"))
114         {
115           validation = true;
116         }
117       }
118
119       XMLReader xmlreader = saxParser.getXMLReader();
120
121       // XMLReader xmlreader = XMLReaderFactory.createXMLReader();
122       try
123       {
124         xmlreader.setFeature("http://xml.org/sax/features/validation",
125                 validation);
126       } catch (SAXException e)
127       {
128         logger.log(Level.FINE, "Cannot set validation " + validation);
129       }
130
131       try
132       {
133         xmlreader
134                 .setFeature(
135                         "http://apache.org/xml/features/nonvalidating/load-external-dtd",
136                         validation);
137       } catch (SAXNotRecognizedException e)
138       {
139         e.printStackTrace();
140         logger
141                 .log(Level.FINE, "Cannot set load-external-dtd "
142                         + validation);
143
144       }
145
146       DAS_Feature_Handler cont_handle = new DAS_Feature_Handler();
147       cont_handle.setDASCommand(url.toString());
148       xmlreader.setContentHandler(cont_handle);
149       xmlreader.setErrorHandler(new org.xml.sax.helpers.DefaultHandler());
150       InputSource insource = new InputSource();
151       insource.setByteStream(dasInStream);
152
153       try
154       {
155         xmlreader.parse(insource);
156         features = cont_handle.get_features();
157         version = cont_handle.getVersion();
158
159         comeBackLater = cont_handle.getComBackLater();
160       } catch (Exception e)
161       {
162         System.out
163                 .println("Error parsing response from: " + url + "\n" + e);
164         logger.log(Level.FINE, "error while parsing response from " + url);
165         comeBackLater = -1;
166         features = new ArrayList();
167       }
168     } catch (Exception ex)
169     {
170       ex.printStackTrace();
171       comeBackLater = -1;
172     }
173   }
174
175   /**
176    * open HttpURLConnection. Recommended way to open HttpURLConnections, since
177    * this take care of setting timeouts properly for java 1.4 and 1.5
178    */
179   public static HttpURLConnection openHttpURLConnection(URL url)
180           throws IOException, ConnectException
181   {
182     HttpURLConnection huc = null;
183     huc = (HttpURLConnection) url.openConnection();
184
185     String os_name = java.lang.System.getProperty("os.name");
186     String os_version = java.lang.System.getProperty("os.version");
187     String os_arch = java.lang.System.getProperty("os.arch");
188     String VERSION = "1.0";
189
190     String userAgent = "Jalview " + VERSION + "(" + os_name + "; "
191             + os_arch + " ; " + os_version + ")";
192     // e.g. "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040803"
193     huc.addRequestProperty("User-Agent", userAgent);
194     // logger.finest("opening "+url);
195
196     int timeout = 10000;
197     System
198             .setProperty("sun.net.client.defaultConnectTimeout", timeout
199                     + "");
200     System.setProperty("sun.net.client.defaultReadTimeout", timeout + "");
201
202     // use reflection to determine if get and set timeout methods for
203     // urlconnection are available
204     // seems java 1.5 does not watch the System properties any longer...
205     // and java 1.4 did not provide these...
206     // for 1.4 see setSystemProperties
207
208     try
209     {
210       // try to use reflection to set timeout property
211       Class urlconnectionClass = Class
212               .forName("java.net.HttpURLConnection");
213
214       Method setconnecttimeout = urlconnectionClass.getMethod(
215               "setConnectTimeout", new Class[]
216               { int.class });
217       setconnecttimeout.invoke(huc, new Object[]
218       { new Integer(timeout) });
219
220       Method setreadtimeout = urlconnectionClass.getMethod(
221               "setReadTimeout", new Class[]
222               { int.class });
223       setreadtimeout.invoke(huc, new Object[]
224       { new Integer(timeout) });
225       // System.out.println("successfully set java 1.5 timeout");
226     } catch (Exception e)
227     {
228       // e.printStackTrace();
229       // most likely it was a NoSuchMEthodException and we are running java 1.4.
230     }
231     return huc;
232   }
233
234   private InputStream open(URL url) throws java.io.IOException,
235           java.net.ConnectException
236   {
237     InputStream inStream = null;
238
239     HttpURLConnection huc = openHttpURLConnection(url);
240
241     inStream = huc.getInputStream();
242
243     return inStream;
244
245   }
246
247   /**
248    * returns a List of Features
249    * 
250    * @return a List of Maps containing the features
251    */
252   public List get_features()
253   {
254
255     return features;
256   }
257
258   /**
259    * Get the version string of the reference object. If it does not match the
260    * version string that is obtained from the reference server there is a
261    * version problem!
262    * 
263    * @return version string. (e.g. a MD5 digest of the reference sequence)
264    */
265   public String getVersion()
266   {
267     return version;
268   }
269
270   public void setVersion(String version)
271   {
272     this.version = version;
273   }
274
275   /**
276    * returns the comeBackLater value - if a server returned suchh -
277    * 
278    * @return comeBackLater in seconds, or -1 if not provided by server
279    */
280   public int getComeBackLater()
281   {
282
283     return comeBackLater;
284
285   }
286
287 }