KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > tasklist > bugs > bugzilla > Bugzilla


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.bugzilla;
21
22 import java.io.*;
23 import java.net.URL JavaDoc;
24 import java.util.*;
25 import java.text.MessageFormat JavaDoc;
26
27 import javax.xml.parsers.SAXParserFactory JavaDoc;
28 import javax.xml.parsers.SAXParser JavaDoc;
29 import javax.xml.parsers.ParserConfigurationException JavaDoc;
30 import org.xml.sax.SAXException JavaDoc;
31 import org.xml.sax.XMLReader JavaDoc;
32 import org.xml.sax.InputSource JavaDoc;
33
34 import org.openide.awt.StatusDisplayer;
35 import org.openide.util.NbBundle;
36
37 /**
38  * A connection to Bugzilla. Connects to the database and provides
39  * descriptions of bugs. Is not thread safe, each thread should use
40  * its own instance of Bugzilla.
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  * serff@netbeans.org:
58  * This class is almost exactally the same as Issuezilla, but modified to
59  * work with bugzilla.
60  *
61  * @author Ivan Bradac, refactored by Jaroslav Tulach, modified by serff
62  */

63 public final class Bugzilla extends java.lang.Object JavaDoc {
64     /** url base of issuezilla. For netbeans it is
65      * "http://openide.netbeans.org/issues/"
66      */

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

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

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

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

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

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

307     private Issue[] getBugs(InputStream in, URL JavaDoc source)
308     throws SAXException JavaDoc, IOException {
309         BugzillaXMLHandler handler = new BugzillaXMLHandler();
310         InputSource JavaDoc input = new InputSource JavaDoc(in);
311         input.setSystemId(source.toExternalForm());
312         saxParser.parse(input, handler);
313         return getBugsFromHandler(handler);
314     }
315     
316     /**
317      * Gets the bugs form the handler. This must be called once the handler
318      * finished its work.
319      */

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

351
352 /* Query *
353     public static void main (String[] args) throws Exception {
354         Bugzilla iz = new Bugzilla (new URL ("http://www.netbeans.org/issues/"));
355         iz.setProxyPool("webcache.czech.sun.com:8080,webczech.uk.sun.com:8080,webcache.holland.sun.com:8080");
356         
357
358         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");
359         
360         String sep = "";
361         for (int i = 0; i < res.length; i++) {
362             System.out.print(sep);
363             System.out.print(res[i]);
364             sep = ", ";
365         }
366         System.out.println();
367     }
368 /**/

369     
370 }
371
Popular Tags