You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2010/08/10 13:32:34 UTC
svn commit: r983934 [4/8] - in /shindig/branches/2.0.x: ./ config/
content/container/ content/samplecontainer/examples/ActivityStreams/
extras/src/main/java/org/apache/shindig/extras/as/core/model/
extras/src/main/java/org/apache/shindig/extras/as/open...
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssResponseRewriter.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssResponseRewriter.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssResponseRewriter.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssResponseRewriter.java Tue Aug 10 11:32:26 2010
@@ -24,7 +24,7 @@ import org.apache.shindig.gadgets.Gadget
import org.apache.shindig.gadgets.http.HttpRequest;
import org.apache.shindig.gadgets.http.HttpResponse;
import org.apache.shindig.gadgets.http.HttpResponseBuilder;
-import org.apache.shindig.gadgets.parse.caja.CajaCssLexerParser;
+import org.apache.shindig.gadgets.parse.caja.CajaCssParser;
import org.apache.shindig.gadgets.uri.ProxyUriManager;
import org.w3c.dom.Element;
@@ -39,6 +39,10 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.caja.lexer.ParseException;
+import com.google.caja.parser.AbstractParseTreeNode;
+import com.google.caja.parser.AncestorChain;
+import com.google.caja.parser.Visitor;
+import com.google.caja.parser.css.CssTree;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
@@ -49,12 +53,12 @@ public class CssResponseRewriter impleme
private static final Logger LOG = Logger.getLogger(CssResponseRewriter.class.getName());
- private final CajaCssLexerParser cssParser;
+ private final CajaCssParser cssParser;
private final ProxyUriManager proxyUriManager;
private final ContentRewriterFeature.Factory rewriterFeatureFactory;
@Inject
- public CssResponseRewriter(CajaCssLexerParser cssParser,
+ public CssResponseRewriter(CajaCssParser cssParser,
ProxyUriManager proxyUriManager, ContentRewriterFeature.Factory rewriterFeatureFactory) {
this.cssParser = cssParser;
this.proxyUriManager = proxyUriManager;
@@ -89,7 +93,7 @@ public class CssResponseRewriter impleme
try {
String original = IOUtils.toString(content);
try {
- List<Object> stylesheet = cssParser.parse(original);
+ CssTree.StyleSheet stylesheet = cssParser.parseDom(original, source);
List<String> stringList = rewrite(stylesheet, source, uriMaker, extractImports);
// Serialize the stylesheet
cssParser.serialize(stylesheet, writer);
@@ -121,7 +125,8 @@ public class CssResponseRewriter impleme
public List<String> rewrite(Element styleNode, Uri source,
UriMaker uriMaker, boolean extractImports) throws RewritingException {
try {
- List<Object> stylesheet = cssParser.parse(styleNode.getTextContent());
+ CssTree.StyleSheet stylesheet =
+ cssParser.parseDom(styleNode.getTextContent(), source);
List<String> imports = rewrite(stylesheet, source, uriMaker, extractImports);
// Write the rewritten CSS back into the element
String content = cssParser.serialize(stylesheet);
@@ -152,26 +157,33 @@ public class CssResponseRewriter impleme
* referenced URIs.
* @return Empty list of extracted import URIs.
*/
- public static List<String> rewrite(List<Object> styleSheet, final Uri source,
+ public static List<String> rewrite(CssTree.StyleSheet styleSheet, final Uri source,
final UriMaker uriMaker, final boolean extractImports) {
final List<String> imports = Lists.newLinkedList();
-
- for (int i = styleSheet.size() - 1; i >= 0; i--) {
- if (styleSheet.get(i) instanceof CajaCssLexerParser.ImportDecl) {
- if (extractImports) {
- imports.add(0, ((CajaCssLexerParser.ImportDecl)styleSheet.get(i)).getUri());
- styleSheet.remove(i);
- } else {
- CajaCssLexerParser.ImportDecl importDecl = (CajaCssLexerParser.ImportDecl) styleSheet
- .get(i);
- importDecl.setUri(rewriteUri(uriMaker, importDecl.getUri(), source));
+ final List<CssTree.UriLiteral> skip = Lists.newLinkedList();
+
+ styleSheet.acceptPreOrder(new Visitor() {
+ public boolean visit(AncestorChain<?> chain) {
+ if (chain.node instanceof CssTree.Import) {
+ CssTree.Import importNode = (CssTree.Import) chain.node;
+ CssTree.UriLiteral uriLiteral = importNode.getUri();
+ skip.add(importNode.getUri());
+ if (extractImports) {
+ imports.add(uriLiteral.getValue());
+ ((AbstractParseTreeNode) chain.getParentNode()).removeChild(chain.node);
+ } else {
+ String rewritten = rewriteUri(uriMaker, uriLiteral.getValue(), source);
+ uriLiteral.setValue(rewritten);
+ }
+ } else if (chain.node instanceof CssTree.UriLiteral &&
+ !skip.contains(chain.node)) {
+ CssTree.UriLiteral uriDecl = (CssTree.UriLiteral) chain.node;
+ String rewritten = rewriteUri(uriMaker, uriDecl.getValue(), source);
+ uriDecl.setValue(rewritten);
}
- } else if (styleSheet.get(i) instanceof CajaCssLexerParser.UriDecl) {
- CajaCssLexerParser.UriDecl uriDecl = (CajaCssLexerParser.UriDecl) styleSheet
- .get(i);
- uriDecl.setUri(rewriteUri(uriMaker, uriDecl.getUri(), source));
- }
- }
+ return true;
+ }}, null);
+
return imports;
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/DomWalker.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/DomWalker.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/DomWalker.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/DomWalker.java Tue Aug 10 11:32:26 2010
@@ -28,9 +28,12 @@ import org.apache.shindig.gadgets.http.H
import org.apache.shindig.gadgets.http.HttpResponseBuilder;
import org.apache.shindig.gadgets.spec.GadgetSpec;
import org.apache.shindig.gadgets.uri.UriCommon.Param;
+import org.apache.commons.lang.StringUtils;
+import org.w3c.dom.Document;
import org.w3c.dom.Node;
+import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -148,7 +151,13 @@ public final class DomWalker {
Map<Visitor, List<Node>> reservations = Maps.newHashMap();
LinkedList<Node> toVisit = Lists.newLinkedList();
- toVisit.add(content.getDocument().getDocumentElement());
+ Document doc = content.getDocument();
+ if (doc == null) {
+ throw new RewritingException("content.getDocument is null. Content: "
+ + content.getContent(),
+ HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ toVisit.add(doc.getDocumentElement());
boolean mutated = false;
while (!toVisit.isEmpty()) {
Node visiting = toVisit.removeFirst();
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java Tue Aug 10 11:32:26 2010
@@ -17,6 +17,10 @@
*/
package org.apache.shindig.gadgets.rewrite;
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
import org.apache.commons.io.IOUtils;
import org.apache.shindig.common.util.CharsetUtil;
import org.apache.shindig.gadgets.GadgetException;
@@ -28,12 +32,12 @@ import org.w3c.dom.Document;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Map;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Object that maintains a String representation of arbitrary contents
@@ -42,15 +46,23 @@ import com.google.common.collect.Maps;
public class MutableContent {
private static final Map<String, Object> EMPTY_MAP = ImmutableMap.of();
+ // String representation of contentBytes taking into account the correct
+ // encoding of the content.
private String content;
private byte[] contentBytes;
+
+ // Encoding of the content bytes. UTF-8 by default.
+ private Charset contentEncoding;
+
private HttpResponse contentSource;
+
private Document document;
private int numChanges;
private final GadgetHtmlParser contentParser;
private Map<String, Object> pipelinedData;
private static final String MUTABLE_CONTENT_LISTENER = "MutableContentListener";
+ private static final Logger logger = Logger.getLogger(MutableContent.class.getName());
public static void notifyEdit(Document doc) {
MutableContent mc = (MutableContent) doc.getUserData(MUTABLE_CONTENT_LISTENER);
@@ -66,6 +78,7 @@ public class MutableContent {
this.contentParser = contentParser;
this.content = content;
this.numChanges = 0;
+ this.contentEncoding = Charsets.UTF_8;
}
/**
@@ -75,6 +88,7 @@ public class MutableContent {
public MutableContent(GadgetHtmlParser contentParser, HttpResponse contentSource) {
this.contentParser = contentParser;
this.contentSource = contentSource;
+ this.contentEncoding = contentSource != null ? contentSource.getEncodingCharset() : null;
}
/**
@@ -98,11 +112,8 @@ public class MutableContent {
} else if (document != null) {
content = HtmlSerialization.serialize(document);
} else if (contentBytes != null) {
- try {
- content = new String(contentBytes, "UTF8");
- } catch (UnsupportedEncodingException e) {
- // Never happens.
- }
+ Charset useEncoding = contentEncoding != null ? contentEncoding : Charsets.UTF_8;
+ content = useEncoding.decode(ByteBuffer.wrap(contentBytes)).toString();
}
}
return content;
@@ -136,37 +147,67 @@ public class MutableContent {
if (contentBytes == null) {
if (contentSource != null) {
try {
- contentBytes = IOUtils.toByteArray(contentSource.getResponse());
+ setContentBytesState(IOUtils.toByteArray(contentSource.getResponse()),
+ contentSource.getEncodingCharset());
contentSource = null;
} catch (IOException e) {
// Doesn't occur; responseBytes wrapped as a ByteArrayInputStream.
}
} else if (content != null) {
- contentBytes = CharsetUtil.getUtf8Bytes(content);
+ // If retrieving a String here, we've already converted to UTF8.
+ // Be sure to reflect this when setting bytes.
+ // In the case of HttpResponseBuilder, this re-sets charset in Content-Type
+ // to UTF-8 rather than whatever it was before. We do this to standardize
+ // on UTF-8 for all String handling.
+ setContentBytesState(CharsetUtil.getUtf8Bytes(content), Charsets.UTF_8);
} else if (document != null) {
- contentBytes = CharsetUtil.getUtf8Bytes(HtmlSerialization.serialize(document));
+ setContentBytesState(
+ CharsetUtil.getUtf8Bytes(HtmlSerialization.serialize(document)), Charsets.UTF_8);
}
}
return contentBytes;
}
/**
- * Sets the object's contentBytes as the given raw input.
+ * Sets the object's contentBytes as the given raw input. If ever interpreted
+ * as a String, the data will be decoded as the encoding specified.
* Note, this operation may clear the document if the content has changed.
* Also note, it's mandated that the new bytes array will NOT be modified
* by the caller of this API. The array is not copied, for performance reasons.
* If the caller may modify a byte array, it MUST pass in a new copy.
* @param newBytes New content.
*/
- public void setContentBytes(byte[] newBytes) {
+ public void setContentBytes(byte[] newBytes, Charset newEncoding) {
if (contentBytes == null || !Arrays.equals(contentBytes, newBytes)) {
- contentBytes = newBytes;
+ setContentBytesState(newBytes, newEncoding);
document = null;
contentSource = null;
content = null;
incrementNumChanges();
}
}
+
+ /**
+ * Sets content to new byte array, with unspecified charset. It is
+ * recommended to use the {@code setContentBytes(byte[], Charset)} API instead,
+ * where possible.
+ * @param newBytes New content.
+ */
+ public final void setContentBytes(byte[] newBytes) {
+ setContentBytes(newBytes, null);
+ }
+
+ /**
+ * Sets internal state having to do with content bytes, from the provided
+ * byte array and charset.
+ * This MUST be the only place in which MutableContent's notion of encoding is mutated.
+ * @param newBytes New content.
+ * @param newEncoding Encoding for the bytes, or null for unspecified.
+ */
+ protected void setContentBytesState(byte[] newBytes, Charset newEncoding) {
+ contentBytes = newBytes;
+ contentEncoding = newEncoding;
+ }
/**
* Notification that the content of the document has changed. Causes the content
@@ -199,7 +240,7 @@ public class MutableContent {
document = contentParser.parseDom(getContent());
document.setUserData(MUTABLE_CONTENT_LISTENER, this, null);
} catch (GadgetException e) {
- // TODO: emit info message
+ logger.log(Level.WARNING, "Got GadgetException when parsing content", e);
return null;
}
return document;
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/ProxyingVisitor.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/ProxyingVisitor.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/ProxyingVisitor.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/ProxyingVisitor.java Tue Aug 10 11:32:26 2010
@@ -20,7 +20,6 @@ package org.apache.shindig.gadgets.rewri
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
-
import org.apache.shindig.common.Pair;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.common.uri.Uri.UriException;
@@ -33,23 +32,28 @@ import org.w3c.dom.Node;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Simple visitor that, when plugged into a DomWalker, rewrites
* resource links to proxied versions of the same.
*/
public class ProxyingVisitor implements DomWalker.Visitor {
+ private static final Logger logger = Logger.getLogger(
+ ProxyUriManager.class.getName());
+
public final static Map<String, String> RESOURCE_TAGS =
ImmutableMap.of(
+ "body", "background",
"img", "src",
- "embed", "src",
+ "input", "src",
"link", "href",
- "script", "src",
- "object", "src");
-
+ "script", "src");
+
private final ContentRewriterFeature.Config featureConfig;
private final ProxyUriManager uriManager;
-
+
public ProxyingVisitor(ContentRewriterFeature.Config featureConfig,
ProxyUriManager uriManager) {
this.featureConfig = featureConfig;
@@ -82,7 +86,8 @@ public class ProxyingVisitor implements
continue;
}
Element element = (Element)proxyPair.one;
- element.setAttribute(RESOURCE_TAGS.get(element.getNodeName()), proxyPair.two.toString());
+ String nodeName = element.getNodeName().toLowerCase();
+ element.setAttribute(RESOURCE_TAGS.get(nodeName), proxyPair.two.toString());
mutated = true;
}
@@ -92,15 +97,21 @@ public class ProxyingVisitor implements
private List<Pair<Node, Uri>> getProxiedUris(Gadget gadget, List<Node> nodes) {
List<ProxyUriManager.ProxyUri> reservedUris =
Lists.newArrayListWithCapacity(nodes.size());
+ List<Node> reservedNodes =
+ Lists.newArrayListWithCapacity(nodes.size());
for (Node node : nodes) {
Element element = (Element)node;
- String uriStr = element.getAttribute(RESOURCE_TAGS.get(element.getNodeName()));
+ String nodeName = node.getNodeName().toLowerCase();
+ String uriStr = element.getAttribute(RESOURCE_TAGS.get(nodeName)).trim();
try {
- reservedUris.add(new ProxyUriManager.ProxyUri(gadget, Uri.parse(uriStr)));
+ ProxyUriManager.ProxyUri proxiedUri = new ProxyUriManager.ProxyUri(
+ gadget, Uri.parse(uriStr));
+ reservedUris.add(proxiedUri);
+ reservedNodes.add(node);
} catch (UriException e) {
- // Uri parse exception, add null.
- reservedUris.add(null);
+ // Uri parse exception, ignore.
+ logger.log(Level.WARNING, "Uri exception when parsing: " + uriStr, e);
}
}
@@ -111,7 +122,7 @@ public class ProxyingVisitor implements
List<Pair<Node, Uri>> proxiedUris = Lists.newArrayListWithCapacity(nodes.size());
Iterator<Uri> uriIt = resourceUris.iterator();
- for (Node node : nodes) {
+ for (Node node : reservedNodes) {
proxiedUris.add(Pair.of(node, uriIt.next()));
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java Tue Aug 10 11:32:26 2010
@@ -19,20 +19,18 @@
package org.apache.shindig.gadgets.rewrite;
import com.google.common.collect.ImmutableList;
-
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
-
+import com.google.inject.name.Names;
import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
+import org.apache.shindig.gadgets.render.CajaResponseRewriter;
import org.apache.shindig.gadgets.render.OpenSocialI18NGadgetRewriter;
import org.apache.shindig.gadgets.render.RenderingGadgetRewriter;
-import org.apache.shindig.gadgets.render.old.SanitizingGadgetRewriter;
-import org.apache.shindig.gadgets.render.old.SanitizingRequestRewriter;
+import org.apache.shindig.gadgets.render.SanitizingGadgetRewriter;
+import org.apache.shindig.gadgets.render.SanitizingResponseRewriter;
import org.apache.shindig.gadgets.rewrite.image.BasicImageRewriter;
-import org.apache.shindig.gadgets.rewrite.old.CssRequestRewriter;
-import org.apache.shindig.gadgets.rewrite.old.HTMLContentRewriter;
import org.apache.shindig.gadgets.servlet.CajaContentRewriter;
import java.util.List;
@@ -44,6 +42,9 @@ public class RewriteModule extends Abstr
@Override
protected void configure() {
+ bind(ResponseRewriterRegistry.class)
+ .annotatedWith(Names.named("shindig.accelerate.response.rewriter.registry"))
+ .to(AccelResponseRewriterRegistry.class);
}
@Provides
@@ -52,13 +53,16 @@ public class RewriteModule extends Abstr
protected List<GadgetRewriter> provideGadgetRewriters(
PipelineDataGadgetRewriter pipelineRewriter,
TemplateRewriter templateRewriter,
- HTMLContentRewriter optimizingRewriter,
- CssRequestRewriter cssRewriter,
+ AbsolutePathReferenceRewriter absolutePathRewriter,
+ StyleTagExtractorContentRewriter styleTagExtractorRewriter,
+ StyleAdjacencyContentRewriter styleAdjacencyRewriter,
+ ProxyingContentRewriter proxyingRewriter,
CajaContentRewriter cajaRewriter,
SanitizingGadgetRewriter sanitizedRewriter,
RenderingGadgetRewriter renderingRewriter,
OpenSocialI18NGadgetRewriter i18nRewriter) {
- return ImmutableList.of(pipelineRewriter, templateRewriter, optimizingRewriter,
+ return ImmutableList.of(pipelineRewriter, templateRewriter,
+ absolutePathRewriter, styleTagExtractorRewriter, styleAdjacencyRewriter, proxyingRewriter,
cajaRewriter, sanitizedRewriter, renderingRewriter, i18nRewriter);
}
@@ -93,9 +97,27 @@ public class RewriteModule extends Abstr
@Provides
@Singleton
protected List<ResponseRewriter> provideResponseRewriters(
- HTMLContentRewriter optimizingRewriter,
- CssRequestRewriter cssRewriter,
- SanitizingRequestRewriter sanitizedRewriter) {
- return ImmutableList.of(optimizingRewriter, cssRewriter, sanitizedRewriter);
+ AbsolutePathReferenceRewriter absolutePathRewriter,
+ StyleTagExtractorContentRewriter styleTagExtractorRewriter,
+ StyleAdjacencyContentRewriter styleAdjacencyRewriter,
+ ProxyingContentRewriter proxyingRewriter,
+ CssResponseRewriter cssRewriter,
+ SanitizingResponseRewriter sanitizedRewriter,
+ CajaResponseRewriter cajaRewriter) {
+ return ImmutableList.of(
+ absolutePathRewriter, styleTagExtractorRewriter, styleAdjacencyRewriter, proxyingRewriter,
+ cssRewriter, sanitizedRewriter, cajaRewriter);
+ }
+
+ @Provides
+ @Singleton
+ @Named("shindig.accelerate.response.rewriters")
+ protected List<ResponseRewriter> provideAccelResponseRewriters(
+ AbsolutePathReferenceRewriter absolutePathReferenceRewriter,
+ StyleTagProxyEmbeddedUrlsRewriter styleTagProxyEmbeddedUrlsRewriter,
+ ProxyingContentRewriter proxyingContentRewriter) {
+ return ImmutableList.of((ResponseRewriter) absolutePathReferenceRewriter,
+ (ResponseRewriter) styleTagProxyEmbeddedUrlsRewriter,
+ (ResponseRewriter) proxyingContentRewriter);
}
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BaseOptimizer.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BaseOptimizer.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BaseOptimizer.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BaseOptimizer.java Tue Aug 10 11:32:26 2010
@@ -24,6 +24,7 @@ import org.apache.shindig.gadgets.http.H
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
+import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import java.awt.image.BufferedImage;
@@ -151,7 +152,7 @@ abstract class BaseOptimizer {
ImageWriteParam writeParam;
public ImageIOOutputter(ImageWriter writer, ImageWriteParam writeParam) {
this.writer = writer;
- this.writeParam = firstNonNull(writeParam, writer.getDefaultWriteParam());
+ this.writeParam = Objects.firstNonNull(writeParam, writer.getDefaultWriteParam());
}
public byte[] toBytes(BufferedImage image) throws IOException {
@@ -195,7 +196,4 @@ abstract class BaseOptimizer {
}
}
}
- private static <T> T firstNonNull(T first, T second) {
- return first != null ? first : Preconditions.checkNotNull(second);
- }
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BasicImageRewriter.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BasicImageRewriter.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BasicImageRewriter.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/image/BasicImageRewriter.java Tue Aug 10 11:32:26 2010
@@ -145,8 +145,8 @@ public class BasicImageRewriter implemen
boolean noExpand = "1".equals(request.getParam(PARAM_NO_EXPAND));
if (noExpand &&
- imageInfo.getHeight() <= requestedHeight &&
- imageInfo.getWidth() <= requestedWidth) {
+ (requestedHeight == null || imageInfo.getHeight() <= requestedHeight) &&
+ (requestedWidth == null || imageInfo.getWidth() <= requestedWidth)) {
// Don't do anything, since the current image fits within the bounding area.
isResizeRequested = false;
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/AccelHandler.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/AccelHandler.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/AccelHandler.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/AccelHandler.java Tue Aug 10 11:32:26 2010
@@ -19,15 +19,15 @@ package org.apache.shindig.gadgets.servl
import com.google.inject.Inject;
import com.google.inject.Singleton;
-
+import com.google.inject.name.Named;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shindig.common.uri.Uri;
-import org.apache.shindig.common.uri.UriBuilder;
import org.apache.shindig.gadgets.Gadget;
import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.http.HttpRequest;
import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.http.HttpResponseBuilder;
import org.apache.shindig.gadgets.http.RequestPipeline;
import org.apache.shindig.gadgets.rewrite.DomWalker;
import org.apache.shindig.gadgets.rewrite.ResponseRewriterRegistry;
@@ -37,20 +37,15 @@ import org.apache.shindig.gadgets.uri.Pr
import org.apache.shindig.gadgets.uri.UriCommon;
import org.apache.shindig.gadgets.uri.UriUtils;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
/**
* Handles requests for accel servlet.
* The objective is to accelerate web pages.
*/
@Singleton
-public class AccelHandler extends ProxyBase {
- private static final Logger logger = Logger.getLogger(ProxyHandler.class.getName());
-
+public class AccelHandler {
static final String ERROR_FETCHING_DATA = "Error fetching data";
// TODO: parameterize these.
@@ -60,57 +55,64 @@ public class AccelHandler extends ProxyB
protected final RequestPipeline requestPipeline;
protected final ResponseRewriterRegistry contentRewriterRegistry;
protected final AccelUriManager uriManager;
+ protected final boolean remapInternalServerError;
@Inject
public AccelHandler(RequestPipeline requestPipeline,
+ @Named("shindig.accelerate.response.rewriter.registry")
ResponseRewriterRegistry contentRewriterRegistry,
- AccelUriManager accelUriManager) {
+ AccelUriManager accelUriManager,
+ @Named("shindig.accelerate.remapInternalServerError")
+ Boolean remapInternalServerError) {
this.requestPipeline = requestPipeline;
this.contentRewriterRegistry = contentRewriterRegistry;
this.uriManager = accelUriManager;
+ this.remapInternalServerError = remapInternalServerError;
}
- @Override
- protected void doFetch(HttpServletRequest request, HttpServletResponse response)
- throws IOException, GadgetException {
+ protected HttpResponse fetch(HttpRequest request) throws IOException, GadgetException {
// TODO: Handle if modified since headers.
// Parse and normalize to get a proxied request uri.
- Uri requestUri = new UriBuilder(request).toUri();
- ProxyUriManager.ProxyUri proxyUri = getProxyUri(requestUri);
+ ProxyUriManager.ProxyUri proxyUri = getProxyUri(request.getUri());
// Fetch the content of the requested uri.
HttpRequest req = buildHttpRequest(request, proxyUri);
HttpResponse results = requestPipeline.execute(req);
- if (!handleErrors(results, response)) {
- // In case of errors where we want to short circuit the rewriting and
- // throw appropriate gadget exception.
- return;
- }
-
- // Rewrite the content.
- try {
- results = contentRewriterRegistry.rewriteHttpResponse(req, results);
- } catch (RewritingException e) {
- if (!isRecoverable(req, results, e)) {
- throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR, e,
- e.getHttpStatusCode());
+ HttpResponse errorResponse = handleErrors(results);
+ if (errorResponse == null) {
+ // No error. Lets rewrite the content.
+ try {
+ results = contentRewriterRegistry.rewriteHttpResponse(req, results);
+ } catch (RewritingException e) {
+ if (!isRecoverable(req, results, e)) {
+ throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR, e,
+ e.getHttpStatusCode());
+ }
}
+ } else {
+ results = errorResponse;
}
// Copy the response headers and status code to the final http servlet
// response.
+ HttpResponseBuilder response = new HttpResponseBuilder();
UriUtils.copyResponseHeadersAndStatusCode(
- results, response,
- UriUtils.DisallowedResponseHeaders.OUTPUT_TRANSFER_DIRECTIVES,
- UriUtils.DisallowedResponseHeaders.CLIENT_STATE_DIRECTIVES);
+ results, response, remapInternalServerError, true,
+ UriUtils.DisallowedHeaders.OUTPUT_TRANSFER_DIRECTIVES,
+ UriUtils.DisallowedHeaders.CLIENT_STATE_DIRECTIVES);
// Override the content type of the final http response if the input request
// had the rewrite mime type header.
- rewriteContentType(req, response);
+ UriUtils.maybeRewriteContentType(req, response);
- IOUtils.copy(results.getResponse(), response.getOutputStream());
+ // Copy the content.
+ // TODO: replace this with streaming APIs when ready
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ IOUtils.copy(results.getResponse(), baos);
+ response.setResponseNoCopy(baos.toByteArray());
+ return response.create();
}
/**
@@ -130,7 +132,7 @@ public class AccelHandler extends ProxyB
} catch (Uri.UriException e) {
throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR,
"Failed to parse uri: " + uriString,
- HttpServletResponse.SC_BAD_GATEWAY);
+ HttpResponse.SC_BAD_GATEWAY);
}
Gadget gadget = DomWalker.makeGadget(requestUri);
@@ -160,67 +162,56 @@ public class AccelHandler extends ProxyB
}
/**
- * Generate a remote content request based on the parameters sent from the client.
+ * Build an HttpRequest object encapsulating the request details as requested
+ * by the user.
* @param request The http request.
* @param uriToProxyOrRewrite The parsed uri to proxy or rewrite through
* accel servlet.
* @return Remote content request based on the parameters sent from the client.
* @throws GadgetException In case the data could not be fetched.
*/
- protected HttpRequest buildHttpRequest(HttpServletRequest request,
+ protected HttpRequest buildHttpRequest(HttpRequest request,
ProxyUriManager.ProxyUri uriToProxyOrRewrite)
throws GadgetException {
Uri tgt = uriToProxyOrRewrite.getResource();
- validateUrl(tgt);
HttpRequest req = uriToProxyOrRewrite.makeHttpRequest(tgt);
- this.setRequestHeaders(request, req);
-
if (req == null) {
throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
"No url parameter in request", HttpResponse.SC_BAD_REQUEST);
}
- return req;
- }
- /**
- * Rewrite the content type of the final http response if the request has the
- * rewrite-mime-type param.
- * @param req The http request.
- * @param response The final http response to be returned to user.
- */
- protected void rewriteContentType(HttpRequest req, HttpServletResponse response) {
- String contentType = response.getContentType();
- String requiredType = req.getRewriteMimeType();
- if (!StringUtils.isEmpty(requiredType)) {
- if (requiredType.endsWith("/*") && !StringUtils.isEmpty(contentType)) {
- requiredType = requiredType.substring(0, requiredType.length() - 2);
- }
- response.setContentType(requiredType);
- }
+ // Copy the post body if it exists.
+ UriUtils.copyRequestData(request, req);
+
+ // Set and copy headers.
+ ServletUtil.setXForwardedForHeader(request, req);
+
+ UriUtils.copyRequestHeaders(
+ request, req,
+ UriUtils.DisallowedHeaders.POST_INCOMPATIBLE_DIRECTIVES);
+
+ req.setFollowRedirects(false);
+ return req;
}
/**
- * Process errors when fetching uri using request pipeline by throwing
- * GadgetException in error cases.
+ * Process errors when fetching uri using request pipeline and return the
+ * error response to be returned to the user if any.
* @param results The http response returned by request pipeline.
- * @param response The http servlet response to be returned to the user.
- * @return True if there is no error, false otherwise.
- * @throws IOException In case of errors.
+ * @return An HttpResponse instance encapsulating error message and status
+ * code to be returned to the user in case of errors, null otherwise.
*/
- protected boolean handleErrors(HttpResponse results, HttpServletResponse response)
- throws IOException {
+ protected HttpResponse handleErrors(HttpResponse results) {
if (results == null) {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST, ERROR_FETCHING_DATA);
- return false;
+ return new HttpResponseBuilder()
+ .setHttpStatusCode(HttpResponse.SC_NOT_FOUND)
+ .setResponse(ERROR_FETCHING_DATA.getBytes())
+ .create();
}
- if (results.getHttpStatusCode() == HttpServletResponse.SC_NOT_FOUND) {
- response.sendError(HttpServletResponse.SC_NOT_FOUND, ERROR_FETCHING_DATA);
- return false;
- } else if (results.isError()) {
- response.sendError(HttpServletResponse.SC_BAD_GATEWAY, ERROR_FETCHING_DATA);
- return false;
+ if (results.isError()) {
+ return results;
}
- return true;
+ return null;
}
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/CajaContentRewriter.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/CajaContentRewriter.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/CajaContentRewriter.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/CajaContentRewriter.java Tue Aug 10 11:32:26 2010
@@ -18,7 +18,6 @@
*/
package org.apache.shindig.gadgets.servlet;
-import com.google.caja.lexer.CharProducer;
import com.google.caja.lexer.ExternalReference;
import com.google.caja.lexer.FetchedData;
import com.google.caja.lexer.InputSource;
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ConcatProxyServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ConcatProxyServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ConcatProxyServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ConcatProxyServlet.java Tue Aug 10 11:32:26 2010
@@ -49,17 +49,19 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet which concatenates the content of several proxied HTTP responses
- *
- * @see org.apache.shindig.gadgets.rewrite.old.HTMLContentRewriter
*/
public class ConcatProxyServlet extends InjectedServlet {
+ private static final long serialVersionUID = -4390212150673709895L;
+
public static final String JSON_PARAM = Param.JSON.getKey();
private static final Pattern JSON_PARAM_PATTERN = Pattern.compile("^\\w*$");
@@ -70,11 +72,11 @@ public class ConcatProxyServlet extends
private static final Logger LOG
= Logger.getLogger(ConcatProxyServlet.class.getName());
- private RequestPipeline requestPipeline;
- private ConcatUriManager concatUriManager;
- private ResponseRewriterRegistry contentRewriterRegistry;
+ private transient RequestPipeline requestPipeline;
+ private transient ConcatUriManager concatUriManager;
+ private transient ResponseRewriterRegistry contentRewriterRegistry;
- private Executor executor = new Executor() {
+ private transient Executor executor = new Executor() {
public void execute(Runnable r) {
// Sequential version of 'execute' by default.
r.run();
@@ -83,26 +85,35 @@ public class ConcatProxyServlet extends
@Inject
public void setRequestPipeline(RequestPipeline requestPipeline) {
+ checkInitialized();
this.requestPipeline = requestPipeline;
}
@Inject
public void setConcatUriManager(ConcatUriManager concatUriManager) {
+ checkInitialized();
this.concatUriManager = concatUriManager;
}
@Inject
public void setContentRewriterRegistry(ResponseRewriterRegistry contentRewriterRegistry) {
+ checkInitialized();
this.contentRewriterRegistry = contentRewriterRegistry;
}
@Inject
public void setExecutor(@Named("shindig.concat.executor") Executor executor) {
+ checkInitialized();
// Executor is independently named to allow separate configuration of
// concat fetch parallelism and other Shindig job execution.
this.executor = executor;
}
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
@SuppressWarnings("boxing")
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingServlet.java Tue Aug 10 11:32:26 2010
@@ -26,6 +26,7 @@ import org.apache.shindig.gadgets.render
import org.apache.shindig.gadgets.render.RenderingResults;
import org.apache.shindig.gadgets.uri.IframeUriManager;
import org.apache.shindig.gadgets.uri.UriStatus;
+import org.apache.shindig.gadgets.uri.UriCommon.Param;
import com.google.inject.Inject;
@@ -35,6 +36,8 @@ import org.apache.commons.lang.StringUti
import java.io.IOException;
import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -42,23 +45,53 @@ import javax.servlet.http.HttpServletRes
* Servlet for rendering Gadgets.
*/
public class GadgetRenderingServlet extends InjectedServlet {
+
+ private static final long serialVersionUID = -5634040113214794888L;
+
static final int DEFAULT_CACHE_TTL = 60 * 5;
private static final Logger LOG = Logger.getLogger(GadgetRenderingServlet.class.getName());
- private Renderer renderer;
- private IframeUriManager iframeUriManager;
+ private transient Renderer renderer;
+ private transient IframeUriManager iframeUriManager;
@Inject
public void setRenderer(Renderer renderer) {
+ checkInitialized();
this.renderer = renderer;
}
@Inject
public void setIframeUriManager(IframeUriManager iframeUriManager) {
+ checkInitialized();
this.iframeUriManager = iframeUriManager;
}
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ // If an If-Modified-Since header is ever provided, we always say
+ // not modified. This is because when there actually is a change,
+ // cache busting should occur.
+ UriStatus urlStatus = getUrlStatus(req);
+ if (req.getHeader("If-Modified-Since") != null &&
+ !"1".equals(req.getParameter("nocache")) &&
+ urlStatus == UriStatus.VALID_VERSIONED) {
+ resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+ render(req, resp, urlStatus);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ render(req, resp, getUrlStatus(req));
+ }
+
private void render(HttpServletRequest req, HttpServletResponse resp, UriStatus urlstatus)
throws IOException {
if (req.getHeader(HttpRequest.DOS_PREVENTION_HEADER) != null) {
@@ -74,62 +107,111 @@ public class GadgetRenderingServlet exte
GadgetContext context = new HttpGadgetContext(req);
RenderingResults results = renderer.render(context);
- switch (results.getStatus()) {
+
+ // process the rendering results
+ postGadgetRendering(new PostGadgetRenderingParams(req, resp, urlstatus, context, results));
+ }
+
+ /**
+ * Implementations that extend this class are strongly discouraged from overriding this method.
+ * To customize the behavior please override the hook methods for each of the
+ * RenderingResults.Status enum values instead.
+ */
+ protected void postGadgetRendering(PostGadgetRenderingParams params) throws IOException {
+ switch (params.getResults().getStatus()) {
case OK:
- if (context.getIgnoreCache() ||
- urlstatus == UriStatus.INVALID_VERSION) {
- HttpUtil.setCachingHeaders(resp, 0);
- } else if (urlstatus == UriStatus.VALID_VERSIONED) {
- // Versioned files get cached indefinitely
- HttpUtil.setCachingHeaders(resp, true);
- } else {
- // Unversioned files get cached for 5 minutes by default, but this can be overridden
- // with a query parameter.
- int ttl = DEFAULT_CACHE_TTL;
- String ttlStr = req.getParameter(ProxyBase.REFRESH_PARAM);
- if (!StringUtils.isEmpty(ttlStr)) {
- try {
- ttl = Integer.parseInt(ttlStr);
- } catch (NumberFormatException e) {
- // Ignore malformed TTL value
- LOG.info("Bad TTL value '" + ttlStr + "' was ignored");
- }
- }
- HttpUtil.setCachingHeaders(resp, ttl, true);
- }
- resp.getWriter().print(results.getContent());
+ onOkRenderingResultsStatus(params);
break;
case ERROR:
- resp.setStatus(results.getHttpStatusCode());
- resp.getWriter().print(StringEscapeUtils.escapeHtml(results.getErrorMessage()));
+ onErrorRenderingResultsStatus(params);
break;
case MUST_REDIRECT:
- resp.sendRedirect(results.getRedirect().toString());
+ onMustRedirectRenderingResultsStatus(params);
break;
}
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- // If an If-Modified-Since header is ever provided, we always say
- // not modified. This is because when there actually is a change,
- // cache busting should occur.
- UriStatus urlstatus = getUrlStatus(req);
- if (req.getHeader("If-Modified-Since") != null &&
- !"1".equals(req.getParameter("nocache")) &&
- urlstatus == UriStatus.VALID_VERSIONED) {
- resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- return;
+ protected void onOkRenderingResultsStatus(PostGadgetRenderingParams params)
+ throws IOException {
+ UriStatus urlStatus = params.getUrlStatus();
+ HttpServletResponse resp = params.getResponse();
+ if (params.getContext().getIgnoreCache() ||
+ urlStatus == UriStatus.INVALID_VERSION) {
+ HttpUtil.setCachingHeaders(resp, 0);
+ } else if (urlStatus == UriStatus.VALID_VERSIONED) {
+ // Versioned files get cached indefinitely
+ HttpUtil.setCachingHeaders(resp, true);
+ } else {
+ // Unversioned files get cached for 5 minutes by default, but this can be overridden
+ // with a query parameter.
+ int ttl = DEFAULT_CACHE_TTL;
+ String ttlStr = params.getRequest().getParameter(Param.REFRESH.getKey());
+ if (!StringUtils.isEmpty(ttlStr)) {
+ try {
+ ttl = Integer.parseInt(ttlStr);
+ } catch (NumberFormatException e) {
+ // Ignore malformed TTL value
+ LOG.info("Bad TTL value '" + ttlStr + "' was ignored");
+ }
+ }
+ HttpUtil.setCachingHeaders(resp, ttl, true);
}
- render(req, resp, urlstatus);
+ resp.getWriter().print(params.getResults().getContent());
}
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- render(req, resp, getUrlStatus(req));
+ protected void onErrorRenderingResultsStatus(PostGadgetRenderingParams params)
+ throws IOException {
+ HttpServletResponse resp = params.getResponse();
+ resp.setStatus(params.getResults().getHttpStatusCode());
+ resp.getWriter().print(StringEscapeUtils.escapeHtml(params.getResults().getErrorMessage()));
}
-
+
+ protected void onMustRedirectRenderingResultsStatus(PostGadgetRenderingParams params)
+ throws IOException {
+ params.getResponse().sendRedirect(params.getResults().getRedirect().toString());
+ }
+
private UriStatus getUrlStatus(HttpServletRequest req) {
return iframeUriManager.validateRenderingUri(new UriBuilder(req).toUri());
}
+
+ /**
+ * Contains the input parameters for post rendering methods.
+ */
+ protected static class PostGadgetRenderingParams {
+ private HttpServletRequest req;
+ private HttpServletResponse resp;
+ private UriStatus urlStatus;
+ private GadgetContext context;
+ private RenderingResults results;
+
+ public PostGadgetRenderingParams (HttpServletRequest req, HttpServletResponse resp,
+ UriStatus urlStatus, GadgetContext context, RenderingResults results) {
+ this.req = req;
+ this.resp = resp;
+ this.urlStatus = urlStatus;
+ this.context = context;
+ this.results = results;
+ }
+
+ public HttpServletRequest getRequest() {
+ return req;
+ }
+
+ public HttpServletResponse getResponse() {
+ return resp;
+ }
+
+ public UriStatus getUrlStatus() {
+ return urlStatus;
+ }
+
+ public GadgetContext getContext() {
+ return context;
+ }
+
+ public RenderingResults getResults() {
+ return results;
+ }
+ }
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HtmlAccelServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HtmlAccelServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HtmlAccelServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HtmlAccelServlet.java Tue Aug 10 11:32:26 2010
@@ -18,43 +18,62 @@
package org.apache.shindig.gadgets.servlet;
import com.google.inject.Inject;
-
import org.apache.shindig.common.servlet.InjectedServlet;
-import org.apache.shindig.gadgets.GadgetContext;
-
-import java.io.IOException;
-import java.util.logging.Logger;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.http.HttpResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Handles requests for accel servlet.
* The objective is to accelerate web pages.
*/
public class HtmlAccelServlet extends InjectedServlet {
+ private static final long serialVersionUID = -424353123863813052L;
- private AccelHandler accelHandler;
- private static Logger logger = Logger.getLogger(
+ private static final Logger logger = Logger.getLogger(
HtmlAccelServlet.class.getName());
-
- public static final String ACCEL_GADGET_PARAM_NAME = "accelGadget";
- public static final String ACCEL_GADGET_PARAM_VALUE = "true";
+ private transient AccelHandler accelHandler;
@Inject
public void setHandler(AccelHandler accelHandler) {
+ checkInitialized();
this.accelHandler = accelHandler;
}
@Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse servletResponse)
throws IOException {
- logger.fine("accel request = " + request.toString());
- accelHandler.fetch(request, response);
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Accel request = " + request.toString());
+ }
+
+ HttpRequest req = ServletUtil.fromHttpServletRequest(request);
+ HttpResponse response = null;
+ try {
+ response = accelHandler.fetch(req);
+ } catch (GadgetException e) {
+ response = ServletUtil.errorResponse(e);
+ }
+
+ ServletUtil.copyResponseToServlet(response, servletResponse);
}
- public static boolean isAccel(GadgetContext context) {
- return context.getParameter(HtmlAccelServlet.ACCEL_GADGET_PARAM_NAME) ==
- HtmlAccelServlet.ACCEL_GADGET_PARAM_VALUE;
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ doGet(request, response);
}
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsServlet.java Tue Aug 10 11:32:26 2010
@@ -29,6 +29,7 @@ import org.apache.shindig.common.servlet
import org.apache.shindig.common.uri.UriBuilder;
import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.GadgetException;
import org.apache.shindig.gadgets.RenderingContext;
import org.apache.shindig.gadgets.config.ConfigContributor;
import org.apache.shindig.gadgets.features.FeatureRegistry;
@@ -44,6 +45,8 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -52,6 +55,9 @@ import javax.servlet.http.HttpServletRes
* Used by type=URL gadgets in loading JavaScript resources.
*/
public class JsServlet extends InjectedServlet {
+
+ private static final long serialVersionUID = 6255917470412008175L;
+
static final String ONLOAD_JS_TPL = "(function() {" +
"var nm='%s';" +
"if (typeof window[nm]==='function') {" +
@@ -60,37 +66,53 @@ public class JsServlet extends InjectedS
"})();";
private static final Pattern ONLOAD_FN_PATTERN = Pattern.compile("[a-zA-Z0-9_]+");
- private FeatureRegistry registry;
+ private transient FeatureRegistry registry;
+ private transient JsUriManager jsUriManager;
+ private transient ContainerConfig containerConfig;
+ private transient Map<String, ConfigContributor> configContributors;
+
@Inject
public void setRegistry(FeatureRegistry registry) {
+ checkInitialized();
this.registry = registry;
}
-
- private JsUriManager jsUriManager;
+
@Inject
public void setUrlGenerator(JsUriManager jsUriManager) {
+ checkInitialized();
this.jsUriManager = jsUriManager;
}
- private ContainerConfig containerConfig;
@Inject
public void setContainerConfig(ContainerConfig containerConfig) {
+ checkInitialized();
this.containerConfig = containerConfig;
}
- private Map<String, ConfigContributor> configContributors;
@Inject
public void setConfigContributors(Map<String, ConfigContributor> configContributors) {
+ checkInitialized();
this.configContributors = configContributors;
}
@Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// If an If-Modified-Since header is ever provided, we always say
// not modified. This is because when there actually is a change,
// cache busting should occur.
- UriStatus vstatus = jsUriManager.processExternJsUri(new UriBuilder(req).toUri()).getStatus();
+ UriStatus vstatus;
+ try {
+ vstatus = jsUriManager.processExternJsUri(new UriBuilder(req).toUri()).getStatus();
+ } catch (GadgetException e) {
+ resp.sendError(e.getHttpStatusCode(), e.getMessage());
+ return;
+ }
if (req.getHeader("If-Modified-Since") != null &&
vstatus == UriStatus.VALID_VERSIONED) {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
@@ -108,7 +130,7 @@ public class JsServlet extends InjectedS
0, resourceName.length() - ".js".length());
}
- Set<String> needed = ImmutableSet.of(StringUtils.split(resourceName, ':'));
+ Set<String> needed = ImmutableSet.copyOf(StringUtils.split(resourceName, ':'));
String debugStr = req.getParameter("debug");
String containerParam = req.getParameter("container");
@@ -117,7 +139,7 @@ public class JsServlet extends InjectedS
boolean debug = "1".equals(debugStr);
final RenderingContext context = "1".equals(containerStr) ?
RenderingContext.CONTAINER : RenderingContext.GADGET;
- final String container =
+ final String container =
containerParam != null ? containerParam : ContainerConfig.DEFAULT_CONTAINER;
GadgetContext ctx = new GadgetContext() {
@@ -125,7 +147,7 @@ public class JsServlet extends InjectedS
public RenderingContext getRenderingContext() {
return context;
}
-
+
@Override
public String getContainer() {
return container;
@@ -169,7 +191,7 @@ public class JsServlet extends InjectedS
jsData.append("gadgets.config.init(").append(JsonSerializer.serialize(config)).append(");\n");
}
}
-
+
String onloadStr = req.getParameter("onload");
if (onloadStr != null) {
if (!ONLOAD_FN_PATTERN.matcher(onloadStr).matches()) {
@@ -178,7 +200,7 @@ public class JsServlet extends InjectedS
}
jsData.append(String.format(ONLOAD_JS_TPL, StringEscapeUtils.escapeJavaScript(onloadStr)));
}
-
+
if (jsData.length() == 0) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/JsonRpcHandler.java Tue Aug 10 11:32:26 2010
@@ -182,7 +182,7 @@ public class JsonRpcHandler {
JSONObject userPrefs = new JSONObject();
// User pref specs
- for (UserPref pref : spec.getUserPrefs()) {
+ for (UserPref pref : spec.getUserPrefs().values()) {
JSONObject up = new JSONObject()
.put("displayName", pref.getDisplayName())
.put("type", pref.getDataType().toString().toLowerCase())
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java Tue Aug 10 11:32:26 2010
@@ -25,8 +25,10 @@ import org.apache.commons.lang.StringUti
import org.apache.shindig.auth.AuthInfo;
import org.apache.shindig.auth.SecurityToken;
import org.apache.shindig.common.JsonSerializer;
+import org.apache.shindig.common.servlet.HttpUtil;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.common.util.Utf8UrlCoder;
+import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.gadgets.AuthType;
import org.apache.shindig.gadgets.FeedProcessor;
import org.apache.shindig.gadgets.FetchResponseUtils;
@@ -38,6 +40,8 @@ import org.apache.shindig.gadgets.http.R
import org.apache.shindig.gadgets.oauth.OAuthArguments;
import org.apache.shindig.gadgets.rewrite.ResponseRewriterRegistry;
import org.apache.shindig.gadgets.rewrite.RewritingException;
+import org.apache.shindig.gadgets.uri.UriCommon;
+import org.apache.shindig.gadgets.uri.UriCommon.Param;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -53,13 +57,12 @@ import javax.servlet.http.HttpServletRes
* Unlike ProxyHandler, this may perform operations such as OAuth or signed fetch.
*/
@Singleton
-public class MakeRequestHandler extends ProxyBase {
+public class MakeRequestHandler {
// Relaxed visibility for ease of integration. Try to avoid relying on these.
public static final String UNPARSEABLE_CRUFT = "throw 1; < don't be evil' >";
public static final String POST_DATA_PARAM = "postData";
public static final String METHOD_PARAM = "httpMethod";
public static final String HEADERS_PARAM = "headers";
- public static final String NOCACHE_PARAM = "nocache";
public static final String CONTENT_TYPE_PARAM = "contentType";
public static final String NUM_ENTRIES_PARAM = "numEntries";
public static final String DEFAULT_NUM_ENTRIES = "3";
@@ -80,8 +83,7 @@ public class MakeRequestHandler extends
/**
* Executes a request, returning the response as JSON to be handled by makeRequest.
*/
- @Override
- protected void doFetch(HttpServletRequest request, HttpServletResponse response)
+ public void fetch(HttpServletRequest request, HttpServletResponse response)
throws GadgetException, IOException {
HttpRequest rcr = buildHttpRequest(request);
@@ -116,18 +118,18 @@ public class MakeRequestHandler extends
* @throws GadgetException
*/
protected HttpRequest buildHttpRequest(HttpServletRequest request) throws GadgetException {
- String urlStr = request.getParameter(URL_PARAM);
+ String urlStr = request.getParameter(Param.URL.getKey());
if (urlStr == null) {
throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
- URL_PARAM + " parameter is missing.", HttpResponse.SC_BAD_REQUEST);
+ Param.URL.getKey() + " parameter is missing.", HttpResponse.SC_BAD_REQUEST);
}
Uri url = null;
try {
- url = validateUrl(Uri.parse(urlStr));
+ url = ServletUtil.validateUrl(Uri.parse(urlStr));
} catch (IllegalArgumentException e) {
throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
- "Invalid " + URL_PARAM + " parameter", HttpResponse.SC_BAD_REQUEST);
+ "Invalid " + Param.URL.getKey() + " parameter", HttpResponse.SC_BAD_REQUEST);
}
HttpRequest req = new HttpRequest(url)
@@ -157,18 +159,18 @@ public class MakeRequestHandler extends
req.addHeader("Content-Type", "application/x-www-form-urlencoded");
}
- req.setIgnoreCache("1".equals(request.getParameter(NOCACHE_PARAM)));
+ req.setIgnoreCache("1".equals(request.getParameter(Param.NO_CACHE.getKey())));
- if (request.getParameter(GADGET_PARAM) != null) {
- req.setGadget(Uri.parse(request.getParameter(GADGET_PARAM)));
+ if (request.getParameter(Param.GADGET.getKey()) != null) {
+ req.setGadget(Uri.parse(request.getParameter(Param.GADGET.getKey())));
}
// If the proxy request specifies a refresh param then we want to force the min TTL for
// the retrieved entry in the cache regardless of the headers on the content when it
// is fetched from the original source.
- if (request.getParameter(REFRESH_PARAM) != null) {
+ if (request.getParameter(Param.REFRESH.getKey()) != null) {
try {
- req.setCacheTtl(Integer.parseInt(request.getParameter(REFRESH_PARAM)));
+ req.setCacheTtl(Integer.parseInt(request.getParameter(Param.REFRESH.getKey())));
} catch (NumberFormatException nfe) {
// Ignore
}
@@ -176,7 +178,7 @@ public class MakeRequestHandler extends
// Allow the rewriter to use an externally forced mime type. This is needed
// allows proper rewriting of <script src="x"/> where x is returned with
// a content type like text/html which unfortunately happens all too often
- req.setRewriteMimeType(request.getParameter(REWRITE_MIME_TYPE_PARAM));
+ req.setRewriteMimeType(request.getParameter(Param.REWRITE_MIME_TYPE.getKey()));
// Figure out whether authentication is required
AuthType auth = AuthType.parse(getParameter(request, AUTHZ_PARAM, null));
@@ -186,7 +188,7 @@ public class MakeRequestHandler extends
req.setOAuthArguments(new OAuthArguments(auth, request));
}
- this.setRequestHeaders(request, req);
+ ServletUtil.setXForwardedForHeader(request, req);
return req;
}
@@ -220,7 +222,7 @@ public class MakeRequestHandler extends
HttpResponse results) throws GadgetException {
boolean getFullHeaders =
Boolean.parseBoolean(getParameter(request, GET_FULL_HEADERS_PARAM, "false"));
- String originalUrl = request.getParameter(ProxyBase.URL_PARAM);
+ String originalUrl = request.getParameter(Param.URL.getKey());
String body = results.getResponseAsString();
if (body.length() > 0) {
if ("FEED".equals(request.getParameter(CONTENT_TYPE_PARAM))) {
@@ -267,4 +269,53 @@ public class MakeRequestHandler extends
int numEntries = Integer.parseInt(getParameter(req, NUM_ENTRIES_PARAM, DEFAULT_NUM_ENTRIES));
return new FeedProcessor().process(url, xml, getSummaries, numEntries).toString();
}
+
+ /**
+ * Extracts the container name from the request.
+ */
+ @SuppressWarnings("deprecation")
+ static String getContainer(HttpServletRequest request) {
+ String container = request.getParameter(Param.CONTAINER.getKey());
+ if (container == null) {
+ container = request.getParameter(Param.SYND.getKey());
+ }
+ return container != null ? container : ContainerConfig.DEFAULT_CONTAINER;
+ }
+
+ /**
+ * getParameter helper method, returning default value if param not present.
+ */
+ static String getParameter(HttpServletRequest request, String key, String defaultValue) {
+ String ret = request.getParameter(key);
+ return ret != null ? ret : defaultValue;
+ }
+
+ /**
+ * Sets cache control headers for the response.
+ */
+ @SuppressWarnings("boxing")
+ static void setResponseHeaders(HttpServletRequest request,
+ HttpServletResponse response, HttpResponse results) throws GadgetException {
+ int refreshInterval = 0;
+ if (results.isStrictNoCache() || "1".equals(request.getParameter(UriCommon.Param.NO_CACHE.getKey()))) {
+ refreshInterval = 0;
+ } else if (request.getParameter(UriCommon.Param.REFRESH.getKey()) != null) {
+ try {
+ refreshInterval = Integer.valueOf(request.getParameter(UriCommon.Param.REFRESH.getKey()));
+ } catch (NumberFormatException nfe) {
+ throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
+ "refresh parameter is not a number");
+ }
+ } else {
+ refreshInterval = Math.max(60 * 60, (int)(results.getCacheTtl() / 1000L));
+ }
+ HttpUtil.setCachingHeaders(response, refreshInterval, false);
+
+ // Always set Content-Disposition header as XSS prevention mechanism.
+ response.setHeader("Content-Disposition", "attachment;filename=p.txt");
+
+ if (response.getContentType() == null) {
+ response.setContentType("application/octet-stream");
+ }
+ }
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestServlet.java Tue Aug 10 11:32:26 2010
@@ -19,9 +19,12 @@
package org.apache.shindig.gadgets.servlet;
import org.apache.shindig.common.servlet.InjectedServlet;
+import org.apache.shindig.gadgets.GadgetException;
import java.io.IOException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -36,17 +39,34 @@ import com.google.inject.Inject;
* makeRequest and open proxy calls.
*/
public class MakeRequestServlet extends InjectedServlet {
- private MakeRequestHandler makeRequestHandler;
+
+ private static final long serialVersionUID = -8298705081500283786L;
+
+ private transient MakeRequestHandler makeRequestHandler;
@Inject
public void setMakeRequestHandler(MakeRequestHandler makeRequestHandler) {
+ checkInitialized();
this.makeRequestHandler = makeRequestHandler;
}
@Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
- makeRequestHandler.fetch(request, response);
+ try {
+ makeRequestHandler.fetch(request, response);
+ } catch (GadgetException e) {
+ int responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+ if (e.getCode() != GadgetException.Code.INTERNAL_SERVER_ERROR) {
+ responseCode = HttpServletResponse.SC_BAD_REQUEST;
+ }
+ response.sendError(responseCode, e.getMessage() != null ? e.getMessage() : "");
+ }
}
@Override
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuthCallbackServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuthCallbackServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuthCallbackServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuthCallbackServlet.java Tue Aug 10 11:32:26 2010
@@ -32,6 +32,8 @@ import java.io.IOException;
import java.util.List;
import java.util.Map;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -50,10 +52,10 @@ import javax.servlet.http.HttpServletRes
*/
public class OAuthCallbackServlet extends InjectedServlet {
- public static final String CALLBACK_STATE_PARAM = "cs";
+ private static final long serialVersionUID = 7126255229334669172L;
+ public static final String CALLBACK_STATE_PARAM = "cs";
public static final String REAL_DOMAIN_PARAM = "d";
-
private static final int ONE_HOUR_IN_SECONDS = 3600;
// This bit of magic passes the entire callback URL into the opening gadget for later use.
@@ -78,15 +80,20 @@ public class OAuthCallbackServlet extend
"</body>\n" +
"</html>\n";
- private BlobCrypter stateCrypter;
-
+ private transient BlobCrypter stateCrypter;
+
@Inject
- public void setStateCrypter(
- @Named(OAuthFetcherConfig.OAUTH_STATE_CRYPTER) BlobCrypter stateCrypter) {
+ public void setStateCrypter(@Named(OAuthFetcherConfig.OAUTH_STATE_CRYPTER) BlobCrypter stateCrypter) {
+ checkInitialized();
this.stateCrypter = stateCrypter;
}
@Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
OAuthCallbackState callbackState = new OAuthCallbackState(stateCrypter,
req.getParameter(CALLBACK_STATE_PARAM));
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java Tue Aug 10 11:32:26 2010
@@ -23,107 +23,66 @@ import com.google.inject.Singleton;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.shindig.common.servlet.HttpUtil;
import org.apache.shindig.common.uri.Uri;
-import org.apache.shindig.common.uri.UriBuilder;
import org.apache.shindig.gadgets.GadgetException;
-import org.apache.shindig.gadgets.LockedDomainService;
import org.apache.shindig.gadgets.http.HttpRequest;
import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.http.HttpResponseBuilder;
import org.apache.shindig.gadgets.http.RequestPipeline;
import org.apache.shindig.gadgets.rewrite.ResponseRewriterRegistry;
import org.apache.shindig.gadgets.rewrite.RewritingException;
import org.apache.shindig.gadgets.uri.ProxyUriManager;
+import org.apache.shindig.gadgets.uri.UriUtils;
+import org.apache.shindig.gadgets.uri.UriUtils.DisallowedHeaders;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
/**
* Handles open proxy requests.
*/
@Singleton
-public class ProxyHandler extends ProxyBase {
- private static final Logger LOG = Logger.getLogger(ProxyHandler.class.getName());
-
+public class ProxyHandler {
// TODO: parameterize these.
static final Integer LONG_LIVED_REFRESH = (365 * 24 * 60 * 60); // 1 year
static final Integer DEFAULT_REFRESH = (60 * 60); // 1 hour
private final RequestPipeline requestPipeline;
- private final LockedDomainService lockedDomainService;
private final ResponseRewriterRegistry contentRewriterRegistry;
- private final ProxyUriManager proxyUriManager;
@Inject
public ProxyHandler(RequestPipeline requestPipeline,
- LockedDomainService lockedDomainService,
- ResponseRewriterRegistry contentRewriterRegistry,
- ProxyUriManager proxyUriManager) {
+ ResponseRewriterRegistry contentRewriterRegistry) {
this.requestPipeline = requestPipeline;
- this.lockedDomainService = lockedDomainService;
this.contentRewriterRegistry = contentRewriterRegistry;
- this.proxyUriManager = proxyUriManager;
}
/**
* Generate a remote content request based on the parameters sent from the client.
*/
- private HttpRequest buildHttpRequest(HttpServletRequest request,
+ private HttpRequest buildHttpRequest(
ProxyUriManager.ProxyUri uriCtx, Uri tgt) throws GadgetException {
- validateUrl(tgt);
+ ServletUtil.validateUrl(tgt);
HttpRequest req = uriCtx.makeHttpRequest(tgt);
- this.setRequestHeaders(request, req);
+ req.setRewriteMimeType(uriCtx.getRewriteMimeType());
return req;
}
- @Override
- protected void doFetch(HttpServletRequest request, HttpServletResponse response)
+ public HttpResponse fetch(ProxyUriManager.ProxyUri proxyUri)
throws IOException, GadgetException {
- if (request.getHeader("If-Modified-Since") != null) {
- response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- return;
- }
-
- // TODO: Consider removing due to redundant logic.
- String host = request.getHeader("Host");
- if (!lockedDomainService.isSafeForOpenProxy(host)) {
- // Force embedded images and the like to their own domain to avoid XSS
- // in gadget domains.
- String msg = "Embed request for url " + getParameter(request, URL_PARAM, "") +
- " made to wrong domain " + host;
- LOG.info(msg);
- throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, msg,
- HttpResponse.SC_BAD_REQUEST);
- }
-
- // Parse request uri:
- ProxyUriManager.ProxyUri proxyUri = proxyUriManager.process(
- new UriBuilder(request).toUri());
-
- try {
- HttpUtil.setCachingHeaders(response,
- proxyUri.translateStatusRefresh(LONG_LIVED_REFRESH, DEFAULT_REFRESH), false);
- } catch (GadgetException gex) {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST, gex.getMessage());
- return;
- }
-
- HttpRequest rcr = buildHttpRequest(request, proxyUri, proxyUri.getResource());
+ HttpRequest rcr = buildHttpRequest(proxyUri, proxyUri.getResource());
if (rcr == null) {
throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
- "No url paramater in request", HttpResponse.SC_BAD_REQUEST);
+ "No url parameter in request", HttpResponse.SC_BAD_REQUEST);
}
+
HttpResponse results = requestPipeline.execute(rcr);
if (results.isError()) {
// Error: try the fallback. Particularly useful for proxied images.
Uri fallbackUri = proxyUri.getFallbackUri();
if (fallbackUri != null) {
- HttpRequest fallbackRcr = buildHttpRequest(request, proxyUri, fallbackUri);
+ HttpRequest fallbackRcr = buildHttpRequest(proxyUri, fallbackUri);
results = requestPipeline.execute(fallbackRcr);
}
}
@@ -136,42 +95,63 @@ public class ProxyHandler extends ProxyB
e.getHttpStatusCode());
}
}
-
- for (Map.Entry<String, String> entry : results.getHeaders().entries()) {
- String name = entry.getKey();
- if (!DISALLOWED_RESPONSE_HEADERS.contains(name.toLowerCase())) {
- response.addHeader(name, entry.getValue());
- }
+
+ HttpResponseBuilder response = new HttpResponseBuilder(results);
+
+ try {
+ ServletUtil.setCachingHeaders(response,
+ proxyUri.translateStatusRefresh(LONG_LIVED_REFRESH, DEFAULT_REFRESH), false);
+ } catch (GadgetException gex) {
+ return ServletUtil.errorResponse(gex);
}
-
- String responseType = results.getHeader("Content-Type");
+
+ UriUtils.copyResponseHeadersAndStatusCode(results, response, true, true,
+ DisallowedHeaders.CACHING_DIRECTIVES, // Proxy sets its own caching headers.
+ DisallowedHeaders.CLIENT_STATE_DIRECTIVES, // Overridden or irrelevant to proxy.
+ DisallowedHeaders.OUTPUT_TRANSFER_DIRECTIVES
+ );
+
+ // Set Content-Type and Content-Disposition. Do this after copy results headers,
+ // in order to prevent those from overwriting the correct values.
+ setResponseContentHeaders(response, results);
+
+ response.setHeader("Content-Type", getContentType(rcr, response));
+
+ // TODO: replace this with streaming APIs when ready
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ IOUtils.copy(results.getResponse(), baos);
+ response.setResponse(baos.toByteArray());
+ return response.create();
+ }
+
+ private String getContentType(HttpRequest rcr, HttpResponseBuilder results) {
+ String contentType = results.getHeader("Content-Type");
if (!StringUtils.isEmpty(rcr.getRewriteMimeType())) {
String requiredType = rcr.getRewriteMimeType();
// Use a 'Vary' style check on the response
if (requiredType.endsWith("/*") &&
- !StringUtils.isEmpty(responseType)) {
+ !StringUtils.isEmpty(contentType)) {
requiredType = requiredType.substring(0, requiredType.length() - 2);
- if (!responseType.toLowerCase().startsWith(requiredType.toLowerCase())) {
- response.setContentType(requiredType);
- responseType = requiredType;
+ if (!contentType.toLowerCase().startsWith(requiredType.toLowerCase())) {
+ contentType = requiredType;
}
} else {
- response.setContentType(requiredType);
- responseType = requiredType;
+ contentType = requiredType;
}
}
+ return contentType;
+ }
- setResponseContentHeaders(response, results);
-
- if (results.getHttpStatusCode() != HttpResponse.SC_OK) {
- if (results.getHttpStatusCode() == HttpResponse.SC_INTERNAL_SERVER_ERROR) {
- // External "internal error" should be mapped to gateway error
- response.sendError(HttpResponse.SC_BAD_GATEWAY);
- } else {
- response.sendError(results.getHttpStatusCode());
- }
+ private void setResponseContentHeaders(HttpResponseBuilder response, HttpResponse results) {
+ // We're skipping the content disposition header for flash due to an issue with Flash player 10
+ // This does make some sites a higher value phishing target, but this can be mitigated by
+ // additional referer checks.
+ if (!"application/x-shockwave-flash".equalsIgnoreCase(results.getHeader("Content-Type")) &&
+ !"application/x-shockwave-flash".equalsIgnoreCase(response.getHeader("Content-Type"))) {
+ response.setHeader("Content-Disposition", "attachment;filename=p.txt");
+ }
+ if (results.getHeader("Content-Type") == null) {
+ response.setHeader("Content-Type", "application/octet-stream");
}
-
- IOUtils.copy(results.getResponse(), response.getOutputStream());
}
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyServlet.java Tue Aug 10 11:32:26 2010
@@ -18,10 +18,20 @@
*/
package org.apache.shindig.gadgets.servlet;
+import com.google.common.base.Preconditions;
import org.apache.shindig.common.servlet.InjectedServlet;
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.common.uri.UriBuilder;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.LockedDomainService;
+import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
import java.io.IOException;
+import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -32,16 +42,70 @@ import com.google.inject.Inject;
* gadgets.io.getProxyUrl).
*/
public class ProxyServlet extends InjectedServlet {
- private ProxyHandler proxyHandler;
+ private static final long serialVersionUID = 9085050443492307723L;
+
+ private static final Logger LOG = Logger.getLogger(ProxyServlet.class.getName());
+
+ private transient ProxyUriManager proxyUriManager;
+ private transient LockedDomainService lockedDomainService;
+ private transient ProxyHandler proxyHandler;
@Inject
public void setProxyHandler(ProxyHandler proxyHandler) {
+ checkInitialized();
this.proxyHandler = proxyHandler;
}
+
+ @Inject
+ public void setProxyUriManager(ProxyUriManager proxyUriManager) {
+ checkInitialized();
+ this.proxyUriManager = proxyUriManager;
+ }
+
+ @Inject
+ public void setLockedDomainService(LockedDomainService lockedDomainService) {
+ checkInitialized();
+ this.lockedDomainService = lockedDomainService;
+ }
@Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse servletResponse)
throws IOException {
- proxyHandler.fetch(request, response);
+ if (request.getHeader("If-Modified-Since") != null) {
+ servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+
+ Uri reqUri = new UriBuilder(request).toUri();
+ HttpResponse response = null;
+ try {
+ // Parse request uri:
+ ProxyUriManager.ProxyUri proxyUri = proxyUriManager.process(reqUri);
+
+ // TODO: Consider removing due to redundant logic.
+ String host = request.getHeader("Host");
+ if (!lockedDomainService.isSafeForOpenProxy(host)) {
+ // Force embedded images and the like to their own domain to avoid XSS
+ // in gadget domains.
+ Uri resourceUri = proxyUri.getResource();
+ String msg = "Embed request for url " +
+ (resourceUri != null ? resourceUri.toString() : "n/a") + " made to wrong domain " + host;
+ LOG.info(msg);
+ throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, msg,
+ HttpResponse.SC_BAD_REQUEST);
+ }
+
+ response = proxyHandler.fetch(proxyUri);
+ } catch (GadgetException e) {
+ response = ServletUtil.errorResponse(new GadgetException(e.getCode(), e.getMessage(),
+ HttpServletResponse.SC_BAD_REQUEST));
+ }
+
+ ServletUtil.copyResponseToServlet(response, servletResponse);
}
}
Modified: shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/RpcServlet.java
URL: http://svn.apache.org/viewvc/shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/RpcServlet.java?rev=983934&r1=983933&r2=983934&view=diff
==============================================================================
--- shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/RpcServlet.java (original)
+++ shindig/branches/2.0.x/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/RpcServlet.java Tue Aug 10 11:32:26 2010
@@ -18,6 +18,7 @@
*/
package org.apache.shindig.gadgets.servlet;
+import com.google.common.base.Preconditions;
import org.apache.commons.io.IOUtils;
import org.apache.shindig.common.servlet.HttpUtil;
import org.apache.shindig.common.servlet.InjectedServlet;
@@ -26,6 +27,8 @@ import org.json.JSONObject;
import com.google.inject.Inject;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -39,19 +42,28 @@ import java.util.logging.Logger;
* Handles RPC metadata requests.
*/
public class RpcServlet extends InjectedServlet {
+
+ private static final long serialVersionUID = 1382573217773582182L;
+
static final String GET_REQUEST_REQ_PARAM = "req";
static final String GET_REQUEST_CALLBACK_PARAM = "callback";
private static final Logger LOG = Logger.getLogger("org.apache.shindig.gadgets");
- private JsonRpcHandler jsonHandler;
+ private transient JsonRpcHandler jsonHandler;
@Inject
public void setJsonRpcHandler(JsonRpcHandler jsonHandler) {
+ checkInitialized();
this.jsonHandler = jsonHandler;
}
@Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String reqValue;
@@ -92,9 +104,7 @@ public class RpcServlet extends Injected
private String validateParameterValue(HttpServletRequest request, String parameter)
throws IllegalArgumentException {
String result = request.getParameter(parameter);
- if (result == null) {
- throw new IllegalArgumentException("No parameter '" + parameter + "' specified.");
- }
+ Preconditions.checkArgument(result != null, "No parameter '%s' specified", parameter);
return result;
}