Issue 461 - Add support for public Google Spreadsheets and ability to sign-out.
Kind of messy, but I don't think any of the previously existing functionality is broken. git-svn-id: http://google-refine.googlecode.com/svn/trunk@2375 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
6692a968be
commit
c07046f542
@ -40,9 +40,6 @@ var ClientSideResourceManager = Packages.com.google.refine.ClientSideResourceMan
|
|||||||
* Function invoked to initialize the extension.
|
* Function invoked to initialize the extension.
|
||||||
*/
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
//Packages.java.lang.System.err.println("Initializing gData extension");
|
|
||||||
//Packages.java.lang.System.err.println(module.getMountPoint());
|
|
||||||
|
|
||||||
var RS = Packages.com.google.refine.RefineServlet;
|
var RS = Packages.com.google.refine.RefineServlet;
|
||||||
RS.registerCommand(module, "deauthorize", Packages.com.google.refine.extension.gdata.DeAuthorizeCommand());
|
RS.registerCommand(module, "deauthorize", Packages.com.google.refine.extension.gdata.DeAuthorizeCommand());
|
||||||
RS.registerCommand(module, "upload", Packages.com.google.refine.extension.gdata.UploadCommand());
|
RS.registerCommand(module, "upload", Packages.com.google.refine.extension.gdata.UploadCommand());
|
||||||
|
@ -53,7 +53,46 @@ Refine.GDataSourceUI.prototype.attachUI = function(body) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
this._body.find('.gdata-signout.button').click(function() {
|
||||||
|
$.get("/command/gdata/deauthorize" );
|
||||||
|
self._body.find('.gdata-page').hide();
|
||||||
|
self._elmts.signinPage.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
var importURL1 = function(evt) {
|
||||||
|
if ($.trim(self._elmts.urlInput1[0].value).length === 0) {
|
||||||
|
window.alert("You must specify a web address (URL) to import.");
|
||||||
|
} else {
|
||||||
|
var doc={}
|
||||||
|
doc.docSelfLink = self._elmts.urlInput1[0].value;
|
||||||
|
if (doc.docSelfLink.contains('spreadsheet')) { // TODO: fragile?
|
||||||
|
doc.type = 'spreadsheet';
|
||||||
|
} else {
|
||||||
|
doc.type = 'table';
|
||||||
|
}
|
||||||
|
self._controller.startImportingDocument(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Consolidate these two URL input forms
|
||||||
|
var importURL2 = function(evt) {
|
||||||
|
if ($.trim(self._elmts.urlInput2[0].value).length === 0) {
|
||||||
|
window.alert("You must specify a web address (URL) to import.");
|
||||||
|
} else {
|
||||||
|
var doc={}
|
||||||
|
doc.docSelfLink = self._elmts.urlInput2[0].value;
|
||||||
|
if (doc.docSelfLink.contains('spreadsheet')) { // TODO: fragile?
|
||||||
|
doc.type = 'spreadsheet';
|
||||||
|
} else {
|
||||||
|
doc.type = 'table';
|
||||||
|
}
|
||||||
|
self._controller.startImportingDocument(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._elmts.urlNextButton1.click(importURL1);
|
||||||
|
this._elmts.urlNextButton2.click(importURL2);
|
||||||
|
|
||||||
|
|
||||||
this._body.find('.gdata-page').hide();
|
this._body.find('.gdata-page').hide();
|
||||||
this._elmts.signinPage.show();
|
this._elmts.signinPage.show();
|
||||||
|
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
<div>
|
<div>
|
||||||
<div bind="signinPage" class="gdata-page">
|
<div bind="signinPage" class="gdata-page">
|
||||||
<p>Please <button class="gdata-signin button button-primary">sign in and authorize</button>
|
<p>Please <button class="gdata-signin button button-primary">sign in and authorize</button>
|
||||||
access to your Google data.</p>
|
access to your Google data.</p></tr>
|
||||||
|
<form bind="form"><div class="grid-layout layout-normal"><table>
|
||||||
|
<tr><td colspan="2">Or enter web address (URL) of a <em>public</em> Google Spreadsheet or Fusion Table below and click Next:</td></tr>
|
||||||
|
<tr bind="urlRow"><td colspan="2"><input bind="urlInput1" name="download" class="default-importing-web-url" /></td></tr>
|
||||||
|
<tr bind="buttons">
|
||||||
|
<td><button bind="urlNextButton1" class="button button-primary" type="button">Next »</button></td>
|
||||||
|
</tr>
|
||||||
|
</table></div></form>
|
||||||
</div>
|
</div>
|
||||||
<div bind="progressPage" class="gdata-page">
|
<div bind="progressPage" class="gdata-page">
|
||||||
<p><img src="images/large-spinner.gif" /> Retrieving Google Docs documents ...</p>
|
<p><img src="images/large-spinner.gif" /> Retrieving Google Docs documents ...</p>
|
||||||
@ -9,8 +16,16 @@
|
|||||||
<div bind="listingPage" class="gdata-page grid-layout layout-full layout-normal"><table>
|
<div bind="listingPage" class="gdata-page grid-layout layout-full layout-normal"><table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Google Docs documents</td>
|
<td>Google Docs documents</td>
|
||||||
<td style="text-align: right;"><button class="gdata-signin button">re-sign in</button> with another account</td>
|
<td style="text-align: center;"><button class="gdata-signin button">re-sign in</button> with another account</td>
|
||||||
|
<td style="text-align: right;"><button class="gdata-signout button">sign out</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td colspan="2"><div bind="listingContainer" class="grid-layout layout-tight gdata-document-container"></div></td></tr>
|
<tr><td colspan="2">Click one of the documents below or enter the web address (URL) of a <em>public</em> Google Spreadsheet or Fusion Table and click "Next":</td></tr>
|
||||||
|
<tr bind="urlRow"><td colspan="2">
|
||||||
|
<form bind="form">
|
||||||
|
<input bind="urlInput2" name="download" class="default-importing-web-url" /></td>
|
||||||
|
</form>
|
||||||
|
<td bind="buttons"><button bind="urlNextButton2" class="button button-primary" type="button">Next »</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td colspan="3"><div bind="listingContainer" class="grid-layout layout-tight gdata-document-container"></div></td></tr>
|
||||||
</table></div>
|
</table></div>
|
||||||
</div>
|
</div>
|
@ -95,19 +95,25 @@ abstract public class GDataExtension {
|
|||||||
|
|
||||||
static public DocsService getDocsService(String token) {
|
static public DocsService getDocsService(String token) {
|
||||||
DocsService service = new DocsService(SERVICE_APP_NAME);
|
DocsService service = new DocsService(SERVICE_APP_NAME);
|
||||||
service.setAuthSubToken(token);
|
if (token != null) {
|
||||||
|
service.setAuthSubToken(token);
|
||||||
|
}
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public SpreadsheetService getSpreadsheetService(String token) {
|
static public SpreadsheetService getSpreadsheetService(String token) {
|
||||||
SpreadsheetService service = new SpreadsheetService(SERVICE_APP_NAME);
|
SpreadsheetService service = new SpreadsheetService(SERVICE_APP_NAME);
|
||||||
service.setAuthSubToken(token);
|
if (token != null) {
|
||||||
|
service.setAuthSubToken(token);
|
||||||
|
}
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public GoogleService getFusionTablesGoogleService(String token) {
|
static public GoogleService getFusionTablesGoogleService(String token) {
|
||||||
GoogleService service = new GoogleService("fusiontables", SERVICE_APP_NAME);
|
GoogleService service = new GoogleService("fusiontables", SERVICE_APP_NAME);
|
||||||
service.setAuthSubToken(token);
|
if (token != null) {
|
||||||
|
service.setAuthSubToken(token);
|
||||||
|
}
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,4 +184,60 @@ abstract public class GDataExtension {
|
|||||||
}
|
}
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isFusionTableURL(URL url) {
|
||||||
|
// http://www.google.com/fusiontables/DataSource?dsrcid=1219
|
||||||
|
String query = url.getQuery();
|
||||||
|
if (query == null) {
|
||||||
|
query = "";
|
||||||
|
}
|
||||||
|
return url.getHost().endsWith(".google.com")
|
||||||
|
&& url.getPath().startsWith("/fusiontables/DataSource")
|
||||||
|
&& query.contains("dsrcid=");
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getFusionTableKey(URL url) {
|
||||||
|
String tableId = getParamValue(url,"dsrcid");
|
||||||
|
// TODO: Any special id format considerations to worry about?
|
||||||
|
// if (tableId.startsWith("p") || !tableId.contains(".")) {
|
||||||
|
// return tableId;
|
||||||
|
// }
|
||||||
|
return tableId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,10 +138,16 @@ public class GDataImporter {
|
|||||||
List<Exception> exceptions) {
|
List<Exception> exceptions) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SpreadsheetEntry spreadsheetEntry = service.getEntry(docURL, SpreadsheetEntry.class);
|
|
||||||
WorksheetEntry worksheetEntry = service.getEntry(worksheetURL, WorksheetEntry.class);
|
WorksheetEntry worksheetEntry = service.getEntry(worksheetURL, WorksheetEntry.class);
|
||||||
|
String spreadsheetName = docURL.toExternalForm();
|
||||||
|
try {
|
||||||
|
SpreadsheetEntry spreadsheetEntry = service.getEntry(docURL, SpreadsheetEntry.class);
|
||||||
|
spreadsheetName = spreadsheetEntry.getTitle().getPlainText();
|
||||||
|
} catch (ServiceException e) { // RedirectRequiredException among others
|
||||||
|
// fall back to just using the URL (better for traceability anyway?)
|
||||||
|
}
|
||||||
|
|
||||||
String fileSource = spreadsheetEntry.getTitle().getPlainText() + " # " +
|
String fileSource = spreadsheetName + " # " +
|
||||||
worksheetEntry.getTitle().getPlainText();
|
worksheetEntry.getTitle().getPlainText();
|
||||||
|
|
||||||
setProgress(job, fileSource, 0);
|
setProgress(job, fileSource, 0);
|
||||||
@ -283,15 +289,8 @@ public class GDataImporter {
|
|||||||
List<Exception> exceptions) {
|
List<Exception> exceptions) {
|
||||||
|
|
||||||
String docUrlString = JSONUtilities.getString(options, "docUrl", null);
|
String docUrlString = JSONUtilities.getString(options, "docUrl", null);
|
||||||
if (docUrlString == null) {
|
String id = getFTid(docUrlString); // Use GDataExtension.getFusionTableKey(url) ?
|
||||||
return;
|
// TODO: Allow arbitrary Fusion Tables URL instead of (in addition to?) constructing our own?
|
||||||
}
|
|
||||||
int equal = docUrlString.lastIndexOf('=');
|
|
||||||
if (equal < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String id = docUrlString.substring(equal + 1);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<FTColumnData> columns = new ArrayList<GDataImporter.FTColumnData>();
|
List<FTColumnData> columns = new ArrayList<GDataImporter.FTColumnData>();
|
||||||
@ -346,6 +345,17 @@ public class GDataImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static private String getFTid(String url) {
|
||||||
|
if (url == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int equal = url.lastIndexOf('=');
|
||||||
|
if (equal < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return url.substring(equal + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static private enum FTColumnType {
|
static private enum FTColumnType {
|
||||||
STRING,
|
STRING,
|
||||||
NUMBER,
|
NUMBER,
|
||||||
|
@ -51,12 +51,14 @@ import org.json.JSONWriter;
|
|||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
import com.google.gdata.client.GoogleService;
|
||||||
import com.google.gdata.client.docs.DocsService;
|
import com.google.gdata.client.docs.DocsService;
|
||||||
|
import com.google.gdata.client.spreadsheet.FeedURLFactory;
|
||||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||||
import com.google.gdata.data.DateTime;
|
import com.google.gdata.data.DateTime;
|
||||||
import com.google.gdata.data.Person;
|
import com.google.gdata.data.Person;
|
||||||
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
|
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
|
||||||
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
|
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
|
||||||
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
||||||
|
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
||||||
import com.google.gdata.util.ServiceException;
|
import com.google.gdata.util.ServiceException;
|
||||||
|
|
||||||
import com.google.refine.ProjectManager;
|
import com.google.refine.ProjectManager;
|
||||||
@ -83,7 +85,7 @@ public class GDataImportingController implements ImportingController {
|
|||||||
@Override
|
@Override
|
||||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
// TODO Auto-generated method stub
|
HttpUtilities.respond(response, "error", "GET not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -193,11 +195,7 @@ public class GDataImportingController implements ImportingController {
|
|||||||
HttpServletRequest request, HttpServletResponse response, Properties parameters)
|
HttpServletRequest request, HttpServletResponse response, Properties parameters)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
String token = TokenCookie.getToken(request);
|
String token = TokenCookie.getToken(request); // authorization token, if logged in
|
||||||
if (token == null) {
|
|
||||||
HttpUtilities.respond(response, "error", "Not authorized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String type = parameters.getProperty("docType");
|
String type = parameters.getProperty("docType");
|
||||||
String urlString = parameters.getProperty("docUrl");
|
String urlString = parameters.getProperty("docUrl");
|
||||||
@ -220,8 +218,19 @@ public class GDataImportingController implements ImportingController {
|
|||||||
JSONUtilities.safePut(options, "worksheets", worksheets);
|
JSONUtilities.safePut(options, "worksheets", worksheets);
|
||||||
|
|
||||||
SpreadsheetService spreadsheetService = GDataExtension.getSpreadsheetService(token);
|
SpreadsheetService spreadsheetService = GDataExtension.getSpreadsheetService(token);
|
||||||
SpreadsheetEntry spreadsheetEntry = spreadsheetService.getEntry(url, SpreadsheetEntry.class);
|
List<WorksheetEntry> worksheetEntries;
|
||||||
for (WorksheetEntry worksheetEntry : spreadsheetEntry.getWorksheets()) {
|
if (token == null) {
|
||||||
|
String visibility = "public";
|
||||||
|
FeedURLFactory factory = FeedURLFactory.getDefault();
|
||||||
|
String key = GDataExtension.getSpreadsheetID(url);
|
||||||
|
url = factory.getWorksheetFeedUrl(key, visibility, "values");
|
||||||
|
WorksheetFeed feed = spreadsheetService.getFeed(url, WorksheetFeed.class);
|
||||||
|
worksheetEntries = feed.getEntries();
|
||||||
|
} else {
|
||||||
|
SpreadsheetEntry spreadsheetEntry = spreadsheetService.getEntry(url, SpreadsheetEntry.class);
|
||||||
|
worksheetEntries = spreadsheetEntry.getWorksheets();
|
||||||
|
}
|
||||||
|
for (WorksheetEntry worksheetEntry : worksheetEntries) {
|
||||||
JSONObject worksheetO = new JSONObject();
|
JSONObject worksheetO = new JSONObject();
|
||||||
JSONUtilities.safePut(worksheetO, "name", worksheetEntry.getTitle().getPlainText());
|
JSONUtilities.safePut(worksheetO, "name", worksheetEntry.getTitle().getPlainText());
|
||||||
JSONUtilities.safePut(worksheetO, "rows", worksheetEntry.getRowCount());
|
JSONUtilities.safePut(worksheetO, "rows", worksheetEntry.getRowCount());
|
||||||
@ -246,12 +255,7 @@ public class GDataImportingController implements ImportingController {
|
|||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
String token = TokenCookie.getToken(request);
|
String token = TokenCookie.getToken(request);
|
||||||
if (token == null) {
|
|
||||||
HttpUtilities.respond(response, "error", "Not authorized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
long jobID = Long.parseLong(parameters.getProperty("jobID"));
|
long jobID = Long.parseLong(parameters.getProperty("jobID"));
|
||||||
ImportingJob job = ImportingManager.getJob(jobID);
|
ImportingJob job = ImportingManager.getJob(jobID);
|
||||||
if (job == null) {
|
if (job == null) {
|
||||||
@ -317,10 +321,6 @@ public class GDataImportingController implements ImportingController {
|
|||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
final String token = TokenCookie.getToken(request);
|
final String token = TokenCookie.getToken(request);
|
||||||
if (token == null) {
|
|
||||||
HttpUtilities.respond(response, "error", "Not authorized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long jobID = Long.parseLong(parameters.getProperty("jobID"));
|
long jobID = Long.parseLong(parameters.getProperty("jobID"));
|
||||||
final ImportingJob job = ImportingManager.getJob(jobID);
|
final ImportingJob job = ImportingManager.getJob(jobID);
|
||||||
|
Loading…
Reference in New Issue
Block a user