- Add preferences to connector. Debug logging does not yet work

- Add rudimentary connector API version checks, although I still need a good way of showing that the connector/server is out of date
- Throw new Error() in translate (so that we get a stack trace)
- Log errors in connector
This commit is contained in:
Simon Kornblith 2011-06-28 18:24:24 +00:00
parent dda8551a22
commit 0d7ffcc1c1
5 changed files with 135 additions and 25 deletions

View file

@ -22,8 +22,10 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
Zotero.Connector = new function() { Zotero.Connector = new function() {
const CONNECTOR_URI = "http://127.0.0.1:23119/"; const CONNECTOR_URI = "http://127.0.0.1:23119/";
const CONNECTOR_SERVER_API_VERSION = 1;
this.isOnline = true; this.isOnline = true;
this.haveRefreshedData = false; this.haveRefreshedData = false;
@ -36,6 +38,18 @@ Zotero.Connector = new function() {
Zotero.Connector.getData(); Zotero.Connector.getData();
} }
/**
* Checks if Zotero is online and passes current status to callback
* @param {Function} callback
*/
this.checkIsOnline = function(callback) {
if(Zotero.Connector.isOnline) {
callback(true);
} else {
Zotero.Connector.getData(callback);
}
}
function _getDataFile() { function _getDataFile() {
var dataFile = Zotero.getZoteroDirectory(); var dataFile = Zotero.getZoteroDirectory();
dataFile.append("connector.json"); dataFile.append("connector.json");
@ -76,9 +90,10 @@ Zotero.Connector = new function() {
this.EXCEPTION_NOT_AVAILABLE = 0; this.EXCEPTION_NOT_AVAILABLE = 0;
this.EXCEPTION_BAD_REQUEST = 400; this.EXCEPTION_BAD_REQUEST = 400;
this.EXCEPTION_NO_ENDPOINT = 404; this.EXCEPTION_NO_ENDPOINT = 404;
this.EXCEPTION_INCOMPATIBLE_VERSION = 412;
this.EXCEPTION_CONNECTOR_INTERNAL = 500; this.EXCEPTION_CONNECTOR_INTERNAL = 500;
this.EXCEPTION_METHOD_NOT_IMPLEMENTED = 501; this.EXCEPTION_METHOD_NOT_IMPLEMENTED = 501;
this.EXCEPTION_CODES = [0, 400, 404, 500, 501]; this.EXCEPTION_CODES = [0, 400, 404, 412, 500, 501];
/** /**
* Updates Zotero's status depending on the success or failure of a request * Updates Zotero's status depending on the success or failure of a request
@ -120,9 +135,9 @@ Zotero.Connector = new function() {
*/ */
this.getData = function(callback) { this.getData = function(callback) {
Zotero.HTTP.doPost(CONNECTOR_URI+"connector/getData", Zotero.HTTP.doPost(CONNECTOR_URI+"connector/getData",
JSON.stringify({"browser":Zotero.browser}), JSON.stringify({"browser":Zotero.browser, "apiVersion":CONNECTOR_SERVER_API_VERSION}),
function(req) { function(req) {
var isOnline = req.status !== 0; var isOnline = req.status !== 0 && req.status !== 412;
if(isOnline) { if(isOnline) {
// if request succeded, update data // if request succeded, update data
@ -172,7 +187,8 @@ Zotero.Connector = new function() {
this.callMethod = function(method, data, callback) { this.callMethod = function(method, data, callback) {
Zotero.HTTP.doPost(CONNECTOR_URI+"connector/"+method, JSON.stringify(data), Zotero.HTTP.doPost(CONNECTOR_URI+"connector/"+method, JSON.stringify(data),
function(req) { function(req) {
_checkState(req.status != 0, function() { _checkState(req.status !== this.EXCEPTION_NOT_AVAILABLE
&& req.status !== this.EXCEPTION_INCOMPATIBLE_VERSION, function() {
if(!callback) return; if(!callback) return;
if(Zotero.Connector.EXCEPTION_CODES.indexOf(req.status) !== -1) { if(Zotero.Connector.EXCEPTION_CODES.indexOf(req.status) !== -1) {

View file

@ -0,0 +1,86 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
Zotero.Connector_Debug = new function() {
/**
* Call a callback depending upon whether debug output is being stored
*/
this.storing = function(callback) {
callback(Zotero.Debug.storing);
}
/**
* Call a callback with the lines themselves
*/
this.get = function(callback) {
callback(Zotero.Debug.get());
}
/**
* Call a callback with the number of lines of output
*/
this.count = function(callback) {
callback(Zotero.Debug.count());
}
/**
* Submit data to the sserver
*/
this.submitReport = function(callback) {
var uploadCallback = function (xmlhttp) {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
if (!xmlhttp.responseXML) {
callback(false, 'Invalid response from server');
return;
}
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
if (reported.length != 1) {
callback(false, 'The server returned an error. Please try again.');
return;
}
var reportID = reported[0].getAttribute('reportID');
callback(true, reportID);
}
Zotero.HTTP.doPost("http://www.zotero.org/repo/report?debug=1", output,
function(xmlhttp) {
if (!xmlhttp.responseXML) {
callback(false, 'Invalid response from server');
return;
}
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
if (reported.length != 1) {
callback(false, 'The server returned an error. Please try again.');
return;
}
var reportID = reported[0].getAttribute('reportID');
callback(true, reportID);
}, {"Content-Type":"application/octet-stream"});
}
}

View file

@ -31,6 +31,7 @@ Zotero.Server = new function() {
300:"Multiple Choices", 300:"Multiple Choices",
400:"Bad Request", 400:"Bad Request",
404:"Not Found", 404:"Not Found",
412:"Precondition Failed",
500:"Internal Server Error", 500:"Internal Server Error",
501:"Method Not Implemented" 501:"Method Not Implemented"
}; };

View file

@ -23,6 +23,8 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
const CONNECTOR_SERVER_API_VERSION = 1;
Zotero.Server.Connector = function() {}; Zotero.Server.Connector = function() {};
Zotero.Server.Connector._waitingForSelection = {}; Zotero.Server.Connector._waitingForSelection = {};
Zotero.Server.Connector.Data = {}; Zotero.Server.Connector.Data = {};
@ -227,6 +229,10 @@ Zotero.Server.Connector.GetData.prototype = {
* @param {Function} sendResponseCallback function to send HTTP response * @param {Function} sendResponseCallback function to send HTTP response
*/ */
"init":function(data, sendResponseCallback) { "init":function(data, sendResponseCallback) {
if(data.apiVersion !== CONNECTOR_SERVER_API_VERSION) {
sendResponseCallback(412);
}
// Translator data // Translator data
var responseData = {"preferences":{}, "translators":[]}; var responseData = {"preferences":{}, "translators":[]};

View file

@ -122,7 +122,7 @@ Zotero.Translate.Sandbox = {
*/ */
"getOption":function(translate, option) { "getOption":function(translate, option) {
if(typeof option !== "string") { if(typeof option !== "string") {
throw("Translate: getOption: option must be a string"); throw(new Error("getOption: option must be a string"));
return; return;
} }
@ -149,7 +149,7 @@ Zotero.Translate.Sandbox = {
} }
if(typeof type !== "string") { if(typeof type !== "string") {
throw("Translate: loadTranslator: type must be a string"); throw(new Error("loadTranslator: type must be a string"));
return; return;
} }
@ -158,7 +158,7 @@ Zotero.Translate.Sandbox = {
translation._parentTranslator = translate; translation._parentTranslator = translate;
if(translation instanceof Zotero.Translate.Export && !(translation instanceof Zotero.Translate.Export)) { if(translation instanceof Zotero.Translate.Export && !(translation instanceof Zotero.Translate.Export)) {
throw("Translate: only export translators may call other export translators"); throw(new Error("Only export translators may call other export translators"));
} }
/** /**
@ -207,7 +207,7 @@ Zotero.Translate.Sandbox = {
safeTranslator.setTranslator = function(arg) { safeTranslator.setTranslator = function(arg) {
var success = translation.setTranslator(arg); var success = translation.setTranslator(arg);
if(!success) { if(!success) {
throw "Translator "+translate.translator[0].translatorID+" attempted to call invalid translatorID "+arg; throw new Error("Translator "+translate.translator[0].translatorID+" attempted to call invalid translatorID "+arg);
} }
}; };
safeTranslator.getTranslators = function() { return translation.getTranslators() }; safeTranslator.getTranslators = function() { return translation.getTranslators() };
@ -226,7 +226,7 @@ Zotero.Translate.Sandbox = {
if(callback) translate.incrementAsyncProcesses(); if(callback) translate.incrementAsyncProcesses();
var haveTranslatorFunction = function(translator) { var haveTranslatorFunction = function(translator) {
translation.translator[0] = translator; translation.translator[0] = translator;
if(!Zotero._loadTranslator(translator)) throw "Translator could not be loaded"; if(!Zotero._loadTranslator(translator)) throw new Error("Translator could not be loaded");
if(Zotero.isFx) { if(Zotero.isFx) {
// do same origin check // do same origin check
@ -243,8 +243,8 @@ Zotero.Translate.Sandbox = {
try { try {
secMan.checkSameOriginURI(outerSandboxURI, innerSandboxURI, false); secMan.checkSameOriginURI(outerSandboxURI, innerSandboxURI, false);
} catch(e) { } catch(e) {
throw "Translate: getTranslatorObject() may not be called from web or search "+ throw new Error("getTranslatorObject() may not be called from web or search "+
"translators to web or search translators from different origins."; "translators to web or search translators from different origins.");
} }
} }
@ -262,8 +262,8 @@ Zotero.Translate.Sandbox = {
return translation._sandboxManager.sandbox; return translation._sandboxManager.sandbox;
} else { } else {
if(Zotero.isConnector && !callback) { if(Zotero.isConnector && !callback) {
throw "Translate: Translator must accept a callback to getTranslatorObject() to "+ throw new Error("Translator must accept a callback to getTranslatorObject() to "+
"operate in this translation environment."; "operate in this translation environment.");
} }
Zotero.Translators.get(translation.translator[0], haveTranslatorFunction); Zotero.Translators.get(translation.translator[0], haveTranslatorFunction);
@ -319,7 +319,7 @@ Zotero.Translate.Sandbox = {
*/ */
"selectItems":function(translate, items, callback) { "selectItems":function(translate, items, callback) {
if(Zotero.Utilities.isEmpty(items)) { if(Zotero.Utilities.isEmpty(items)) {
throw "Translate: translator called select items with no items"; throw new Error("Translator called select items with no items");
} }
if(translate._selectedItems) { if(translate._selectedItems) {
@ -423,7 +423,7 @@ Zotero.Translate.Sandbox = {
} }
if(!item.title) { if(!item.title) {
throw "No title specified for item"; throw new Error("No title specified for item");
} }
// create short title // create short title
@ -520,7 +520,7 @@ Zotero.Translate.Sandbox = {
*/ */
"nextCollection":function(translate) { "nextCollection":function(translate) {
if(!translate.translator[0].configOptions.getCollections) { if(!translate.translator[0].configOptions.getCollections) {
throw("Translate: getCollections configure option not set; cannot retrieve collection"); throw(new Error("getCollections configure option not set; cannot retrieve collection"));
} }
return translate._itemGetter.nextCollection(); return translate._itemGetter.nextCollection();
@ -594,7 +594,7 @@ Zotero.Translate.Base.prototype = {
*/ */
"setTranslator":function(translator) { "setTranslator":function(translator) {
if(!translator) { if(!translator) {
throw new Error("Zotero.Translate: no translator specified"); throw new Error("No translator specified");
} }
this.translator = null; this.translator = null;
@ -604,7 +604,7 @@ Zotero.Translate.Base.prototype = {
if(translator.translatorID) { if(translator.translatorID) {
this.translator = [translator]; this.translator = [translator];
} else { } else {
throw("No translatorID specified"); throw(new Error("No translatorID specified"));
} }
} else { } else {
this.translator = [translator]; this.translator = [translator];
@ -748,7 +748,7 @@ Zotero.Translate.Base.prototype = {
*/ */
"getTranslators":function(getAllTranslators) { "getTranslators":function(getAllTranslators) {
// do not allow simultaneous instances of getTranslators // do not allow simultaneous instances of getTranslators
if(this._currentState == "detect") throw "Translate: getTranslators: detection is already running"; if(this._currentState == "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect"; this._currentState = "detect";
this._getAllTranslators = getAllTranslators; this._getAllTranslators = getAllTranslators;
this._getTranslatorsGetPotentialTranslators(); this._getTranslatorsGetPotentialTranslators();
@ -832,7 +832,7 @@ Zotero.Translate.Base.prototype = {
this._currentState = "translate"; this._currentState = "translate";
if(!this.translator || !this.translator.length) { if(!this.translator || !this.translator.length) {
throw("Translate: Failed: no translator specified"); throw new Error("Failed: no translator specified");
} }
this._libraryID = libraryID; this._libraryID = libraryID;
@ -1300,6 +1300,7 @@ Zotero.Translate.Web.prototype._translateRPCComplete = function(obj, failureCode
for(var i in obj.items) { for(var i in obj.items) {
this._runHandler("itemDone", null, obj.items[i]); this._runHandler("itemDone", null, obj.items[i]);
} }
this.newItems = obj.items;
this.complete(true); this.complete(true);
} }
} }
@ -1551,7 +1552,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = function() {
var io = this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this.translator[0].configOptions["dataMode"]); var io = this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this.translator[0].configOptions["dataMode"]);
this.__defineGetter__("string", function() { return io.string; }); this.__defineGetter__("string", function() { return io.string; });
} else if(!Zotero.Translate.IO.Write) { } else if(!Zotero.Translate.IO.Write) {
throw "Translate: Writing to files is not supported in this build of Zotero."; throw new Error("Writing to files is not supported in this build of Zotero.");
} else { } else {
this._io = new Zotero.Translate.IO.Write(this.location, this._io = new Zotero.Translate.IO.Write(this.location,
this.translator[0].configOptions["dataMode"], this.translator[0].configOptions["dataMode"],
@ -1687,7 +1688,7 @@ Zotero.Translate.IO = {
var dp = Components.classes["@mozilla.org/xmlextras/domparser;1"] var dp = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser); .createInstance(Components.interfaces.nsIDOMParser);
} catch(e) { } catch(e) {
throw "DOMParser not supported"; throw new Error("DOMParser not supported");
} }
} }
@ -1698,7 +1699,7 @@ Zotero.Translate.IO = {
} }
if(nodes.getElementsByTagName("parsererror").length) { if(nodes.getElementsByTagName("parsererror").length) {
throw("DOMParser error: loading data into data store failed"); throw new Error("DOMParser error: loading data into data store failed");
} }
return nodes; return nodes;
@ -1945,7 +1946,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
type = type.toLowerCase(); type = type.toLowerCase();
if(!containerTypes[type]) { if(!containerTypes[type]) {
throw "Invalid container type in Zotero.RDF.newContainer"; throw new Error("Invalid container type in Zotero.RDF.newContainer");
} }
var about = this._getResource(about); var about = this._getResource(about);
@ -2016,7 +2017,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
"getResourceURI":function(resource) { "getResourceURI":function(resource) {
if(typeof(resource) == "string") return resource; if(typeof(resource) == "string") return resource;
if(resource.uri) return resource.uri; if(resource.uri) return resource.uri;
if(resource.toNT == undefined) throw "Zotero.RDF: getResourceURI called on invalid resource"; if(resource.toNT == undefined) throw new Error("Zotero.RDF: getResourceURI called on invalid resource");
return resource.toNT(); return resource.toNT();
}, },