Inital commit
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
/* Copyright (c) 2006 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.gbase.basic;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Add a new item to Google Base using the Google Base data API server.
|
||||
*/
|
||||
public class InsertExample {
|
||||
/**
|
||||
* URL of the authenticated customer feed.
|
||||
*/
|
||||
private static final String ITEMS_FEED = "http://base.google.com/base/feeds/items";
|
||||
|
||||
/**
|
||||
* The data item we are going to insert, in XML/Atom format.
|
||||
*/
|
||||
private static final String DATA_ITEM =
|
||||
"<?xml version='1.0'?>\n" +
|
||||
"<entry xmlns='http://www.w3.org/2005/Atom'\n" +
|
||||
" xmlns:g='http://base.google.com/ns/1.0'>\n" +
|
||||
" <g:item_type type='text'>testrecipes</g:item_type>\n" +
|
||||
" <title type='text'>Fabulous cheese cake</title>\n" +
|
||||
" <content type='xhtml'>All that you need is lots of patience.</content>\n" +
|
||||
"</entry>";
|
||||
|
||||
/**
|
||||
* URL used for authenticating and obtaining an authentication token.
|
||||
* More details about how it works:
|
||||
* <code>http://code.google.com/apis/accounts/AuthForInstalledApps.html<code>
|
||||
*/
|
||||
private static final String AUTHENTICATION_URL = "https://www.google.com/accounts/ClientLogin";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account email here.
|
||||
*/
|
||||
private static final String EMAIL = "";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account password here.
|
||||
*/
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
/**
|
||||
* The main method constructs a <code>InsertExample</code> instance, obtains an
|
||||
* authorization token and posts a new item to Google Base.
|
||||
*/
|
||||
public static void main(String[] args) throws MalformedURLException, IOException {
|
||||
InsertExample insertExample = new InsertExample();
|
||||
String token = insertExample.authenticate();
|
||||
System.out.println("Obtained authorization token: " + token);
|
||||
insertExample.postItem(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts <code>DATA_ITEM</code> by making a POST request to
|
||||
* <code>ITEMS_URL<code>.
|
||||
* @param token authentication token obtained using <code>authenticate</code>
|
||||
* @throws IOException if an I/O exception occurs while creating/writing/
|
||||
* reading the request
|
||||
*/
|
||||
public void postItem(String token) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection)(new URL(ITEMS_FEED)).openConnection();
|
||||
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Set the properties of the connection: the Http method, the content type
|
||||
// of the POST request and the authorization header
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/atom+xml");
|
||||
connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
|
||||
|
||||
// Post the data item
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(DATA_ITEM.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
// Retrieve the output
|
||||
int responseCode = connection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == HttpURLConnection.HTTP_CREATED) {
|
||||
inputStream = connection.getInputStream();
|
||||
} else {
|
||||
inputStream = connection.getErrorStream();
|
||||
}
|
||||
|
||||
// write the output to the console
|
||||
System.out.println(toString(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the authentication token for the provided set of credentials.
|
||||
* @return the authorization token that can be used to access authenticated
|
||||
* Google Base data API feeds
|
||||
*/
|
||||
public String authenticate() {
|
||||
// create the login request
|
||||
String postOutput = null;
|
||||
try {
|
||||
URL url = new URL(AUTHENTICATION_URL);
|
||||
postOutput = makeLoginRequest(url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Could not connect to authentication server: "
|
||||
+ e.toString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Parse the result of the login request. If everything went fine, the
|
||||
// response will look like
|
||||
// HTTP/1.0 200 OK
|
||||
// Server: GFE/1.3
|
||||
// Content-Type: text/plain
|
||||
// SID=DQAAAGgA...7Zg8CTN
|
||||
// LSID=DQAAAGsA...lk8BBbG
|
||||
// Auth=DQAAAGgA...dk3fA5N
|
||||
// so all we need to do is look for "Auth" and get the token that comes after it
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(postOutput, "=\n ");
|
||||
String token = null;
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
if (tokenizer.nextToken().equals("Auth")) {
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
token = tokenizer.nextToken();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token == null) {
|
||||
System.out.println("Authentication error. Response from server:\n" + postOutput);
|
||||
System.exit(1);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a HTTP POST request to the provided {@code url} given the provided
|
||||
* {@code parameters}. It returns the output from the POST handler as a
|
||||
* String object.
|
||||
*
|
||||
* @param url the URL to post the request
|
||||
* @return the output from the handler
|
||||
* @throws IOException if an I/O exception occurs while
|
||||
* creating/writing/reading the request
|
||||
*/
|
||||
private String makeLoginRequest(URL url)
|
||||
throws IOException {
|
||||
// Create a login request. A login request is a POST request that looks like
|
||||
// POST /accounts/ClientLogin HTTP/1.0
|
||||
// Content-type: application/x-www-form-urlencoded
|
||||
// Email=johndoe@gmail.com&Passwd=north23AZ&service=gbase&source=Insert Example
|
||||
|
||||
// Open connection
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
|
||||
// Set properties of the connection
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setDoInput(true);
|
||||
urlConnection.setDoOutput(true);
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
|
||||
// Form the POST parameters
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("Email=").append(URLEncoder.encode(EMAIL, "UTF-8"));
|
||||
content.append("&Passwd=").append(URLEncoder.encode(PASSWORD, "UTF-8"));
|
||||
content.append("&source=").append(URLEncoder.encode("Google Base data API example", "UTF-8"));
|
||||
content.append("&service=").append(URLEncoder.encode("gbase", "UTF-8"));
|
||||
|
||||
OutputStream outputStream = urlConnection.getOutputStream();
|
||||
outputStream.write(content.toString().getBytes("UTF-8"));
|
||||
outputStream.close();
|
||||
|
||||
// Retrieve the output
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.getInputStream();
|
||||
} else {
|
||||
inputStream = urlConnection.getErrorStream();
|
||||
}
|
||||
|
||||
return toString(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the content of the input stream to a <code>String<code>.
|
||||
*/
|
||||
private String toString(InputStream inputStream) throws IOException {
|
||||
String string;
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
if (inputStream != null) {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
while (null != (string = reader.readLine())) {
|
||||
outputBuilder.append(string).append('\n');
|
||||
}
|
||||
}
|
||||
return outputBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Copyright (c) 2006 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.gbase.basic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
/**
|
||||
* Dumps to the console the response of a Google Base data API query.
|
||||
*/
|
||||
public class QueryExample1 {
|
||||
/**
|
||||
* Url of the Google Base data API snippet feed.
|
||||
*/
|
||||
private static final String SNIPPETS_FEED = "http://base.google.com/base/feeds/snippets";
|
||||
|
||||
/**
|
||||
* The query that is sent over to the Google Base data API server.
|
||||
*/
|
||||
private static final String QUERY = "cars [item type : products]";
|
||||
|
||||
/**
|
||||
* Connect to <code>SNIPPETS_FEED</code> and display the response.
|
||||
* @throws IOException if an error occured while connecting or reading from
|
||||
* the feed
|
||||
*/
|
||||
public void displayItems() throws IOException {
|
||||
URL url = new URL(SNIPPETS_FEED + "?bq=" +
|
||||
URLEncoder.encode(QUERY, "UTF-8"));
|
||||
|
||||
HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();
|
||||
InputStream inputStream = httpConnection.getInputStream();
|
||||
|
||||
int ch;
|
||||
while ((ch=inputStream.read()) > 0) {
|
||||
System.out.print((char)ch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method simply creates a <code>QueryExample2</code> instance and
|
||||
* calls <code>displayItems</code>.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
new QueryExample1().displayItems();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/* Copyright (c) 2006 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.gbase.basic;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
/**
|
||||
* Display the titles of the Google Base items that match a specific query.
|
||||
*/
|
||||
public class QueryExample2 {
|
||||
/**
|
||||
* Url of the Google Base data API snippet feed.
|
||||
*/
|
||||
private static final String SNIPPETS_FEED = "http://base.google.com/base/feeds/snippets";
|
||||
|
||||
/**
|
||||
* The query that is sent over to the Google Base data API server.
|
||||
*/
|
||||
private static final String QUERY = "cars [item type : products]";
|
||||
|
||||
/**
|
||||
* Create a <code>QueryExample2</code> instance and
|
||||
* call <code>displayItems</code>.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException, SAXException,
|
||||
ParserConfigurationException {
|
||||
new QueryExample2().displayItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the Google Base data API server, retrieve the items that match
|
||||
* <code>QUERY</code> and call <code>DisplayTitlesHandler</code> to extract
|
||||
* and display the titles from the XML response.
|
||||
*/
|
||||
public void displayItems() throws IOException, SAXException,
|
||||
ParserConfigurationException {
|
||||
/*
|
||||
* Create a URL object, open an Http connection on it and get the input
|
||||
* stream that reads the Http response.
|
||||
*/
|
||||
URL url = new URL(SNIPPETS_FEED + "?bq=" +
|
||||
URLEncoder.encode(QUERY, "UTF-8"));
|
||||
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
|
||||
InputStream inputStream = httpConnection.getInputStream();
|
||||
|
||||
/*
|
||||
* Create a SAX XML parser and pass in the input stream to the parser.
|
||||
* The parser will use DisplayTitleHandler to extract the titles from the
|
||||
* XML stream.
|
||||
*/
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = factory.newSAXParser();
|
||||
parser.parse(inputStream, new DisplayTitlesHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple SAX event handler, which prints out the titles of all entries in the
|
||||
* Atom response feed.
|
||||
*/
|
||||
private static class DisplayTitlesHandler extends DefaultHandler {
|
||||
/**
|
||||
* Stack containing the opening XML tags of the response.
|
||||
*/
|
||||
private Stack<String> xmlTags = new Stack<String>();
|
||||
|
||||
/**
|
||||
* Counter that keeps track of the currently parsed item.
|
||||
*/
|
||||
private int itemNo = 0;
|
||||
|
||||
/**
|
||||
* True if we are inside of a data entry's title, false otherwise.
|
||||
*/
|
||||
private boolean insideEntryTitle = false;
|
||||
|
||||
/**
|
||||
* Receive notification of an opening XML tag: push the tag to
|
||||
* <code>xmlTags</code>. If the tag is a title tag inside an entry tag,
|
||||
* turn <code>insideEntryTitle</code> to <code>true</code>.
|
||||
*/
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (qName.equals("title") && xmlTags.peek().equals("entry")) {
|
||||
insideEntryTitle = true;
|
||||
System.out.print("Item " + ++itemNo + ": ");
|
||||
}
|
||||
xmlTags.push(qName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive notification of a closing XML tag: remove the tag from teh stack.
|
||||
* If we were inside of an entry's title, turn <code>insideEntryTitle</code>
|
||||
* to <code>false</code>.
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
// If a "title" element is closed, we start a new line, to prepare
|
||||
// printing the new title.
|
||||
xmlTags.pop();
|
||||
if (insideEntryTitle) {
|
||||
insideEntryTitle = false;
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method for receiving notification of character data inside an
|
||||
* XML element.
|
||||
*/
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
// display the character data if the opening tag is "title" and its parent is
|
||||
// "entry"
|
||||
if (insideEntryTitle) {
|
||||
System.out.print(new String(ch, start, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/* Copyright (c) 2006 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.gbase.basic;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Display all items of a specific customer.
|
||||
*/
|
||||
public class QueryExample3 {
|
||||
/**
|
||||
* URL of the authenticated customer feed.
|
||||
*/
|
||||
private static final String ITEMS_FEED = "http://base.google.com/base/feeds/items";
|
||||
|
||||
/**
|
||||
* URL used for authenticating and obtaining an authentication token.
|
||||
* More details about how it works:
|
||||
* <code>http://code.google.com/apis/accounts/AuthForInstalledApps.html<code>
|
||||
*/
|
||||
private static final String AUTHENTICATION_URL = "https://www.google.com/accounts/ClientLogin";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account email here.
|
||||
*/
|
||||
private static final String EMAIL = "";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account password here.
|
||||
*/
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
/**
|
||||
* Create a <code>QueryExample3</code> instance and call
|
||||
* <code>displayMyItems</code>, which displays all items that belong to the
|
||||
* currently authenticated user.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
QueryExample3 queryExample = new QueryExample3();
|
||||
String token = queryExample.authenticate();
|
||||
queryExample.displayMyItems(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the authentication token for the provided set of credentials.
|
||||
* @return the authorization token that can be used to access authenticated
|
||||
* Google Base data API feeds
|
||||
*/
|
||||
public String authenticate() {
|
||||
// create the login request
|
||||
String postOutput = null;
|
||||
try {
|
||||
URL url = new URL(AUTHENTICATION_URL);
|
||||
postOutput = makeLoginRequest(url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Could not connect to authentication server: "
|
||||
+ e.toString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Parse the result of the login request. If everything went fine, the
|
||||
// response will look like
|
||||
// HTTP/1.0 200 OK
|
||||
// Server: GFE/1.3
|
||||
// Content-Type: text/plain
|
||||
// SID=DQAAAGgA...7Zg8CTN
|
||||
// LSID=DQAAAGsA...lk8BBbG
|
||||
// Auth=DQAAAGgA...dk3fA5N
|
||||
// so all we need to do is look for "Auth" and get the token that comes after it
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(postOutput, "=\n ");
|
||||
String token = null;
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
if (tokenizer.nextToken().equals("Auth")) {
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
token = tokenizer.nextToken();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token == null) {
|
||||
System.out.println("Authentication error. Response from server:\n" + postOutput);
|
||||
System.exit(1);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the "items" feed, that is the feed that contains the items that
|
||||
* belong to the currently authenticated user.
|
||||
*
|
||||
* @param token the authorization token, as returned by
|
||||
* <code>authenticate<code>
|
||||
* @throws IOException if an IOException occurs while creating/reading the
|
||||
* request
|
||||
*/
|
||||
public void displayMyItems(String token) throws MalformedURLException, IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection)(new URL(ITEMS_FEED)).openConnection() ;
|
||||
// Set properties of the connection
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = connection.getInputStream();
|
||||
} else {
|
||||
inputStream = connection.getErrorStream();
|
||||
}
|
||||
|
||||
System.out.println(toString(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a HTTP POST request to the provided {@code url} given the provided
|
||||
* {@code parameters}. It returns the output from the POST handler as a
|
||||
* String object.
|
||||
*
|
||||
* @param url the URL to post the request
|
||||
* @return the output from the Google Accounts server, as string
|
||||
* @throws IOException if an I/O exception occurs while
|
||||
* creating/writing/reading the request
|
||||
*/
|
||||
private String makeLoginRequest(URL url)
|
||||
throws IOException {
|
||||
// Create a login request. A login request is a POST request that looks like
|
||||
// POST /accounts/ClientLogin HTTP/1.0
|
||||
// Content-type: application/x-www-form-urlencoded
|
||||
// Email=johndoe@gmail.com&Passwd=north23AZ&service=gbase&source=Insert Example
|
||||
|
||||
// Open connection
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
|
||||
// Set properties of the connection
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setDoInput(true);
|
||||
urlConnection.setDoOutput(true);
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
|
||||
// Form the POST parameters
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("Email=").append(URLEncoder.encode(EMAIL, "UTF-8"));
|
||||
content.append("&Passwd=").append(URLEncoder.encode(PASSWORD, "UTF-8"));
|
||||
content.append("&service=").append(URLEncoder.encode("gbase", "UTF-8"));
|
||||
content.append("&source=").append(URLEncoder.encode("Google Base data API example", "UTF-8"));
|
||||
|
||||
OutputStream outputStream = urlConnection.getOutputStream();
|
||||
outputStream.write(content.toString().getBytes("UTF-8"));
|
||||
outputStream.close();
|
||||
|
||||
// Retrieve the output
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.getInputStream();
|
||||
} else {
|
||||
inputStream = urlConnection.getErrorStream();
|
||||
}
|
||||
|
||||
return toString(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the content of the input stream to a <code>String<code>.
|
||||
*/
|
||||
private String toString(InputStream inputStream) throws IOException {
|
||||
String string;
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
if (inputStream != null) {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(inputStream));
|
||||
while (null != (string = reader.readLine())) {
|
||||
outputBuilder.append(string).append('\n');
|
||||
}
|
||||
}
|
||||
return outputBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/* Copyright (c) 2006 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.gbase.basic;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Update a Google Base data item using the Google Base data API server.
|
||||
*/
|
||||
public class UpdateExample {
|
||||
/**
|
||||
* URL of the authenticated customer feed.
|
||||
*/
|
||||
private static final String ITEMS_FEED = "http://base.google.com/base/feeds/items";
|
||||
|
||||
/**
|
||||
* The data item we are going to insert, in XML/Atom format.
|
||||
*/
|
||||
private static final String DATA_ITEM =
|
||||
"<?xml version='1.0'?>\n" +
|
||||
"<entry xmlns='http://www.w3.org/2005/Atom'\n" +
|
||||
" xmlns:g='http://base.google.com/ns/1.0'>\n" +
|
||||
" <g:item_type type='text'>testrecipes</g:item_type>\n" +
|
||||
" <title type='text'>Fabulous cheese cake</title>\n" +
|
||||
" <content type='xhtml'>All that you need is lots of patience.</content>\n" +
|
||||
"</entry>";
|
||||
|
||||
/**
|
||||
* The updated data item, in XML/Atom format. It adds an additional label to
|
||||
* <code>DATA_ITEM</code>.
|
||||
*/
|
||||
private static final String NEW_DATA_ITEM =
|
||||
"<?xml version='1.0'?>\n" +
|
||||
"<entry xmlns='http://www.w3.org/2005/Atom'\n" +
|
||||
" xmlns:g='http://base.google.com/ns/1.0'>\n" +
|
||||
" <g:item_type type='text'>testrecipes</g:item_type>\n" +
|
||||
" <title type='text'>Yummy cheese cake</title>\n" +
|
||||
" <content type='xhtml'>All that you need is lots of patience.</content>\n" +
|
||||
" <g:main_ingredient type='text'>cheese</g:main_ingredient>\n" +
|
||||
"</entry>";
|
||||
|
||||
/**
|
||||
* URL used for authenticating and obtaining an authentication token.
|
||||
* More details about how it works:
|
||||
* <code>http://code.google.com/apis/accounts/AuthForInstalledApps.html<code>
|
||||
*/
|
||||
private static final String AUTHENTICATION_URL =
|
||||
"https://www.google.com/accounts/ClientLogin";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account email here.
|
||||
*/
|
||||
private static final String EMAIL = "";
|
||||
|
||||
/**
|
||||
* Fill in your Google Account password here.
|
||||
*/
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
/**
|
||||
* The main method constructs an <code>UpdateExample</code> instance,
|
||||
* obtains an authorization token, posts a new item to Google Base, extracts
|
||||
* the new item's id from the reponse and uses it to update the item.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
throws MalformedURLException, IOException {
|
||||
UpdateExample updateExample = new UpdateExample();
|
||||
String token = updateExample.authenticate();
|
||||
System.out.println("Obtained authorization token: " + token);
|
||||
|
||||
System.out.println("Posting item:\n" + DATA_ITEM);
|
||||
String itemUrl = updateExample.extractItemUrlFromResponse(
|
||||
updateExample.postItem(token));
|
||||
|
||||
System.out.println("Updating item: " + itemUrl);
|
||||
String updateResponse = updateExample.updateItem(token, itemUrl);
|
||||
System.out.println(updateResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the authentication token for the provided set of credentials.
|
||||
* @return the authorization token that can be used to access authenticated
|
||||
* Google Base data API feeds
|
||||
*/
|
||||
public String authenticate() {
|
||||
// create the login request
|
||||
String postOutput = null;
|
||||
try {
|
||||
URL url = new URL(AUTHENTICATION_URL);
|
||||
postOutput = makeLoginRequest(url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Could not connect to authentication server: "
|
||||
+ e.toString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Parse the result of the login request. If everything went fine, the
|
||||
// response will look like
|
||||
// HTTP/1.0 200 OK
|
||||
// Server: GFE/1.3
|
||||
// Content-Type: text/plain
|
||||
// SID=DQAAAGgA...7Zg8CTN
|
||||
// LSID=DQAAAGsA...lk8BBbG
|
||||
// Auth=DQAAAGgA...dk3fA5N
|
||||
// so all we need to do is look for "Auth" and get the token that comes after it
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(postOutput, "=\n ");
|
||||
String token = null;
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
if (tokenizer.nextToken().equals("Auth")) {
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
token = tokenizer.nextToken();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token == null) {
|
||||
System.out.println("Authentication error. Response from server:\n" + postOutput);
|
||||
System.exit(1);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the POST XML response returned by <code>insertResponse</code> and
|
||||
* extract the Google Base item id of the newly created item. To keep parsing
|
||||
* simple, we assume that the first "id" tag contains the Atom item id; this
|
||||
* is true for the Google Base data API servers, but it's not enforced by Atom -
|
||||
* see how the title is parsed in {@link QueryExample2}
|
||||
* @param insertResponse the response sent by the Google Base data API server
|
||||
* after the insert operation
|
||||
* @return the Url that identifies the item, for example: <code>
|
||||
* http://base.google.com/base/feeds/items/18020038538902937385</code>
|
||||
*/
|
||||
public String extractItemUrlFromResponse(String insertResponse) {
|
||||
int startIndex = insertResponse.indexOf("<id>") + 4;
|
||||
int endIndex = insertResponse.indexOf("</id>");
|
||||
String itemUrl = insertResponse.substring(startIndex, endIndex);
|
||||
return itemUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts <code>DATA_ITEM</code> by making a POST request to
|
||||
* <code>ITEMS_FEED<code>.
|
||||
* @param token authentication token obtained using <code>authenticate</code>
|
||||
* @return the Google Base data API server's insert response
|
||||
* @throws IOException if an I/O exception occurs while creating/writing/
|
||||
* reading the request
|
||||
*/
|
||||
public String postItem(String token) throws IOException {
|
||||
return makeHttpRequest(token, ITEMS_FEED, DATA_ITEM, "POST",
|
||||
HttpURLConnection.HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates <code>NEW_DATA_ITEM</code> by making a PUT request to
|
||||
* <code>itemUrl</code>.
|
||||
*
|
||||
* @param token authentication token obtained using <code>authenticate</code>
|
||||
* @param itemUrl the identifier of the item to update, which has the form
|
||||
* <code>ITEMS_URL + "/itemId"</code>
|
||||
* @return the Google Base data API server's update response
|
||||
* @throws IOException if an I/O exception occurs while creating/writing/
|
||||
* reading the request
|
||||
*/
|
||||
public String updateItem(String token, String itemUrl)
|
||||
throws MalformedURLException, IOException {
|
||||
return makeHttpRequest(token, itemUrl, NEW_DATA_ITEM, "PUT",
|
||||
HttpURLConnection.HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an Http request to <code>url</code>, using <code>httpMethod</code>,
|
||||
* post <code>item</code> and return the response.
|
||||
*
|
||||
* @param token authentication token obtained using <code>authenticate</code>
|
||||
* @param url the identifier of the item to update, which has the form
|
||||
* <code>ITEMS_URL + "/itemId"</code>
|
||||
* @param item the item to be posted via the request
|
||||
* @param httpMethod the httpMethod to use for posting (should be PUT or POST)
|
||||
* @param expectedResponseCode the response code returned in case of a
|
||||
* successful operation
|
||||
* @return the Google Base data API update response
|
||||
* @throws IOException if an I/O exception occurs while
|
||||
* creating/writing/reading the request
|
||||
*/
|
||||
private String makeHttpRequest(String token, String url, String item,
|
||||
String httpMethod, int expectedResponseCode) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection)(new URL(url)).openConnection() ;
|
||||
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Set the properties of the connection: the http request method, the
|
||||
// content type and the authorization header
|
||||
connection.setRequestMethod(httpMethod);
|
||||
connection.setRequestProperty("Content-Type", "application/atom+xml");
|
||||
connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
|
||||
|
||||
// Post the data item
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(item.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
// Retrieve the output
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode == expectedResponseCode) {
|
||||
return toString(connection.getInputStream());
|
||||
} else {
|
||||
throw new RuntimeException(toString(connection.getErrorStream()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a HTTP POST request to the provided {@code url} given the provided
|
||||
* {@code parameters}. It returns the output from the POST handler as a
|
||||
* String object.
|
||||
*
|
||||
* @param url the URL to post the request
|
||||
* @return the output from the server
|
||||
* @throws IOException if an I/O exception occurs while
|
||||
* creating/writing/reading the request
|
||||
*/
|
||||
private String makeLoginRequest(URL url)
|
||||
throws IOException {
|
||||
// Create a login request. A login request is a POST request that looks like
|
||||
// POST /accounts/ClientLogin HTTP/1.0
|
||||
// Content-type: application/x-www-form-urlencoded
|
||||
// Email=johndoe@gmail.com&Passwd=north23AZ&service=gbase&source=Insert Example
|
||||
|
||||
// Open connection
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
|
||||
// Set properties of the connection
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setDoInput(true);
|
||||
urlConnection.setDoOutput(true);
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
|
||||
// Form the POST parameters
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("Email=").append(URLEncoder.encode(EMAIL, "UTF-8"));
|
||||
content.append("&Passwd=").append(URLEncoder.encode(PASSWORD, "UTF-8"));
|
||||
content.append("&source=").append(URLEncoder.encode("Google Base data API example", "UTF-8"));
|
||||
content.append("&service=").append(URLEncoder.encode("gbase", "UTF-8"));
|
||||
|
||||
OutputStream outputStream = urlConnection.getOutputStream();
|
||||
outputStream.write(content.toString().getBytes("UTF-8"));
|
||||
outputStream.close();
|
||||
|
||||
// Retrieve the output
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.getInputStream();
|
||||
} else {
|
||||
inputStream = urlConnection.getErrorStream();
|
||||
}
|
||||
|
||||
return toString(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the content of the input stream to a <code>String<code>.
|
||||
*/
|
||||
private String toString(InputStream inputStream) throws IOException {
|
||||
String lineToRead;
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
if (inputStream != null) {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
while (null != (lineToRead = reader.readLine())) {
|
||||
outputBuilder.append(lineToRead).append('\n');
|
||||
}
|
||||
}
|
||||
return outputBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,641 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Linux/x86 (vers 1st November 2003), see www.w3.org" />
|
||||
|
||||
<title>Google Base data API: Sample Applications</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<P>Sample standalone applications accessing Google Base data API feeds</P>
|
||||
|
||||
<h2><a name="intro" id="intro"></a>Introduction</h2>The Google Base data Java
|
||||
<a href='http://code.google.com/apis/base/sample-apps.html'>Client
|
||||
Library</a> offers a nice object oriented abstraction for accessing the
|
||||
Google Base data API. However, if you prefer to interact with the Google Base
|
||||
data API servers directly, here are a few examples that will start you up.
|
||||
|
||||
<p>This document assumes you know Java programming (including some basic
|
||||
knowledge of Http connections and SAX parsers) and that you are familiar with
|
||||
<a href="http://code.google.com/apis/base/concepts.html">Google Base
|
||||
concepts</a>. You need to understand the following concepts before you can
|
||||
take full advantage of the sample applications:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href=
|
||||
"http://code.google.com/apis/base/attrs-queries.html#queries">queries</a></li>
|
||||
|
||||
<li><a href=
|
||||
"http://code.google.com/apis/base/attrs-queries.html#gbItemTypes">item
|
||||
types</a></li>
|
||||
|
||||
<li><a href=
|
||||
"http://code.google.com/apis/base/attrs-queries.html#gbAttrs">attributes</a></li>
|
||||
</ul>
|
||||
|
||||
<p>This tutorial consists of stepping through 5 examples. The first example
|
||||
shows how to connect to a Google Base data API feed and query data. The
|
||||
second example extends this by showing how to parse the result and extract
|
||||
data of interest from the feed. The third example introduces authentication
|
||||
and demonstrates how to display your own items, rather than querying
|
||||
snippets. The fourth example demonstrates how to insert your own item into
|
||||
Google Base, while the last example shows how to update a previously inserted
|
||||
item.</p>
|
||||
|
||||
<h2><a name="queryExample1" id="queryExample1"></a>Query Example 1 - query
|
||||
the Google Base data API and display the result</h2>
|
||||
|
||||
<p><code>QueryExample1</code> is a simple Java application that runs from the
|
||||
command line. It performs an unauthenticated query on the public <a href=
|
||||
'http://code.google.com/apis/base/snippets-feed.html'>snippets feed</a>
|
||||
(<code>/feeds/snippets</code>) and it dumps the query response to the console
|
||||
(it won't look pretty!).</p>
|
||||
|
||||
<h3><a name="QE1run" id="QE1run"></a>Running
|
||||
<code>QueryExample1</code></h3>Edit QueryExample1.java and fill in the
|
||||
|
||||
Compile and run the example using your favorite editor, or using the
|
||||
command line:
|
||||
<pre>
|
||||
javac sample.gbase/basic/QueryExample1.java
|
||||
java sample.gbase/basic/QueryExample1
|
||||
|
||||
</pre>The output (conveniently formatted) will look like:
|
||||
<pre>
|
||||
<feed>
|
||||
<id>http://0.baseapitest.googlebase-api.jc.borg.google.com.:31911/base/feeds/snippets</id>
|
||||
<updated>2006-08-22T14:14:11.984Z</updated>
|
||||
<title type="text">Items matching query: cars [item type : products]</title>
|
||||
<link rel="alternate" type="text/html" href="http://base.google.com"/>
|
||||
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://0.baseapitest.googlebase-api.jc.borg.google.com.:31911/base/feeds/snippets"/>
|
||||
<link rel="self" type="application/atom+xml" href="http://0.baseapitest.googlebase-api.jc.borg.google.com.:31911/base/feeds/snippets?key=ABQ...9P2Y4A&bq=cars+%5Bitem+type+%3A+products%5D"/>
|
||||
<link rel="next" type="application/atom+xml" href="http://0.baseapitest.googlebase-api.jc.borg.google.com.:31911/base/feeds/snippets?start-index=26&max-results=25&key=ABQ...9P2Y4A&bq=cars+%5Bitem+type+%3A+products%5D"/>
|
||||
<generator version="1.0" uri="http://base.google.com">GoogleBase</generator>
|
||||
<openSearch:totalResults>278120</openSearch:totalResults>
|
||||
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
|
||||
<entry>
|
||||
<id>http://0.baseapitest.googlebase-api.jc.borg.google.com.:31911/base/feeds/snippets/10062394959501653657</id>
|
||||
<published>2006-06-30T21:45:12.000Z</published>
|
||||
<updated>2006-07-28T00:58:14.000Z</updated>
|
||||
...
|
||||
|
||||
</pre>
|
||||
|
||||
<h3><a name="QE1stepThru" id="QE1stepThru"></a>Stepping through the
|
||||
<code>QueryExample1</code> code</h3>
|
||||
|
||||
<p>At the very beginning we define the url of the feed we are connecting to
|
||||
and the query that we are going to run:</p>
|
||||
<pre>
|
||||
private static final String SNIPPETS_FEED = "http://base.google.com/base/feeds/snippets";
|
||||
|
||||
private static final String QUERY = "cars [item type : products]";
|
||||
|
||||
</pre>Feel free to change the query to a more relevant or interesting one. Take
|
||||
a look at the <a href=
|
||||
'http://code.google.com/apis/base/query-lang-spec.htm'>Google Base Query
|
||||
Language</a> description if you need some inspiration.
|
||||
|
||||
<p>After opening a connection on the snippets feed, we grab the connection's
|
||||
input stream, and dump its content to the output, character by character:</p>
|
||||
<pre>
|
||||
HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();
|
||||
InputStream inputStream = httpConnection.getInputStream();
|
||||
|
||||
int ch;
|
||||
while ((ch=inputStream.read()) > 0) {
|
||||
System.out.print((char)ch);
|
||||
}
|
||||
|
||||
</pre>In the <code>main</code> method, all we do is create a
|
||||
<code>QueryExample1</code> instance, and invoke its <code>displayItems</code>
|
||||
method:
|
||||
<pre>
|
||||
public static void main(String[] args) throws IOException, SAXException,
|
||||
ParserConfigurationException {
|
||||
new QueryExample1().displayItems();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="queryExample2" id="queryExample2"></a>Query Example 2 - query
|
||||
the Google Base data API, parse the result and display the titles of returned
|
||||
data items</h2>
|
||||
|
||||
<p>One major problem with <code>QueryExample1</code> is that it simply dumps
|
||||
the items returned for the query to the console, and the result is barely
|
||||
readable. In any real life application the query result would need to be
|
||||
parsed, interpreted and relevant information should be extracted and
|
||||
displayed to the user. In <code>QueryExample2</code> we demonstrate a
|
||||
possible way of doing this by using a SAX parser to extract each data item's
|
||||
title from the result, and display it to the console. Some very basic
|
||||
understanding of how SAX parsers work is necessary in order to fully
|
||||
understand this example.</p>
|
||||
|
||||
<p>One might argue that for this task we don't even need a SAX parser. We
|
||||
could just search for all <code><title></code> tags in the result and
|
||||
display the characters that they enclose. Unfortunately, that wouldn't work,
|
||||
as the Atom response also has a <code><title></code> tag, which is the
|
||||
title of the feed:</p>
|
||||
<pre>
|
||||
<feed>
|
||||
...
|
||||
<title type="text">Items matching query: cars [item type : products]</title>
|
||||
...
|
||||
<entry>
|
||||
...
|
||||
<title type='text'>Great care for sale</title>
|
||||
...
|
||||
|
||||
</pre>Atom does not mandate that the feed's <code><title></code> tag
|
||||
should appear at a specific position inside the feed, so we need to make sure
|
||||
we only display the <code><title></code> tags which are sub-elements of
|
||||
an <code><entry></code> tag.<br />
|
||||
<br />
|
||||
|
||||
<h3><a name="QE2run" id=
|
||||
"QE2run"></a>Running<code>QueryExample2</code></h3>
|
||||
Compile and run the example using your favorite editor, or using the
|
||||
command line:
|
||||
<pre>
|
||||
javac sample.gbase/basic/QueryExample2.java
|
||||
java sample.gbase/basic/QueryExample2
|
||||
|
||||
</pre>The output will look like:
|
||||
<pre>
|
||||
Item 1: Johnny Lightning MUSCLE CARS R8 1967 Chevelle SS
|
||||
Item 2: Johnny Lightning MUSCLE CARS USA 2005 Ford GT
|
||||
...
|
||||
Item 25: The Cars movie Hinged tool Box Toy Organize lunch RARE
|
||||
|
||||
</pre>
|
||||
|
||||
<ul class="noindent"></ul>
|
||||
|
||||
<h3><a name="QE2stepThru" id="QE2stepThru"></a>Stepping through the
|
||||
<code>QueryExample2</code> code</h3>
|
||||
|
||||
<p>Just as in the previous example, we first send the query to the Google
|
||||
Base data API server, and obtain an <code>inputStream</code> containing the
|
||||
response:</p>
|
||||
<pre>
|
||||
URL url = new URL(SNIPPETS_FEED + "?bq=" +
|
||||
URLEncoder.encode(QUERY, "UTF-8"));
|
||||
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
|
||||
InputStream inputStream = httpConnection.getInputStream();
|
||||
</pre>
|
||||
|
||||
<p>We then use a standard SAX parser to parse the result. We obtain a
|
||||
SAXParser instance using a SAXParserFactory:</p>
|
||||
<pre>
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = factory.newSAXParser();
|
||||
</pre>We then parse the result <code>inputStream</code> using
|
||||
<code>DisplayTitlesHandler</code>, our custom SAX event handler:
|
||||
<pre>
|
||||
parser.parse(inputStream, new DisplayTitlesHandler());
|
||||
</pre>
|
||||
|
||||
<p><code>DisplayTitlesHandler</code> is derived from the no-op SAX parser,
|
||||
<code>org.xml.sax.helpers.DefaultHandler</code>. The logic inside
|
||||
<code>DisplayTitlesHandler</code> is pretty simple: we keep a stack of the
|
||||
currently open XML tags and print all character data when we are inside a
|
||||
<code><title></code> tag with a <code><entry></code> parent. The
|
||||
<code>insideEntryTitle</code> flag is turned on each time we are inside a
|
||||
<code><entry><title></code> pair:</p>
|
||||
<pre>
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (qName.equals("title") && xmlTags.peek().equals("entry")) {
|
||||
insideEntryTitle = true;
|
||||
System.out.print("Item " + ++itemNo + ": ");
|
||||
}
|
||||
xmlTags.push(qName);
|
||||
}
|
||||
</pre>Since <code>startElement</code> is invoked each time the SAX parser
|
||||
encounters an opening XML tag, we switch on <code>insideEntryTitle</code> only
|
||||
if the currently parsed opening tag is <code><title></code> and the tag
|
||||
on the top of the stack is <code><entry></code> . We are also printing
|
||||
here the "Item no: " messages, rather than in the <code>characters</code>
|
||||
method, as <code>characters</code> can be called multiple times for different
|
||||
chunks of the title's character data.<br />
|
||||
<br />
|
||||
The <code>endElement</code> method is invoked each time an XML tag closes.
|
||||
All we need to do here is to remove the closing XML tag from the stack and,
|
||||
in case the removed XML tag was an entry's title, flip
|
||||
<code>insideEntryTitle</code> to false and go to a new line in the console,
|
||||
in preparation for printing out the next title:
|
||||
<pre>
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
xmlTags.pop();
|
||||
if (insideEntryTitle) {
|
||||
insideEntryTitle = false;
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
</pre>The <code>characters</code> method is invoked when the parser encounters
|
||||
character data inside an XML element. If we are inside the
|
||||
<code><title></code> tag, that is, if the <code>insideEntryTitle</code>
|
||||
flag is on, we display the current characters: <code>length</code> characters
|
||||
from the <code>ch</code> array, starting with <code>start</code>. As noted
|
||||
earlier, we can't use <code>println</code> here to get to a new line, as <code>
|
||||
characters</code> can be invoked multiple times for different chunks of the
|
||||
same title:
|
||||
<pre>
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
if (insideEntryTitle) {
|
||||
System.out.print(new String(ch, start, length));
|
||||
}
|
||||
}
|
||||
</pre>In the <code>main</code> method, all we do is create a
|
||||
<code>QueryExample2</code> instance, and invoke its <code>displayItems</code>
|
||||
method:
|
||||
<pre>
|
||||
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
|
||||
new QueryExample2().displayItems();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="queryExample3" id="queryExample3"></a>Query Example 3 -
|
||||
Introducing authentication. Querying your own items using the items
|
||||
feed.</h2>
|
||||
|
||||
<p>The previous two examples demonstrated how to query the Google Base data
|
||||
API public feeds, also known as snippets. Snippets are accessible to anyone
|
||||
without authentication. The downside is that snippets are the "indexable"
|
||||
version of the items and can slightly differ from the original items. It can
|
||||
also take a while for a newly inserted or updated item to show up in the
|
||||
snippets feed. Therefore, if you need to change your own items, the Google
|
||||
Base data API server exposes the customer-specific "items" feed. This feed is
|
||||
very similar to the "snippets" feed, except that:</p>
|
||||
|
||||
<ul>
|
||||
<li>it only allows you to query your own items, and thus you need to
|
||||
authenticate in order to access it</li>
|
||||
|
||||
<li>there is no delay between updating an item and being able to display it
|
||||
in the "items" feed</li>
|
||||
</ul>Read <a href='http://code.google.com/apis/base/items-feed.html'>here</a>
|
||||
more about the characteristics of the "items" feed. You will need a Google
|
||||
Account email and password in order to run this example. If you don't have a
|
||||
Google Account, sign up for one <a href=
|
||||
'https://www.google.com/accounts/NewAccount'>here</a>.
|
||||
|
||||
<p>QueryExample3 connects to your "items" feed, and dumps your items to the
|
||||
console, just as in <code>QueryExample1</code>. If you don't have any items
|
||||
in Google Base yet, use <a href='#insertRun'>InsertExample</a> to insert one,
|
||||
or go to the <a href='http://base.google.com/base/step1offer?hl=en_US'>Google
|
||||
Base Provider Frontenac</a> and insert one.</p>
|
||||
|
||||
<h3><a name="QE3run" id="QE3run"></a>Running <code>QueryExample3</code></h3>
|
||||
|
||||
<ol>
|
||||
<li>Edit QueryExample3.java and make the following changes:
|
||||
|
||||
<ul>
|
||||
<li>Enter your Google Accounts email address and your password in the
|
||||
<code>EMAIL</code> and <code>PASSWORD</code> static strings:
|
||||
<pre>
|
||||
private static final String EMAIL = "";
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Compile and run the example using your favorite editor, or the command
|
||||
line:
|
||||
<pre>
|
||||
javac sample.gbase/basic/QueryExample3.java
|
||||
java sample.gbase/basic/QueryExample3
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>The output will look like:
|
||||
<pre>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<feed>
|
||||
<id>http://base.google.com/base/feeds/items</id>
|
||||
<updated>2006-08-22T12:00:00.000Z</updated>
|
||||
<title type="text">Items matching query: [customer id(int):1870031]</title>
|
||||
...
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3><a name="QE3stepThru" id="QE3stepThru"></a>Stepping through the
|
||||
<code>QueryExample3</code> code</h3>
|
||||
|
||||
<p>As opposed to the previous examples, here we need to obtain an
|
||||
authorization token by authenticating with the Google Accounts server. We
|
||||
then use this authorization token to invoke <code>displayMyItems</code>:</p>
|
||||
<pre>
|
||||
public static void main(String[] args) throws IOException {
|
||||
QueryExample3 queryExample = new QueryExample3();
|
||||
String token = queryExample.authenticate();
|
||||
new QueryExample3().displayMyItems(token);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>We authenticate using <a href=
|
||||
'http://code.google.com/apis/accounts/AuthForInstalledApps.html'>authentication
|
||||
for installed applications</a>. The authentication procedure is simple. We
|
||||
make a POST request to <code>AUTHENTICATION_URL</code>:</p>
|
||||
<pre>
|
||||
private static final String AUTHENTICATION_URL = "https://www.google.com/accounts/ClientLogin";
|
||||
</pre>The POST request is constructed in <code>makeLoginRequest</code>, and it
|
||||
looks like this:
|
||||
<pre>
|
||||
// POST /accounts/ClientLogin HTTP/1.0
|
||||
// Content-type: application/x-www-form-urlencoded
|
||||
// Email=johndoe@gmail.com&Passwd=north23AZ&service=gbase&source=Insert Example
|
||||
</pre><code>makeLoginRequest</code> sends the request to the Google Accounts
|
||||
server and returns the response as a <code>String</code>. A successful response
|
||||
will have the following structure:
|
||||
<pre>
|
||||
// HTTP/1.0 200 OK
|
||||
// Server: GFE/1.3
|
||||
// Content-Type: text/plain
|
||||
// SID=DQAAAGgA...7Zg8CTN
|
||||
// LSID=DQAAAGsA...lk8BBbG
|
||||
// Auth=DQAAAGgA...dk3fA5N
|
||||
</pre><code>authenticate</code> first obtains the authentication response from
|
||||
<code>makeLoginRequest</code> and stores it in <code>postOutput</code>:
|
||||
<pre>
|
||||
String postOutput = null;
|
||||
try {
|
||||
URL url = new URL(AUTHENTICATION_URL);
|
||||
postOutput = makeLoginRequest(url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Authentication error: " + e.toString());
|
||||
}
|
||||
</pre>It then tokenizes <code>postOutput</code>, and returns the next token
|
||||
after "Auth", or <code>null</code> if the token is not found:
|
||||
<pre>
|
||||
StringTokenizer tokenizer = new StringTokenizer(postOutput, "=\n ");
|
||||
String token = null;
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
if (tokenizer.nextToken().equals("Auth")) {
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
token = tokenizer.nextToken();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
</pre><br />
|
||||
<br />
|
||||
|
||||
<p>The items are displayed in <code>displayMyItems</code>, which is very
|
||||
similar to <code>displayItems</code> in QueryExample1, except that it injects
|
||||
the authorization token in the Http header (as in this example):</p>
|
||||
<pre>
|
||||
connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
|
||||
</pre>
|
||||
|
||||
<h2><a name="insertExample" id="insertExample"></a>Insert Example - Adding
|
||||
your own item to Google Base.</h2>
|
||||
|
||||
<p>The previous examples demonstrated how to query the Google Base data API
|
||||
server, both for snippets (unauthenticated feeds) and for items
|
||||
(authenticated feeds, containing a specific customer's items). Let's
|
||||
demonstrate now how to add to Google Base all the cool stuff you have, so
|
||||
that the world can see it. Again, you will need a Google Account email and
|
||||
password in order to run this example. If you don't have a Google Account,
|
||||
sign up for one <a href=
|
||||
'https://www.google.com/accounts/NewAccount'>here</a>.</p>
|
||||
|
||||
<p>In this example we will connect to your "items" feed, and do an Http POST
|
||||
operation (as opposed to GET, used for querying) to add a new item. The item
|
||||
to be added is encoded in Atom format, and is defined a <code>String</code>
|
||||
constant:</p>
|
||||
<pre>
|
||||
private static final String DATA_ITEM =
|
||||
"<?xml version=\'1.0\'?>\n" +
|
||||
"<entry xmlns=\'http://www.w3.org/2005/Atom\' xmlns:g=\'http://base.google.com/ns/1.0\'>\n" +
|
||||
" <category scheme=\'http://base.google.com/categories/itemtypes\' term=\'Products\'/>\n" +
|
||||
" <g:item_type type=\'text\'>Products</g:item_type>\n" +
|
||||
" <title type=\'text\'>My cool car is for sale</title>" +
|
||||
" <content type=\'xhtml\'>Light pink, yellow seats.</content>" +
|
||||
"</entry>";
|
||||
</pre>It's a very simple item, consisting only of an item type ("products", in
|
||||
our case), a title and a content (description). Feel free to change these
|
||||
fields to contain your personalized items or to add new attributes and labels
|
||||
(use the responses dumped by <code>QueryExample1</code> and
|
||||
<code>QueryExample3</code> as an inspiration for adding new attributes).
|
||||
|
||||
<h3><a name="insertRun" id="insertRun"></a>Running
|
||||
<code>InsertExample</code></h3>
|
||||
|
||||
<ol>
|
||||
<li>Edit InsertExample.java and make the following changes:
|
||||
|
||||
<ul>
|
||||
<li>Enter your Google Accounts email address and your password in the
|
||||
<code>EMAIL</code> and <code>PASSWORD</code> static strings:
|
||||
<pre>
|
||||
private static final String EMAIL = "";
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Compile and run the example using your favorite editor, or the command
|
||||
line:
|
||||
<pre>
|
||||
javac sample.gbase/basic/InsertExample.java
|
||||
java sample.gbase/basic/InsertExample
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>The output will look like:
|
||||
<pre>
|
||||
Obtained authorization token: DQAAAGgA...dk3fA5N
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<entry>
|
||||
<id>http://base.google.com/base/feeds/items/16024998325761524417</id>
|
||||
<published>2006-08-23T15:18:55.184Z</published>
|
||||
<updated>2006-08-23T15:18:55.184Z</updated>
|
||||
<category scheme="http://base.google.com/categories/itemtypes" term="Products"/>
|
||||
<title type="text">My cool car is for sale</title>
|
||||
<content type="xhtml">Light pink, yellow seats.</content>
|
||||
<link rel="self" type="application/atom+xml" href="http://base.google.com/base/feeds/items/16024998325761524417"/>
|
||||
<link rel="edit" type="application/atom+xml" href="http://base.google.com/base/feeds/items/16024998325761524417"/>
|
||||
<g:item_type type="text">Products</g:item_type>
|
||||
</entry>
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3><a name="InsertStepThru" id="InsertStepThru"></a>Stepping through the
|
||||
<code>InsertExample</code> code</h3>
|
||||
|
||||
<p>We use the same feed as in QueryExample3.java to insert the item:</p>
|
||||
<pre>
|
||||
private static final String ITEMS_FEED = "http://base.google.com/base/feeds/items";
|
||||
</pre>Authentication is also performed as in <a href=
|
||||
'#QE3stepThru'>QueryExample3</a>, using <code>makeLoginRequest</code> to
|
||||
request an authorization token and <code>authenticate</code> to parse the
|
||||
authentication response. The insertion of the new data item is done in
|
||||
<code>postItem</code>, which connects to the items feed:
|
||||
<pre>
|
||||
HttpURLConnection connection = (HttpURLConnection)(new URL(ITEMS_FEED)).openConnection();
|
||||
</pre>Once the connection is created, we need to set its properties: the Http
|
||||
request method, the content type of the information that is being posted, the
|
||||
authorization header:
|
||||
<pre>
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/atom+xml");
|
||||
connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
|
||||
</pre>We then obtain the output stream of the connection and dump
|
||||
<code>DATA_ITEM</code> into it:
|
||||
<pre>
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(DATA_ITEM.getBytes());
|
||||
outputStream.close();
|
||||
</pre>The rest of the method is already familiar: we obtain the response code
|
||||
and print out to the console the contents of the input stream corresponding to
|
||||
the response code.<br />
|
||||
<br />
|
||||
|
||||
<h2><a name="updateExample" id="updateExample"></a>Update Example - Modifying
|
||||
your Google Base items.</h2>
|
||||
|
||||
<p>The previous examples demonstrated how to query the Google Base data API
|
||||
server both for authenticated and unauthenticated feeds and how to insert a
|
||||
new item. We will combine this knowledge in order to demonstrate how to
|
||||
update an already existing item. Again, you will need a Google Account email
|
||||
and password in order to run this example. If you don't have a Google
|
||||
Account, sign up for one <a href=
|
||||
'https://www.google.com/accounts/NewAccount'>here</a>. This example does not
|
||||
introduce important new concepts, but rather uses all the essentials that
|
||||
have been presented in the previous examples: we will authenticate, insert an
|
||||
item, and then update the inserted item by adding a new label to it.</p>
|
||||
|
||||
<h3><a name="updateRun" id="updateRun"></a>Running
|
||||
<code>UpdateExample</code></h3>
|
||||
|
||||
<ol>
|
||||
<li>Edit UpdateExample.java and make the following changes:
|
||||
|
||||
<ul>
|
||||
<li>Enter your Google Accounts email address and your password in the
|
||||
<code>EMAIL</code> and <code>PASSWORD</code> static strings:
|
||||
<pre>
|
||||
private static final String EMAIL = "";
|
||||
private static final String PASSWORD = "";
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Compile and run the example using your favorite editor, or the command
|
||||
line:
|
||||
<pre>
|
||||
javac sample.gbase/basic/UpdateExample.java
|
||||
java sample.gbase/basic/UpdateExample
|
||||
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>The output will look like:
|
||||
<pre>
|
||||
Obtained authorization token: DQAAAGgA...dk3fA5N
|
||||
Posting item:
|
||||
<?xml version='1.0'?>
|
||||
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:g='http://base.google.com/ns/1.0'>
|
||||
<category scheme='http://base.google.com/categories/itemtypes' term='Products'/>
|
||||
<g:item_type type='text'>Products</g:item_type>
|
||||
<title type='text'>My cool car is for sale</title>
|
||||
<content type='xhtml'>Light pink, yellow seats.</content>
|
||||
</entry>
|
||||
|
||||
Updating item: http://base.google.com/base/feeds/items/18020038538902937385
|
||||
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<entry>
|
||||
<id>http://base.google.com/base/feeds/items/18020038538902937385</id>
|
||||
<updated>2006-08-23T16:20:21.601Z</updated>
|
||||
<category scheme="http://base.google.com/categories/itemtypes" term="Products"/>
|
||||
<title type="text">My cool car is for sale</title>
|
||||
<content type="xhtml">Light pink, yellow seats.</content>
|
||||
<link rel="self" type="application/atom+xml" href="http://base.google.com/base/feeds/items/18020038538902937385"/>
|
||||
<link rel="edit" type="application/atom+xml" href="http://base.google.com/base/feeds/items/18020038538902937385"/>
|
||||
<g:item_type type="text">Products</g:item_type>
|
||||
</entry>
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3><a name="UpdateStepThru" id="UpdateStepThru"></a>Stepping through the
|
||||
<code>UpdateExample</code> code</h3>
|
||||
|
||||
<p>The <code>main</code> method of <code>UpdateExample</code> provides a good
|
||||
outline of the example's structure:</p>
|
||||
<pre>
|
||||
public static void main(String[] args) throws MalformedURLException, IOException {
|
||||
UpdateExample updateExample = new UpdateExample();
|
||||
String token = updateExample.authenticate();
|
||||
System.out.println("Obtained authorization token: " + token);
|
||||
|
||||
System.out.println("Posting item:\n" + DATA_ITEM);
|
||||
String itemUrl = updateExample.extractItemUrlFromResponse(
|
||||
updateExample.postItem(token));
|
||||
|
||||
System.out.println("Updating item: " + itemUrl);
|
||||
String updateResponse = updateExample.updateItem(token, itemUrl);
|
||||
System.out.println(updateResponse);
|
||||
}
|
||||
</pre>Just like in the previous examples, we start by authenticating and
|
||||
obtaining an authorization token using the <code>authenticate</code> method:
|
||||
<pre>
|
||||
String token = updateExample.authenticate();
|
||||
</pre>We then insert <code>DATA_ITEM</code> using <code>postItem</code>:
|
||||
<pre>
|
||||
String itemUrl = updateExample.extractItemUrlFromResponse(
|
||||
updateExample.postItem(token));
|
||||
</pre>In the line above, we pass the output of the post operation
|
||||
to<code>extractItemUrlFromResponse</code> (rather than dumping it out to the
|
||||
console), which extracts the inserted item's id:
|
||||
<pre>
|
||||
<id>http://base.google.com/base/feeds/items/18020038538902937385</id>
|
||||
</pre>We assume that the item's id is surrounded by the first
|
||||
<id></id> tags; this is true for the Google Base data API servers,
|
||||
but it's not enforced by the Atom protocol. See how the title gets parsed in
|
||||
<a href='#QE2stepThru'>Query Example 2</a>, for a superior approach on parsing
|
||||
the item's title.
|
||||
|
||||
<p>Once <code>DATA_ITEM</code> is successfully inserted, we replace it with
|
||||
<code>NEW_DATA_ITEM</code> using <code>updateItem</code>. Updating an item is
|
||||
very similar to inserting a new one - in fact so similar that both operations
|
||||
can be performed by the same method: <code>makeHttpRequest</code>.
|
||||
<code>makeHttpRequest</code> receives as parameters the authorization token,
|
||||
the url to connect to, the item to be inserted or posted, the http method to
|
||||
use (this will be POST for inserting, and PUT for deleting) and the response
|
||||
code to expect in case of a successful operation (HTTP_CREATED in case of
|
||||
insert, HTTP_OK in case of update). Thus, <code>postItem</code> will contain
|
||||
a simple invocation to <code>makeHttpRequest</code>:</p>
|
||||
<pre>
|
||||
public String postItem(String token) throws IOException {
|
||||
return makeHttpRequest(token, ITEMS_FEED, NEW_DATA_ITEM, "POST", HttpURLConnection.HTTP_CREATED);
|
||||
}
|
||||
|
||||
</pre>Similarly, <code>updateItem</code> invokes <code>makeHttpRequest</code>
|
||||
with slightly different parameters:
|
||||
<pre>
|
||||
public String updateItem(String token, String itemUrl) throws MalformedURLException, IOException {
|
||||
return makeHttpRequest(token, itemUrl, NEW_DATA_ITEM, "PUT", HttpURLConnection.HTTP_OK);
|
||||
}
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user