Author: zhoresh
Date: Thu Nov  4 00:30:42 2010
New Revision: 1030777

URL: http://svn.apache.org/viewvc?rev=1030777&view=rev
Log:
Ref http://codereview.appspot.com/2851041/
Add proxy request to GadgetHandler

Modified:
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandler.java
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerApi.java
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/uri/ProxyUriBase.java
    
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java
    
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandler.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandler.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandler.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandler.java
 Thu Nov  4 00:30:42 2010
@@ -46,6 +46,7 @@ import java.util.concurrent.CompletionSe
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.ExecutorService;
+import java.util.logging.Logger;
 
 import javax.servlet.http.HttpServletResponse;
 
@@ -60,12 +61,18 @@ public class GadgetsHandler {
   static final String FAILURE_METADATA = "Failed to get gadget metadata.";
   @VisibleForTesting
   static final String FAILURE_TOKEN = "Failed to get gadget token.";
+  @VisibleForTesting
+  static final String FAILURE_PROXY = "Failed to get proxy data.";
 
   private static final List<String> DEFAULT_METADATA_FIELDS =
       ImmutableList.of("iframeUrl", "userPrefs.*", "modulePrefs.*", "views.*");
 
   private static final List<String> DEFAULT_TOKEN_FIELDS = 
ImmutableList.of("token");
 
+  private static final List<String> DEFAULT_PROXY_FIELDS = 
ImmutableList.of("proxyUrl");
+
+  private static final Logger LOG = 
Logger.getLogger(GadgetsHandler.class.getName());
+
   protected final ExecutorService executor;
   protected final GadgetsHandlerService handlerService;
 
@@ -106,6 +113,18 @@ public class GadgetsHandler {
     }.execute(request);
   }
 
+  @Operation(httpMethods = {"POST", "GET"}, path = "proxy.get")
+  public Map<String, GadgetsHandlerApi.BaseResponse> proxy(BaseRequestItem 
request)
+      throws ProtocolException {
+    return new AbstractExecutor() {
+      @Override
+      protected Callable<CallableData> createJob(String url, BaseRequestItem 
request)
+          throws ProcessingException {
+        return createProxyJob(url, request);
+      }
+    }.execute(request);
+  }
+
   @Operation(httpMethods = "GET", path = "/@metadata.supportedFields")
   public Set<String> supportedFields(RequestItem request) {
     return ImmutableSet.copyOf(beanFilter
@@ -118,6 +137,12 @@ public class GadgetsHandler {
         beanFilter.getBeanFields(GadgetsHandlerApi.TokenResponse.class, 5));
   }
 
+  @Operation(httpMethods = "GET", path = "/@proxy.supportedFields")
+  public Set<String> proxySupportedFields(RequestItem request) {
+    return ImmutableSet.copyOf(
+        beanFilter.getBeanFields(GadgetsHandlerApi.ProxyResponse.class, 5));
+  }
+
   /**
    * Class to handle threaded reply.
    * Mainly it made to support filtering the id (url)
@@ -214,6 +239,23 @@ public class GadgetsHandler {
     };
   }
 
+  // Hook to override in sub-class.
+  protected Callable<CallableData> createProxyJob(final String url,
+      BaseRequestItem request) throws ProcessingException {
+    final ProxyRequestData proxyRequest = new ProxyRequestData(url, request);
+    return new Callable<CallableData>() {
+      public CallableData call() throws Exception {
+        try {
+          return new CallableData(url, handlerService.getProxy(proxyRequest));
+        } catch (Exception e) {
+          return new CallableData(url,
+            handlerService.createErrorResponse(null, e, FAILURE_PROXY));
+        }
+      }
+    };
+  }
+
+
   /**
    * Gadget context classes used to translate JSON BaseRequestItem into a more
    * meaningful model objects that Java can work with.
@@ -236,6 +278,29 @@ public class GadgetsHandler {
       this.fields = processFields(request, defaultFields);
     }
 
+    protected Boolean getBooleanParam(BaseRequestItem request, String field) {
+      String val = request.getParameter(field);
+      if (val != null) {
+        return "1".equals(val) || Boolean.valueOf(val);
+      }
+      return false;
+    }
+
+    protected Integer getIntegerParam(BaseRequestItem request, String field)
+        throws ProcessingException {
+      String val = request.getParameter(field);
+      Integer intVal = null;
+      if (val != null) {
+        try {
+          intVal = Integer.valueOf(val);
+        } catch (NumberFormatException e) {
+          throw new ProcessingException("Error parsing " + field + " 
parameter",
+              HttpServletResponse.SC_BAD_REQUEST);
+        }
+      }
+      return intVal;
+    }
+
     public Uri getUrl() {
       return uri;
     }
@@ -254,6 +319,87 @@ public class GadgetsHandler {
     }
   }
 
+  protected class ProxyRequestData extends AbstractRequest
+      implements GadgetsHandlerApi.ProxyRequest {
+
+    private final String gadget;
+    private final Integer refresh;
+    private final boolean debug;
+    private final boolean ignoreCache;
+    private final String fallbackUrl;
+    private final String mimetype;
+    private final boolean sanitize;
+    private final boolean cajole;
+    private final GadgetsHandlerApi.ImageParams imageParams;
+
+    public ProxyRequestData(String url, BaseRequestItem request) throws 
ProcessingException {
+      super(url, request, DEFAULT_PROXY_FIELDS);
+      this.ignoreCache = getBooleanParam(request, "ignoreCache");
+      this.debug = getBooleanParam(request, "debug");
+      this.sanitize = getBooleanParam(request, "sanitize");
+      this.cajole = getBooleanParam(request, "cajole");
+      this.gadget = request.getParameter("gadget");
+      this.fallbackUrl = request.getParameter("fallback_url");
+      this.mimetype = request.getParameter("rewriteMime");
+      this.refresh = getIntegerParam(request, "refresh");
+      imageParams = getImageParams(request);
+    }
+
+    private GadgetsHandlerApi.ImageParams getImageParams(BaseRequestItem 
request)
+        throws ProcessingException {
+      GadgetsHandlerApi.ImageParams params = null;
+      Boolean doNotExpand = getBooleanParam(request, "no_expand");
+      Integer height = getIntegerParam(request, "resize_h");
+      Integer width = getIntegerParam(request, "resize_w");
+      Integer quality = getIntegerParam(request, "resize_q");
+
+      if (height != null || width != null) {
+        return beanDelegator.createDelegator(null, 
GadgetsHandlerApi.ImageParams.class,
+            ImmutableMap.<String, Object>of(
+                "height", BeanDelegator.nullable(height),
+                "width", BeanDelegator.nullable(width),
+                "quality", BeanDelegator.nullable(quality),
+                "donotexpand", BeanDelegator.nullable(doNotExpand)));
+      }
+      return params;
+    }
+
+    public boolean getDebug() {
+      return debug;
+    }
+
+    public String getFallbackUrl() {
+      return fallbackUrl;
+    }
+
+    public boolean getIgnoreCahce() {
+      return ignoreCache;
+    }
+
+    public GadgetsHandlerApi.ImageParams getImageParams() {
+      return imageParams;
+    }
+
+    public Integer getRefresh() {
+      return refresh;
+    }
+
+    public String getRewriteMimeType() {
+      return mimetype;
+    }
+
+    public boolean getSanitize() {
+      return sanitize;
+    }
+
+    public boolean getCajole() {
+      return cajole;
+    }
+
+    public String getGadget() {
+      return gadget;
+    }
+  }
 
   protected class TokenRequestData extends AbstractRequest
       implements GadgetsHandlerApi.TokenRequest {
@@ -284,8 +430,8 @@ public class GadgetsHandler {
       this.locale =
           (lang != null && country != null) ? new Locale(lang, country) : 
(lang != null)
               ? new Locale(lang) : GadgetSpec.DEFAULT_LOCALE;
-      this.ignoreCache = Boolean.valueOf(request.getParameter("ignoreCache"));
-      this.debug = Boolean.valueOf(request.getParameter("debug"));
+      this.ignoreCache = getBooleanParam(request, "ignoreCache");
+      this.debug = getBooleanParam(request, "debug");
     }
 
     public int getModuleId() {

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerApi.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerApi.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerApi.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerApi.java
 Thu Nov  4 00:30:42 2010
@@ -54,8 +54,10 @@ public class GadgetsHandlerApi {
     @Unfiltered
     public Error getError();
     /** The response expiration time (miliseconds since epoch), -1 for no 
caching */
+    @Unfiltered
     public Long getExpireTimeMs();
     /** The response time (miliseconds since epoch) - usefull for 
misconfigured client time */
+    @Unfiltered
     public Long getResponseTimeMs();
   }
 
@@ -100,10 +102,8 @@ public class GadgetsHandlerApi {
     public Uri getHref();
     public boolean getQuirks();
     public String getContent();
-    public int getPreferredHeight();
-    public int getPreferredWidth();
-    public boolean needsUserPrefSubstitution();
-    public Map<String, String> getAttributes();
+    public int getPreferredHeight(); // Default to 0
+    public int getPreferredWidth();  // Default to 0
   }
 
   public enum UserPrefDataType {
@@ -116,7 +116,6 @@ public class GadgetsHandlerApi {
     public String getDefaultValue();
     public boolean getRequired();
     public UserPrefDataType getDataType();
-    public Map<String, String> getEnumValues();
     public List<EnumValuePair> getOrderedEnumValues();
   }
 
@@ -172,4 +171,50 @@ public class GadgetsHandlerApi {
   public interface TokenResponse extends BaseResponse {
     public String getToken();
   }
+
+  public interface ProxyRequest extends BaseRequest {
+    // The BaseRequest.url store the resource to proxy
+    public String getGadget();
+    public Integer getRefresh();
+    public boolean getDebug();
+    public boolean getIgnoreCahce();
+    public String getFallbackUrl();
+    public String getRewriteMimeType();
+    public boolean getSanitize();
+    public boolean getCajole();
+    public ImageParams getImageParams();
+  }
+
+  public interface ImageParams {
+    public Integer getHeight();
+    public Integer getWidth();
+    public Integer getQuality();
+    public Boolean getDoNotExpand();
+  }
+
+  public interface ProxyResponse extends BaseResponse {
+    public Uri getProxyUrl();
+    public HttpResponse getProxyContent();
+  }
+
+  public interface HttpResponse {
+    public int getCode();
+    public String getEncoding();
+    public String getContentBase64();
+    public List<NameValuePair> getHeaders();
+  }
+
+  public interface NameValuePair {
+    public String getName();
+    public String getValue();
+  }
+
+  public interface JsRequest extends BaseRequest {
+    public List<String> getFeatures();
+    public boolean getForContainer();
+  }
+
+  public interface JsResponse extends BaseResponse {
+    public Uri getJsUrl();
+  }
 }

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java
 Thu Nov  4 00:30:42 2010
@@ -19,10 +19,13 @@
 package org.apache.shindig.gadgets.servlet;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
+import org.apache.commons.codec.binary.Base64InputStream;
+import org.apache.commons.io.IOUtils;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.auth.SecurityTokenCodec;
 import org.apache.shindig.auth.SecurityTokenException;
@@ -30,6 +33,7 @@ import org.apache.shindig.common.uri.Uri
 import org.apache.shindig.common.util.TimeSource;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.RenderingContext;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.process.ProcessingException;
@@ -42,12 +46,19 @@ import org.apache.shindig.gadgets.spec.U
 import org.apache.shindig.gadgets.spec.View;
 import org.apache.shindig.gadgets.spec.UserPref.EnumValuePair;
 import org.apache.shindig.gadgets.uri.IframeUriManager;
+import org.apache.shindig.gadgets.uri.JsUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager.ProxyUri;
 import org.apache.shindig.protocol.conversion.BeanDelegator;
 import org.apache.shindig.protocol.conversion.BeanFilter;
 
+import java.io.IOException;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.servlet.http.HttpServletResponse;
 
@@ -60,6 +71,8 @@ public class GadgetsHandlerService {
 
   private static final Locale DEFAULT_LOCALE = new Locale("all", "all");
 
+  private static final Logger LOG = 
Logger.getLogger(GadgetsHandler.class.getName());
+
   // Map shindig data class to API interfaces
   @VisibleForTesting
   static final Map<Class<?>, Class<?>> apiClasses =
@@ -91,6 +104,9 @@ public class GadgetsHandlerService {
   protected final Processor processor;
   protected final IframeUriManager iframeUriManager;
   protected final SecurityTokenCodec securityTokenCodec;
+  protected final ProxyUriManager proxyUriManager;
+  protected final JsUriManager jsUriManager;
+  protected final ProxyHandler proxyHandler;
   protected final BeanDelegator beanDelegator;
   protected final long specRefreshInterval;
   protected final BeanFilter beanFilter;
@@ -98,12 +114,16 @@ public class GadgetsHandlerService {
   @Inject
   public GadgetsHandlerService(TimeSource timeSource, Processor processor,
       IframeUriManager iframeUriManager, SecurityTokenCodec securityTokenCodec,
+      ProxyUriManager proxyUriManager, JsUriManager jsUriManager, ProxyHandler 
proxyHandler,
       @Named("shindig.cache.xml.refreshInterval") long specRefreshInterval,
       BeanFilter beanFilter) {
     this.timeSource = timeSource;
     this.processor = processor;
     this.iframeUriManager = iframeUriManager;
     this.securityTokenCodec = securityTokenCodec;
+    this.proxyUriManager = proxyUriManager;
+    this.jsUriManager = jsUriManager;
+    this.proxyHandler = proxyHandler;
     this.specRefreshInterval = specRefreshInterval;
     this.beanFilter = beanFilter;
 
@@ -170,6 +190,57 @@ public class GadgetsHandlerService {
     return createTokenResponse(request.getUrl(), token, fields, expiryTimeMs);
   }
 
+  public GadgetsHandlerApi.ProxyResponse 
getProxy(GadgetsHandlerApi.ProxyRequest request)
+      throws ProcessingException {
+    if (request.getContainer() == null) {
+      throw new ProcessingException("Missing container paramater", 
HttpResponse.SC_BAD_REQUEST);
+    }
+    if (request.getUrl() == null) {
+      throw new ProcessingException("Missing proxy url paramater", 
HttpResponse.SC_BAD_REQUEST);
+    }
+    if (request.getFields() == null) {
+      throw new ProcessingException("Missing fields paramater", 
HttpResponse.SC_BAD_REQUEST);
+    }
+    Set<String> fields = beanFilter.processBeanFields(request.getFields());
+
+    ProxyUri proxyUri = createProxyUri(request);
+    List<Uri> uris = proxyUriManager.make(ImmutableList.of(proxyUri), null);
+
+    HttpResponse httpResponse = null;
+    try {
+      if (isFieldIncluded(fields, "proxyContent")) {
+        httpResponse = proxyHandler.fetch(proxyUri);
+      }
+    } catch (IOException e) {
+      LOG.log(Level.INFO, "Failed to fetch resource " + 
proxyUri.getResource().toString(), e);
+      throw new ProcessingException("Error getting response content", 
HttpResponse.SC_BAD_GATEWAY);
+    } catch (GadgetException e) {
+      // TODO: Clean this log if it is too spammy
+      LOG.log(Level.INFO, "Failed to fetch resource " + 
proxyUri.getResource().toString(), e);
+      throw new ProcessingException("Error getting response content", 
HttpResponse.SC_BAD_GATEWAY);
+    }
+
+    try {
+      return createProxyResponse(uris.get(0), httpResponse, fields,
+          getProxyExpireMs(proxyUri, httpResponse));
+    } catch (IOException e) {
+      // Should never happen!
+      LOG.log(Level.WARNING, "Error creating proxy response", e);
+      throw new ProcessingException("Error getting response content",
+          HttpResponse.SC_INTERNAL_SERVER_ERROR);
+    }
+  }
+
+  protected Long getProxyExpireMs(ProxyUri proxyUri, HttpResponse 
httpResponse) {
+    Long expireMs = null;
+    if (httpResponse != null) {
+      expireMs = httpResponse.getCacheExpiration();
+    } else if (proxyUri.getRefresh() != null) {
+      expireMs = timeSource.currentTimeMillis() + proxyUri.getRefresh() * 1000;
+    }
+    return expireMs;
+  }
+
   /**
    * GadgetContext for metadata request. Used by the gadget processor
    */
@@ -247,6 +318,7 @@ public class GadgetsHandlerService {
       return createErrorResponse(uri, processingExc.getHttpStatusCode(),
           processingExc.getMessage());
     }
+    LOG.log(Level.WARNING, "Error handling request: " + (uri != null ? 
uri.toString() : ""), e);
     return createErrorResponse(uri, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, defaultMsg);
   }
 
@@ -289,4 +361,64 @@ public class GadgetsHandlerService {
                 "expiretimems", BeanDelegator.nullable(tokenExpire))),
         fields);
   }
+
+  @VisibleForTesting
+  ProxyUri createProxyUri(GadgetsHandlerApi.ProxyRequest request) {
+    ProxyUriManager.ProxyUri proxyUri = new 
ProxyUriManager.ProxyUri(request.getRefresh(),
+        request.getDebug(), request.getIgnoreCahce(), request.getContainer(),
+        request.getGadget(), request.getUrl());
+
+    proxyUri.setFallbackUrl(request.getFallbackUrl())
+        .setRewriteMimeType(request.getRewriteMimeType())
+        .setSanitizeContent(request.getSanitize())
+        .setCajoleContent(request.getCajole());
+
+    GadgetsHandlerApi.ImageParams image = request.getImageParams();
+    if (image != null) {
+      proxyUri.setResize( image.getWidth(), image.getHeight(),
+          image.getQuality(), image.getDoNotExpand());
+    }
+    return proxyUri;
+  }
+
+  @VisibleForTesting
+  GadgetsHandlerApi.ProxyResponse createProxyResponse(Uri uri, HttpResponse 
httpResponse,
+      Set<String> fields, Long expireMs) throws IOException {
+
+    GadgetsHandlerApi.HttpResponse beanHttp = null;
+    if (httpResponse != null) {
+      // Stream out the base64-encoded data.
+      // Ctor args indicate to encode w/o line breaks.
+      Base64InputStream b64input = new 
Base64InputStream(httpResponse.getResponse(), true, 0, null);
+      String content = IOUtils.toString(b64input);
+
+      ImmutableList.Builder<GadgetsHandlerApi.NameValuePair> headersBuilder =
+          ImmutableList.builder();
+      for (final Map.Entry<String, String> entry : 
httpResponse.getHeaders().entries()) {
+        headersBuilder.add(
+            beanDelegator.createDelegator(null, 
GadgetsHandlerApi.NameValuePair.class,
+                ImmutableMap.<String, Object>of("name", entry.getKey(), 
"value", entry.getValue()))
+        );
+      }
+
+      beanHttp = beanDelegator.createDelegator(null, 
GadgetsHandlerApi.HttpResponse.class,
+          ImmutableMap.<String, Object>of(
+              "code", httpResponse.getHttpStatusCode(),
+              "encoding", httpResponse.getEncoding(),
+              "contentbase64", content,
+              "headers", headersBuilder.build()));
+    }
+
+    return (GadgetsHandlerApi.ProxyResponse) beanFilter.createFilteredBean(
+      beanDelegator.createDelegator(null, 
GadgetsHandlerApi.ProxyResponse.class,
+          ImmutableMap.<String, Object>builder()
+              .put("proxyurl", uri)
+              .put("proxycontent", BeanDelegator.nullable(beanHttp))
+              .put("url", BeanDelegator.NULL)
+              .put("error", BeanDelegator.NULL)
+              .put("responsetimems", timeSource.currentTimeMillis())
+              .put("expiretimems", BeanDelegator.nullable(expireMs))
+              .build()),
+      fields);
+  }
 }

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/uri/ProxyUriBase.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/uri/ProxyUriBase.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/uri/ProxyUriBase.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/uri/ProxyUriBase.java
 Thu Nov  4 00:30:42 2010
@@ -217,7 +217,9 @@ public class ProxyUriBase {
     // Add all params common to both chained and query syntax.
     String container = getContainer();
     queryBuilder.addQueryParameter(Param.CONTAINER.getKey(), container);
-    queryBuilder.addQueryParameter(Param.GADGET.getKey(), getGadget());
+    if (getGadget() != null) {
+      queryBuilder.addQueryParameter(Param.GADGET.getKey(), getGadget());
+    }
     queryBuilder.addQueryParameter(Param.DEBUG.getKey(), isDebug() ? "1" : 
"0");
     queryBuilder.addQueryParameter(Param.NO_CACHE.getKey(), isNoCache() ? "1" 
: "0");
     if (!isNoCache()) {

Modified: 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java
 Thu Nov  4 00:30:42 2010
@@ -18,23 +18,37 @@
  */
 package org.apache.shindig.gadgets.servlet;
 
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.capture;
+
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.auth.SecurityTokenCodec;
 import org.apache.shindig.auth.SecurityTokenException;
 import org.apache.shindig.common.EasyMockTestCase;
 import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.util.FakeTimeSource;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.GadgetException.Code;
 import org.apache.shindig.gadgets.features.FeatureRegistry;
+import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.http.HttpResponseBuilder;
 import org.apache.shindig.gadgets.process.ProcessingException;
+import org.apache.shindig.gadgets.uri.JsUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager.ProxyUri;
 import org.apache.shindig.protocol.conversion.BeanDelegator;
 import org.apache.shindig.protocol.conversion.BeanFilter;
+import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.nio.charset.Charset;
 import java.util.List;
 import java.util.Map;
 
@@ -48,6 +62,8 @@ public class GadgetsHandlerServiceTest e
   private static final Long SPEC_REFRESH_INTERVAL_MS = 456L;
   private static final Long METADATA_EXPIRY_TIME_MS = CURRENT_TIME_MS + 
SPEC_REFRESH_INTERVAL_MS;
   private static final Long TOKEN_EXPIRY_TIME_MS = CURRENT_TIME_MS + 789L;
+  private static final Uri RESOURCE = Uri.parse("http://example.com/data";);
+  private static final String FALLBACK = "http://example.com/data2";;
 
   private final BeanDelegator delegator = new BeanDelegator(
     GadgetsHandlerService.apiClasses, GadgetsHandlerService.enumConversionMap);
@@ -56,6 +72,9 @@ public class GadgetsHandlerServiceTest e
   private final FeatureRegistry mockRegistry = mock(FeatureRegistry.class);
   private final FakeProcessor processor = new FakeProcessor(mockRegistry);
   private final FakeIframeUriManager urlGenerator = new FakeIframeUriManager();
+  private final ProxyUriManager proxyUriManager = mock(ProxyUriManager.class);
+  private final JsUriManager jsUriManager = mock(JsUriManager.class);
+  private final ProxyHandler proxyHandler = mock(ProxyHandler.class);
 
   private FakeSecurityTokenCodec tokenCodec;
   private GadgetsHandlerService gadgetHandler;
@@ -64,7 +83,8 @@ public class GadgetsHandlerServiceTest e
   public void setUp() {
     tokenCodec = new FakeSecurityTokenCodec();
     gadgetHandler = new GadgetsHandlerService(timeSource, processor, 
urlGenerator,
-        tokenCodec, SPEC_REFRESH_INTERVAL_MS, new BeanFilter());
+        tokenCodec, proxyUriManager, jsUriManager, proxyHandler,
+        SPEC_REFRESH_INTERVAL_MS, new BeanFilter());
   }
 
   // Next test verify that the API data classes are configured correctly.
@@ -98,7 +118,7 @@ public class GadgetsHandlerServiceTest e
         
response.getModulePrefs().getLinks().get(FakeProcessor.LINK_REL).getRel());
     assertEquals(1, response.getUserPrefs().size());
     assertEquals("up_one", 
response.getUserPrefs().get("up_one").getDisplayName());
-    assertEquals(4, 
response.getUserPrefs().get("up_one").getEnumValues().size());
+    assertEquals(4, 
response.getUserPrefs().get("up_one").getOrderedEnumValues().size());
     assertEquals(CURRENT_TIME_MS, response.getResponseTimeMs());
     assertEquals(METADATA_EXPIRY_TIME_MS, response.getExpireTimeMs());
     verify();
@@ -239,6 +259,150 @@ public class GadgetsHandlerServiceTest e
     verify();
   }
 
+  @Test
+  public void testCreateProxyUri() throws Exception {
+    GadgetsHandlerApi.ImageParams image = 
mock(GadgetsHandlerApi.ImageParams.class);
+    expect(image.getDoNotExpand()).andStubReturn(true);
+    expect(image.getHeight()).andStubReturn(120);
+    expect(image.getWidth()).andStubReturn(210);
+    expect(image.getQuality()).andStubReturn(77);
+
+    GadgetsHandlerApi.ProxyRequest request = 
mock(GadgetsHandlerApi.ProxyRequest.class);
+    expect(request.getContainer()).andStubReturn(CONTAINER);
+    expect(request.getUrl()).andStubReturn(RESOURCE);
+    expect(request.getCajole()).andStubReturn(true);
+    expect(request.getRefresh()).andStubReturn(new Integer(333));
+    expect(request.getDebug()).andStubReturn(true);
+    expect(request.getFallbackUrl()).andStubReturn(FALLBACK);
+    
expect(request.getGadget()).andStubReturn(FakeProcessor.SPEC_URL.toString());
+    expect(request.getIgnoreCahce()).andStubReturn(true);
+    expect(request.getImageParams()).andStubReturn(image);
+    expect(request.getRewriteMimeType()).andStubReturn("image/png");
+    expect(request.getSanitize()).andStubReturn(true);
+    replay();
+    ProxyUri pUri = gadgetHandler.createProxyUri(request);
+
+    ProxyUri expectedUri = new ProxyUri(333, true, true, CONTAINER,
+        FakeProcessor.SPEC_URL.toString(), RESOURCE);
+    
expectedUri.setCajoleContent(true).setRewriteMimeType("image/png").setSanitizeContent(true);
+    expectedUri.setResize(210, 120, 77, true).setFallbackUrl(FALLBACK);
+    assertEquals(pUri, expectedUri);
+    verify();
+  }
+
+  @Test
+  public void testValidateProxyResponse() throws Exception {
+    GadgetsHandlerApi.ProxyResponse response =
+        gadgetHandler.createProxyResponse(RESOURCE, null, 
ImmutableSet.<String>of("*"), 1000001L);
+
+    BeanDelegator.validateDelegator(response);
+    assertEquals(RESOURCE, response.getProxyUrl());
+    assertNull(response.getProxyContent());
+  }
+
+  @Test
+  public void testCreateProxyResponse() throws Exception {
+    HttpResponseBuilder httpResponse = new HttpResponseBuilder();
+    httpResponse.setContent("Content");
+    httpResponse.addHeader("header", "hval");
+    httpResponse.setEncoding(Charset.forName("UTF8"));
+    httpResponse.setHttpStatusCode(404);
+
+    GadgetsHandlerApi.ProxyResponse response = 
gadgetHandler.createProxyResponse(
+        RESOURCE, httpResponse.create(), ImmutableSet.<String>of("*"), 
1000001L);
+    BeanDelegator.validateDelegator(response);
+    assertEquals("Content",
+        new 
String(Base64.decodeBase64(response.getProxyContent().getContentBase64())));
+    assertEquals(404, response.getProxyContent().getCode());
+    assertEquals(2, response.getProxyContent().getHeaders().size());
+    assertEquals("Date", 
response.getProxyContent().getHeaders().get(0).getName());
+    assertEquals("header", 
response.getProxyContent().getHeaders().get(1).getName());
+    assertEquals("hval", 
response.getProxyContent().getHeaders().get(1).getValue());
+  }
+
+  @Test
+  public void testFilterProxyResponse() throws Exception {
+    HttpResponse httpResponse = new HttpResponse("data");
+    GadgetsHandlerApi.ProxyResponse response = 
gadgetHandler.createProxyResponse(
+        RESOURCE, httpResponse, ImmutableSet.<String>of("proxyurl"), 1000001L);
+    assertNull(response.getProxyContent());
+    assertEquals(RESOURCE, response.getProxyUrl());
+  }
+
+  @Test
+  public void testGetProxySimple() throws Exception {
+    List<String> fields = ImmutableList.of("proxyurl");
+    Uri resUri = Uri.parse("server.com/gadgets/proxy?url=" + RESOURCE);
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(RESOURCE, 
CONTAINER, fields);
+    Capture<List<ProxyUri>> uriCapture = new Capture<List<ProxyUri>>();
+    expect(proxyUriManager.make(capture(uriCapture), EasyMock.anyInt()))
+        .andReturn(ImmutableList.of(resUri));
+    replay();
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+    assertEquals(1, uriCapture.getValue().size());
+    ProxyUri pUri = uriCapture.getValue().get(0);
+    assertEquals(CONTAINER, pUri.getContainer());
+    assertEquals(resUri, response.getProxyUrl());
+    assertNull(response.getProxyContent());
+    verify();
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testGetProxyNoContainer() throws Exception {
+    List<String> fields = ImmutableList.of("*");
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(RESOURCE, 
null, fields);
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testGetProxyNoResource() throws Exception {
+    List<String> fields = ImmutableList.of("*");
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(null, 
CONTAINER, fields);
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testGetProxyNoFields() throws Exception {
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(RESOURCE, 
CONTAINER, null);
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+  }
+
+  @Test
+  public void testGetProxyData() throws Exception {
+    List<String> fields = ImmutableList.of("proxycontent.*");
+    Uri resUri = Uri.parse("server.com/gadgets/proxy?url=" + RESOURCE);
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(RESOURCE, 
CONTAINER, fields);
+    Capture<List<ProxyUri>> uriCapture = new Capture<List<ProxyUri>>();
+    expect(proxyUriManager.make(capture(uriCapture), EasyMock.anyInt()))
+        .andReturn(ImmutableList.of(resUri));
+    HttpResponse httpResponse = new HttpResponse("response");
+    
expect(proxyHandler.fetch(EasyMock.isA(ProxyUri.class))).andReturn(httpResponse);
+    replay();
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+    assertEquals(1, uriCapture.getValue().size());
+    ProxyUri pUri = uriCapture.getValue().get(0);
+    assertEquals(CONTAINER, pUri.getContainer());
+    assertNull(response.getProxyUrl());
+    assertEquals("response",
+        new 
String(Base64.decodeBase64(response.getProxyContent().getContentBase64())));
+    verify();
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testGetProxyDataFail() throws Exception {
+    List<String> fields = ImmutableList.of("proxycontent.*");
+    Uri resUri = Uri.parse("server.com/gadgets/proxy?url=" + RESOURCE);
+    GadgetsHandlerApi.ProxyRequest request = createProxyRequest(RESOURCE, 
CONTAINER, fields);
+    Capture<List<ProxyUri>> uriCapture = new Capture<List<ProxyUri>>();
+    expect(proxyUriManager.make(capture(uriCapture), EasyMock.anyInt()))
+        .andReturn(ImmutableList.of(resUri));
+    HttpResponse httpResponse = new HttpResponse("response");
+    expect(proxyHandler.fetch(EasyMock.isA(ProxyUri.class)))
+        .andThrow(new GadgetException(Code.FAILED_TO_RETRIEVE_CONTENT));
+    replay();
+    GadgetsHandlerApi.ProxyResponse response = gadgetHandler.getProxy(request);
+  }
+
   private GadgetsHandlerApi.TokenData createTokenData(String ownerId, String 
viewerId) {
     GadgetsHandlerApi.TokenData token = 
mock(GadgetsHandlerApi.TokenData.class);
     if (ownerId != null) {
@@ -271,6 +435,14 @@ public class GadgetsHandlerServiceTest e
     return request;
   }
 
+  private GadgetsHandlerApi.ProxyRequest createProxyRequest(Uri url, String 
container,
+      List<String> fields) {
+    GadgetsHandlerApi.ProxyRequest request = 
mock(GadgetsHandlerApi.ProxyRequest.class);
+    EasyMock.expect(request.getFields()).andStubReturn(fields);
+    EasyMock.expect(request.getContainer()).andStubReturn(container);
+    EasyMock.expect(request.getUrl()).andStubReturn(url);
+    return request;
+  }
   private class FakeSecurityTokenCodec implements SecurityTokenCodec {
     public SecurityToken inputToken = null;
     public SecurityTokenException exc = null;

Modified: 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java?rev=1030777&r1=1030776&r2=1030777&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java
 Thu Nov  4 00:30:42 2010
@@ -22,6 +22,7 @@ import com.google.common.collect.Immutab
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.auth.SecurityTokenCodec;
 import org.apache.shindig.auth.SecurityTokenException;
@@ -29,9 +30,14 @@ import org.apache.shindig.common.EasyMoc
 import org.apache.shindig.common.JsonAssert;
 import org.apache.shindig.common.testing.FakeGadgetToken;
 import org.apache.shindig.common.testing.TestExecutorService;
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.util.FakeTimeSource;
+import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.process.ProcessingException;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.uri.JsUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager;
+import org.apache.shindig.gadgets.uri.ProxyUriManager.ProxyUri;
 import org.apache.shindig.protocol.DefaultHandlerRegistry;
 import org.apache.shindig.protocol.HandlerExecutionListener;
 import org.apache.shindig.protocol.HandlerRegistry;
@@ -48,6 +54,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import javax.servlet.http.HttpServletResponse;
@@ -64,6 +71,9 @@ public class GadgetsHandlerTest extends 
   private final FakeProcessor processor = new FakeProcessor();
   private final FakeIframeUriManager urlGenerator = new FakeIframeUriManager();
   private final Map<String, FormDataItem> emptyFormItems = 
Collections.emptyMap();
+  private final ProxyUriManager proxyUriManager = mock(ProxyUriManager.class);
+  private final JsUriManager jsUriManager = mock(JsUriManager.class);
+  private final ProxyHandler proxyHandler = mock(ProxyHandler.class);
 
   private Injector injector;
   private BeanJsonConverter converter;
@@ -81,7 +91,8 @@ public class GadgetsHandlerTest extends 
   private void registerGadgetsHandler(SecurityTokenCodec codec) {
     BeanFilter beanFilter = new BeanFilter();
     GadgetsHandlerService service = new GadgetsHandlerService(timeSource, 
processor,
-        urlGenerator, codec, SPEC_REFRESH_INTERVAL, beanFilter);
+        urlGenerator, codec, proxyUriManager, jsUriManager, proxyHandler,
+        SPEC_REFRESH_INTERVAL, beanFilter);
     GadgetsHandler handler =
         new GadgetsHandler(new TestExecutorService(), service, beanFilter);
     registry = new DefaultHandlerRegistry(
@@ -196,19 +207,16 @@ public class GadgetsHandlerTest extends 
     JSONObject userPrefData = userPrefs.getJSONObject("up_one");
     assertNotNull(userPrefData);
 
-    JSONObject upEnums = userPrefData.getJSONObject("enumValues");
-    assertNotNull(upEnums);
-    assertEquals("disp1", upEnums.get("val1"));
-    assertEquals("disp2", upEnums.get("abc"));
-    assertEquals("disp3", upEnums.get("z_xabc"));
-    assertEquals("disp4", upEnums.get("foo"));
-
     JSONArray orderedEnums = userPrefData.getJSONArray("orderedEnumValues");
     assertNotNull(orderedEnums);
     assertEquals(4, orderedEnums.length());
+    assertEquals("disp1", 
orderedEnums.getJSONObject(0).getString("displayValue"));
     assertEquals("val1", orderedEnums.getJSONObject(0).getString("value"));
+    assertEquals("disp2", 
orderedEnums.getJSONObject(1).getString("displayValue"));
     assertEquals("abc", orderedEnums.getJSONObject(1).getString("value"));
+    assertEquals("disp3", 
orderedEnums.getJSONObject(2).getString("displayValue"));
     assertEquals("z_xabc", orderedEnums.getJSONObject(2).getString("value"));
+    assertEquals("disp4", 
orderedEnums.getJSONObject(3).getString("displayValue"));
     assertEquals("foo", orderedEnums.getJSONObject(3).getString("value"));
   }
 
@@ -338,4 +346,106 @@ public class GadgetsHandlerTest extends 
     assertEquals(HttpServletResponse.SC_BAD_REQUEST,
         gadget2.getJSONObject("error").getInt("code"));
   }
+
+  private JSONObject makeSimpleProxyRequest(String fields, String... uris) 
throws JSONException {
+    JSONObject params = new JSONObject().put("ids", ImmutableList.copyOf(uris))
+        .put("container", CONTAINER);
+    if (fields != null) {
+      params.put("fields", fields);
+    }
+    JSONObject req =
+        new JSONObject().put("method", "gadgets.proxy").put("id", 
"req1").put("params", params);
+    return req;
+  }
+
+  @Test
+  public void testSimpleProxy() throws Exception {
+    registerGadgetsHandler(null);
+    String resUri = "http://example.com/data";;
+    String proxyUri = "http://shindig.com/gadgets/proxy?url="; + resUri;
+    JSONObject request = makeSimpleProxyRequest(null, resUri);
+    Capture<List<ProxyUri>> captureProxyUri = new Capture<List<ProxyUri>>();
+    EasyMock.expect(proxyUriManager.make(EasyMock.capture(captureProxyUri),
+        
EasyMock.isNull(Integer.class))).andReturn(ImmutableList.<Uri>of(Uri.parse(proxyUri)));
+    replay();
+    RpcHandler operation = registry.getRpcHandler(request);
+    Object responseObj = operation.execute(emptyFormItems, token, 
converter).get();
+    JSONObject response = new 
JSONObject(converter.convertToString(responseObj));
+
+    JSONObject gadget1 = response.getJSONObject(resUri);
+    assertEquals(proxyUri, gadget1.getString("proxyUrl"));
+    ProxyUri pUri = captureProxyUri.getValue().get(0);
+    ProxyUri expectedUri = new ProxyUri(null, false, false, CONTAINER, null, 
Uri.parse(resUri));
+    assertTrue(expectedUri.equals(pUri));
+    assertFalse(gadget1.has("error"));
+    verify();
+  }
+
+  @Test
+  public void testSimpleProxyData() throws Exception {
+    registerGadgetsHandler(null);
+    String resUri = "http://example.com/data";;
+    String proxyUri = "http://shindig.com/gadgets/proxy?url="; + resUri;
+    JSONObject request = makeSimpleProxyRequest("*", resUri);
+    Capture<List<ProxyUri>> captureProxyUri = new Capture<List<ProxyUri>>();
+    EasyMock.expect(proxyUriManager.make(EasyMock.capture(captureProxyUri),
+        
EasyMock.isNull(Integer.class))).andReturn(ImmutableList.<Uri>of(Uri.parse(proxyUri)));
+    String responseData = "response data";
+    HttpResponse httpResponse = new HttpResponse(responseData);
+    
EasyMock.expect(proxyHandler.fetch(EasyMock.isA(ProxyUri.class))).andReturn(httpResponse);
+    replay();
+
+    RpcHandler operation = registry.getRpcHandler(request);
+    Object responseObj = operation.execute(emptyFormItems, token, 
converter).get();
+    JSONObject response = new 
JSONObject(converter.convertToString(responseObj));
+
+    JSONObject gadget1 = response.getJSONObject(resUri);
+    assertEquals(proxyUri, gadget1.getString("proxyUrl"));
+    ProxyUri pUri = captureProxyUri.getValue().get(0);
+    ProxyUri expectedUri = new ProxyUri(null, false, false, CONTAINER, null, 
Uri.parse(resUri));
+    assertTrue(expectedUri.equals(pUri));
+    assertEquals(responseData, new String(Base64.decodeBase64(((JSONObject)
+        gadget1.get("proxyContent")).getString("contentBase64").getBytes())));
+    assertFalse(gadget1.has("error"));
+    verify();
+  }
+
+  private JSONObject makeComplexProxyRequest(String... uris) throws 
JSONException {
+    JSONObject req =
+        new JSONObject().put("method", "gadgets.proxy").put("id", 
"req1").put("params",
+            new JSONObject().put("ids", 
ImmutableList.copyOf(uris)).put("container", CONTAINER)
+                .put("ignoreCache", "1").put("debug", "1").put("sanitize", 
"true")
+                .put("cajole", "true").put("gadget", 
GADGET1_URL).put("refresh", "333")
+                .put("rewriteMime", "text/xml").put("fallback_url", uris[0])
+                .put("no_expand", "true").put("resize_h", 
"444").put("resize_w", "555")
+                .put("resize_q", "88")
+                );
+    return req;
+  }
+
+  @Test
+  public void testComplexProxy() throws Exception {
+    registerGadgetsHandler(null);
+    String resUri = "http://example.com/data";;
+    String proxyUri = "http://shindig.com/gadgets/proxy?url="; + resUri;
+    JSONObject request = makeComplexProxyRequest(resUri);
+    Capture<List<ProxyUri>> captureProxyUri = new Capture<List<ProxyUri>>();
+    EasyMock.expect(proxyUriManager.make(EasyMock.capture(captureProxyUri),
+        
EasyMock.isNull(Integer.class))).andReturn(ImmutableList.<Uri>of(Uri.parse(proxyUri)));
+    replay();
+    RpcHandler operation = registry.getRpcHandler(request);
+    Object responseObj = operation.execute(emptyFormItems, token, 
converter).get();
+    JSONObject response = new 
JSONObject(converter.convertToString(responseObj));
+
+    JSONObject gadget1 = response.getJSONObject(resUri);
+    assertEquals(proxyUri, gadget1.getString("proxyUrl"));
+    ProxyUri pUri = captureProxyUri.getValue().get(0);
+    ProxyUri expectedUri = new ProxyUri(333, true, true, CONTAINER, 
GADGET1_URL, Uri.parse(resUri));
+    
expectedUri.setCajoleContent(true).setRewriteMimeType("text/xml").setSanitizeContent(true);
+    expectedUri.setFallbackUrl(resUri).setResize(555, 444, 88, true);
+    assertTrue(expectedUri.equals(pUri));
+    assertFalse(gadget1.has("error"));
+    verify();
+  }
+
 }


Reply via email to