Inital commit
This commit is contained in:
@@ -0,0 +1,575 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.projecthosting;
|
||||
|
||||
import com.google.gdata.client.projecthosting.IssuesQuery;
|
||||
import com.google.gdata.client.projecthosting.ProjectHostingService;
|
||||
import com.google.gdata.data.HtmlTextConstruct;
|
||||
import com.google.gdata.data.Person;
|
||||
import com.google.gdata.data.TextContent;
|
||||
import com.google.gdata.data.projecthosting.BlockedOn;
|
||||
import com.google.gdata.data.projecthosting.BlockedOnUpdate;
|
||||
import com.google.gdata.data.projecthosting.Blocking;
|
||||
import com.google.gdata.data.projecthosting.Cc;
|
||||
import com.google.gdata.data.projecthosting.CcUpdate;
|
||||
import com.google.gdata.data.projecthosting.IssueCommentsEntry;
|
||||
import com.google.gdata.data.projecthosting.IssueCommentsFeed;
|
||||
import com.google.gdata.data.projecthosting.IssuesEntry;
|
||||
import com.google.gdata.data.projecthosting.IssuesFeed;
|
||||
import com.google.gdata.data.projecthosting.Label;
|
||||
import com.google.gdata.data.projecthosting.Owner;
|
||||
import com.google.gdata.data.projecthosting.Updates;
|
||||
import com.google.gdata.util.AuthenticationException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This is a simple client that provides high-level operations on the Google
|
||||
* Code Project Hosting Issue Tracker Data API. It can also be used as a
|
||||
* command-line application to test out some of the features of the API.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ProjectHostingClient {
|
||||
|
||||
private ProjectHostingService service;
|
||||
|
||||
private static final String FEED_URI_BASE =
|
||||
"https://code.google.com/feeds/issues";
|
||||
|
||||
private static final String PROJECTION = "/full";
|
||||
|
||||
// User-provided input
|
||||
private String project;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
/** Issues API base URL constructed from the given project name. */
|
||||
private String issuesBaseUri;
|
||||
|
||||
/** Default issues feed URL constructed from the given project name. */
|
||||
private URL issuesFeedUrl;
|
||||
|
||||
/** Group 1 of the regex will match the ID of the issue. */
|
||||
private Pattern issueIdPattern;
|
||||
|
||||
/** Group 1 of the regex will match the ID of the comment. */
|
||||
private Pattern commentIdPattern;
|
||||
|
||||
private static final String DIVIDER =
|
||||
"-----------------------------------------------------------------------";
|
||||
|
||||
/**
|
||||
* Constructs a new client.
|
||||
*
|
||||
* @throws AuthenticationException if authentication fails
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
public ProjectHostingClient(
|
||||
ProjectHostingService service, String project, String username,
|
||||
String password) throws AuthenticationException, MalformedURLException {
|
||||
this.service = service;
|
||||
this.project = project;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
|
||||
// Login via ClientLogin
|
||||
if ((username != null) && (password != null)) {
|
||||
service.setUserCredentials(username, password);
|
||||
}
|
||||
|
||||
issuesBaseUri = FEED_URI_BASE + "/p/" + project + "/issues";
|
||||
issuesFeedUrl = makeIssuesFeedUrl(project);
|
||||
String issuesBaseUriHttp = issuesBaseUri.replaceFirst("https", "http");
|
||||
issueIdPattern = Pattern.compile(
|
||||
issuesBaseUriHttp + PROJECTION + "/(\\d+)$");
|
||||
commentIdPattern = Pattern.compile(
|
||||
issuesBaseUriHttp + "/\\d+/comments" + PROJECTION + "/(\\d+)$");
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for {@code issuesFeedUrl}.
|
||||
*/
|
||||
protected URL getIssuesFeedUrl() {
|
||||
return issuesFeedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method for {@code issuesFeedUrl}.
|
||||
*/
|
||||
protected void setIssuesFeedUrl(URL url) {
|
||||
issuesFeedUrl = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs issues feed URL.
|
||||
*
|
||||
* @param proj name of the project for the issues feed
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
protected URL makeIssuesFeedUrl(String proj)
|
||||
throws MalformedURLException {
|
||||
return new URL(FEED_URI_BASE + "/p/" + proj + "/issues" + PROJECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs issue entry URL.
|
||||
*
|
||||
* @param issueId ID number of an issue to construct the issue entry URL
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
protected URL makeIssueEntryUrl(String issueId)
|
||||
throws MalformedURLException {
|
||||
return new URL(issuesBaseUri + PROJECTION + "/" + issueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs comments feed URL.
|
||||
*
|
||||
* @param issueId ID number of an issue to construct the comments URL
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
protected URL makeCommentsFeedUrl(String issueId)
|
||||
throws MalformedURLException {
|
||||
return new URL(issuesBaseUri + "/" + issueId + "/comments" + PROJECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs comment entry URL.
|
||||
*
|
||||
* @param issueId ID number of an issue the comment belongs to
|
||||
* @param commentId ID number of the comment
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
protected URL makeCommentEntryUrl(String issueId, String commentId)
|
||||
throws MalformedURLException {
|
||||
return new URL(issuesBaseUri + "/" + issueId + "/comments" + PROJECTION
|
||||
+ "/" + commentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves issues feed.
|
||||
*
|
||||
* @param feedUrl feed URL of issues to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssuesFeed getIssuesFeed(URL feedUrl)
|
||||
throws IOException, ServiceException {
|
||||
return service.getFeed(feedUrl, IssuesFeed.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a particular issue entry.
|
||||
*
|
||||
* @param issueId ID number of an issue to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssuesEntry getIssueEntry(String issueId)
|
||||
throws IOException, ServiceException {
|
||||
return getIssueEntry(makeIssueEntryUrl(issueId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a particular issue entry.
|
||||
*
|
||||
* @param entryUrl URL of an issue entry to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssuesEntry getIssueEntry(URL entryUrl)
|
||||
throws IOException, ServiceException {
|
||||
return service.getEntry(entryUrl, IssuesEntry.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves comments feed.
|
||||
*
|
||||
* @param issueId ID number of an issue to retrieve comments from
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsFeed getCommentsFeed(String issueId)
|
||||
throws IOException, ServiceException {
|
||||
return getCommentsFeed(makeCommentsFeedUrl(issueId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves comments feed.
|
||||
*
|
||||
* @param feedUrl comments feed URL to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsFeed getCommentsFeed(URL feedUrl)
|
||||
throws IOException, ServiceException {
|
||||
return service.getFeed(feedUrl, IssueCommentsFeed.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a particular comment entry.
|
||||
*
|
||||
* @param issueId ID number of an issue the comment belongs to
|
||||
* @param commentId ID number of a comment to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsEntry getCommentEntry(
|
||||
String issueId, String commentId)
|
||||
throws IOException, ServiceException {
|
||||
return getCommentEntry(makeCommentEntryUrl(issueId, commentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a particular comment entry.
|
||||
*
|
||||
* @param entryUrl comment entry URL to retrieve
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsEntry getCommentEntry(URL entryUrl)
|
||||
throws IOException, ServiceException {
|
||||
return service.getEntry(entryUrl, IssueCommentsEntry.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an issue entry to the issues feed.
|
||||
*
|
||||
* @param entry issue entry to insert
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssuesEntry insertIssue(IssuesEntry entry)
|
||||
throws IOException, ServiceException {
|
||||
return service.insert(issuesFeedUrl, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a comment entry to the comments feed.
|
||||
*
|
||||
* @param issueId ID number of an issue to insert the comment entry to
|
||||
* @param entry comment entry to insert
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsEntry insertComment(
|
||||
String issueId, IssueCommentsEntry entry)
|
||||
throws IOException, ServiceException {
|
||||
return insertComment(makeCommentsFeedUrl(issueId), entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a comment entry to the comments feed.
|
||||
*
|
||||
* @param commentsFeedUrl comments feed URL to insert the comment entry to
|
||||
* @param entry comment entry to insert
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssueCommentsEntry insertComment(
|
||||
URL commentsFeedUrl, IssueCommentsEntry entry)
|
||||
throws IOException, ServiceException {
|
||||
return service.insert(commentsFeedUrl, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries issues using the given query parameters.
|
||||
*
|
||||
* @param query issues query object with query parameters set
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected IssuesFeed queryIssues(IssuesQuery query)
|
||||
throws IOException, ServiceException {
|
||||
return service.query(query, IssuesFeed.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the numeric issue ID from the given {@code issueUrl}.
|
||||
*
|
||||
* @param issueUrl URI to find the issue ID from
|
||||
*/
|
||||
protected String getIssueId(String issueUrl) {
|
||||
Matcher matcher = issueIdPattern.matcher(issueUrl);
|
||||
return matcher.matches() ? matcher.group(1) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the numeric commentId from the given {@code commentUrl}.
|
||||
*
|
||||
* @param commentUrl URI to find the comment ID from
|
||||
*/
|
||||
protected String getCommentId(String commentUrl) {
|
||||
Matcher matcher = commentIdPattern.matcher(commentUrl);
|
||||
return matcher.matches() ? matcher.group(1) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints issues in the given issues feed.
|
||||
*
|
||||
* @param issuesFeed issues feed to print
|
||||
*/
|
||||
protected void printIssues(IssuesFeed issuesFeed) {
|
||||
for (IssuesEntry issueEntry : issuesFeed.getEntries()) {
|
||||
printIssue(issueEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an issue entry in human-readable format.
|
||||
*
|
||||
* @param entry issue entry to print
|
||||
*/
|
||||
protected void printIssue(IssuesEntry entry) {
|
||||
System.out.println(DIVIDER);
|
||||
if (entry.getId() != null) {
|
||||
String issueId = getIssueId(entry.getId());
|
||||
System.out.printf("Issue #%s:\t%s\n", issueId, entry.getId());
|
||||
} else {
|
||||
System.out.println("Issue");
|
||||
}
|
||||
|
||||
if (entry.getTitle() != null) {
|
||||
System.out.println("\tSummary\n\t\t" + entry.getTitle().getPlainText());
|
||||
}
|
||||
|
||||
Person author = entry.getAuthors().get(0);
|
||||
printPerson("Reporter", author.getName(), author.getUri());
|
||||
|
||||
TextContent textContent = (TextContent) entry.getContent();
|
||||
if ((textContent != null) && (textContent.getContent() != null)) {
|
||||
HtmlTextConstruct textConstruct =
|
||||
(HtmlTextConstruct) textContent.getContent();
|
||||
System.out.println("\tDescription\n\t\t" + textConstruct.getHtml());
|
||||
}
|
||||
|
||||
if (entry.hasStatus()) {
|
||||
System.out.println("\tStatus\n\t\t" + entry.getStatus().getValue());
|
||||
}
|
||||
|
||||
if (entry.hasOwner()) {
|
||||
Owner owner = entry.getOwner();
|
||||
printPerson(
|
||||
"Owner", owner.getUsername().getValue(),
|
||||
(owner.getUri() == null) ? null : owner.getUri().getValue());
|
||||
}
|
||||
|
||||
if (entry.getLabels().size() > 0) {
|
||||
System.out.println("\tLabel");
|
||||
for (Label label : entry.getLabels()) {
|
||||
System.out.println("\t\t" + label.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getCcs().size() > 0) {
|
||||
System.out.println("\tCC");
|
||||
for (Cc cc : entry.getCcs()) {
|
||||
printPerson(
|
||||
null, cc.getUsername().getValue(),
|
||||
(cc.getUri() == null) ? null : cc.getUri().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getBlockedOns().size() > 0) {
|
||||
System.out.println("\tBlockedOn");
|
||||
for (BlockedOn blockedOn : entry.getBlockedOns()) {
|
||||
System.out.print("\t\t");
|
||||
if (blockedOn.hasProject()) {
|
||||
System.out.print(blockedOn.getProject().getValue() + ":");
|
||||
}
|
||||
System.out.println(blockedOn.getId().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getBlockings().size() > 0) {
|
||||
System.out.println("\tBlocking");
|
||||
for (Blocking blocking : entry.getBlockings()) {
|
||||
System.out.print("\t\t");
|
||||
if (blocking.hasProject()) {
|
||||
System.out.print(blocking.getProject().getValue() + ":");
|
||||
}
|
||||
System.out.println(blocking.getId().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.hasMergedInto()) {
|
||||
System.out.print("\tMergedInto\n\t\t");
|
||||
if (entry.getMergedInto().hasProject()) {
|
||||
System.out.print(entry.getMergedInto().getProject().getValue() + ":");
|
||||
}
|
||||
System.out.println(entry.getMergedInto().getId().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints Username and URI associated with the labeled person.
|
||||
*
|
||||
* @param label label to print
|
||||
* @param name username of the person to print
|
||||
* @param uri uri of the person to print, usually the profile url
|
||||
*/
|
||||
protected void printPerson(String label, String name, String uri) {
|
||||
if (label != null) {
|
||||
System.out.printf("\t%s\n", label);
|
||||
}
|
||||
System.out.print("\t\t" + name);
|
||||
if (uri != null) {
|
||||
System.out.println("\t" + uri);
|
||||
} else {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints issues and their comments.
|
||||
*
|
||||
* @param issuesFeed issues feed to print
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected void printIssuesAndComments(IssuesFeed issuesFeed)
|
||||
throws IOException, ServiceException {
|
||||
for (IssuesEntry issueEntry : issuesFeed.getEntries()) {
|
||||
printIssueAndComments(issueEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an issue and its comments.
|
||||
*
|
||||
* @param issueId ID number of an issue to print
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected void printIssueAndComments(String issueId)
|
||||
throws IOException, ServiceException {
|
||||
printIssueAndComments(getIssueEntry(issueId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an issue and its comments.
|
||||
*
|
||||
* @param issueUrl URL of an issue to print
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected void printIssueAndComments(URL issueUrl)
|
||||
throws IOException, ServiceException {
|
||||
printIssueAndComments(getIssueEntry(issueUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an issue and its comments.
|
||||
*
|
||||
* @param issue issue entry to print
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
protected void printIssueAndComments(IssuesEntry entry)
|
||||
throws IOException, ServiceException {
|
||||
printIssue(entry);
|
||||
String issueId = getIssueId(entry.getId());
|
||||
IssueCommentsFeed commentsFeed = getCommentsFeed(issueId);
|
||||
printComments(commentsFeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints comments in the given comments feed.
|
||||
*
|
||||
* @param commentsFeed comments feed to print
|
||||
*/
|
||||
protected void printComments(IssueCommentsFeed commentsFeed) {
|
||||
for (IssueCommentsEntry commentEntry : commentsFeed.getEntries()) {
|
||||
printComment(commentEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a comment entry in human-readable format.
|
||||
*
|
||||
* @param entry comment entry to print
|
||||
*/
|
||||
protected void printComment(IssueCommentsEntry entry) {
|
||||
System.out.println(DIVIDER);
|
||||
if (entry.getId() != null) {
|
||||
String commentId = getCommentId(entry.getId());
|
||||
System.out.printf("Comment #%s:\t%s\n", commentId, entry.getId());
|
||||
} else {
|
||||
System.out.println("Comment");
|
||||
}
|
||||
|
||||
Person author = entry.getAuthors().get(0);
|
||||
printPerson("Author", author.getName(), author.getUri());
|
||||
|
||||
TextContent textContent = (TextContent) entry.getContent();
|
||||
if ((textContent != null) && (textContent.getContent() != null)) {
|
||||
HtmlTextConstruct textConstruct =
|
||||
(HtmlTextConstruct) textContent.getContent();
|
||||
System.out.println("\tComment\n\t\t" + textConstruct.getHtml());
|
||||
}
|
||||
|
||||
if (entry.hasUpdates()) {
|
||||
Updates updates = entry.getUpdates();
|
||||
|
||||
if (updates.hasSummary()) {
|
||||
System.out.println("\tSummary\n\t\t" + updates.getSummary().getValue());
|
||||
}
|
||||
|
||||
if (updates.hasStatus()) {
|
||||
System.out.println("\tStatus\n\t\t" + updates.getStatus().getValue());
|
||||
}
|
||||
|
||||
if (updates.hasOwnerUpdate()) {
|
||||
System.out.println(
|
||||
"\tOwner\n\t\t" + updates.getOwnerUpdate().getValue());
|
||||
}
|
||||
|
||||
if (updates.getLabels().size() > 0) {
|
||||
System.out.println("\tLabel");
|
||||
for (Label label : updates.getLabels()) {
|
||||
System.out.println("\t\t" + label.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (updates.getCcUpdates().size() > 0) {
|
||||
System.out.println("\tCC");
|
||||
for (CcUpdate cc : updates.getCcUpdates()) {
|
||||
System.out.println("\t\t" + cc.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (updates.getBlockedOnUpdates().size() > 0) {
|
||||
System.out.println("\tBlockedOnUpdate");
|
||||
for (BlockedOnUpdate blockedOnUpdate : updates.getBlockedOnUpdates()) {
|
||||
System.out.println("\t\t" + blockedOnUpdate.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (updates.hasMergedIntoUpdate()) {
|
||||
System.out.println(
|
||||
"\tMergedIntoUpdate\n\t\t" +
|
||||
updates.getMergedIntoUpdate().getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.projecthosting;
|
||||
|
||||
import com.google.gdata.client.projecthosting.IssuesQuery;
|
||||
import com.google.gdata.client.projecthosting.ProjectHostingService;
|
||||
import sample.util.SimpleCommandLineParser;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.projecthosting.IssuesFeed;
|
||||
import com.google.gdata.util.AuthenticationException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* A Command-line application using the {@link ProjectHostingClient} to make
|
||||
* calls to the Google Code Issue Tracker Data API.
|
||||
* The following operations are handled:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Retrieving the list of issues in a project</li>
|
||||
* <li>Querying issues with query parameters</li>
|
||||
* <li>Retrieving the list of comments in a given issue</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ProjectHostingReadDemo {
|
||||
|
||||
/** Disable default public constructor */
|
||||
private ProjectHostingReadDemo() {
|
||||
}
|
||||
|
||||
/** Client that provides high level operations of the API */
|
||||
private ProjectHostingClient client;
|
||||
|
||||
private static final String DIVIDER =
|
||||
"=====================================================================\n";
|
||||
|
||||
/**
|
||||
* Constructs the command line application.
|
||||
*
|
||||
* @throws AuthenticationException if authentication fails
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
public ProjectHostingReadDemo(
|
||||
ProjectHostingService service, String project, String username,
|
||||
String password) throws AuthenticationException, MalformedURLException {
|
||||
client = new ProjectHostingClient(service, project, username, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point. Parses arguments and creates and invokes the demo.
|
||||
*/
|
||||
public static void main(String[] arg) throws Exception {
|
||||
SimpleCommandLineParser parser = new SimpleCommandLineParser(arg);
|
||||
|
||||
// Parse command-line flags
|
||||
String project = parser.getValue("project");
|
||||
String username = parser.getValue("username");
|
||||
String password = parser.getValue("password");
|
||||
|
||||
boolean help = parser.containsKey("help");
|
||||
if (help || (project == null)) {
|
||||
usage();
|
||||
System.exit(help ? 0 : 1);
|
||||
}
|
||||
|
||||
if (username == null) {
|
||||
System.out.println(
|
||||
"***WARNING*** Unauthenticated user. To see any restricted issues, "
|
||||
+ "you must authenticate yourself and have proper permission setting "
|
||||
+ "for the project " + project + ".\n"
|
||||
+ "You can authenticate yourself by specifying <username> and "
|
||||
+ "<password> when you invoke this demo as follows:");
|
||||
usage();
|
||||
}
|
||||
|
||||
ProjectHostingService service =
|
||||
new ProjectHostingService("projecthosting-read-demo");
|
||||
|
||||
try {
|
||||
new ProjectHostingReadDemo(service, project, username, password).run();
|
||||
} catch (AuthenticationException e) {
|
||||
System.out.println("The username/password entered is invalid.");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Input stream for reading user input. */
|
||||
private static final BufferedReader IN =
|
||||
new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
/**
|
||||
* Prompts and returns user input as an integer.
|
||||
* It will keep asking until the user provides a valid number.
|
||||
*
|
||||
* @throws IOException if there is a I/O related problem
|
||||
*/
|
||||
private static int readInteger(String name) throws IOException {
|
||||
while (true) {
|
||||
String input = readString(name);
|
||||
try {
|
||||
return Integer.parseInt(input);
|
||||
} catch (NumberFormatException nfe) {
|
||||
System.out.println("Invalid number " + input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts and returns user input as a string.
|
||||
*
|
||||
* @throws IOException if there is a I/O related problem
|
||||
*/
|
||||
private static String readString(String name) throws IOException {
|
||||
System.out.print("Please enter " + name + ": ");
|
||||
System.out.flush();
|
||||
String result = IN.readLine();
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the main loop for reading issues and comments.
|
||||
* It offers a choice for users to read issues or a specific issue
|
||||
* and its comments and continues to do so until "exit" is selected.
|
||||
*
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
private void run() throws IOException, ServiceException {
|
||||
while (true) {
|
||||
System.out.println(
|
||||
DIVIDER
|
||||
+ "Main menu:\n"
|
||||
+ "[0] Exit\n"
|
||||
+ "[1] Read issues\n"
|
||||
+ "[2] Read an issue and its comments");
|
||||
int choice = readInteger("action");
|
||||
switch (choice) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
addAndRunQuery();
|
||||
break;
|
||||
case 2:
|
||||
String issueId = readString("issue ID");
|
||||
client.printIssueAndComments(issueId);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Invalid choice " + choice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and runs a query. The user is prompted to add query parameters
|
||||
* until "done" is selected at which point it runs the query and displays
|
||||
* issues returned.
|
||||
* Choice #1 runs the query and shows the issues returned.
|
||||
* Choice #2-13 lets users add query parameters.
|
||||
*
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
private void addAndRunQuery() throws IOException, ServiceException {
|
||||
IssuesQuery query = new IssuesQuery(client.getIssuesFeedUrl());
|
||||
while (true) {
|
||||
System.out.println(
|
||||
DIVIDER
|
||||
+ "Set query parameters. Choose [1] when you're done.\n"
|
||||
+ "[0] Return to the main menu\n"
|
||||
+ "[1] Done. Query issues now.\n"
|
||||
+ "[2] Set full-text query\n"
|
||||
+ "[3] Set published-min\n"
|
||||
+ "[4] Set published-max\n"
|
||||
+ "[5] Set updated-min\n"
|
||||
+ "[6] Set updated-max\n"
|
||||
+ "[7] Set start-index\n"
|
||||
+ "[8] Set max-results\n"
|
||||
+ "[9] Set owner\n"
|
||||
+ "[10] Set reporter\n"
|
||||
+ "[11] Set status\n"
|
||||
+ "[12] Set label\n"
|
||||
+ "[13] Set canned-query");
|
||||
int choice = readInteger("action");
|
||||
switch (choice) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
IssuesFeed resultFeed = client.queryIssues(query);
|
||||
int numResult = resultFeed.getEntries().size();
|
||||
System.out.println(
|
||||
"Query returned " + numResult + " matching issues.");
|
||||
client.printIssues(resultFeed);
|
||||
return;
|
||||
case 2:
|
||||
String textQuery = readString("full-text query");
|
||||
query.setFullTextQuery(textQuery);
|
||||
break;
|
||||
case 3:
|
||||
String publishedMin = readString("published-min");
|
||||
query.setPublishedMin(DateTime.parseDate(publishedMin));
|
||||
break;
|
||||
case 4:
|
||||
String publishedMax = readString("published-max");
|
||||
query.setPublishedMax(DateTime.parseDate(publishedMax));
|
||||
break;
|
||||
case 5:
|
||||
String updatedMin = readString("updated-min");
|
||||
query.setUpdatedMin(DateTime.parseDate(updatedMin));
|
||||
break;
|
||||
case 6:
|
||||
String updatedMax = readString("updated-max");
|
||||
query.setUpdatedMax(DateTime.parseDate(updatedMax));
|
||||
break;
|
||||
case 7:
|
||||
int startIndex = readInteger("start-index");
|
||||
query.setStartIndex(startIndex);
|
||||
break;
|
||||
case 8:
|
||||
int maxResults = readInteger("max-results");
|
||||
query.setMaxResults(maxResults);
|
||||
break;
|
||||
case 9:
|
||||
String owner = readString("owner");
|
||||
query.setOwner(owner);
|
||||
break;
|
||||
case 10:
|
||||
String reporter = readString("reporter");
|
||||
query.setAuthor(reporter);
|
||||
break;
|
||||
case 11:
|
||||
String status = readString("status");
|
||||
query.setStatus(status);
|
||||
break;
|
||||
case 12:
|
||||
String label = readString("label");
|
||||
query.setLabel(label);
|
||||
break;
|
||||
case 13:
|
||||
String cannedQuery = readString("canned-query");
|
||||
query.setCan(cannedQuery);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Invalid choice " + choice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints usage of this application.
|
||||
*/
|
||||
private static void usage() {
|
||||
System.out.println(
|
||||
"Syntax: ProjectHostingReadDemo --project <project> "
|
||||
+ "[--username <username> --password <password>]\n"
|
||||
+ "\t<project>\tProject on which the demo will run.\n"
|
||||
+ "\t<username>\tGoogle Account username\n"
|
||||
+ "\t<password>\tGoogle Account password\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.projecthosting;
|
||||
|
||||
import com.google.gdata.client.projecthosting.ProjectHostingService;
|
||||
import sample.util.SimpleCommandLineParser;
|
||||
import com.google.gdata.data.HtmlTextConstruct;
|
||||
import com.google.gdata.data.Person;
|
||||
import com.google.gdata.data.PlainTextConstruct;
|
||||
import com.google.gdata.data.projecthosting.Cc;
|
||||
import com.google.gdata.data.projecthosting.CcUpdate;
|
||||
import com.google.gdata.data.projecthosting.IssueCommentsEntry;
|
||||
import com.google.gdata.data.projecthosting.IssuesEntry;
|
||||
import com.google.gdata.data.projecthosting.Label;
|
||||
import com.google.gdata.data.projecthosting.Owner;
|
||||
import com.google.gdata.data.projecthosting.OwnerUpdate;
|
||||
import com.google.gdata.data.projecthosting.SendEmail;
|
||||
import com.google.gdata.data.projecthosting.Status;
|
||||
import com.google.gdata.data.projecthosting.Summary;
|
||||
import com.google.gdata.data.projecthosting.Updates;
|
||||
import com.google.gdata.data.projecthosting.Username;
|
||||
import com.google.gdata.util.AuthenticationException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* Demonstrates how to use the Google Data API's Java client library to
|
||||
* interface with the Google Code Issue Tracker Data API.
|
||||
* There are examples for the following operations:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Creating a new issue</li>
|
||||
* <li>Updating the issue by adding a comment with updates</li>
|
||||
* <li>Closing the issue by adding a comment with status "Fixed"</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ProjectHostingWriteDemo {
|
||||
|
||||
/** Disable default public constructor */
|
||||
private ProjectHostingWriteDemo() {
|
||||
}
|
||||
|
||||
/** Client that provides high level operations of the API */
|
||||
private ProjectHostingClient client;
|
||||
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Constructs the command line application.
|
||||
*
|
||||
* @throws AuthenticationException if authentication fails
|
||||
* @throws MalformedURLException if there's a problem with URL
|
||||
*/
|
||||
public ProjectHostingWriteDemo(
|
||||
ProjectHostingService service, String project, String username,
|
||||
String password) throws AuthenticationException, MalformedURLException {
|
||||
this.username = username;
|
||||
client = new ProjectHostingClient(service, project, username, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point. Parses arguments and creates and invokes the demo.
|
||||
*/
|
||||
public static void main(String[] arg) throws Exception {
|
||||
SimpleCommandLineParser parser = new SimpleCommandLineParser(arg);
|
||||
|
||||
// Parse command-line flags
|
||||
String project = parser.getValue("project");
|
||||
String username = parser.getValue("username");
|
||||
String password = parser.getValue("password");
|
||||
|
||||
boolean help = parser.containsKey("help");
|
||||
if (help || (project == null) || (username == null) || (password == null)) {
|
||||
usage();
|
||||
System.exit(help ? 0 : 1);
|
||||
}
|
||||
|
||||
ProjectHostingService service =
|
||||
new ProjectHostingService("projecthosting-write-demo");
|
||||
|
||||
try {
|
||||
new ProjectHostingWriteDemo(service, project, username, password).run();
|
||||
} catch (AuthenticationException e) {
|
||||
System.out.println("The username/password entered is invalid.");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new issue and adds two comments to it, first to update the
|
||||
* issue and second to close it.
|
||||
*
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
private void run() throws IOException, ServiceException {
|
||||
// Create an issue
|
||||
IssuesEntry issueInserted = client.insertIssue(makeNewIssue());
|
||||
|
||||
String issueId = client.getIssueId(issueInserted.getId());
|
||||
System.out.println("Issue #" + issueId + " created");
|
||||
|
||||
// Add comments and updates to the issue created
|
||||
addComment(issueId, makeUpdatingComment());
|
||||
addComment(issueId, makePlainComment());
|
||||
addComment(issueId, makeClosingComment());
|
||||
|
||||
// Print the issue and comments added
|
||||
System.out.println("-----------------------------------------------------");
|
||||
System.out.println("Issue created and comments added:");
|
||||
client.printIssueAndComments(issueInserted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given comment to the given issue.
|
||||
*
|
||||
* @throws IOException if there is a problem communicating with the server
|
||||
* @throws ServiceException if the service is unable to handle the request
|
||||
*/
|
||||
private void addComment(String issueId, IssueCommentsEntry issueComment)
|
||||
throws IOException, ServiceException {
|
||||
IssueCommentsEntry commentInserted = client.insertComment(
|
||||
issueId, issueComment);
|
||||
String commentId = client.getCommentId(commentInserted.getId());
|
||||
System.out.println("Comment #" + commentId + " added in issue #" + issueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new issue that can be inserted to the issues feed.
|
||||
*/
|
||||
protected IssuesEntry makeNewIssue() {
|
||||
Person author = new Person();
|
||||
author.setName(username);
|
||||
|
||||
Owner owner = new Owner();
|
||||
owner.setUsername(new Username(username));
|
||||
|
||||
Cc cc = new Cc();
|
||||
cc.setUsername(new Username(username));
|
||||
|
||||
IssuesEntry entry = new IssuesEntry();
|
||||
entry.getAuthors().add(author);
|
||||
|
||||
// Uncomment the following line to set the owner along with issue creation.
|
||||
// It's intentionally commented out so we can demonstrate setting the owner
|
||||
// field using setOwnerUpdate() as shown in makeUpdatingComment() below.
|
||||
// entry.setOwner(owner);
|
||||
|
||||
entry.setContent(new HtmlTextConstruct("issue description"));
|
||||
entry.setTitle(new PlainTextConstruct("issue summary"));
|
||||
entry.setStatus(new Status("New"));
|
||||
entry.addLabel(new Label("Priority-High"));
|
||||
entry.addLabel(new Label("Milestone-2009"));
|
||||
entry.addCc(cc);
|
||||
entry.setSendEmail(new SendEmail("False"));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comment that updates an existing issue.
|
||||
*/
|
||||
protected IssueCommentsEntry makeUpdatingComment() {
|
||||
Person author = new Person();
|
||||
author.setName(username);
|
||||
|
||||
// Create issue updates
|
||||
Updates updates = new Updates();
|
||||
updates.setSummary(new Summary("New issue summary"));
|
||||
updates.setStatus(new Status("Accepted"));
|
||||
updates.setOwnerUpdate(new OwnerUpdate(username));
|
||||
updates.addLabel(new Label("-Priority-High"));
|
||||
updates.addLabel(new Label("Priority-Low"));
|
||||
updates.addLabel(new Label("-Milestone-2009"));
|
||||
updates.addLabel(new Label("Milestone-2010"));
|
||||
updates.addLabel(new Label("Type-Enhancement"));
|
||||
updates.addCcUpdate(new CcUpdate("-" + username));
|
||||
|
||||
// Create issue comment entry
|
||||
IssueCommentsEntry entry = new IssueCommentsEntry();
|
||||
entry.getAuthors().add(author);
|
||||
entry.setContent(new HtmlTextConstruct("some comment"));
|
||||
entry.setUpdates(updates);
|
||||
entry.setSendEmail(new SendEmail("False"));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comment without any updates.
|
||||
*/
|
||||
protected IssueCommentsEntry makePlainComment() {
|
||||
Person author = new Person();
|
||||
author.setName(username);
|
||||
|
||||
// Create issue comment entry
|
||||
IssueCommentsEntry entry = new IssueCommentsEntry();
|
||||
entry.getAuthors().add(author);
|
||||
entry.setContent(new HtmlTextConstruct("Some comment"));
|
||||
entry.setSendEmail(new SendEmail("False"));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comment that closes an issue by setting Status to "Fixed".
|
||||
*/
|
||||
protected IssueCommentsEntry makeClosingComment() {
|
||||
Person author = new Person();
|
||||
author.setName(username);
|
||||
|
||||
// Set the Status as Fixed
|
||||
Updates updates = new Updates();
|
||||
updates.setStatus(new Status("Fixed"));
|
||||
|
||||
// Create issue comment entry
|
||||
IssueCommentsEntry entry = new IssueCommentsEntry();
|
||||
entry.getAuthors().add(author);
|
||||
entry.setContent(new HtmlTextConstruct("This was fixed last week."));
|
||||
entry.setUpdates(updates);
|
||||
entry.setSendEmail(new SendEmail("False"));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints usage of this application.
|
||||
*/
|
||||
private static void usage() {
|
||||
System.out.println(
|
||||
"Syntax: ProjectHostingWriteDemo --project <project> "
|
||||
+ "--username <username> --password <password>\n"
|
||||
+ "\t<project>\tProject on which the demo will run. This demo will "
|
||||
+ "create a new issue in the given project and add comments to it.\n"
|
||||
+ "\t<username>\tGoogle Account username\n"
|
||||
+ "\t<password>\tGoogle Account password\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
Google Code Issues Data API Java Sample - README.txt
|
||||
----------------------------------------------------
|
||||
|
||||
These Java samples are simple applications that show how to create, read issues
|
||||
and comments from Google Code using the GData Java client library.
|
||||
|
||||
|
||||
The applications can be built and run using the provided Ant build file found at
|
||||
gdata/java/build-samples.xml. The samples can be run in the following manner:
|
||||
|
||||
1. Edit gdata/java/build-samples/build.properties to enter your
|
||||
Google Account username and password.
|
||||
|
||||
2. Invoke the samples using the appropriate commandline:
|
||||
|
||||
ant -f gdata/java/build-samples.xml sample.projecthosting.read.run
|
||||
ant -f gdata/java/build-samples.xml sample.projecthosting.write.run
|
||||
|
||||
Alternately, you can compile and run them from the command line:
|
||||
|
||||
java sample.projecthosting.ProjectHostingReadDemo
|
||||
--project [project]
|
||||
--username [user]
|
||||
--password [pass]
|
||||
|
||||
java sample.projecthosting.ProjectHostingWriteDemo
|
||||
--project [project]
|
||||
--username [user]
|
||||
--password [pass]
|
||||
|
||||
NOTE: The ProjectHostingWriteDemo will create issues and add comments to them,
|
||||
so it is recommended that you use a test project.
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user