| /******************************************************************************* |
| * Copyright (c) 2004, 2008 Tasktop Technologies and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.sandbox.bridge.bugs; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.util.regex.Pattern; |
| |
| import javax.security.auth.login.LoginException; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCorePlugin; |
| import org.eclipse.mylyn.internal.bugzilla.core.IBugzillaConstants; |
| import org.eclipse.mylyn.internal.bugzilla.ui.BugzillaUiPlugin; |
| import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; |
| import org.eclipse.mylyn.tasks.core.TaskRepository; |
| |
| /** |
| * Queries the Bugzilla server for the list of bugs matching search criteria. |
| * |
| * @author Mik Kersten (hardening of initial prototype) |
| */ |
| // TODO: Delete once not needed by sandbox |
| public class BugzillaSearchEngine { |
| |
| protected static final String QUERYING_SERVER = "Querying Bugzilla Server..."; |
| |
| /** |
| * regular expression matching values of query matches' attributes in Eclipse.org Bugzilla |
| */ |
| public static final Pattern reValue = Pattern.compile("<td><nobr>([^<]*)</nobr>"); |
| |
| public static final Pattern reValueBugzilla220 = Pattern.compile("<td style=\"white-space: nowrap\">([^<]*)"); |
| |
| // private final String urlString; |
| |
| private final TaskRepository repository; |
| |
| private final boolean maxReached = false; |
| |
| // private String queryStringWithoutLogin; |
| |
| public BugzillaSearchEngine(TaskRepository repository, String queryUrl) { |
| // urlString = queryUrl; |
| // queryStringWithoutLogin = urlString; |
| // urlString = urlString.concat(IBugzillaConstants.CONTENT_TYPE_RDF); |
| this.repository = repository; |
| // this.proxySettings = proxySettings; |
| // if (repository.hasCredentials()) { |
| // try { |
| // urlString = BugzillaClient.addCredentials(urlString, |
| // repository.getCharacterEncoding(), repository |
| // .getUserName(), repository.getPassword()); |
| // } catch (UnsupportedEncodingException e) { |
| // /* |
| // * Do nothing. Every implementation of the Java platform is |
| // * required to support the standard charset "UTF-8" |
| // */ |
| // } |
| // } |
| } |
| |
| /** |
| * Wrapper for search |
| * |
| * @param collector |
| * - The collector for the results to go into |
| */ |
| public IStatus search(ProgressQueryHitCollector collector) throws LoginException { |
| return this.search(collector, 0, IBugzillaConstants.RETURN_ALL_HITS); |
| } |
| |
| /** |
| * Wrapper for search |
| * |
| * @param collector |
| * - The collector for the results to go into |
| * @param startMatches |
| * - The number of matches to start with for the progress monitor |
| */ |
| public IStatus search(ProgressQueryHitCollector collector, int startMatches) throws LoginException { |
| return this.search(collector, startMatches, BugzillaUiPlugin.getDefault().getMaxResults()); |
| } |
| |
| /** |
| * Executes the query, parses the response, and adds hits to the search result collector. |
| * |
| * @param collector |
| * - The collector for the search results |
| * @param startMatches |
| * - The number of matches to start with for the progress monitor |
| * @param maxHits |
| * - the maximum number of matches to return or IBugzillaConstants.RETURN_ALL_HITS for unlimited |
| */ |
| public IStatus search(ProgressQueryHitCollector collector, int startMatches, int maxHits) throws LoginException { |
| IProgressMonitor monitor = collector.getProgressMonitor(); |
| IStatus status = null; |
| boolean possibleBadLogin = false; |
| int numCollected = 0; |
| BufferedReader in = null; |
| |
| try { |
| monitor.beginTask(QUERYING_SERVER, maxHits);// IProgressMonitor.UNKNOWN |
| collector.aboutToStart(startMatches); |
| |
| throw new OperationCanceledException("Bugzilla Active Searchn not implemented"); |
| |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // |
| // BugzillaRepositoryQuery query = new BugzillaRepositoryQuery(repository.getRepositoryUrl(), urlString, |
| // "summary"); |
| // |
| // BugzillaRepositoryConnector bugzillaConnector = (BugzillaRepositoryConnector) TasksUi.getRepositoryManager() |
| // .getRepositoryConnector(BugzillaCorePlugin.CONNECTOR_KIND); |
| // |
| // BugzillaClient client = bugzillaConnector.getClientManager().getClient(repository, |
| // new NullProgressMonitor()); |
| // client.getSearchHits(query, collector, bugzillaConnector.getTaskDataHandler() |
| // .getAttributeMapper(repository), new NullProgressMonitor()); |
| } catch (CoreException e) { |
| status = new MultiStatus(BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, |
| "Core Exception occurred while querying Bugzilla Server " + repository.getRepositoryUrl() + ".\n" |
| + "\nClick Details for more information.", e); |
| ((MultiStatus) status).add(e.getStatus()); |
| |
| // write error to log |
| BugzillaCorePlugin.log(status); |
| } catch (OperationCanceledException e) { |
| status = new Status(IStatus.CANCEL, BugzillaUiPlugin.ID_PLUGIN, IStatus.CANCEL, "", null); |
| // } catch (final UnrecognizedReponseException e) { |
| // |
| // PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { |
| // public void run() { |
| // WebBrowserDialog.openAcceptAgreement(null, "Report Download Failed", |
| // "Unrecognized response from server", e.getMessage()); |
| // } |
| // }); |
| // status = new MultiStatus(BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, |
| // "Unrecognized response from Bugzilla server " + repository.getRepositoryUrl(), e); |
| // |
| // IStatus s = new Status(IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, e.getClass().toString() |
| // + ": ", e); |
| // ((MultiStatus) status).add(s); |
| // s = new Status(IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, IStatus.OK, "search failed", e); |
| // ((MultiStatus) status).add(s); |
| |
| } catch (Exception e) { |
| status = new MultiStatus(BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, |
| "An error occurred while querying Bugzilla Server " + repository.getRepositoryUrl() + ".\n" |
| + "\nCheck network connection and repository configuration in " |
| + TasksUiPlugin.LABEL_VIEW_REPOSITORIES + ".", e); |
| |
| IStatus s = new Status(IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, e.getClass().toString() |
| + ": ", e); |
| ((MultiStatus) status).add(s); |
| s = new Status(IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, IStatus.OK, "search failed", e); |
| ((MultiStatus) status).add(s); |
| } finally { |
| if (monitor != null) { |
| monitor.done(); |
| } |
| collector.done(); |
| try { |
| if (in != null) { |
| in.close(); |
| } |
| } catch (IOException e) { |
| BugzillaCorePlugin.log(new Status(IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, IStatus.ERROR, |
| "Problem closing the stream", e)); |
| } |
| } |
| |
| // if we haven't collected any serach results and we suspect a bad |
| // login, we assume it was a bad login |
| if (numCollected == 0 && possibleBadLogin) { |
| throw new LoginException(IBugzillaConstants.MESSAGE_LOGIN_FAILURE + " for repository: " |
| + repository.getRepositoryUrl() + " username: " + repository.getUserName()); |
| } |
| |
| if (status == null) { |
| return new Status(IStatus.OK, BugzillaUiPlugin.ID_PLUGIN, IStatus.OK, "", null); |
| } else { |
| return status; |
| } |
| } |
| |
| // /** Old code used by a unit test. */ |
| // public static BugzillaQueryHit createHit(Pattern regularExpression, IProgressMonitor monitor, BufferedReader in, |
| // String serverUrl, int id) throws IOException { |
| // String line; |
| // // String severity = null; |
| // String priority = null; |
| // // String platform = null; |
| // // String owner = null; |
| // String state = null; |
| // // String result = null; |
| // for (int i = 0; i < 6; i++) { |
| // Matcher matcher; |
| // do { |
| // matcher = null; |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // line = in.readLine(); |
| // if (line == null) |
| // break; |
| // line = line.trim(); |
| // matcher = regularExpression.matcher(line); |
| // } while (!matcher.find()); |
| // if (null != matcher) { |
| // switch (i) { |
| // // case 0: |
| // // severity = matcher.group(1); |
| // // break; |
| // case 1: |
| // priority = matcher.group(1); |
| // break; |
| // // case 2: |
| // // platform = matcher.group(1); |
| // // break; |
| // // case 3: |
| // // owner = matcher.group(1); |
| // // break; |
| // case 4: |
| // state = matcher.group(1); |
| // break; |
| // case 5: |
| // // result = matcher.group(1); |
| // // break; |
| // } |
| // } |
| // } |
| // |
| // // two more |
| // line = in.readLine(); |
| // line = in.readLine(); |
| // |
| // String description = "<activate to view summary>"; |
| // if (line != null) { |
| // description = line.substring(8); |
| // } |
| // if (description.startsWith(">")) { |
| // description = description.substring(1); |
| // } |
| // |
| // // String query = ""; |
| // // try { |
| // // String recentQuery = BugzillaUiPlugin.getMostRecentQuery(); |
| // // if (recentQuery != null) |
| // // query = recentQuery; |
| // // } catch (Exception e) { |
| // // // ignore, for testing |
| // // } |
| // |
| // BugzillaQueryHit hit = new BugzillaQueryHit(TasksUiPlugin.getTaskList(), description, |
| // priority, serverUrl, String.valueOf(id), null, state); |
| // |
| // return hit; |
| // } |
| |
| public boolean isMaxReached() { |
| return maxReached; |
| } |
| } |
| |
| // /** regular expression matching Bugzilla query results format used in |
| // Eclipse.org Bugzilla */ |
| // protected static final Pattern re = Pattern.compile("<a |
| // href=\"show_bug.cgi\\?taskId=(\\d+)\">", Pattern.CASE_INSENSITIVE); |
| // |
| // |
| // /** regular expression matching Bugzilla query results format used in |
| // v2.12 */ |
| // protected static final Pattern reOld = Pattern.compile("<a |
| // href=\"show_bug.cgi\\?taskId=(\\d+)\">\\d+</a>\\s*<td |
| // class=severity><nobr>([^>]+)</nobr><td |
| // class=priority><nobr>([^>]+)</nobr><td |
| // class=platform><nobr>([^>]*)</nobr><td |
| // class=owner><nobr>([^>]*)</nobr><td class=status><nobr>([^>]*)</nobr><td |
| // class=resolution><nobr>([^>]*)</nobr><td class=summary>(.*)$", |
| // Pattern.CASE_INSENSITIVE); |
| |
| // /** |
| // * Executes the query, parses the response, and adds hits to the search |
| // result collector. |
| // * |
| // * <p> |
| // * The output for a single match looks like this: |
| // * <pre> |
| // * <tr class="bz_enhancement bz_P5 "> |
| // * |
| // * <td> |
| // * <a href="show_bug.cgi?taskId=6747">6747</a> |
| // * </td> |
| // * |
| // * <td><nobr>enh</nobr> |
| // * </td> |
| // * <td><nobr>P5</nobr> |
| // * </td> |
| // * <td><nobr>All</nobr> |
| // * </td> |
| // * <td><nobr>Olivier_Thomann@oti.com</nobr> |
| // * </td> |
| // * <td><nobr>ASSI</nobr> |
| // * </td> |
| // * <td><nobr></nobr> |
| // * </td> |
| // * <td>Code Formatter exchange several blank lines w/ one |
| // * </td> |
| // * |
| // * </tr> |
| // * <pre> |
| // * |
| // * <p>Or in the older format: |
| // * <pre> |
| // * <A HREF="show_bug.cgi?taskId=8">8</A> <td |
| // class=severity><nobr>blo</nobr><td class=priority><nobr>P1</nobr><td |
| // class=platform><nobr>PC</nobr><td |
| // class=owner><nobr>cubranic@cs.ubc.ca</nobr><td |
| // class=status><nobr>CLOS</nobr><td class=resolution><nobr>DUPL</nobr><td |
| // class=summary>"Document root" missing when querying on files and |
| // revisions |
| // * </pre> |
| // * @param collector - The collector for the search results |
| // * @param startMatches - The number of matches to start with for the |
| // progress monitor |
| // * @param maxMatches - the maximum number of matches to return or -1 for |
| // unlimited |
| // */ |
| // public IStatus search(IBugzillaSearchResultCollector collector, int |
| // startMatches, int maxMatches) |
| // throws LoginException { |
| // IProgressMonitor monitor = collector.getProgressMonitor(); |
| // IStatus status = null; |
| // boolean possibleBadLogin = false; |
| // int numCollected = 0; |
| // BufferedReader in = null; |
| // |
| // try { |
| // monitor.beginTask(QUERYING_SERVER, IProgressMonitor.UNKNOWN); |
| // collector.aboutToStart(startMatches); |
| // |
| // URLConnection cntx = BugzillaPlugin.getDefault().getUrlConnection(new |
| // URL(urlString)); |
| // if (cntx == null || !(cntx instanceof HttpURLConnection)) { |
| // return null; |
| // } |
| // |
| // HttpURLConnection connect = (HttpURLConnection) cntx; |
| // connect.connect(); |
| // int responseCode = connect.getResponseCode(); |
| // if (responseCode != HttpURLConnection.HTTP_OK) { |
| // String msg; |
| // if (responseCode == -1 || responseCode == |
| // HttpURLConnection.HTTP_FORBIDDEN) |
| // msg = repository.getUrl() |
| // + " does not seem to be a valid Bugzilla server. Check Bugzilla |
| // preferences."; |
| // else |
| // msg = "HTTP Error " + responseCode + " (" + connect.getResponseMessage() |
| // + ") while querying Bugzilla Server. Check Bugzilla preferences."; |
| // |
| // throw new BugzillaException(msg); |
| // } |
| // |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // |
| // in = new BufferedReader(new InputStreamReader(connect.getInputStream())); |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // |
| // String line; |
| // while ((line = in.readLine()) != null) { |
| // if (maxMatches != -1 && numCollected >= maxMatches) { |
| // maxReached = true; |
| // break; |
| // } |
| // |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // |
| // // create regular expressions that can be mathced to check if we |
| // // have |
| // // bad login information |
| // Pattern loginRe = Pattern.compile("<title>.*login.*</title>.*"); |
| // Pattern invalidRe = |
| // Pattern.compile(".*<title>.*invalid.*password.*</title>.*"); |
| // Pattern passwordRe = |
| // Pattern.compile(".*<title>.*password.*invalid.*</title>.*"); |
| // Pattern emailRe = Pattern.compile(".*<title>.*check e-mail.*</title>.*"); |
| // Pattern errorRe = Pattern.compile(".*<title>.*error.*</title>.*"); |
| // |
| // String lowerLine = line.toLowerCase(Locale.ENGLISH); |
| // |
| // // check if we have anything that suggests bad login info |
| // if (loginRe.matcher(lowerLine).find() || |
| // invalidRe.matcher(lowerLine).find() || |
| // passwordRe.matcher(lowerLine).find() |
| // || emailRe.matcher(lowerLine).find() || |
| // errorRe.matcher(lowerLine).find()) |
| // possibleBadLogin = true; |
| // |
| // Matcher matcher = reOld.matcher(line); |
| // if (matcher.find()) { |
| // int taskId = Integer.parseInt(matcher.group(1)); |
| // String severity = matcher.group(2); |
| // String priority = matcher.group(3); |
| // String platform = matcher.group(4); |
| // String owner = matcher.group(5); |
| // String state = matcher.group(6); |
| // String result = matcher.group(7); |
| // String summary = matcher.group(8); |
| // String query = BugzillaPlugin.getMostRecentQuery(); |
| // if (query == null) |
| // query = ""; |
| // |
| // String server = repository.getUrl(); |
| // |
| // BugzillaSearchHit hit = new BugzillaSearchHit(server, taskId, summary, |
| // severity, priority, |
| // platform, state, result, owner, query); |
| // collector.accept(hit); |
| // numCollected++; |
| // |
| // } else { |
| // matcher = re.matcher(line); |
| // if (matcher.find()) { |
| // Pattern regularExpression; |
| // |
| // BugzillaServerVersion bugzillaServerVersion = |
| // IBugzillaConstants.BugzillaServerVersion.fromString(repository.getVersion()); |
| // if (bugzillaServerVersion != null && |
| // bugzillaServerVersion.compareTo(BugzillaServerVersion.SERVER_220) >= 0) { |
| // regularExpression = reValueBugzilla220; |
| // } else { |
| // regularExpression = reValue; |
| // } |
| // |
| // int taskId = Integer.parseInt(matcher.group(1)); |
| // BugzillaSearchHit hit = createHit(regularExpression, monitor, in, |
| // repository.getUrl(), taskId); |
| // collector.accept(hit); |
| // numCollected++; |
| // } |
| // } |
| // |
| // // } else if (re.matches(line, match)) { |
| // // RegularExpression regularExpression; |
| // // if |
| // (repository.getVersion().equals(BugzillaServerVersion.SERVER_220.toString())) |
| // { |
| // // regularExpression = reValueBugzilla220; |
| // // } else { |
| // // regularExpression = reValue; |
| // // } |
| // // |
| // // int taskId = Integer.parseInt(match.getCapturedText(1)); |
| // // BugzillaSearchHit hit = createHit(regularExpression, monitor, in, |
| // match, repository.getUrl() |
| // // .toExternalForm(), taskId); |
| // // collector.accept(hit); |
| // // numCollected++; |
| // // } |
| // if (monitor.isCanceled()) { |
| // throw new OperationCanceledException("Search cancelled"); |
| // } |
| // } |
| // } catch (CoreException e) { |
| // status = new MultiStatus(IBugzillaConstants.PLUGIN_ID, IStatus.ERROR, |
| // "Core Exception occurred while querying Bugzilla Server " + |
| // repository.getUrl() |
| // + ".\n" + "\nClick Details for more information.", e); |
| // ((MultiStatus) status).add(e.getStatus()); |
| // |
| // // write error to log |
| // BugzillaPlugin.log(status); |
| // } catch (OperationCanceledException e) { |
| // status = new Status(IStatus.CANCEL, IBugzillaConstants.PLUGIN_ID, |
| // IStatus.CANCEL, "", null); |
| // } catch (Exception e) { |
| // status = new MultiStatus(IBugzillaConstants.PLUGIN_ID, IStatus.ERROR, "An |
| // error occurred while querying Bugzilla Server " + repository.getUrl() + |
| // ".\n" |
| // + "\nCheck network connection repository configuration in Task |
| // Repositories view.", e); |
| // |
| // IStatus s = new Status(IStatus.ERROR, IBugzillaConstants.PLUGIN_ID, |
| // IStatus.ERROR, e.getClass().toString() |
| // + ": ", e); |
| // ((MultiStatus) status).add(s); |
| // s = new Status(IStatus.ERROR, IBugzillaConstants.PLUGIN_ID, IStatus.OK, |
| // "search failed", e); |
| // ((MultiStatus) status).add(s); |
| // |
| // // write error to log |
| // //BugzillaPlugin.log(status); |
| // |
| // |
| // } finally { |
| // monitor.done(); |
| // collector.done(); |
| // try { |
| // if (in != null) |
| // in.close(); |
| // } catch (IOException e) { |
| // BugzillaPlugin.log(new Status(IStatus.ERROR, |
| // IBugzillaConstants.PLUGIN_ID, IStatus.ERROR, |
| // "Problem closing the stream", e)); |
| // } |
| // } |
| // |
| // // if we haven't collected any serach results and we suspect a bad |
| // // login, we assume it was a bad login |
| // if (numCollected == 0 && possibleBadLogin) { |
| // throw new LoginException(IBugzillaConstants.MESSAGE_LOGIN_FAILURE + " for |
| // repository: " + repository.getUrl() + " username: " + |
| // repository.getUserName()); |
| // } |
| // |
| // if (status == null) |
| // return new Status(IStatus.OK, NewSearchUI.PLUGIN_ID, IStatus.OK, "", |
| // null); |
| // else |
| // return status; |
| // } |