/*
* Copyright (c) 2010, Thomas F. Morris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Google nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine.extension.gdata;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.refine.util.ParsingUtilities;
import edu.mit.simile.butterfly.ButterflyModule;
/**
* @author Tom Morris <tfmorris@gmail.com>
* @copyright 2010 Thomas F. Morris
* @license New BSD http://www.opensource.org/licenses/bsd-license.php
*/
abstract public class GDataExtension {
static final String SERVICE_APP_NAME = "OpenRefine-GData-Extension";
static final String CLIENT_ID = "647865400439.apps.googleusercontent.com";
static final String CLIENT_SECRET = "0mW9OJji1yrgJk5AjJc5Pn6I"; // not really that secret, but the protocol accounts for that
/** Global instance of the HTTP transport. */
static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
/** Global instance of the JSON factory. */
static final JsonFactory JSON_FACTORY = new JacksonFactory();
static public String getAuthorizationUrl(ButterflyModule module, HttpServletRequest request)
throws MalformedURLException {
String authorizedUrl = makeRedirectUrl(module, request);
// New Oauth2
GoogleAuthorizationCodeRequestUrl url = new GoogleAuthorizationCodeRequestUrl(
CLIENT_ID,
authorizedUrl, // execution continues at authorized on redirect
Arrays.asList("https://www.googleapis.com/auth/fusiontables",
"https://www.googleapis.com/auth/drive", // create new spreadsheets
"https://spreadsheets.google.com/feeds"));
return url.toString();
}
private static String makeRedirectUrl(ButterflyModule module, HttpServletRequest request)
throws MalformedURLException {
StringBuffer sb = new StringBuffer(module.getMountPoint().getMountPoint());
sb.append("authorized?winname=");
sb.append(ParsingUtilities.encode(request.getParameter("winname")));
sb.append("&cb=");
sb.append(ParsingUtilities.encode(request.getParameter("cb")));
URL thisUrl = new URL(request.getRequestURL().toString());
URL authorizedUrl = new URL(thisUrl, sb.toString());
return authorizedUrl.toExternalForm();
}
static public String getTokenFromCode(ButterflyModule module, HttpServletRequest request)
throws MalformedURLException {
String redirectUrl = makeRedirectUrl(module, request);
StringBuffer fullUrlBuf = request.getRequestURL();
if (request.getQueryString() != null) {
fullUrlBuf.append('?').append(request.getQueryString());
}
AuthorizationCodeResponseUrl authResponse =
new AuthorizationCodeResponseUrl(fullUrlBuf.toString());
// check for user-denied error
if (authResponse.getError() != null) {
// authorization denied...
} else {
// request access token using authResponse.getCode()...
String code = authResponse.getCode();
try {
GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(HTTP_TRANSPORT,
JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, code, redirectUrl).execute();
String token = response.getAccessToken();
return token;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
static public DocsService getDocsService(String token) {
DocsService service = new DocsService(SERVICE_APP_NAME);
if (token != null) {
service.setAuthSubToken(token);
}
return service;
}
static public SpreadsheetService getSpreadsheetService(String token) {
SpreadsheetService service = new SpreadsheetService(SERVICE_APP_NAME);
if (token != null) {
service.setAuthSubToken(token);
}
return service;
}
static public Drive getDriveService(String token) {
GoogleCredential credential = new GoogleCredential().setAccessToken(token);
return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(SERVICE_APP_NAME).build();
}
static boolean isSpreadsheetURL(String url) {
// e.g. http://spreadsheets.google.com/ccc?key=tI36b9Fxk1lFBS83iR_3XQA&hl=en
// TODO: The following should work, but the GData implementation is too limited
// try {
// FeedURLFactory.getSpreadsheetKeyFromUrl(url);
// return true;
// } catch (IllegalArgumentException e) {
// return false;
// }
try {
return url.contains("spreadsheet") && getSpreadsheetID(new URL(url)) != null;
} catch (MalformedURLException e) {
return false;
}
}
static String getSpreadsheetID(URL url) {
return getParamValue(url,"key");
}
static private String getParamValue(URL url, String key) {
String query = url.getQuery();
if (query != null) {
String[] parts = query.split("&");
for (String part : parts) {
if (part.startsWith(key+"=")) {
int offset = key.length()+1;
String tableId = part.substring(offset);
return tableId;
}
}
}
return null;
}
}