You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by jo...@gmail.com on 2010/02/03 04:08:03 UTC
Proposal #1: return simple DOM with error text when relevant
(issue199073)
Reviewers: shindig.remailer_gmail.com,
Description:
This patch returns a bare-bones DOM that includes error info from a
DOMException generated by parsing invalid text. The purpose is to echo
the error text back to a gadget developer rather than obscure it without
any context.
The implementation isn't perfect in that it would arguably be better for
MutableContent.getDocument() to throw a suitable Exception on parse
failure. However, doing so changes the MutableContent API to throw a
checked Exception, which could force several downstream API changes. An
alternative would be to add a MutableContent.checkDocument() API that
does throw an exception, whose use would be isolated to HtmlRenderer.
This forces DOM parsing before any rewriters are run, however, which has
non-trivial performance impact when String-based rewriters are run.
This implementation's main semantic downside is that the status code
returned for an erroring-render is 200 rather than 404.
Input welcome.
Please review this at http://codereview.appspot.com/199073/show
Affected files:
java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlParser.java
Index:
java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlParser.java
===================================================================
---
java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlParser.java
(revision 905859)
+++
java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlParser.java
(working copy)
@@ -21,7 +21,6 @@
import org.apache.shindig.common.cache.CacheProvider;
import org.apache.shindig.common.util.HashUtil;
import org.apache.shindig.gadgets.GadgetException;
-import org.apache.shindig.gadgets.GadgetException.Code;
import org.apache.shindig.gadgets.parse.nekohtml.NekoSimplifiedHtmlParser;
import com.google.common.collect.BiMap;
@@ -31,8 +30,10 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -50,6 +51,7 @@
private Cache<String, Document> documentCache;
private Cache<String, DocumentFragment> fragmentCache;
private Provider<HtmlSerializer> serializerProvider = new
DefaultSerializerProvider();
+ private DOMImplementation domImpl;
/**
* Allowed tag names for OpenSocial Data and template blocks.
@@ -73,6 +75,11 @@
public void setSerializerProvider(Provider<HtmlSerializer> serProvider) {
this.serializerProvider = serProvider;
}
+
+ @Inject
+ public void setDomImplementation(DOMImplementation domImpl) {
+ this.domImpl = domImpl;
+ }
/**
* @param content
@@ -99,9 +106,9 @@
document = parseDomImpl(source);
} catch (GadgetException e) {
throw e;
- } catch (Exception e) {
+ } catch (DOMException e) {
// DOMException is a RuntimeException
- throw new GadgetException(Code.HTML_PARSE_ERROR, e);
+ return errorDom(e);
}
HtmlSerialization.attach(document, serializerProvider.get(), source);
@@ -240,9 +247,10 @@
DocumentFragment fragment = null;
try {
fragment = parseFragmentImpl(source);
- } catch (Exception e) {
+ } catch (DOMException e) {
// DOMException is a RuntimeException
- throw new GadgetException(Code.HTML_PARSE_ERROR, e);
+ appendParseException(result, e);
+ return;
}
reprocessScriptForOpenSocial(fragment);
@@ -261,6 +269,27 @@
}
}
+ protected Document errorDom(DOMException e) {
+ // Create a bare-bones DOM whose body is just error text.
+ // We do this to echo information to the developer that originally
+ // supplied the data, since doing so is more useful than simply
+ // returning a black-box HTML error code stemming from an NPE or other
condition downstream.
+ // The method is protected to allow overriding of this behavior.
+ Document doc = domImpl.createDocument(null, null, null);
+ Node html = doc.createElement("html");
+ html.appendChild(doc.createElement("head"));
+ Node body = doc.createElement("body");
+ appendParseException(body, e);
+ html.appendChild(body);
+ doc.appendChild(html);
+ return doc;
+ }
+
+ private void appendParseException(Node node, DOMException e) {
+ node.appendChild(node.getOwnerDocument().createTextNode(
+ GadgetException.Code.HTML_PARSE_ERROR.toString() + ": " +
e.toString()));
+ }
+
protected boolean shouldCache() {
return documentCache != null && documentCache.getCapacity() != 0;
}