Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: cvebrowser/dictionary/data/net/MitreDataRepository.java


1   package cvebrowser.dictionary.data.net;
2   
3   import java.net.URL;
4   import java.net.URLConnection;
5   
6   import java.io.InputStream;
7   import java.io.FileOutputStream;
8   import java.io.BufferedOutputStream;
9   import java.io.OutputStream;
10  import java.io.IOException;
11  import java.io.FileNotFoundException;
12  import java.io.ObjectOutputStream;
13  import java.io.ObjectInputStream;
14  
15  import java.util.zip.GZIPInputStream;
16  import java.util.zip.GZIPOutputStream;
17  import java.util.Properties;
18  import java.util.ResourceBundle;
19  import java.util.Locale;
20  
21  import gnu.getopt.Getopt;
22  
23  import cvebrowser.util.CommandLine;
24  import cvebrowser.util.parser.FileType;
25  import cvebrowser.util.parser.ParserException;
26  import cvebrowser.util.parser.Types;
27  import cvebrowser.dictionary.data.parser.CSVMitreFileFactory;
28  import cvebrowser.dictionary.data.parser.CSVFile;
29  import cvebrowser.dictionary.data.parser.DataParserException;
30  
31  /**
32   * MitreDataRepository - Manages access to the CVE Mitre data file.
33   * @version 0.2 - 07/06/2003
34   * @since 0.1
35   * @author Jose Vicente Nunez Zuleta (josevnz@users.sourceforge.net)
36   *
37   */
38  public final class MitreDataRepository {
39  
40      /**
41       * Size of the network buffer size
42       */
43      public static final int NET_BUFFER_SIZE = 8192;
44      
45      /**
46       * Size of the local file buffer
47       */
48      public static final int FILE_BUFFER_SIZE = 8192;
49      
50      /**
51       * Number of retry atempts after a failed connection
52       */
53      public static final int NUMBER_OF_RETRY = 3;
54      
55      /**
56       * Amount of time to wait between retry, in miliseconds
57       */
58      public static final int RETRY_WAIT = 10000;
59      
60      /**
61       * Expected number of arguments
62       */
63      public static final int EXPECTED_PARAMETERS=2;
64      
65      private URL _url;
66      private String _fileName;
67      private byte [] _buffer;
68      private Properties _config = new Properties();
69      private static ResourceBundle _bundle = null;
70      private int _numberOfRetries = NUMBER_OF_RETRY;
71      private int _retryWait = RETRY_WAIT;
72  
73      /**
74       * Parametric constructor.
75       * @param url_ URL where the Mitre CVE data file is located
76       * @param fileName_ Destination filename for the downloaded file.
77       * @throws IllegalArgumentException if any of the arguments is missing.
78       * @since 0.1
79       */
80      public MitreDataRepository(URL url_, String fileName_) {
81        if (url_ == null) {
82          throw new IllegalArgumentException(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.MitreDataRepository.message.error.MissingUrl"));
83        }
84        if (fileName_ == null) {
85          throw new IllegalArgumentException(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.MitreDataRepository.message.error.MissingFilename"));
86        }
87        _url = url_;
88        _fileName = fileName_;
89      }
90      
91      /**
92       * Set the default amount of retries after a failure
93       * @param number_ number of retries
94       * @throws IllegalArgumentException If the number of retries is invalid
95       * @since 0.1
96       */
97      public void setNumberOfRetries(int number_) throws IllegalArgumentException {
98        if (number_ < 0) {
99          throw new IllegalArgumentException(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.setNumberOfRetries.message.error.IncorrectNumberOfRetries"));
100       } else {
101         _numberOfRetries = number_;
102       }
103     }
104     
105     /**
106      * Get the current number of retries
107      * @return int Number of retries
108      * @since 0.1
109      */
110     public int getNumberOfRetries() {
111       return _numberOfRetries;
112     }
113     
114     /**
115      * Set the number of retries when getting a conection
116      * @param time_ Number of miliseconds to wait
117      *@throws IllegalArgumentException if the timeout time is invalid
118      * @since 0.1
119      */
120     public void setRetriesWait(int time_) throws IllegalArgumentException {
121       if (time_ < 0) {
122         throw new IllegalArgumentException(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.setNumberOfRetries.message.error.IncorrectTimeout"));
123       } else {
124         _retryWait = time_;
125       }
126     }
127     
128     /**
129      * Return the current retry time
130      * @return int retry time in miliseconds
131      * @since 0.1
132      */
133     public int getRetriesTimeout() {
134       return _retryWait;
135     }
136     
137     /**
138      * Returns a new URLConnection object
139      * @return URLConnection conection to the desired url
140      * @throws IOException
141      * @throws InterruptedException
142      * @since 0.1
143      */
144      private URLConnection getConnection() throws IOException, InterruptedException {
145        URLConnection conn = null;
146        int currentAttempt = 1;
147        while ( (currentAttempt <= _numberOfRetries) && (conn == null) ) {
148          try {
149            conn = _url.openConnection();
150          } catch (IOException ioexp) {
151            if (currentAttempt <= _numberOfRetries) {
152              conn = null;
153              wait(_retryWait); // wait some time before retrying again...
154            } else {
155              throw ioexp; // Re - launch the exception
156            }
157          }
158          currentAttempt++;
159        }
160        return conn;
161      }
162      
163      /**
164       * Returns the type of the polled data file, using content heuristics.
165       * @return int The data type.
166       * @throws IOException Error getting the data type.
167       * @throws InterruptedException if the inputstream cannot be obtained
168       * @throws DataParserException
169       * @throws ParserException
170       * @see cvebrowser.util.parser.Types
171       * @since 0.1
172       */
173      public int getType() throws IOException, InterruptedException, DataParserException, ParserException {
174        int type = Types.DATA_TYPE_UNKNOWN;
175        InputStream inputstream = null;
176        CSVFile csvFile = null;
177        try {
178          inputstream = getInputStream();
179          csvFile = CSVMitreFileFactory.getCSVFile(inputstream);
180          type = csvFile.getType();
181        } catch (IOException ioexp) {
182          throw ioexp;
183        } finally {
184        if (csvFile != null) {
185          try {
186            csvFile.close();
187          } catch (Exception ignore) {};
188        }
189        }
190        return type;
191      }
192      
193      /**
194       * Tells if the CVE file is compressed or not
195       * @return boolean
196       * @throws IOException Error getting the stream
197       * @throws InterruptedException
198       * @since 0.1
199       */
200      public boolean isCompressed() throws IOException, InterruptedException {
201      boolean isCompressed = true;
202      InputStream inputstream = null;
203      try {
204        inputstream = new GZIPInputStream( (getConnection()).getInputStream());
205      } catch (IOException ioexp) {
206          if (ioexp.toString().indexOf("Not in GZIP format") != -1) { // Is not compressed
207            isCompressed = false;
208       } else { // other type of error, let the caller to deal with it.
209            throw ioexp;
210       }
211      } finally {
212        if (inputstream != null) {
213          try {
214            inputstream.close();
215          } catch (Exception ignore) {};
216        }
217      }
218      return isCompressed;
219      }
220      
221      /**
222       * Get an InputStream, regardless if the data file is compressed or not.
223       * @return InputStream. Can be null on errors.
224       * @throws IOException If the inputstream cannot be obtained
225       * @throws InterruptedException if the inputstream cannot be obtained
226       * @since 0.1
227       */
228      public InputStream getInputStream() throws IOException, InterruptedException {
229      URLConnection conn = null;
230      InputStream inputstream = null;
231      try {
232        conn = getConnection();
233        // Check if the Stream is compressed and deal with it in the most appropiate way
234        inputstream = conn.getInputStream();
235      } catch (IOException ioexp) {
236        throw ioexp;
237      } finally {
238        // empty
239      }
240      return inputstream;
241      }
242       
243     /**
244      * Returns the version of the CVE / CAN datafile. An internal check is made to check wich type of data file is being polled.
245      * @return String Version of the CVE file
246      * @throws IOException Error getting the version
247      * @throws InterruptedException Error getting the version
248      * @throws NumberFormatException If the serial is not a number
249      * @throws DataParserException
250      * @throws ParserException
251      * @since 0.1
252      */
253     public String getVersion() throws IOException, InterruptedException, NumberFormatException, DataParserException, ParserException {
254      String version = null;
255      InputStream inputstream = null;
256      CSVFile csvFile = null;
257      try {
258        csvFile = CSVMitreFileFactory.getCSVFile(getInputStream());
259        version = csvFile.getVersion();
260        Integer.parseInt(version); // final test, check if is a number
261      } catch (NumberFormatException nfexp) {
262        throw nfexp;
263      } catch (IOException ioexp) {
264        throw ioexp;
265      } finally {
266        if (csvFile != null) {
267          try {
268            csvFile.close();
269          } catch (Exception ignore) {};
270        }
271      }
272      return version;
273     }
274 
275     /**
276      * Download the file to the desired location. If the file is not compressed then is compressed on the fly using GZIP.
277      * @return int Number of bytes downloaded
278      * @throws IOException
279      * @throws InterruptedException
280      * @since 0.1
281      */
282     public int download() throws IOException, InterruptedException {
283       InputStream input = null;
284             OutputStream localFile = null;
285       byte [] buffer = null;
286       int readBytes = 0;
287       try {
288                 URLConnection urlcon = _url.openConnection();
289                 input = urlcon.getInputStream();
290     if (! isCompressed()) {
291       localFile = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(_fileName), FILE_BUFFER_SIZE));
292     } else {
293       localFile = new BufferedOutputStream(new FileOutputStream(_fileName), FILE_BUFFER_SIZE);
294     }
295                 buffer = new byte[urlcon.getContentLength()];
296     int currbytes = 0;
297                 while((currbytes = input.read(buffer)) != -1) {
298                     localFile.write(buffer, 0, currbytes);
299         readBytes += currbytes;
300                 }
301     ((BufferedOutputStream) localFile).flush();
302       } catch (FileNotFoundException fne) {
303         // Add extra information to the exception, the regular Java message is too simple.
304         throw new FileNotFoundException(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.MitreDataRepository.message.error.downloadUrlIsIncorrect") + ", " + fne);
305             } catch (IOException ioe) {
306                 throw ioe;
307       } finally {
308                 if (localFile != null) {
309                     try { localFile.close(); } catch (IOException ignore) {};
310                 }
311             }
312       return readBytes;
313     }
314     
315     /**
316      * Command line entry point
317      * Currently recognized parameters.
318      * <ul>
319      * <li> -s : Where to download the file.
320      * <li> -d : Where to save the file
321      * </ul>
322      * Optional parameters:
323      * <ul>
324      * <li> -l : Languaje to use
325      * <li> -k : Country to use
326      * <li> -h : Show the localized mini help.
327      * </ul>
328      * @param argv_
329      * @throws IllegalArgumentException
330      * @throws NetException
331      */
332     public static void main (String [] argv_) throws NetException {
333       Getopt optList = new Getopt(MitreDataRepository.class.getName(), argv_, "s:d:l:k:h");
334       MitreDataRepository instance = null;
335       String sourceUrl = null;
336       String destFileName = null;
337       boolean getHelp = false;
338       String languaje = null;
339       String country = null;
340       int requiredParametersCounter = 0;
341       try {
342         int option;
343         String arg;
344         while ((option = optList.getopt()) != -1) {
345           switch(option) {
346             case 's':
347               sourceUrl = optList.getOptarg().trim();
348               requiredParametersCounter++;
349               break;
350             case 'd':
351               destFileName = optList.getOptarg().trim();
352               requiredParametersCounter++;
353               break;
354             case 'h':
355               getHelp = true;
356               break;
357             case 'l':
358               languaje = optList.getOptarg().trim();
359               break;
360             case 'k':
361               country = optList.getOptarg().trim();
362               break;
363             case '?':
364               break; // getopt() already printed an error
365             default:
366               //
367           }
368         }
369         CommandLine.setDefaultLanguaje(languaje, country);
370         _bundle = ResourceBundle.getBundle(MitreDataRepository.class.getName(), Locale.getDefault());
371         if (getHelp) {
372           System.out.println(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.main.info.usageMode"));
373           return;
374         }
375         CommandLine.checkAllTheParameters(requiredParametersCounter, EXPECTED_PARAMETERS, true);
376         System.out.println(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.main.info.downloadInfo") + "('" + sourceUrl + "', '" + destFileName + "')");
377         instance = new MitreDataRepository(new URL(sourceUrl), destFileName);
378         int bytes = instance.download();
379         System.out.println(_bundle.getString("cvebrowser.dictionary.data.net.MitreDataRepository.main.info.bytesDownloaded") + ": " + bytes);
380       } catch (Exception exp) {
381         throw new NetException(exp.toString(), exp);
382       }
383     }
384     
385     /**
386      * Make this class uncloneable. Anyone who wants to use this class must use the constructor.
387      * @throws CloneNotSupportedException
388      */
389      public final Object clone() throws java.lang.CloneNotSupportedException {
390      throw new java.lang.CloneNotSupportedException();
391      }
392      
393      /**
394      * Make this class unserializable. Any attempt to serialize will throw an exception.
395      * @param out_
396      * @throws IOException
397      */
398      private final void writeObject(ObjectOutputStream out_) throws java.io.IOException {
399        throw new java.io.IOException();
400      }
401      
402      /**
403      * Make this class undeserializeable. Throw an exception if this method is ever called.
404      * @param in_
405      * @throws IOException
406      */
407      private final void readObject(ObjectInputStream in_) throws java.io.IOException {
408        throw new java.io.IOException();
409      }
410 } // end of class