From: <jbo...@li...> - 2006-02-16 14:13:24
|
Author: aron.gombas Date: 2006-02-16 09:13:07 -0500 (Thu, 16 Feb 2006) New Revision: 2488 Added: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebCrawlingServiceImpl.java Removed: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebScrapingServiceImpl.java Modified: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraSoapServiceImpl.java trunk/labs/kosmos/src/test/hu/midori/kosmos/server/jira/JiraServiceTest.java trunk/labs/kosmos/web-server/WEB-INF/kosmos-services-servlet.xml Log: JIRA crawling impl refactored to use abstract impl Modified: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraSoapServiceImpl.java =================================================================== --- trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraSoapServiceImpl.java 2006-02-16 14:00:51 UTC (rev 2487) +++ trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraSoapServiceImpl.java 2006-02-16 14:13:07 UTC (rev 2488) @@ -140,8 +140,7 @@ openIssues, codingInProgressIssues, reopenedIssues, resolvedIssues, closedIssues, blockerOpenIssues, criticalOpenIssues, majorOpenIssues, minorOpenIssues, trivialOpenIssues, optionalOpenIssues, (List<Map.Entry<String, Integer>>)trimList(openIssuesPerAssignee), - issuesPerStatusChartLocator, openIssuesPerPriorityChartLocator, openIssuesPerAssigneeChartLocator - ); + issuesPerStatusChartLocator, openIssuesPerPriorityChartLocator, openIssuesPerAssigneeChartLocator); log.debug(String.format("Adding %s...", project)); projects.add(project); } Added: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebCrawlingServiceImpl.java =================================================================== --- trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebCrawlingServiceImpl.java 2006-02-16 14:00:51 UTC (rev 2487) +++ trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebCrawlingServiceImpl.java 2006-02-16 14:13:07 UTC (rev 2488) @@ -0,0 +1,236 @@ +/* + * Kosmos. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package hu.midori.kosmos.server.jira; + +import hu.midori.kosmos.model.JiraProject; +import hu.midori.kosmos.model.ZoomableImageLocator; +import hu.midori.kosmos.protocol.JiraService; +import hu.midori.kosmos.server.util.ChartUtils; +import hu.midori.kosmos.server.util.ScrapingUtils; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import net.sf.saxon.om.NodeInfo; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; + +/** + * Implementation of the <i>JIRA</i> service. + * <p> + * Downloads JIRA webpages and analyze them using web-crawling techniques. + * Useful in environments where the JIRA remote API is not enabled. + * + * @author <a href="mailto:aro...@mi...">Aron Gombas</a> + * @version $Id$ + */ +public class JiraWebCrawlingServiceImpl extends AbstractJiraServiceImpl implements JiraService { + private final static Log log = LogFactory.getLog(JiraWebCrawlingServiceImpl.class); + + @SuppressWarnings("unchecked") + public List<JiraProject> getProjects(String url) { + log.debug("Returning projects..."); + + List<JiraProject> projects = new ArrayList<JiraProject>(); + updateTimestamp(); + + beginStoreSession(); + + try { + // download database info + connect(url); + + Document dom = ScrapingUtils.downloadHtmlDom(new URL(ScrapingUtils.removeUserInfoFromUrl(url))); + + disconnect(url); + + // run XQueries + String queryProject = + "for " + + "$d in //table " + + "where " + + "contains($d/child::tr/child::td/child::h3/child::a/@href, '/secure/BrowseProjects.jspa') " + + "return " + + "<dummy>" + + "{ data(fn:substring-after(fn:normalize-space($d/child::tr/child::td/child::h3/text()), ' ')) }|" + + "{ data(fn:substring-after(fn:substring-before($d/child::tr/child::td/child::h3/font/text(), ')'), ' ')) }|" + + "{ data($d/following-sibling::table/child::tr/child::td/child::p[1]/child::a[2]) }|" + + "{ data(fn:normalize-space(fn:string-join($d/following-sibling::table/child::tr/child::td/child::p[1]/text(), ''))) }|" + + "{ data($d/following-sibling::table/child::tr/child::td/child::p[1]/child::a[1]) }" + + "</dummy>"; + List resultProject = ScrapingUtils.runXQuery(dom, queryProject); + if(resultProject.size() < 1) + throw new IllegalStateException(String.format("Couldn't find JIRA project properties (%d) at \"%s\"", resultProject.size(), url)); + + String queryIssueStatus = + "for " + + "$d in //tr " + + "where " + + "count($d/child::td) = 4 and " + + "contains($d/child::td[2]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + + "contains($d/child::td[2]/child::a[1]/@href, 'status') " + // can be "status" or "statusIds" + "return " + + "<dummy>" + + "{ data(fn:substring-after(fn:substring-after($d/child::td[2]/child::a[1]/@href, 'status'), '=')) }|" +// TODO should grab the next number after "status" + "{ data(fn:normalize-space(fn:string-join($d/child::td[3]/text(), ''))) }" + + "</dummy>"; + List resultIssueStatus = ScrapingUtils.runXQuery(dom, queryIssueStatus); + + String queryIssuePriority = + "for " + + "$d in //tr " + + "where " + + "count($d/child::td) = 4 and " + + "contains($d/child::td[2]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + + "contains($d/child::td[2]/child::a[1]/@href, 'priority') " + + "return " + + "<dummy>" + + "{ data(fn:substring(fn:substring-after(fn:substring-after($d/child::td[2]/child::a[1]/@href, 'priority'), '='), 1, 1)) }|" +// TODO not appropriate, because priority is hardwired to a single character + "{ data(fn:normalize-space(fn:string-join($d/child::td[3]/text(), ''))) }" + + "</dummy>"; + List resultIssuePriority = ScrapingUtils.runXQuery(dom, queryIssuePriority); + + String queryIssueAssignee = + "for " + + "$d in //tr " + + "where " + + "count($d/child::td) = 3 and " + + "contains($d/child::td[1]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + + "contains($d/child::td[1]/child::a[1]/@href, 'assignee') " + + "return " + + "<dummy>" + + "{ data(fn:normalize-space($d/child::td[1]/child::a[1]/text())) }|" + + "{ data(fn:normalize-space(fn:string-join($d/child::td[2]/text(), ''))) }" + + "</dummy>"; + List resultIssueAssignee = ScrapingUtils.runXQuery(dom, queryIssueAssignee); + + // scrape + for(Iterator itProject = resultProject.iterator(); itProject.hasNext();) { + String valueProject = ScrapingUtils.eliminateEmptyValues(((NodeInfo)itProject.next()).getStringValue()); + log.debug(String.format("Scraped project: \"%s\"", valueProject)); + + StringTokenizer tokenizerProject = new StringTokenizer(valueProject, "|"); + String name = tokenizerProject.nextToken(); + String projectKey = tokenizerProject.nextToken(); + String projectUrl = tokenizerProject.nextToken(); + String description = tokenizerProject.nextToken(); + String lead = tokenizerProject.nextToken(); + + // scrape issue statuses + int openIssues = 0; + int codingInProgressIssues = 0; + int reopenedIssues = 0; + int resolvedIssues = 0; + int closedIssues = 0; + for(Iterator itIssueStatus = resultIssueStatus.iterator(); itIssueStatus.hasNext();) { + String valueIssueStatus = ((NodeInfo)itIssueStatus.next()).getStringValue(); + log.debug(String.format("Scraped issue status: \"%s\"", valueIssueStatus)); + + StringTokenizer tokenizerIssueStatus = new StringTokenizer(valueIssueStatus, "|"); + int status = Integer.parseInt(tokenizerIssueStatus.nextToken()); + int count = Integer.parseInt(tokenizerIssueStatus.nextToken()); + switch(status) { + case 1: openIssues = count; break; + // TODO what is 2? + case 3: codingInProgressIssues = count; break; + case 4: reopenedIssues = count; break; + case 5: resolvedIssues = count; break; + case 6: closedIssues = count; break; + default: throw new IllegalArgumentException(String.format("Unknown issue status: %d", status)); + } + } + + // scrape issue priorities + int blockerOpenIssues = 0; + int criticalOpenIssues = 0; + int majorOpenIssues = 0; + int minorOpenIssues = 0; + int trivialOpenIssues = 0; + int optionalOpenIssues = 0; + for(Iterator itIssuePriority = resultIssuePriority.iterator(); itIssuePriority.hasNext();) { + String valueIssuePriority = ((NodeInfo)itIssuePriority.next()).getStringValue(); + log.debug(String.format("Scraped issue priority: \"%s\"", valueIssuePriority)); + + StringTokenizer tokenizerIssuePriority = new StringTokenizer(valueIssuePriority, "|"); + int priority = Integer.parseInt(tokenizerIssuePriority.nextToken()); + int count = Integer.parseInt(tokenizerIssuePriority.nextToken()); + switch(priority) { + case 1: blockerOpenIssues = count; break; + case 2: criticalOpenIssues = count; break; + case 3: majorOpenIssues = count; break; + case 4: minorOpenIssues = count; break; + case 5: trivialOpenIssues = count; break; + // TODO what is 6? + case 7: optionalOpenIssues = count; break; + default: throw new IllegalArgumentException(String.format("Unknown issue priority: %d", priority)); + } + } + + // scrape issue assignees + Map<String, Integer> openIssuesPerAssigneeMap = new HashMap<String, Integer>(); + for(Iterator itIssueAssignee = resultIssueAssignee.iterator(); itIssueAssignee.hasNext();) { + String valueIssueAssignee = ((NodeInfo)itIssueAssignee.next()).getStringValue(); + log.debug(String.format("Scraped issue assignee: \"%s\"", valueIssueAssignee)); + + StringTokenizer tokenizerIssueAssignee = new StringTokenizer(valueIssueAssignee, "|"); + String assignee = tokenizerIssueAssignee.nextToken(); + int count = Integer.parseInt(tokenizerIssueAssignee.nextToken()); + openIssuesPerAssigneeMap.put(assignee, count); + } + + // generate charts + String prefix = ScrapingUtils.removeUserInfoFromUrl(url); + List<Map.Entry<String, Integer>> openIssuesPerAssignee = (List<Map.Entry<String, Integer>>)ChartUtils.countMapToSortedList(openIssuesPerAssigneeMap); + + ZoomableImageLocator openIssuesPerAssigneeChartLocator = generateOpenIssuesPerAssigneeChart(prefix, openIssuesPerAssignee); + ZoomableImageLocator issuesPerStatusChartLocator = generateIssuePerStatusChart(prefix, openIssues, codingInProgressIssues, reopenedIssues, resolvedIssues, closedIssues); + ZoomableImageLocator openIssuesPerPriorityChartLocator = generateIssuePerPriorityChart(prefix, blockerOpenIssues, criticalOpenIssues, majorOpenIssues, minorOpenIssues, trivialOpenIssues, optionalOpenIssues); + + // save + JiraProject project = new JiraProject(name, prefix, projectKey, projectUrl, description, lead, + openIssues, codingInProgressIssues, reopenedIssues, resolvedIssues, closedIssues, + blockerOpenIssues, criticalOpenIssues, majorOpenIssues, minorOpenIssues, trivialOpenIssues, optionalOpenIssues, + (List<Map.Entry<String, Integer>>)trimList(openIssuesPerAssignee), + issuesPerStatusChartLocator, openIssuesPerPriorityChartLocator, openIssuesPerAssigneeChartLocator); + log.debug(String.format("Adding %s...", project)); + projects.add(project); + } + } catch(Exception ex) { + log.error("Unable to scrape", ex); + } + + endStoreSession(); + + return projects; + } + + /** Connects to the given public or secure JIRA URL. */ + protected void connect(String url) throws MalformedURLException { + // authenticate if project is secured + String userInfo[] = ScrapingUtils.parseUserInfoFromUrl(url); + if(userInfo != null) { + String userName = userInfo[0]; + String password = userInfo[1]; + + log.debug(String.format("Signing in as \"%s\" \"%s\"...", userName, password)); + // do nothing + } + } + + /** Disconnects from the given URL. */ + protected void disconnect(String url) { + // do nothing + } +} Deleted: trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebScrapingServiceImpl.java =================================================================== --- trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebScrapingServiceImpl.java 2006-02-16 14:00:51 UTC (rev 2487) +++ trunk/labs/kosmos/src/java/hu/midori/kosmos/server/jira/JiraWebScrapingServiceImpl.java 2006-02-16 14:13:07 UTC (rev 2488) @@ -1,268 +0,0 @@ -/* - * Kosmos. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ -package hu.midori.kosmos.server.jira; - -import hu.midori.kosmos.model.JiraProject; -import hu.midori.kosmos.model.ZoomableImageLocator; -import hu.midori.kosmos.protocol.JiraService; -import hu.midori.kosmos.server.AbstractKosmosService; -import hu.midori.kosmos.server.util.ChartUtils; -import hu.midori.kosmos.server.util.ColorCodedKey; -import hu.midori.kosmos.server.util.ScrapingUtils; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -import net.sf.saxon.om.NodeInfo; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; - -/** - * Implementation of the <i>JIRA</i> service. - * <p> - * Downloads JIRA webpages and analyze them using web-scraping techniques. - * Useful in environments where the JIRA remote API is not enabled. - * - * @author <a href="mailto:aro...@mi...">Aron Gombas</a> - * @version $Id$ - */ -public class JiraWebScrapingServiceImpl extends AbstractKosmosService implements JiraService { - private final static Log log = LogFactory.getLog(JiraWebScrapingServiceImpl.class); - - @SuppressWarnings("unchecked") - public List<JiraProject> getProjects(String url) { - log.debug("Returning projects..."); - - List<JiraProject> projects = new ArrayList<JiraProject>(); - updateTimestamp(); - - beginStoreSession(); - - try { - // download database info - connect(url); - - Document dom = ScrapingUtils.downloadHtmlDom(new URL(ScrapingUtils.removeUserInfoFromUrl(url))); - - disconnect(url); - - // run XQueries - String queryProject = - "for " + - "$d in //table " + - "where " + - "contains($d/child::tr/child::td/child::h3/child::a/@href, '/secure/BrowseProjects.jspa') " + - "return " + - "<dummy>" + - "{ data(fn:substring-after(fn:normalize-space($d/child::tr/child::td/child::h3/text()), ' ')) }|" + - "{ data(fn:substring-after(fn:substring-before($d/child::tr/child::td/child::h3/font/text(), ')'), ' ')) }|" + - "{ data($d/following-sibling::table/child::tr/child::td/child::p[1]/child::a[2]) }|" + - "{ data(fn:normalize-space(fn:string-join($d/following-sibling::table/child::tr/child::td/child::p[1]/text(), ''))) }|" + - "{ data($d/following-sibling::table/child::tr/child::td/child::p[1]/child::a[1]) }" + - "</dummy>"; - List resultProject = ScrapingUtils.runXQuery(dom, queryProject); - if(resultProject.size() < 1) - throw new IllegalStateException(String.format("Couldn't find JIRA project properties (%d) at \"%s\"", resultProject.size(), url)); - - String queryIssueStatus = - "for " + - "$d in //tr " + - "where " + - "count($d/child::td) = 4 and " + - "contains($d/child::td[2]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + - "contains($d/child::td[2]/child::a[1]/@href, 'status') " + // can be "status" or "statusIds" - "return " + - "<dummy>" + - "{ data(fn:substring-after(fn:substring-after($d/child::td[2]/child::a[1]/@href, 'status'), '=')) }|" +// TODO should grab the next number after "status" - "{ data(fn:normalize-space(fn:string-join($d/child::td[3]/text(), ''))) }" + - "</dummy>"; - List resultIssueStatus = ScrapingUtils.runXQuery(dom, queryIssueStatus); - - String queryIssuePriority = - "for " + - "$d in //tr " + - "where " + - "count($d/child::td) = 4 and " + - "contains($d/child::td[2]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + - "contains($d/child::td[2]/child::a[1]/@href, 'priority') " + - "return " + - "<dummy>" + - "{ data(fn:substring(fn:substring-after(fn:substring-after($d/child::td[2]/child::a[1]/@href, 'priority'), '='), 1, 1)) }|" +// TODO not appropriate, because priority is hardwired to a single character - "{ data(fn:normalize-space(fn:string-join($d/child::td[3]/text(), ''))) }" + - "</dummy>"; - List resultIssuePriority = ScrapingUtils.runXQuery(dom, queryIssuePriority); - - String queryIssueAssignee = - "for " + - "$d in //tr " + - "where " + - "count($d/child::td) = 3 and " + - "contains($d/child::td[1]/child::a[1]/@href, '/secure/IssueNavigator.jspa') and " + - "contains($d/child::td[1]/child::a[1]/@href, 'assignee') " + - "return " + - "<dummy>" + - "{ data(fn:normalize-space($d/child::td[1]/child::a[1]/text())) }|" + - "{ data(fn:normalize-space(fn:string-join($d/child::td[2]/text(), ''))) }" + - "</dummy>"; - List resultIssueAssignee = ScrapingUtils.runXQuery(dom, queryIssueAssignee); - - // scrape - for(Iterator itProject = resultProject.iterator(); itProject.hasNext();) { - String valueProject = ScrapingUtils.eliminateEmptyValues(((NodeInfo)itProject.next()).getStringValue()); - log.debug(String.format("Scraped project: \"%s\"", valueProject)); - - StringTokenizer tokenizerProject = new StringTokenizer(valueProject, "|"); - String name = tokenizerProject.nextToken(); - String projectKey = tokenizerProject.nextToken(); - String projectUrl = tokenizerProject.nextToken(); - String description = tokenizerProject.nextToken(); - String lead = tokenizerProject.nextToken(); - - // scrape issue statuses - int openIssues = 0; - int codingInProgressIssues = 0; - int reopenedIssues = 0; - int resolvedIssues = 0; - int closedIssues = 0; - for(Iterator itIssueStatus = resultIssueStatus.iterator(); itIssueStatus.hasNext();) { - String valueIssueStatus = ((NodeInfo)itIssueStatus.next()).getStringValue(); - log.debug(String.format("Scraped issue status: \"%s\"", valueIssueStatus)); - - StringTokenizer tokenizerIssueStatus = new StringTokenizer(valueIssueStatus, "|"); - int status = Integer.parseInt(tokenizerIssueStatus.nextToken()); - int count = Integer.parseInt(tokenizerIssueStatus.nextToken()); - switch(status) { - case 1: openIssues = count; break; - // TODO what is 2? - case 3: codingInProgressIssues = count; break; - case 4: reopenedIssues = count; break; - case 5: resolvedIssues = count; break; - case 6: closedIssues = count; break; - default: throw new IllegalArgumentException(String.format("Unknown issue status: %d", status)); - } - } - - // scrape issue priorities - int blockerOpenIssues = 0; - int criticalOpenIssues = 0; - int majorOpenIssues = 0; - int minorOpenIssues = 0; - int trivialOpenIssues = 0; - int optionalOpenIssues = 0; - for(Iterator itIssuePriority = resultIssuePriority.iterator(); itIssuePriority.hasNext();) { - String valueIssuePriority = ((NodeInfo)itIssuePriority.next()).getStringValue(); - log.debug(String.format("Scraped issue priority: \"%s\"", valueIssuePriority)); - - StringTokenizer tokenizerIssuePriority = new StringTokenizer(valueIssuePriority, "|"); - int priority = Integer.parseInt(tokenizerIssuePriority.nextToken()); - int count = Integer.parseInt(tokenizerIssuePriority.nextToken()); - switch(priority) { - case 1: blockerOpenIssues = count; break; - case 2: criticalOpenIssues = count; break; - case 3: majorOpenIssues = count; break; - case 4: minorOpenIssues = count; break; - case 5: trivialOpenIssues = count; break; - // TODO what is 6? - case 7: optionalOpenIssues = count; break; - default: throw new IllegalArgumentException(String.format("Unknown issue priority: %d", priority)); - } - } - - // scrape issue assignees - String prefix = ScrapingUtils.removeUserInfoFromUrl(url); - - Map<String, Integer> openIssuesPerAssigneeMap = new HashMap<String, Integer>(); - for(Iterator itIssueAssignee = resultIssueAssignee.iterator(); itIssueAssignee.hasNext();) { - String valueIssueAssignee = ((NodeInfo)itIssueAssignee.next()).getStringValue(); - log.debug(String.format("Scraped issue assignee: \"%s\"", valueIssueAssignee)); - - StringTokenizer tokenizerIssueAssignee = new StringTokenizer(valueIssueAssignee, "|"); - String assignee = tokenizerIssueAssignee.nextToken(); - int count = Integer.parseInt(tokenizerIssueAssignee.nextToken()); - openIssuesPerAssigneeMap.put(assignee, count); - } - List<Map.Entry<String, Integer>> openIssuesPerAssignee = (List<Map.Entry<String, Integer>>)ChartUtils.countMapToSortedList(openIssuesPerAssigneeMap); - - ZoomableImageLocator openIssuesPerAssigneeChartLocator = storeChart(prefix + "_open_issues_per_assignee", ChartUtils.generatePieChart(ChartUtils.collectionToPieDataset(openIssuesPerAssignee, ChartUtils.MAX_ITEMS))); - - // generate issues-per-status chart - List<Map.Entry<ColorCodedKey, Integer>> issuesPerStatusMap = new ArrayList<Map.Entry<ColorCodedKey, Integer>>(); - if(openIssues > 0) - issuesPerStatusMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.openIssues"), JiraConstants.OPEN_COLOR), openIssues).entrySet()); - if(codingInProgressIssues > 0) - issuesPerStatusMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.codingInProgressIssues"), JiraConstants.CODING_IN_PROGRESS_COLOR), codingInProgressIssues).entrySet()); - if(reopenedIssues > 0) - issuesPerStatusMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.reopenedIssues"), JiraConstants.REOPENED_COLOR), reopenedIssues).entrySet()); - if(resolvedIssues > 0) - issuesPerStatusMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.resolvedIssues"), JiraConstants.RESOLVED_COLOR), resolvedIssues).entrySet()); - if(closedIssues > 0) - issuesPerStatusMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.closedIssues"), JiraConstants.CLOSED_COLOR), closedIssues).entrySet()); - - ZoomableImageLocator issuesPerStatusChartLocator = storeChart(prefix + "_issues_per_status", ChartUtils.generateColorCodedPieChart(ChartUtils.collectionToPieDataset(issuesPerStatusMap))); - - // generate issues-per-priority chart - List<Map.Entry<ColorCodedKey, Integer>> openIssuesPerPriorityMap = new ArrayList<Map.Entry<ColorCodedKey, Integer>>(); - if(blockerOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.blockerOpenIssues"), JiraConstants.BLOCKER_COLOR), blockerOpenIssues).entrySet()); - if(criticalOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.criticalOpenIssues"), JiraConstants.CRITICAL_COLOR), criticalOpenIssues).entrySet()); - if(majorOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.majorOpenIssues"), JiraConstants.MAJOR_COLOR), majorOpenIssues).entrySet()); - if(minorOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.minorOpenIssues"), JiraConstants.MINOR_COLOR), minorOpenIssues).entrySet()); - if(trivialOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.trivialOpenIssues"), JiraConstants.TRIVIAL_COLOR), trivialOpenIssues).entrySet()); - if(optionalOpenIssues > 0) - openIssuesPerPriorityMap.addAll(Collections.singletonMap(new ColorCodedKey(getResourceString("hu.midori.kosmos.server.jira.jira_monitoring", "jiraproject.optionalOpenIssues"), JiraConstants.OPTIONAL_COLOR), optionalOpenIssues).entrySet()); - - ZoomableImageLocator openIssuesPerPriorityChartLocator = storeChart(prefix + "_open_issues_per_priority", ChartUtils.generateColorCodedPieChart(ChartUtils.collectionToPieDataset(openIssuesPerPriorityMap))); - - // save - JiraProject project = new JiraProject(name, prefix, projectKey, projectUrl, description, lead, - openIssues, codingInProgressIssues, reopenedIssues, resolvedIssues, closedIssues, - blockerOpenIssues, criticalOpenIssues, majorOpenIssues, minorOpenIssues, trivialOpenIssues, optionalOpenIssues, - (List<Map.Entry<String, Integer>>)trimList(openIssuesPerAssignee), - issuesPerStatusChartLocator, openIssuesPerPriorityChartLocator, openIssuesPerAssigneeChartLocator); - log.debug(String.format("Adding %s...", project)); - projects.add(project); - } - } catch(Exception ex) { - log.error("Unable to scrape", ex); - } - - endStoreSession(); - - return projects; - } - - /** Connects to the given public or secure JIRA URL. */ - protected void connect(String url) throws MalformedURLException { - // authenticate if project is secured - String userInfo[] = ScrapingUtils.parseUserInfoFromUrl(url); - if(userInfo != null) { - String userName = userInfo[0]; - String password = userInfo[1]; - - log.debug(String.format("Signing in as \"%s\" \"%s\"...", userName, password)); - // do nothing - } - } - - /** Disconnects from the given URL. */ - protected void disconnect(String url) { - // do nothing - } -} Modified: trunk/labs/kosmos/src/test/hu/midori/kosmos/server/jira/JiraServiceTest.java =================================================================== --- trunk/labs/kosmos/src/test/hu/midori/kosmos/server/jira/JiraServiceTest.java 2006-02-16 14:00:51 UTC (rev 2487) +++ trunk/labs/kosmos/src/test/hu/midori/kosmos/server/jira/JiraServiceTest.java 2006-02-16 14:13:07 UTC (rev 2488) @@ -22,7 +22,7 @@ * @version $Id$ */ public class JiraServiceTest extends AbstractKosmosServiceTest { - private JiraService service = new JiraWebScrapingServiceImpl(); + private JiraService service = new JiraWebCrawlingServiceImpl(); /** Tests with invalid URL. */ public void testInvalidUrl() { Modified: trunk/labs/kosmos/web-server/WEB-INF/kosmos-services-servlet.xml =================================================================== --- trunk/labs/kosmos/web-server/WEB-INF/kosmos-services-servlet.xml 2006-02-16 14:00:51 UTC (rev 2487) +++ trunk/labs/kosmos/web-server/WEB-INF/kosmos-services-servlet.xml 2006-02-16 14:13:07 UTC (rev 2488) @@ -22,7 +22,7 @@ </bean> <!-- JIRA service --> - <bean id="jiraService" class="hu.midori.kosmos.server.jira.JiraWebScrapingServiceImpl"> + <bean id="jiraService" class="hu.midori.kosmos.server.jira.JiraWebCrawlingServiceImpl"> <property name="store" ref="webdavStaticContentStore"/> </bean> |