KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > tasklist > bugs > issuezilla > Issuezilla


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.tasklist.bugs.issuezilla;
21
22 import java.io.*;
23 import java.net.URL JavaDoc;
24 import java.net.MalformedURLException JavaDoc;
25 import java.net.URLConnection JavaDoc;
26 import java.util.*;
27 import java.text.MessageFormat JavaDoc;
28
29 import javax.xml.parsers.SAXParserFactory JavaDoc;
30 import javax.xml.parsers.SAXParser JavaDoc;
31 import javax.xml.parsers.ParserConfigurationException JavaDoc;
32 import org.openide.awt.StatusDisplayer;
33 import org.xml.sax.SAXException JavaDoc;
34
35 import org.openide.util.NbBundle;
36
37 /**
38  * A connection to Issuezilla. Connects to the database and provides
39  * descriptions of issues. Is not thread safe, each thread should use
40  * its own instance of Issuezilla.
41  *
42  * tor@netbeans.org:
43  * This class is virtually identical to
44  * nbbuild/antsrc/org/netbeans/nbbuild/Issuezilla.java
45  * At first, I inclouded its class file directly as part of
46  * the build. However, treating Issuezilla as a black box
47  * didn't work well because when connections fail (and are
48  * retried), or even during a query, there is no feedback - and
49  * since issuezilla is so slow, it's hard to know in the GUI
50  * that things are working. Therefore, I've modified the java
51  * file to give us a little bit more feedback.
52  * In CVS I stored the original file as the first revision,
53  * so you can easily diff to see what has changed - and generate
54  * a patch which you can then apply to an updated version
55  * of nbbuild/antsrc/ to keep the two in sync.
56  *
57  * @author Ivan Bradac, refactored by Jaroslav Tulach
58  */

59 public final class Issuezilla extends java.lang.Object JavaDoc {
60     /** url base of issuezilla. For netbeans it is
61      * "http://openide.netbeans.org/issues/"
62      */

63     private java.net.URL JavaDoc urlBase;
64     /** sax parser to use */
65     private SAXParser JavaDoc saxParser;
66
67     /** maximum IO failures during connection to IZ */
68     private int maxIOFailures = 15;
69     
70     private Vector proxyServer = null;
71     
72     private int lastProxy = -1;
73    
74    
75     /** Creates new connection to issuezilla. The urlBase should
76      * point to URL where issuezilla produces its XML results.
77      * In case of NetBeans the URL is
78      * <B>"http://openide.netbeans.org/issues/xml.cgi"</B>
79      * @param urlBase a URI to issuezilla's XML service
80      */

81     public Issuezilla(java.net.URL JavaDoc urlBase) {
82         this.urlBase = urlBase;
83         
84         try {
85             SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
86             factory.setValidating (false);
87             saxParser = factory.newSAXParser();
88         } catch (Exception JavaDoc ex) {
89             ex.printStackTrace();
90             throw new IllegalStateException JavaDoc ("Cannot initialize parser");
91         }
92     }
93     
94     public void setProxyPool( String JavaDoc proxyPool ) {
95         java.util.StringTokenizer JavaDoc tokens = new java.util.StringTokenizer JavaDoc( proxyPool, "," );
96         
97         proxyServer = new Vector();
98         
99         while ( tokens.hasMoreTokens() ) {
100             proxyServer.add( tokens.nextToken() );
101         }
102         rotateProxy();
103     }
104     
105     private void rotateProxy() {
106         if (proxyServer == null) return;
107         
108         if (proxyServer.size() == 0) return;
109         
110         if (lastProxy + 2 > proxyServer.size()) lastProxy = 0;
111         else lastProxy++;
112         
113         String JavaDoc proxyString = (String JavaDoc) proxyServer.get( lastProxy );
114         String JavaDoc host = proxyString.substring(0, proxyString.indexOf(':'));
115         String JavaDoc port = proxyString.substring(proxyString.indexOf(':')+1);
116   
117         System.out.println("Rotating http proxy server to " + host + ":" + port);
118         
119         if (!port.equals("")) {
120             System.getProperties ().put ("http.proxyPort", port);
121         }
122         if (!host.equals("")) {
123             System.getProperties ().put ("http.proxyHost", host);
124         }
125     }
126     
127     /** Getter of an issue for given number.
128      * @param number number of the issue
129      * @return the issue
130      * @exception IOException if connection fails
131      * @exception SAXException if parsing fails
132      */

133     public Issue getBug (int number) throws SAXException JavaDoc, IOException {
134         Issue[] arr = getBugs (new int[] { number });
135         if (arr.length != 1) {
136             throw new java.io.InvalidObjectException JavaDoc ("Issue not read");
137         }
138         
139         return arr[0];
140     }
141     
142     /** Getter of more issues at once.
143      * @param numbers array of integers with numbers of bugs to retrieve
144      * @return the issue array
145      * @exception IOException if connection fails
146      * @exception SAXException if parsing fails
147      */

148     public Issue[] getBugs (int[] numbers) throws SAXException JavaDoc, IOException {
149         int maxIssuesAtOnce = 10;
150         
151         Issue[] result = new Issue[numbers.length];
152         
153         GLOBAL: for (int issueToProcess = 0; issueToProcess < numbers.length; ) {
154             int lastIssueRightNow = Math.min (numbers.length, issueToProcess + maxIssuesAtOnce);
155         
156             StringBuffer JavaDoc sb = new StringBuffer JavaDoc (numbers.length * 8);
157             String JavaDoc sep = "xml.cgi?id=";
158             IOException lastEx = null;
159             for (int i = issueToProcess; i < lastIssueRightNow; i++) {
160                 sb.append (sep);
161                 sb.append (numbers[i]);
162                 sep = ",";
163             }
164             sb.append ("&show_attachments=false");
165
166             for (int iterate = 0; iterate < maxIOFailures; iterate++) {
167                 URL JavaDoc u = null;
168                 try {
169                     u = new URL JavaDoc(urlBase, sb.toString());
170                     
171                     InputStream is = u.openStream();
172
173                     Issue[] arr;
174                     try {
175                         arr = getBugs(is);
176                     } finally {
177                         is.close();
178                     }
179                     
180                     // copy the results and go on
181
for (int i = 0; i < arr.length; ) {
182                         result[issueToProcess++] = arr[i++];
183                     }
184                     
185
186                     continue GLOBAL;
187                 }
188                 catch (IOException ex) {
189                     synchronized ( this ) {
190                         try {
191                             StatusDisplayer.getDefault().setStatusText(
192                                    MessageFormat.format(
193                                     NbBundle.getMessage(Issuezilla.class,
194                          "CantConnect"), // NOI18N
195
new String JavaDoc[] {
196                                        new Date().toString(),
197                                        urlBase.getHost()
198                                    }));
199                             rotateProxy();
200                             this.wait( 5000 );
201                         }
202                         catch (InterruptedException JavaDoc ex1) {}
203                     }
204                     lastEx = ex;
205                 }
206             }
207         
208             throw lastEx;
209         } // end of GLOBAL
210

211         return result;
212     }
213     
214     /** Executes a query and returns array of issue numbers that fullfils the query.
215      * @param query the query string that should be appended to the URL after question mark part
216      * @return array of integers
217      */

218     public int[] query (String JavaDoc query) throws SAXException JavaDoc, IOException {
219         URL JavaDoc u = new URL JavaDoc (urlBase, "buglist.cgi?" + query);
220         IOException lastEx = null;
221         BufferedReader reader = null;
222
223         for (int iterate = 0; iterate < maxIOFailures; iterate++) {
224             try {
225                 reader = new BufferedReader (
226                     new InputStreamReader (u.openStream (), "UTF-8")
227                 );
228             }
229             catch (IOException ex) {
230                 synchronized ( this ) {
231                     try {
232                         StatusDisplayer.getDefault().setStatusText(
233                             NbBundle.getMessage(
234                                 Issuezilla.class, "CantConnect", // NOI18N
235
new Date().toString(),
236                                 urlBase.getHost()
237                             )
238                         );
239                         rotateProxy();
240                         this.wait( 5000 );
241                     }
242                     catch (InterruptedException JavaDoc ex1) {}
243                 }
244                 lastEx = ex;
245             }
246         }
247         if (reader == null) {
248             if (lastEx != null) throw lastEx;
249             else throw new IOException("Can't get connection to " + u.toString() + " for " + maxIOFailures + "times.");
250         }
251         
252         ArrayList result = new ArrayList ();
253         
254         String JavaDoc magic = "show_bug.cgi?id=";
255         for (;;) {
256             String JavaDoc line = reader.readLine();
257             if (line == null) {
258                 break;
259             }
260             
261             int index = line.indexOf (magic);
262             if (index == -1) {
263                 continue;
264             }
265             
266             index += magic.length ();
267             
268             int end = line.indexOf ('"', index);
269             if (end == -1) {
270                 throw new IOException ("No ending \" from index " + index + " in " + line);
271             }
272         
273             String JavaDoc number = line.substring (index, end);
274             StatusDisplayer.getDefault().setStatusText(
275                        MessageFormat.format(
276                                     NbBundle.getMessage(Issuezilla.class,
277                          "QueryBug"), // NOI18N
278
new String JavaDoc[] {
279                                        number
280             }));
281
282             
283             result.add (Integer.valueOf (number));
284         }
285         
286         int[] arr = new int[result.size ()];
287         
288         Iterator it = result.iterator ();
289         for (int i = 0; i < arr.length; i++) {
290             arr[i] = ((Integer JavaDoc)it.next ()).intValue();
291         }
292         
293         return arr;
294     }
295         
296         
297     
298     /**
299      * Gets the Issuezilla bugs from the InputStream.
300      *
301      * @return Issue[] objects from the InputStream containing
302      * their XML representation.
303      */

304     private Issue[] getBugs(InputStream in)
305     throws SAXException JavaDoc, IOException {
306         IssuezillaXMLHandler handler = new IssuezillaXMLHandler();
307         saxParser.parse(in, handler);
308         return getBugsFromHandler(handler);
309     }
310     
311     /**
312      * Gets the bugs form the handler. This must be called once the handler
313      * finished its work.
314      */

315     private Issue[] getBugsFromHandler(IssuezillaXMLHandler handler) {
316         List bugList = handler.getBugList();
317         if (bugList == null) {
318             return null;
319         }
320         Issue[] bugs = new Issue[bugList.size()];
321         for (int i = 0; i < bugList.size(); i++) {
322             Issue bug = new Issue();
323             Map atts = (Map) bugList.get(i);
324             Iterator it = atts.entrySet().iterator();
325             while (it.hasNext()) {
326                 Map.Entry entry = (Map.Entry) it.next();
327                 bug.setAttribute((String JavaDoc) entry.getKey(), entry.getValue());
328             }
329             bugs[i] = bug;
330         }
331         return bugs;
332     }
333 /*
334     public static void main (String[] args) throws Exception {
335         Issuezilla iz = new Issuezilla (new URL ("http://www.netbeans.org/issues/"));
336         
337         
338         //Issue[] arr = new Issue[] { iz.getBug (16000) };
339         Issue[] arr = iz.getBugs (new int[] { 10001, 10000 });
340         System.out.println("arr: " + arr.length);
341         for (int i = 0; i < arr.length; i++) {
342             System.out.println(i + " = " + arr[i]);
343         }
344     }
345 */

346
347 /* Query *
348     public static void main (String[] args) throws Exception {
349         Issuezilla iz = new Issuezilla (new URL ("http://www.netbeans.org/issues/"));
350         iz.setProxyPool("webcache.czech.sun.com:8080,webczech.uk.sun.com:8080,webcache.holland.sun.com:8080");
351         
352
353         int[] res = iz.query ("issue_status=NEW&issue_status=ASSIGNED&issue_status=STARTED&issue_status=REOPENED&email1=tulach&emailtype1=substring&emailassigned_to1=1&email2=&emailtype2=substring&emailreporter2=1&issueidtype=include&issue_id=&changedin=&votes=&chfieldfrom=&chfieldto=Now&chfieldvalue=&short_desc=&short_desc_type=substring&long_desc=&long_desc_type=substring&issue_file_loc=&issue_file_loc_type=substring&status_whiteboard=&status_whiteboard_type=substring&field0-0-0=noop&type0-0-0=noop&value0-0-0=&cmdtype=doit&newqueryname=&order=%27Importance%27");
354         
355         String sep = "";
356         for (int i = 0; i < res.length; i++) {
357             System.out.print(sep);
358             System.out.print(res[i]);
359             sep = ", ";
360         }
361         System.out.println();
362     }
363 /**/

364
365     /**
366      * Retrieves component names
367      * @param base service URL e.g. <code>http://tasklist.netbeans.org/issues/</code>
368      */

369     public static String JavaDoc[] getComponents(URL JavaDoc base) {
370         List components = new ArrayList(23);
371         try {
372             URL JavaDoc list = new URL JavaDoc(base, "enter_bug.cgi");
373             URLConnection JavaDoc io = list.openConnection();
374             io.connect();
375             InputStream in = new BufferedInputStream(io.getInputStream());
376             int next = in.read();
377             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
378             while (next != -1) {
379                 sb.append((char) next);
380                 next = in.read();
381             }
382
383             // parse output looking for componet names by MAGIC
384

385             String JavaDoc sample = sb.toString();
386             String JavaDoc MAGIC = "enter_bug.cgi?component="; // NOi18N
387

388             int entry = 0;
389             int end = -1;
390             while (true) {
391                 entry = sample.indexOf(MAGIC, entry);
392                 if (entry == -1) break;
393                 end = sample.indexOf("\"", entry);
394                 if (entry == -1) break;
395                 String JavaDoc component = sample.substring(entry + MAGIC.length(), end);
396                 entry = end;
397                 components.add(component);
398             }
399             return (String JavaDoc[]) components.toArray(new String JavaDoc[components.size()]);
400
401         } catch (MalformedURLException JavaDoc e) {
402             return new String JavaDoc[0];
403         } catch (IOException e) {
404             return new String JavaDoc[0];
405         }
406     }
407
408 }
409
Popular Tags