You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by Kevin Brown <et...@apache.org> on 2008/03/29 01:38:03 UTC

Re: svn commit: r642404 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/ main/java/org/apache/shindig/gadgets/http/ main/java/org/apache/shindig/social/ main/java/org/apache/shindig/social/opensocial/ main/java/or

Ok, this actually didn't work out as I planned. I'm going to roll this patch
back and then include it with the Guice patch to make life less painful.

Sorry everyone.

On Fri, Mar 28, 2008 at 3:05 PM, <et...@apache.org> wrote:

> Author: etnu
> Date: Fri Mar 28 15:05:22 2008
> New Revision: 642404
>
> URL: http://svn.apache.org/viewvc?rev=642404&view=rev
> Log:
> Committing Brian Eaton's SHINDIG-157 patch.
>
> This is being committed now to facilitate easier integration with
> SHINDIG-152.
>
>
> Modified:
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicRemoteContentFetcher.java
> Fri Mar 28 15:05:22 2008
> @@ -30,7 +30,7 @@
>  * Implementation of a {@code RemoteObjectFetcher} using standard java.net
>  * classes.
>  */
> -public class BasicRemoteContentFetcher implements RemoteContentFetcher {
> +public class BasicRemoteContentFetcher extends RemoteContentFetcher {
>   private static final int CONNECT_TIMEOUT_MS = 5000;
>
>   private final int maxObjSize;
> @@ -41,6 +41,7 @@
>    * @param maxObjSize Maximum size, in bytes, of object to fetch
>    */
>   public BasicRemoteContentFetcher(int maxObjSize) {
> +    super(null);
>     this.maxObjSize = maxObjSize;
>   }
>
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsFeatureLoader.java
> Fri Mar 28 15:05:22 2008
> @@ -238,7 +238,8 @@
>    * @param renderingContext
>    */
>   private void processContext(ParsedFeature feature, Element context,
> -                              RenderingContext renderingContext) {
> +                              RenderingContext renderingContext)
> +  throws GadgetException {
>     String syndicator = XmlUtil.getAttribute(context, "synd",
>         SyndicatorConfig.DEFAULT_SYNDICATOR);
>     NodeList libraries = context.getElementsByTagName("script");
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/JsLibrary.java
> Fri Mar 28 15:05:22 2008
> @@ -113,9 +113,10 @@
>    *     kept as a url reference, otherwise the file will be fetched and
> treated
>    *     as a FILE type.
>    * @return The newly created library.
> +   * @throws GadgetException
>    */
>   public static JsLibrary create(Type type, String content, String
> feature,
> -      RemoteContentFetcher fetcher) {
> +      RemoteContentFetcher fetcher) throws GadgetException {
>     String optimizedContent = null;
>     String debugContent;
>     switch (type) {
> @@ -168,9 +169,10 @@
>    * @param url
>    * @param fetcher
>    * @return The contents of the JS file, or null if it can't be fetched.
> +   * @throws GadgetException
>    */
>   private static String loadDataFromUrl(String url,
> -      RemoteContentFetcher fetcher) {
> +      RemoteContentFetcher fetcher) throws GadgetException {
>     try {
>       logger.info("Attempting to load js from: " + url);
>       URI uri = new URI(url);
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/NullRequestSigner.java
> Fri Mar 28 15:05:22 2008
> @@ -1,38 +0,0 @@
> -/*
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -package org.apache.shindig.gadgets;
> -
> -import java.net.URL;
> -
> -/**
> - * Request signer interface that does nothing, for convenience of writing
> - * code that may or may not need to sign requests.
> - */
> -public class NullRequestSigner implements RequestSigner {
> -
> -  public String getApprovalUrl() {
> -    return null;
> -  }
> -
> -  public Status getSigningStatus() {
> -    return Status.OK;
> -  }
> -
> -  @SuppressWarnings("unused")
> -  public URL signRequest(String method, URL resource, String postBody)
> throws GadgetException {
> -    return resource;
> -  }
> -
> -}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentFetcher.java
> Fri Mar 28 15:05:22 2008
> @@ -18,11 +18,29 @@
>  package org.apache.shindig.gadgets;
>
>
> -public interface RemoteContentFetcher {
> +/**
> + * Fetches data over HTTP.
> + *
> + * Subclasses can use a chain-of-responsibility pattern to add
> functionality
> + * to the fetching process.  For example, a SigningFetcher can talk to a
> + * CachingFetcher can talk to a ThrottlingFetcher that talks to a
> + * RemoteFetcher that gets the actual data.
> + */
> +public abstract class RemoteContentFetcher {
> +
> +  /** next fetcher in the chain, may be null */
> +  protected RemoteContentFetcher nextFetcher;
> +
> +  protected RemoteContentFetcher(RemoteContentFetcher nextFetcher) {
> +    this.nextFetcher = nextFetcher;
> +  }
> +
>   /**
> -   * Fetch content using the HTTP GET method
> +   * Fetch HTTP content.
> +   *
>    * @param request The request to fetch.
>    * @return RemoteContent
> +   * @throws GadgetException
>    */
> -  public RemoteContent fetch(RemoteContentRequest request);
> +  public abstract RemoteContent fetch(RemoteContentRequest request)
> throws GadgetException;
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContentRequest.java
> Fri Mar 28 15:05:22 2008
> @@ -33,9 +33,6 @@
>  * Holds request data for passing to a RemoteContentFetcher.
>  * Instances of this object are immutable.
>  *
> - * TODO: We should probably just stick the method in here. Having
> separate
> - * calls for POST vs. get seems unnecessary.
> - *
>  * TODO: This naming seems really ridiculous now. Why don't we just call
> it
>  * what it is -- an HTTP request?
>  */
> @@ -47,6 +44,13 @@
>    */
>   public InputStream getPostBody() {
>     return new ByteArrayInputStream(postBody);
> +  }
> +
> +  /**
> +   * @return the post body bytes
> +   */
> +  public byte[] getPostBodyBytes() {
> +    return postBody;
>   }
>
>   /**
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RequestSigner.java
> Fri Mar 28 15:05:22 2008
> @@ -1,60 +0,0 @@
> -/*
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -package org.apache.shindig.gadgets;
> -
> -import java.net.URL;
> -
> -/**
> - * Interface for generating signed requests and handling responses.
> - *
> - * Most of the functionality here isn't used at the moment, just enough
> to
> - * implement signed fetch.  The status and approval bits will be used for
> - * full OAuth.
> - */
> -public interface RequestSigner {
> -
> -  /**
> -   * Whether the signing request succeeded.
> -   */
> -  public enum Status {
> -    OK,
> -    APPROVAL_NEEDED,
> -  }
> -
> -  /**
> -   * Signs a URL and post body, returning a modified URL including the
> -   * signature.  The post body is not modified.
> -   *
> -   * @param method how the request will be sent
> -   * @param resource the URL to sign
> -   * @param postBody the body of the request (may be null)
> -   *
> -   * @return a signed URL
> -   * @throws GadgetException if an error occurs.
> -   */
> -  public URL signRequest(String method, URL resource, String postBody)
> -  throws GadgetException;
> -
> -  /**
> -   * @return the status associated with the last signing request.  May
> return
> -   * APPROVAL_NEEDED if user interaction is required.
> -   */
> -  public Status getSigningStatus();
> -
> -  /**
> -   * @return the URL the user needs to visit to approve the access
> request.
> -   */
> -  public String getApprovalUrl();
> -}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SignedFetchRequestSigner.java
> Fri Mar 28 15:05:22 2008
> @@ -1,277 +0,0 @@
> -/*
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -package org.apache.shindig.gadgets;
> -
> -import net.oauth.OAuth;
> -import net.oauth.OAuthAccessor;
> -import net.oauth.OAuthConsumer;
> -import net.oauth.OAuthMessage;
> -import net.oauth.OAuth.Parameter;
> -import net.oauth.signature.RSA_SHA1;
> -
> -import org.apache.shindig.util.Crypto;
> -import org.apache.shindig.util.TimeSource;
> -
> -import java.net.MalformedURLException;
> -import java.net.URL;
> -import java.security.PrivateKey;
> -import java.util.ArrayList;
> -import java.util.HashSet;
> -import java.util.List;
> -import java.util.Map;
> -import java.util.regex.Pattern;
> -
> -/**
> - * Implements signed fetch based on the OAuth request signing algorithm.
> - *
> - * Subclasses can override signMessage to use their own crypto if they
> don't
> - * like the oauth.net code for some reason.
> - *
> - * Instances of this class are only accessed by a single thread at a
> time,
> - * but instances may be created by multiple threads.
> - */
> -public class SignedFetchRequestSigner implements RequestSigner {
> -
> -  protected static final String OPENSOCIAL_OWNERID =
> "opensocial_owner_id";
> -
> -  protected static final String OPENSOCIAL_VIEWERID =
> "opensocial_viewer_id";
> -
> -  protected static final String OPENSOCIAL_APPID = "opensocial_app_id";
> -
> -  protected static final String XOAUTH_PUBLIC_KEY =
> -    "xoauth_signature_publickey";
> -
> -  protected static final Pattern ALLOWED_PARAM_NAME = Pattern
> -      .compile("[\\w_\\-]+");
> -
> -  protected final TimeSource clock = new TimeSource();
> -
> -  /**
> -   * Authentication token for the user and gadget making the request.
> -   */
> -  protected GadgetToken authToken;
> -
> -  /**
> -   * Private key we pass to the OAuth RSA_SHA1 algorithm.  This can be a
> -   * PrivateKey object, or a PEM formatted private key, or a DER encoded
> byte
> -   * array for the private key.  (No, really, they accept any of them.)
> -   */
> -  protected Object privateKeyObject;
> -
> -  /**
> -   * The name of the key, included in the fetch to help with key
> rotation.
> -   */
> -  protected String keyName;
> -
> -  /**
> -   * Constructor for subclasses that don't want this code to use their
> -   * keys.
> -   */
> -  protected SignedFetchRequestSigner(GadgetToken authToken) {
> -    init(authToken, null, null);
> -  }
> -
> -  /**
> -   * Constructor based on signing with the given PrivateKey object.
> -   *
> -   * @param authToken verified gadget security token
> -   * @param keyName name of the key to include in the request
> -   * @param privateKey the key to use for the signing
> -   */
> -  public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
> -      PrivateKey privateKey) {
> -    init(authToken, keyName, privateKey);
> -  }
> -
> -  /**
> -   * Constructor based on signing with the given PrivateKey object.
> -   *
> -   * @param authToken verified gadget security token
> -   * @param keyName name of the key to include in the request
> -   * @param privateKey base64 encoded private key
> -   */
> -  public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
> -      String privateKey) {
> -    init(authToken, keyName, privateKey);
> -  }
> -
> -  /**
> -   * Constructor based on signing with the given PrivateKey object.
> -   *
> -   * @param authToken verified gadget security token
> -   * @param keyName name of the key to include in the request
> -   * @param privateKey DER encoded private key
> -   */
> -  public SignedFetchRequestSigner(GadgetToken authToken, String keyName,
> -      byte[] privateKey) {
> -    init(authToken, keyName, privateKey);
> -  }
> -
> -  protected void init(GadgetToken authToken, String keyName,
> -      Object privateKeyObject) {
> -    this.authToken = authToken;
> -    this.keyName = keyName;
> -    this.privateKeyObject = privateKeyObject;
> -  }
> -
> -  /**
> -   * Signed fetch doesn't require approvals, always returns null.
> -   */
> -  public String getApprovalUrl() {
> -    return null;
> -  }
> -
> -  /**
> -   * Signed fetch doesn't require approvals, always returns Status.OK
> -   */
> -  public Status getSigningStatus() {
> -    return Status.OK;
> -  }
> -
> -  public URL signRequest(String method, URL resource, String postBody)
> -  throws GadgetException {
> -    try {
> -      // Parse the request into parameters for OAuth signing, stripping
> out
> -      // any OAuth or OpenSocial parameters injected by the client
> -      String query = resource.getQuery();
> -      resource = removeQuery(resource);
> -      List<OAuth.Parameter> queryParams = sanitize(OAuth.decodeForm
> (query));
> -      List<OAuth.Parameter> postParams = sanitize(OAuth.decodeForm
> (postBody));
> -      List<OAuth.Parameter> msgParams = new ArrayList<OAuth.Parameter>();
> -      msgParams.addAll(queryParams);
> -      msgParams.addAll(postParams);
> -
> -      // Add the OpenSocial parameters
> -      addOpenSocialParams(msgParams);
> -
> -      // Add the OAuth parameters
> -      addOAuthParams(msgParams);
> -
> -      // Build and sign the OAuthMessage; note that the resource here has
> -      // no query string, the parameters are all in msgParams
> -      OAuthMessage message = new OAuthMessage(method, resource.toString
> (),
> -          msgParams);
> -
> -      // Sign the message, this may jump into a subclass
> -      signMessage(message);
> -
> -      // Rebuild the query string, including all of the parameters we
> added.
> -      // We have to be careful not to copy POST parameters into the
> query.
> -      // If post and query parameters share a name, they end up being
> removed
> -      // from the query.
> -      HashSet<String> forPost = new HashSet<String>();
> -      for (OAuth.Parameter param : postParams) {
> -        forPost.add(param.getKey());
> -      }
> -      List<Map.Entry<String, String>> newQuery =
> -        new ArrayList<Map.Entry<String, String>>();
> -      for (Map.Entry<String, String> param : message.getParameters()) {
> -        if (! forPost.contains(param.getKey())) {
> -          newQuery.add(param);
> -        }
> -      }
> -      String finalQuery = OAuth.formEncode(newQuery);
> -      return new URL(resource.getProtocol(), resource.getHost(),
> -          resource.getPort(), resource.getPath() + '?' + finalQuery);
> -    } catch (Exception e) {
> -      throw new GadgetException(
> GadgetException.Code.INTERNAL_SERVER_ERROR,
> -          e);
> -    }
> -  }
> -
> -  private URL removeQuery(URL resource) throws MalformedURLException {
> -    return new URL(resource.getProtocol(), resource.getHost(),
> -        resource.getPort(), resource.getPath());
> -  }
> -
> -
> -  private void addOpenSocialParams(List<Parameter> msgParams) {
> -    String owner = authToken.getOwnerId();
> -    if (owner != null) {
> -      msgParams.add(new OAuth.Parameter(OPENSOCIAL_OWNERID, owner));
> -    }
> -
> -    String viewer = authToken.getViewerId();
> -    if (viewer != null) {
> -      msgParams.add(new OAuth.Parameter(OPENSOCIAL_VIEWERID, viewer));
> -    }
> -
> -    String app = authToken.getAppId();
> -    if (app != null) {
> -      msgParams.add(new OAuth.Parameter(OPENSOCIAL_APPID, app));
> -    }
> -
> -  }
> -
> -  private void addOAuthParams(List<Parameter> msgParams) {
> -    msgParams.add(new OAuth.Parameter(OAuth.OAUTH_TOKEN, ""));
> -
> -    String domain = authToken.getDomain();
> -    if (domain != null) {
> -      msgParams.add(new OAuth.Parameter(OAuth.OAUTH_CONSUMER_KEY,
> domain));
> -    }
> -
> -    if (keyName != null) {
> -      msgParams.add(new OAuth.Parameter(XOAUTH_PUBLIC_KEY, keyName));
> -    }
> -
> -    String nonce = Long.toHexString(Crypto.rand.nextLong());
> -    msgParams.add(new OAuth.Parameter(OAuth.OAUTH_NONCE, nonce));
> -
> -    String timestamp = Long.toString(clock.currentTimeMillis()/1000L);
> -    msgParams.add(new OAuth.Parameter(OAuth.OAUTH_TIMESTAMP, timestamp));
> -
> -    msgParams.add(new OAuth.Parameter(OAuth.OAUTH_SIGNATURE_METHOD,
> -        OAuth.RSA_SHA1));
> -  }
> -
> -  /**
> -   * Sign a message and append the oauth signature parameter to the
> message
> -   * object.
> -   *
> -   * @param message the message to sign
> -   *
> -   * @throws Exception because the OAuth libraries require it.
> -   */
> -  protected void signMessage(OAuthMessage message) throws Exception {
> -    OAuthConsumer consumer = new OAuthConsumer(null, null, null, null);
> -    consumer.setProperty(RSA_SHA1.PRIVATE_KEY, privateKeyObject);
> -    OAuthAccessor accessor = new OAuthAccessor(consumer);
> -    message.sign(accessor);
> -  }
> -
> -  /**
> -   * Strip out any owner or viewer id passed by the client.
> -   */
> -  private List<Parameter> sanitize(List<Parameter> params) {
> -    ArrayList<Parameter> list = new ArrayList<Parameter>();
> -    for (Parameter p : params) {
> -      if (allowParam(p.getKey())) {
> -        list.add(p);
> -      }
> -    }
> -    return list;
> -  }
> -
> -  private boolean allowParam(String paramName) {
> -    String canonParamName = paramName.toLowerCase();
> -    return (!(canonParamName.startsWith("oauth") ||
> -        canonParamName.startsWith("xoauth") ||
> -        canonParamName.startsWith("opensocial")) &&
> -        ALLOWED_PARAM_NAME.matcher(canonParamName).matches());
> -  }
> -
> -
> -}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> Fri Mar 28 15:05:22 2008
> @@ -21,10 +21,12 @@
>
>  import org.apache.shindig.gadgets.Gadget;
>  import org.apache.shindig.gadgets.GadgetContext;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetServer;
>  import org.apache.shindig.gadgets.GadgetSigner;
>  import org.apache.shindig.gadgets.GadgetToken;
> -import org.apache.shindig.gadgets.RequestSigner;
> +import org.apache.shindig.gadgets.RemoteContentFetcher;
> +import org.apache.shindig.util.BlobCrypter;
>
>  import java.util.Set;
>  import java.util.logging.Logger;
> @@ -105,24 +107,16 @@
>   public abstract String getIframeUrl(Gadget gadget);
>
>   /**
> -   * Constructs a RequestSigner object that can be used to sign requests
> from
> -   * the given gadget token to implement signed fetch.
> -   *
> +   * Constructs a RemoteFetcher object that signs requests and then
> forwards
> +   * them to the next content fetcher in the chain.
> +   *
> +   * @param remoteFetcher
>    * @param token the decrypted, verified security token
>    * @return a request signer implementing signed fetch.
>    *
> -   * @see org.apache.shindig.gadgets.SignedFetchRequestSigner
> -   */
> -  public abstract RequestSigner makeSignedFetchRequestSigner(GadgetToken
> token);
> -
> -  /**
> -   * Constructs a RequestSigner object that can be used to sign requests
> from
> -   * the given gadget token to implement full OAuth.
> -   *
> -   * @param token the decrypted, verified security token
> -   * @return a request signer implementing signed fetch.
> +   * @see org.apache.shindig.gadgets.SigningFetcher
>    */
> -  public abstract RequestSigner makeOAuthRequestSigner(GadgetToken
> token);
> +  public abstract RemoteContentFetcher
> makeSigningFetcher(RemoteContentFetcher remoteFetcher, GadgetToken token);
>
>   /**
>    * Initializes this handler using the provided implementation.
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> Fri Mar 28 15:05:22 2008
> @@ -22,6 +22,7 @@
>  import org.apache.shindig.gadgets.BasicGadgetBlacklist;
>  import org.apache.shindig.gadgets.BasicGadgetSigner;
>  import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> +import org.apache.shindig.gadgets.DataFetcher;
>  import org.apache.shindig.gadgets.Gadget;
>  import org.apache.shindig.gadgets.GadgetContext;
>  import org.apache.shindig.gadgets.GadgetException;
> @@ -36,8 +37,7 @@
>  import org.apache.shindig.gadgets.JsLibrary;
>  import org.apache.shindig.gadgets.MessageBundleFetcher;
>  import org.apache.shindig.gadgets.RemoteContentFetcher;
> -import org.apache.shindig.gadgets.RequestSigner;
> -import org.apache.shindig.gadgets.SignedFetchRequestSigner;
> +import org.apache.shindig.gadgets.SigningFetcher;
>  import org.apache.shindig.gadgets.SyndicatorConfig;
>  import org.apache.shindig.gadgets.UserPrefs;
>  import org.apache.shindig.gadgets.spec.GadgetSpec;
> @@ -47,6 +47,8 @@
>  import java.io.File;
>  import java.io.IOException;
>  import java.io.UnsupportedEncodingException;
> +import java.net.URI;
> +import java.net.URISyntaxException;
>  import java.net.URLEncoder;
>  import java.util.Map;
>  import java.util.Set;
> @@ -227,12 +229,8 @@
>   }
>
>   @Override
> -  public RequestSigner makeOAuthRequestSigner(GadgetToken token) {
> -    return null;
> -  }
> -
> -  @Override
> -  public RequestSigner makeSignedFetchRequestSigner(GadgetToken token) {
> +  public RemoteContentFetcher makeSigningFetcher(
> +      RemoteContentFetcher fetcher, GadgetToken token) {
>     // Real implementations should use their own key, probably pulled from
>     // disk rather than hardcoded in the source.
>     final String PRIVATE_KEY_TEXT =
> @@ -251,7 +249,7 @@
>       "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54" +
>       "Lw03eHTNQghS0A==";
>     final String PRIVATE_KEY_NAME = "shindig-insecure-key";
> -    return new SignedFetchRequestSigner(token, PRIVATE_KEY_NAME,
> -        PRIVATE_KEY_TEXT);
> +    return SigningFetcher.makeFromB64PrivateKey(
> +        fetcher, token, PRIVATE_KEY_NAME, PRIVATE_KEY_TEXT);
>   }
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyHandler.java
> Fri Mar 28 15:05:22 2008
> @@ -24,7 +24,6 @@
>  import org.apache.shindig.gadgets.RemoteContent;
>  import org.apache.shindig.gadgets.RemoteContentFetcher;
>  import org.apache.shindig.gadgets.RemoteContentRequest;
> -import org.apache.shindig.gadgets.RequestSigner;
>  import org.apache.shindig.util.InputStreamConsumer;
>
>  import org.json.JSONException;
> @@ -32,15 +31,12 @@
>
>  import java.io.IOException;
>  import java.io.UnsupportedEncodingException;
> -import java.net.MalformedURLException;
>  import java.net.URI;
>  import java.net.URISyntaxException;
> -import java.net.URL;
>  import java.net.URLDecoder;
>  import java.util.Arrays;
>  import java.util.Collections;
>  import java.util.Enumeration;
> -import java.util.HashMap;
>  import java.util.TreeMap;
>  import java.util.HashSet;
>  import java.util.List;
> @@ -60,8 +56,10 @@
>   private static final String NOCACHE_PARAM = "nocache";
>   private static final String URL_PARAM = "url";
>   private static final String AUTHZ_PARAM = "authz";
> +  private static final String UNSIGNED_FETCH = "none";
> +  private static final String SIGNED_FETCH = "signed";
>
> -  private final RemoteContentFetcher fetcher;
> +  private final RemoteContentFetcher remoteFetcher;
>
>   private final static Set<String> DISALLOWED_RESPONSE_HEADERS
>     = new HashSet<String>();
> @@ -71,25 +69,49 @@
>   }
>
>   public ProxyHandler(RemoteContentFetcher fetcher) {
> -    this.fetcher = fetcher;
> +    this.remoteFetcher = fetcher;
>   }
>
> +  /**
> +   * Information about our chain of RemoteContentFetchers.
> +   *
> +   * This class is kind of silly at the moment, but it'll be useful once
> +   * we need to peek at the state of intermediate fetchers in the chain.
> +   * (Which we will need to do for OAuth.)
> +   */
> +  private static class FetcherChain {
> +    public RemoteContentFetcher fetcher;
> +
> +    public FetcherChain(RemoteContentFetcher fetcher) {
> +      this.fetcher = fetcher;
> +    }
> +  }
> +
>   public void fetchJson(HttpServletRequest request,
>                         HttpServletResponse response,
>                         CrossServletState state)
>       throws ServletException, IOException, GadgetException {
> +
> +    // Build up the request to make
> +    RemoteContentRequest rcr = buildRemoteContentRequest(request);
> +
> +    // Figure out whether we need to sign the request
> +    FetcherChain chain = buildFetcherChain(request, response, state);
> +
> +    // Dispatch the request and serialize the response.
> +    RemoteContent results = chain.fetcher.fetch(rcr);
>
> -    // Fetch the content and convert it into JSON.
> -    RemoteContent results = fetchContent(request, state);
> -    response.setStatus(HttpServletResponse.SC_OK);
>     String output;
>     try {
> +      JSONObject resp = new JSONObject();
> +      response.setStatus(HttpServletResponse.SC_OK);
> +      if (results != null) {
> +        resp.put("body", results.getResponseAsString());
> +        resp.put("rc", results.getHttpStatusCode());
> +      }
>       // Use raw param as key as URL may have to be decoded
> -      JSONObject resp = new JSONObject()
> -          .put("body", results.getResponseAsString())
> -          .put("rc", results.getHttpStatusCode());
> -      String url = request.getParameter(URL_PARAM);
> -      JSONObject json = new JSONObject().put(url, resp);
> +      String originalUrl = request.getParameter(URL_PARAM);
> +      JSONObject json = new JSONObject().put(originalUrl, resp);
>       output = UNPARSEABLE_CRUFT + json.toString();
>     } catch (JSONException e) {
>       output = "";
> @@ -100,67 +122,16 @@
>     response.getWriter().write(output);
>   }
>
> -  public void fetch(HttpServletRequest request,
> -                    HttpServletResponse response,
> -                    CrossServletState state)
> -      throws ServletException, IOException, GadgetException {
> -    RemoteContent results = fetchContent(request, state);
> -
> -    if (request.getHeader("If-Modified-Since") != null) {
> -      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
> -      return;
> -    }
> -
> -    int status = results.getHttpStatusCode();
> -    response.setStatus(status);
> -    if (status == HttpServletResponse.SC_OK) {
> -      Map<String, List<String>> headers = results.getAllHeaders();
> -      if (headers.get("Cache-Control") == null) {
> -        // Cache for 1 hour by default for images.
> -        HttpUtil.setCachingHeaders(response, 60 * 60);
> -      }
> -      for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
> -        String name = entry.getKey();
> -        List<String> values = entry.getValue();
> -        if (name != null && values != null
> -            && !DISALLOWED_RESPONSE_HEADERS.contains(name.toLowerCase()))
> {
> -          for (String value : values) {
> -            response.addHeader(name, value);
> -          }
> -        }
> -      }
> -      response.getOutputStream().write(
> -          InputStreamConsumer.readToByteArray(results.getResponse()));
> -    }
> -  }
> -
> -  /**
> -   * Fetch the content for a request
> -   *
> -   * @param request
> -   */
>   @SuppressWarnings("unchecked")
> -  private RemoteContent fetchContent(HttpServletRequest request,
> -      CrossServletState state) throws ServletException, GadgetException {
> -    String encoding = request.getCharacterEncoding();
> -    if (encoding == null) {
> -      encoding = "UTF-8";
> -    }
> -
> +  private RemoteContentRequest
> buildRemoteContentRequest(HttpServletRequest request)
> +  throws ServletException {
>     try {
> -      URL originalUrl = validateUrl(request.getParameter(URL_PARAM));
> -      GadgetSigner signer = state.getGadgetSigner();
> -      URL signedUrl;
> -      if ("signed".equals(request.getParameter(AUTHZ_PARAM))) {
> -        GadgetToken token = extractAndValidateToken(request, signer);
> -        if (token == null) {
> -          return new RemoteContent(HttpServletResponse.SC_UNAUTHORIZED,
> -              "Invalid security token.".getBytes(), null);
> -        }
> -        signedUrl = signUrl(state, originalUrl, token, request);
> -      } else {
> -        signedUrl = originalUrl;
> +
> +      String encoding = request.getCharacterEncoding();
> +      if (encoding == null) {
> +        encoding = "UTF-8";
>       }
> +
>       String method = request.getMethod();
>       Map<String, List<String>> headers = null;
>       byte[] postBody = null;
> @@ -180,7 +151,8 @@
>             String[] parts = header.split("=");
>             if (parts.length != 2) {
>               // Malformed headers
> -              return RemoteContent.ERROR;
> +              throw new GadgetException(
> GadgetException.Code.INTERNAL_SERVER_ERROR,
> +              "malformed header specified");
>             }
>             headers.put(URLDecoder.decode(parts[0], encoding),
>                 Arrays.asList(URLDecoder.decode(parts[1], encoding)));
> @@ -199,19 +171,93 @@
>       removeUnsafeHeaders(headers);
>
>       RemoteContentRequest.Options options
> -          = new RemoteContentRequest.Options();
> +        = new RemoteContentRequest.Options();
>       options.ignoreCache = "1".equals(request.getParameter
> (NOCACHE_PARAM));
> +      URI target = validateUrl(request.getParameter(URL_PARAM));
>       RemoteContentRequest req = new RemoteContentRequest(
> -          method, signedUrl.toURI(), headers, postBody, options);
> -      return fetcher.fetch(req);
> +          method, target, headers, postBody, options);
> +
> +      return req;
>     } catch (UnsupportedEncodingException e) {
>       throw new ServletException(e);
> -    } catch (URISyntaxException e) {
> +    } catch (GadgetException e) {
>       throw new ServletException(e);
>     }
>   }
>
>   /**
> +   * At the moment our fetcher chain is short.  In the future we might
> add
> +   * additional layers for things like caching or throttling.
> +   */
> +  private FetcherChain buildFetcherChain(HttpServletRequest request,
> +      HttpServletResponse response, CrossServletState state) throws
> GadgetException {
> +    String authzType = getParameter(request, AUTHZ_PARAM, "");
> +    if (authzType.equals("") || authzType.equals(UNSIGNED_FETCH)) {
> +      return new FetcherChain(remoteFetcher);
> +    }
> +    GadgetSigner signer = state.getGadgetSigner();
> +    if (signer == null) {
> +      throw new GadgetException(GadgetException.Code.UNSUPPORTED_FEATURE,
> +          "authenticated makeRequest not supported");
> +    }
> +    String tokenString = getParameter(request, SECURITY_TOKEN_PARAM, "");
> +    GadgetToken securityToken = signer.createToken(tokenString);
> +    if (securityToken == null) {
> +      throw new GadgetException(GadgetException.Code.INVALID_GADGET_TOKEN
> );
> +    }
> +    RemoteContentFetcher realFetcher = null;
> +    if (authzType.equals(SIGNED_FETCH)) {
> +      realFetcher = state.makeSigningFetcher(remoteFetcher,
> securityToken);
> +    }
> +    if (realFetcher == null) {
> +      throw new GadgetException(GadgetException.Code.UNSUPPORTED_FEATURE,
> +          String.format("Unsupported auth type %s", authzType));
> +    }
> +    return new FetcherChain(realFetcher);
> +  }
> +
> +
> +  /**
> +   * This is called for embedding images inline in gadgets, e.g. via img
> src links
> +   * created via IG_Embed.
> +   */
> +  public void fetch(HttpServletRequest request,
> +                    HttpServletResponse response,
> +                    CrossServletState state)
> +      throws ServletException, IOException, GadgetException {
> +    RemoteContentRequest rcr = buildRemoteContentRequest(request);
> +    RemoteContent results = remoteFetcher.fetch(rcr);
> +
> +    // TODO: why are we checking for caching headers *after* we sent the
> request?
> +    if (request.getHeader("If-Modified-Since") != null) {
> +      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
> +      return;
> +    }
> +
> +    int status = results.getHttpStatusCode();
> +    response.setStatus(status);
> +    if (status == HttpServletResponse.SC_OK) {
> +      Map<String, List<String>> headers = results.getAllHeaders();
> +      if (headers.get("Cache-Control") == null) {
> +        // Cache for 1 hour by default for images.
> +        HttpUtil.setCachingHeaders(response, 60 * 60);
> +      }
> +      for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
> +        String name = entry.getKey();
> +        List<String> values = entry.getValue();
> +        if (name != null && values != null
> +            && !DISALLOWED_RESPONSE_HEADERS.contains(name.toLowerCase()))
> {
> +          for (String value : values) {
> +            response.addHeader(name, value);
> +          }
> +        }
> +      }
> +      response.getOutputStream().write(
> +          InputStreamConsumer.readToByteArray(results.getResponse()));
> +    }
> +  }
> +
> +  /**
>    * Removes unsafe headers from the header set.
>    * @param headers
>    */
> @@ -229,12 +275,14 @@
>
>   /**
>    * Validates that the given url is valid for this request.
> +   *
> +   * non-private for testing only.
>    *
>    * @param urlToValidate
>    * @return A URL object of the URL
>    * @throws ServletException if the URL fails security checks or is
> malformed.
>    */
> -  private URL validateUrl(String urlToValidate) throws ServletException {
> +   URI validateUrl(String urlToValidate) throws ServletException {
>     if (urlToValidate == null) {
>       throw new ServletException("url parameter is missing.");
>     }
> @@ -257,39 +305,10 @@
>                       "/", url.getQuery(),
>                       url.getFragment());
>       }
> -      return url.toURL();
> +      return url;
>     } catch (URISyntaxException use) {
>       throw new ServletException("Malformed URL " + use.getMessage());
> -    } catch (MalformedURLException mfe) {
> -      throw new ServletException("Malformed URL " + mfe.getMessage());
>     }
> -  }
> -
> -  /**
> -   * @param request
> -   * @return A valid token for the given input.
> -   * @throws GadgetException
> -   */
> -  private GadgetToken extractAndValidateToken(HttpServletRequest request,
> -      GadgetSigner signer) throws GadgetException {
> -    if (signer == null) {
> -      return null;
> -    }
> -    String token = getParameter(request, SECURITY_TOKEN_PARAM, "");
> -    return signer.createToken(token);
> -  }
> -
> -  /**
> -   * Sign a URL with a GadgetToken if needed
> -   * @return The signed url.
> -   */
> -  @SuppressWarnings("unchecked")
> -  private URL signUrl(CrossServletState state, URL originalUrl,
> GadgetToken token,
> -      HttpServletRequest request) throws GadgetException {
> -    String method = getParameter(request, METHOD_PARAM, "GET");
> -    String body = getParameter(request, POST_DATA_PARAM, null);
> -    RequestSigner signer = state.makeSignedFetchRequestSigner(token);
> -    return signer.signRequest(method, originalUrl, body);
>   }
>
>   /**
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataHandler.java
> Fri Mar 28 15:05:22 2008
> @@ -17,6 +17,8 @@
>  */
>  package org.apache.shindig.social;
>
> +import org.apache.shindig.gadgets.GadgetException;
> +
>  public interface GadgetDataHandler {
>   /**
>    * Determines whether this handler should be used to process the request
> @@ -32,6 +34,7 @@
>    *
>    * @param request The request from the json
>    * @return The corresponding response item
> +   * @throws GadgetException
>    */
> -  ResponseItem handleRequest(RequestItem request);
> +  ResponseItem handleRequest(RequestItem request) throws GadgetException;
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/ActivitiesService.java
> Fri Mar 28 15:05:22 2008
> @@ -17,6 +17,7 @@
>  */
>  package org.apache.shindig.social.opensocial;
>
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>
>  import org.apache.shindig.social.ResponseItem;
> @@ -30,9 +31,10 @@
>    * @param ids The ids of the people to fetch activities for.
>    * @param token A valid GadgetToken
>    * @return a response item with the list of activities.
> +   * @throws GadgetException
>    */
>   public ResponseItem<List<Activity>> getActivities(List<String> ids,
> -      GadgetToken token);
> +      GadgetToken token) throws GadgetException;
>
>   /**
>    * Creates the passed in activity for the given user. Once
> createActivity is
> @@ -41,7 +43,8 @@
>    * @param activity The activity to create.
>    * @param token A valid GadgetToken
>    * @return a response item containing any errors
> +   * @throws GadgetException
>    */
>   public ResponseItem createActivity(String personId, Activity activity,
> -      GadgetToken token);
> +      GadgetToken token) throws GadgetException;
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/DataService.java
> Fri Mar 28 15:05:22 2008
> @@ -18,6 +18,7 @@
>  package org.apache.shindig.social.opensocial;
>
>  import org.apache.shindig.social.ResponseItem;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>
>  import java.util.List;
> @@ -32,9 +33,10 @@
>    * @param token The GadgetToken for this request
>    * @return ResponseItem a response item with the error code set if
>    *     there was a problem
> +   * @throws GadgetException
>    */
>   public ResponseItem<Map<String, Map<String, String>>> getPersonData(
> -      List<String> ids, List<String> keys, GadgetToken token);
> +      List<String> ids, List<String> keys, GadgetToken token) throws
> GadgetException;
>
>   /**
>    * Updates the data key for the given person with the new value.
> @@ -45,7 +47,8 @@
>    * @param token The GadgetToken for this request
>    * @return ResponseItem a response item with the error code set if
>    *     there was a problem
> +   * @throws GadgetException
>    */
>   public ResponseItem updatePersonData(String id, String key,
> -      String value, GadgetToken token);
> +      String value, GadgetToken token) throws GadgetException;
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/OpenSocialDataHandler.java
> Fri Mar 28 15:05:22 2008
> @@ -21,6 +21,7 @@
>  import org.json.JSONObject;
>  import org.json.JSONArray;
>
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>
>  import org.apache.shindig.social.samplecontainer.BasicPeopleService;
> @@ -76,7 +77,7 @@
>     }
>   }
>
> -  public ResponseItem handleRequest(RequestItem request) {
> +  public ResponseItem handleRequest(RequestItem request) throws
> GadgetException {
>     OpenSocialDataType type = OpenSocialDataType.valueOf(request.getType
> ());
>     ResponseItem response = new ResponseItem<Object>(
>         ResponseError.NOT_IMPLEMENTED,
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/opensocial/PeopleService.java
> Fri Mar 28 15:05:22 2008
> @@ -22,6 +22,7 @@
>  import org.apache.shindig.social.opensocial.model.IdSpec;
>  import org.apache.shindig.social.opensocial.model.ApiCollection;
>  import org.apache.shindig.social.ResponseItem;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>
>  import java.util.List;
> @@ -35,9 +36,10 @@
>    * @param idSpec The idSpec to translate into ids
>    * @return a list of person ids
>    * @throws JSONException If the idSpec is malformed
> +   * @throws GadgetException
>    */
>   public List<String> getIds(IdSpec idSpec, GadgetToken token)
> -      throws JSONException;
> +      throws JSONException, GadgetException;
>
>   public enum SortOrder {
>     topFriends, name
> @@ -55,8 +57,9 @@
>    * @param first The index of the first person to fetch.
>    * @param max The max number of people to fetch.
>    * @return a list of people.
> +   * @throws GadgetException
>    */
>   public ResponseItem<ApiCollection<Person>> getPeople(List<String> ids,
>       SortOrder sortOrder, FilterType filter, int first, int max,
> -      Set<String> profileDetails, GadgetToken token);
> +      Set<String> profileDetails, GadgetToken token) throws
> GadgetException;
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicActivitiesService.java
> Fri Mar 28 15:05:22 2008
> @@ -17,6 +17,7 @@
>  */
>  package org.apache.shindig.social.samplecontainer;
>
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>
>  import org.apache.shindig.social.ResponseItem;
> @@ -34,7 +35,7 @@
>  */
>  public class BasicActivitiesService implements ActivitiesService {
>   public ResponseItem<List<Activity>> getActivities(List<String> ids,
> -      GadgetToken token) {
> +      GadgetToken token) throws GadgetException {
>     Map<String, List<Activity>> allActivities =
>         XmlStateFileFetcher.get().getActivities();
>
> @@ -52,7 +53,7 @@
>   }
>
>   public ResponseItem createActivity(String personId, Activity activity,
> -        GadgetToken token) {
> +        GadgetToken token) throws GadgetException {
>     // TODO: Validate the activity and do any template expanding
>     activity.setUserId(personId);
>     activity.setPostedTime(new Date().getTime());
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicDataService.java
> Fri Mar 28 15:05:22 2008
> @@ -17,6 +17,7 @@
>  */
>  package org.apache.shindig.social.samplecontainer;
>
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>  import org.apache.shindig.social.ResponseError;
>  import org.apache.shindig.social.ResponseItem;
> @@ -30,7 +31,7 @@
>  public class BasicDataService implements DataService {
>
>   public ResponseItem<Map<String, Map<String, String>>> getPersonData(
> -        List<String> ids, List<String> keys, GadgetToken token) {
> +        List<String> ids, List<String> keys, GadgetToken token) throws
> GadgetException {
>
>     Map<String, Map<String, String>> allData
>         = XmlStateFileFetcher.get().getAppData();
> @@ -57,7 +58,7 @@
>   }
>
>   public ResponseItem updatePersonData(String id, String key, String
> value,
> -      GadgetToken token) {
> +      GadgetToken token) throws GadgetException {
>     if (!isValidKey(key)) {
>       return new ResponseItem<Object>(ResponseError.BAD_REQUEST,
>           "The person data key had invalid characters",
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/BasicPeopleService.java
> Fri Mar 28 15:05:22 2008
> @@ -22,6 +22,7 @@
>  import org.apache.shindig.social.opensocial.model.IdSpec;
>  import org.apache.shindig.social.opensocial.model.Person;
>  import org.apache.shindig.social.opensocial.model.ApiCollection;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetToken;
>  import org.json.JSONException;
>
> @@ -44,7 +45,7 @@
>
>   public ResponseItem<ApiCollection<Person>> getPeople(List<String> ids,
>       SortOrder sortOrder, FilterType filter, int first, int max,
> -      Set<String> profileDetails, GadgetToken token) {
> +      Set<String> profileDetails, GadgetToken token) throws
> GadgetException {
>     Map<String, Person> allPeople = XmlStateFileFetcher.get
> ().getAllPeople();
>
>     List<Person> people = new ArrayList<Person>();
> @@ -79,7 +80,7 @@
>   }
>
>   public List<String> getIds(IdSpec idSpec, GadgetToken token)
> -      throws JSONException {
> +      throws JSONException, GadgetException {
>     Map<String, List<String>> friendIds
>         = XmlStateFileFetcher.get().getFriendIds();
>
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/StateFileDataHandler.java
> Fri Mar 28 15:05:22 2008
> @@ -19,6 +19,7 @@
>
>  import org.json.JSONException;
>  import org.json.JSONObject;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.social.ResponseItem;
>  import org.apache.shindig.social.ResponseError;
>  import org.apache.shindig.social.GadgetDataHandler;
> @@ -49,7 +50,7 @@
>     }
>   }
>
> -  public ResponseItem handleRequest(RequestItem request) {
> +  public ResponseItem handleRequest(RequestItem request) throws
> GadgetException {
>     RequestType type = RequestType.valueOf(request.getType());
>     ResponseItem response = null;
>
> @@ -93,4 +94,4 @@
>
>     return response;
>   }
> -}
> \ No newline at end of file
> +}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
> Fri Mar 28 15:05:22 2008
> @@ -1,6 +1,7 @@
>  package org.apache.shindig.social.samplecontainer;
>
>  import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.RemoteContent;
>  import org.apache.shindig.gadgets.RemoteContentFetcher;
>  import org.apache.shindig.gadgets.RemoteContentRequest;
> @@ -94,7 +95,7 @@
>     this.doEvil = doEvil;
>   }
>
> -  private Document fetchStateDocument() {
> +  private Document fetchStateDocument() throws GadgetException {
>     if (document != null) {
>       return document;
>     }
> @@ -130,14 +131,14 @@
>     }
>   }
>
> -  public Map<String, Map<String, String>> getAppData() {
> +  public Map<String, Map<String, String>> getAppData() throws
> GadgetException {
>     if (allData == null) {
>       setupAppData();
>     }
>     return allData;
>   }
>
> -  private void setupAppData() {
> +  private void setupAppData() throws GadgetException {
>     allData = new HashMap<String, Map<String, String>>();
>
>     Element root = fetchStateDocument().getDocumentElement();
> @@ -165,7 +166,7 @@
>     }
>   }
>
> -  public void setAppData(String id, String key, String value) {
> +  public void setAppData(String id, String key, String value) throws
> GadgetException {
>     if (allData == null) {
>       setupAppData();
>     }
> @@ -179,21 +180,21 @@
>     personData.put(key, value);
>   }
>
> -  public Map<String, List<String>> getFriendIds() {
> +  public Map<String, List<String>> getFriendIds() throws GadgetException
> {
>     if (friendIdMap == null) {
>       setupPeopleData();
>     }
>     return friendIdMap;
>   }
>
> -  public Map<String, Person> getAllPeople() {
> +  public Map<String, Person> getAllPeople() throws GadgetException {
>     if (allPeople == null) {
>       setupPeopleData();
>     }
>     return allPeople;
>   }
>
> -  private void setupPeopleData() {
> +  private void setupPeopleData() throws GadgetException {
>     Element root = fetchStateDocument().getDocumentElement();
>
>     allPeople = new HashMap<String, Person>();
> @@ -258,7 +259,7 @@
>     return friends;
>   }
>
> -  public Map<String, List<Activity>> getActivities() {
> +  public Map<String, List<Activity>> getActivities() throws
> GadgetException {
>     if (allActivities == null) {
>       setupActivities();
>     }
> @@ -266,7 +267,7 @@
>     return allActivities;
>   }
>
> -  private void setupActivities() {
> +  private void setupActivities() throws GadgetException {
>     allActivities = new HashMap<String, List<Activity>>();
>
>     Element root = fetchStateDocument().getDocumentElement();
> @@ -290,7 +291,7 @@
>   }
>
>   private void createActivities(Node streamItem, String userId,
> -      String streamTitle) {
> +      String streamTitle) throws GadgetException {
>     NodeList activityItems = streamItem.getChildNodes();
>     if (activityItems != null) {
>       for (int i = 0; i < activityItems.getLength(); i++) {
> @@ -336,7 +337,7 @@
>     return media;
>   }
>
> -  public void createActivity(String userId, Activity activity) {
> +  public void createActivity(String userId, Activity activity) throws
> GadgetException {
>     if (allActivities == null) {
>       setupActivities();
>     }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
> Fri Mar 28 15:05:22 2008
> @@ -22,16 +22,18 @@
>  import org.apache.commons.codec.digest.DigestUtils;
>
>  import java.io.UnsupportedEncodingException;
> +import java.net.URLDecoder;
>  import java.net.URLEncoder;
>  import java.security.GeneralSecurityException;
>  import java.util.HashMap;
> -import java.util.Iterator;
>  import java.util.Map;
>
>  /**
>  * Utility class for managing signed, encrypted, and time stamped blobs.
>  * Blobs are made up of name/value pairs.  Time stamps are automatically
>  * included under BlobCrypter.TIMESTAMP_KEY.
> + *
> + * Thread safe.
>  */
>  public class BlobCrypter {
>
> @@ -174,8 +176,8 @@
>     String[] items = base.split("[&=]");
>     Map<String, String> map = new HashMap<String, String>();
>     for (int i=0; i < items.length; ) {
> -      String key = items[i++];
> -      String val = items[i++];
> +      String key = URLDecoder.decode(items[i++], UTF8);
> +      String val = URLDecoder.decode(items[i++], UTF8);
>       map.put(key, val);
>     }
>     return map;
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/EasyMockTestCase.java
> Fri Mar 28 15:05:22 2008
> @@ -17,7 +17,7 @@
>  */
>  package org.apache.shindig.gadgets;
>
> -import org.easymock.EasyMock;
> +import org.easymock.classextension.EasyMock;
>
>  import junit.framework.TestCase;
>
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTestFixture.java
> Fri Mar 28 15:05:22 2008
> @@ -93,12 +93,7 @@
>     }
>
>     @Override
> -    public RequestSigner makeOAuthRequestSigner(GadgetToken token) {
> -      return null;
> -    }
> -
> -    @Override
> -    public RequestSigner makeSignedFetchRequestSigner(GadgetToken token)
> {
> +    public RemoteContentFetcher makeSigningFetcher(RemoteContentFetcher
> fetcher, GadgetToken token) {
>       // Real implementations should use their own key, probably pulled
> from
>       // disk rather than hardcoded in the source.
>       final String PRIVATE_KEY_TEXT =
> @@ -117,8 +112,8 @@
>         "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54"
> +
>         "Lw03eHTNQghS0A==";
>       final String PRIVATE_KEY_NAME = "shindig-insecure-key";
> -      return new SignedFetchRequestSigner(token, PRIVATE_KEY_NAME,
> -          PRIVATE_KEY_TEXT);
> +      return SigningFetcher.makeFromB64PrivateKey(
> +          fetcher, token, PRIVATE_KEY_NAME, PRIVATE_KEY_TEXT);
>     }
>   };
>
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/JsLibraryTest.java
> Fri Mar 28 15:05:22 2008
> @@ -34,7 +34,7 @@
>         "};";
>   private final static String URL_JS = "while(true){alert('hello');}";
>
> -  public void testInline() {
> +  public void testInline() throws GadgetException {
>     JsLibrary lib
>         = JsLibrary.create(JsLibrary.Type.INLINE, INLINE_JS, null, null);
>     assertEquals(JsLibrary.Type.INLINE, lib.getType());
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
> Fri Mar 28 15:05:22 2008
> @@ -1,225 +0,0 @@
> -/*
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -package org.apache.shindig.gadgets;
> -
> -import junit.framework.Assert;
> -import junit.framework.TestCase;
> -
> -import net.oauth.OAuth;
> -import net.oauth.OAuthAccessor;
> -import net.oauth.OAuthConsumer;
> -import net.oauth.OAuthMessage;
> -import net.oauth.OAuth.Parameter;
> -import net.oauth.signature.RSA_SHA1;
> -
> -import java.net.URL;
> -import java.util.ArrayList;
> -import java.util.List;
> -
> -
> -/**
> - * Tests the signed fetch code.
> - */
> -public class SignedFetchRequestSignerTest extends TestCase {
> -  private static final String PRIVATE_KEY_TEXT =
> -    "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V" +
> -    "A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d" +
> -    "7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ" +
> -    "hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H" +
> -    "X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm" +
> -    "uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw" +
> -    "rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z" +
> -    "zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn" +
> -    "qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG" +
> -    "WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno" +
> -    "cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+" +
> -    "3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8" +
> -    "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54" +
> -    "Lw03eHTNQghS0A==";
> -
> -  private static final String CERTIFICATE_TEXT =
> -    "-----BEGIN CERTIFICATE-----\n" +
> -    "MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0\n"
> +
> -    "IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV\n"
> +
> -    "BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
> +
> -    "gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY\n"
> +
> -    "zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb\n"
> +
> -    "mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3\n"
> +
> -    "DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d\n"
> +
> -    "4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb\n"
> +
> -    "WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J\n" +
> -    "-----END CERTIFICATE-----";
> -
> -  private SignedFetchRequestSigner signer;
> -  private BasicGadgetToken authToken;
> -  private OAuthAccessor accessor;
> -
> -  @Override
> -  public void setUp() throws Exception {
> -    authToken = new BasicGadgetToken("o", "v", "a", "d");
> -    signer = new SignedFetchRequestSigner(authToken, "foo",
> PRIVATE_KEY_TEXT);
> -    OAuthConsumer consumer = new OAuthConsumer(null, null, null, null);
> -    consumer.setProperty(RSA_SHA1.X509_CERTIFICATE, CERTIFICATE_TEXT);
> -    accessor = new OAuthAccessor(consumer);
> -  }
> -
> -  public void testParametersSet() throws Exception {
> -    URL unsigned = new URL("http://test");
> -    URL out = signer.signRequest("GET", unsigned, null);
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertTrue(contains(queryParams, "opensocial_owner_id", "o"));
> -    Assert.assertTrue(contains(queryParams, "opensocial_viewer_id",
> "v"));
> -    Assert.assertTrue(contains(queryParams, "opensocial_app_id", "a"));
> -    Assert.assertTrue(contains(queryParams, OAuth.OAUTH_CONSUMER_KEY,
> "d"));
> -    Assert.assertTrue(
> -        contains(queryParams, "xoauth_signature_publickey", "foo"));
> -  }
> -
> -  public void testTrickyParametersInQuery() throws Exception {
> -    String tricky = "%6fpensocial_owner_id=gotcha";
> -    URL unsigned = new URL("http://test?" + tricky);
> -    URL out = signer.signRequest("GET", unsigned, null);
> -    Assert.assertFalse(out.getQuery().contains("gotcha"));
> -    assertSignatureOK("GET", out.toString(), null);
> -  }
> -
> -  public void testTrickyParametersInBody() throws Exception {
> -    URL unsigned = new URL("http://test");
> -    String tricky = "%6fpensocial_owner_id=gotcha";
> -    URL out = signer.signRequest("POST", unsigned, tricky);
> -    assertSignatureInvalid("POST", out.toString(), tricky);
> -  }
> -
> -  public void testGetNoQuery() throws Exception {
> -    URL unsigned = new URL("http://test");
> -    URL out = signer.signRequest("GET", unsigned, null);
> -    assertSignatureOK("GET", out.toString(), null);
> -  }
> -
> -  public void testGetWithQuery() throws Exception {
> -    URL unsigned = new URL("http://test?a=b");
> -    URL out = signer.signRequest("GET", unsigned, null);
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertTrue(contains(queryParams, "a", "b"));
> -    assertSignatureOK("GET", out.toString(), null);
> -  }
> -
> -
> -  public void testGetWithQueryMultiParam() throws Exception {
> -    URL unsigned = new URL("http://test?a=b&a=c");
> -    URL out = signer.signRequest("GET", unsigned, null);
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertTrue(contains(queryParams, "a", "b"));
> -    Assert.assertTrue(contains(queryParams, "a", "c"));
> -    assertSignatureOK("GET", out.toString(), null);
> -  }
> -
> -  public void testPostNoQueryNoData() throws Exception {
> -    URL unsigned = new URL("http://test");
> -    URL out = signer.signRequest("POST", unsigned, null);
> -    assertSignatureOK("POST", out.toString(), null);
> -  }
> -
> -  public void testPostWithQueryNoData() throws Exception {
> -    URL unsigned =  new URL("http://test?name=value");
> -    URL out = signer.signRequest("POST", unsigned, null);
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertTrue(contains(queryParams, "name", "value"));
> -    assertSignatureOK("POST", out.toString(), null);
> -  }
> -
> -  public void testPostNoQueryWithData() throws Exception {
> -    URL unsigned =  new URL("http://test");
> -    URL out = signer.signRequest("POST", unsigned, "name=value");
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertFalse(contains(queryParams, "name", "value"));
> -    assertSignatureOK("POST", out.toString(), "name=value");
> -  }
> -
> -  public void testPostWithQueryWithData() throws Exception {
> -    URL unsigned =  new URL("http://test?queryName=queryValue");
> -    URL out = signer.signRequest("POST", unsigned, "name=value");
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertTrue(contains(queryParams, "queryName", "queryValue"));
> -    assertSignatureOK("POST", out.toString(), "name=value");
> -  }
> -
> -  public void testStripOpenSocialParamsFromQuery() throws Exception {
> -    URL unsigned =  new URL("http://test?opensocial_foo=bar");
> -    URL out = signer.signRequest("POST", unsigned, "name=value");
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertFalse(contains(queryParams, "opensocial_foo", "bar"));
> -    assertSignatureOK("POST", out.toString(), "name=value");
> -  }
> -
> -  public void testStripOAuthParamsFromQuery() throws Exception {
> -    URL unsigned =  new URL("http://test?oauth_foo=bar");
> -    URL out = signer.signRequest("POST", unsigned, "name=value");
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(out.getQuery());
> -    Assert.assertFalse(contains(queryParams, "oauth_foo", "bar"));
> -    assertSignatureOK("POST", out.toString(), "name=value");
> -  }
> -
> -  public void testStripOpenSocialParamsFromBody() throws Exception {
> -    URL unsigned =  new URL("http://test");
> -    URL out = signer.signRequest("POST", unsigned, "opensocial_foo=bar");
> -    assertSignatureInvalid("POST", out.toString(), "opensocial_foo=bar");
> -  }
> -
> -  public void testStripOAuthParamsFromBody() throws Exception {
> -    URL unsigned =  new URL("http://test");
> -    URL out = signer.signRequest("POST", unsigned, "oauth_foo=bar");
> -    assertSignatureInvalid("POST", out.toString(), "oauth_foo=bar");
> -  }
> -
> -  private void assertSignatureOK(String method, String urlStr, String
> body)
> -  throws Exception {
> -    URL url = new URL(urlStr);
> -    URL noQuery = new URL(url.getProtocol(), url.getHost(), url.getPort
> (),
> -        url.getPath());
> -    List<OAuth.Parameter> queryParams = OAuth.decodeForm(url.getQuery());
> -    List<OAuth.Parameter> postParams = OAuth.decodeForm(body);
> -
> -    ArrayList<OAuth.Parameter> msgParams = new ArrayList<OAuth.Parameter
> >();
> -    msgParams.addAll(queryParams);
> -    msgParams.addAll(postParams);
> -
> -    OAuthMessage message = new OAuthMessage(method, noQuery.toString(),
> -        msgParams);
> -
> -    // Throws on failure
> -    message.validateSignature(accessor);
> -  }
> -
> -  private void assertSignatureInvalid(String method, String urlStr,
> String body) {
> -    try {
> -      assertSignatureOK(method, urlStr, body);
> -      fail("Signature verification should have failed");
> -    } catch (Exception e) {
> -      // good
> -    }
> -  }
> -
> -  // Checks whether the given parameter list contains the specified
> -  // key/value pair
> -  private boolean contains(List<Parameter> params, String key, String
> value) {
> -    for (Parameter p : params) {
> -      if (p.getKey().equals(key) && p.getValue().equals(value)) {
> -        return true;
> -      }
> -    }
> -    return false;
> -  }
> -}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/ProxyHandlerTest.java
> Fri Mar 28 15:05:22 2008
> @@ -25,6 +25,7 @@
>  import java.io.PrintWriter;
>  import java.net.URI;
>
> +import org.apache.shindig.gadgets.GadgetException;
>  import org.apache.shindig.gadgets.GadgetTestFixture;
>  import org.apache.shindig.gadgets.RemoteContent;
>  import org.apache.shindig.gadgets.RemoteContentRequest;
> @@ -142,17 +143,54 @@
>     writer.close();
>   }
>
> +  public void testSignedPostRequest() throws Exception {
> +    String postBody = "foo=bar%20baz";
> +    setupPostRequestMock(URL_ONE, postBody);
> +    expect(request.getParameter
> ("st")).andReturn("fake-token").atLeastOnce();
> +    expect(request.getParameter
> ("authz")).andReturn("signed").atLeastOnce();
> +    RemoteContent resp = new RemoteContent(200, DATA_ONE.getBytes(),
> null);
> +    expect(fetcher.fetch(
> +        looksLikeSignedFetch(URL_ONE, postBody.getBytes
> ()))).andReturn(resp);
> +    replay();
> +    proxyHandler.fetchJson(request, response, state);
> +    verify();
> +    writer.close();
> +  }
> +
> +  public void testInvalidSigningType() throws Exception {
> +    setupGetRequestMock(URL_ONE);
> +    expect(request.getParameter
> ("st")).andReturn("fake-token").atLeastOnce();
> +    expect(request.getParameter
> ("authz")).andReturn("garbage").atLeastOnce();
> +    replay();
> +    try {
> +      proxyHandler.fetchJson(request, response, state);
> +      fail("proxyHandler accepted invalid authz type");
> +    } catch (GadgetException e) {
> +      assertEquals(GadgetException.Code.UNSUPPORTED_FEATURE, e.getCode
> ());
> +    }
> +  }
> +
>   private RemoteContentRequest looksLikeSignedFetch(String url) {
> -    EasyMock.reportMatcher(new SignedFetchArgumentMatcher(url));
> +    return looksLikeSignedFetch(url, null);
> +  }
> +
> +  private RemoteContentRequest looksLikeSignedFetch(String url, byte[]
> postBody) {
> +    EasyMock.reportMatcher(new SignedFetchArgumentMatcher(url,
> postBody));
>     return null;
>   }
>
>   private class SignedFetchArgumentMatcher implements IArgumentMatcher {
>
>     private String expectedUrl;
> +    private byte[] postBody;
>
>     public SignedFetchArgumentMatcher(String expectedUrl) {
> +      this(expectedUrl, null);
> +    }
> +
> +    public SignedFetchArgumentMatcher(String expectedUrl, byte[]
> postBody) {
>       this.expectedUrl = expectedUrl;
> +      this.postBody = postBody;
>     }
>
>     public void appendTo(StringBuffer sb) {
> @@ -164,11 +202,95 @@
>     public boolean matches(Object arg0) {
>       RemoteContentRequest request = (RemoteContentRequest)arg0;
>       String url = request.getUri().toASCIIString();
> -      return (url.startsWith(expectedUrl) &&
> -          url.contains("opensocial_owner_id") &&
> +      if (url.startsWith(expectedUrl) &&
> +          url.contains("opensocial_owner_id") &&
>           url.contains("opensocial_viewer_id") &&
> -          url.contains("opensocial_app_id"));
> +          url.contains("opensocial_app_id") &&
> +          byteArrayEquals(postBody, request.getPostBodyBytes())) {
> +        return true;
> +      }
> +      return false;
>     }
>
> +    private boolean byteArrayEquals(byte[] expected, byte[] actual) {
> +      if (expected == null) {
> +        expected = new byte[0];
> +      }
> +      if (actual == null) {
> +        actual = new byte[0];
> +      }
> +      if (expected.length != actual.length) {
> +        return false;
> +      }
> +      for (int i=0; i < expected.length; i++) {
> +        if (expected[i] != actual[i]) {
> +          return false;
> +        }
> +      }
> +      return true;
> +    }
> +  }
> +
> +  public void testValidateUrlNoPath() throws Exception {
> +    URI url = proxyHandler.validateUrl("http://www.example.com");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(-1, url.getPort());
> +    assertEquals("/", url.getPath());
> +    assertNull(url.getQuery());
> +    assertNull(url.getFragment());
> +  }
> +
> +  public void testValidateUrlWithPath() throws Exception {
> +    URI url = proxyHandler.validateUrl("http://www.example.com/foo");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(-1, url.getPort());
> +    assertEquals("/foo", url.getPath());
> +    assertNull(url.getQuery());
> +    assertNull(url.getFragment());
> +  }
> +
> +  public void testValidateUrlWithPort() throws Exception {
> +    URI url = proxyHandler.validateUrl("http://www.example.com:8080/foo
> ");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(8080, url.getPort());
> +    assertEquals("/foo", url.getPath());
> +    assertNull(url.getQuery());
> +    assertNull(url.getFragment());
> +  }
> +
> +  public void testValidateUrlWithEncodedPath() throws Exception {
> +    URI url = proxyHandler.validateUrl("
> http://www.example.com:8080/foo%20bar");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(8080, url.getPort());
> +    assertEquals("/foo%20bar", url.getRawPath());
> +    assertEquals("/foo bar", url.getPath());
> +    assertNull(url.getQuery());
> +    assertNull(url.getFragment());
> +  }
> +
> +  public void testValidateUrlWithEncodedQuery() throws Exception {
> +    URI url = proxyHandler.validateUrl("
> http://www.example.com:8080/foo?q=with%20space");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(8080, url.getPort());
> +    assertEquals("/foo", url.getPath());
> +    assertEquals("q=with%20space", url.getRawQuery());
> +    assertEquals("q=with space", url.getQuery());
> +    assertNull(url.getFragment());
> +  }
> +
> +  public void testValidateUrlWithNoPathAndEncodedQuery() throws Exception
> {
> +    URI url = proxyHandler.validateUrl("
> http://www.example.com?q=with%20space");
> +    assertEquals("http", url.getScheme());
> +    assertEquals("www.example.com", url.getHost());
> +    assertEquals(-1, url.getPort());
> +    assertEquals("/", url.getPath());
> +    assertEquals("q=with%20space", url.getRawQuery());
> +    assertEquals("q=with space", url.getQuery());
> +    assertNull(url.getFragment());
>   }
>  }
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java?rev=642404&r1=642403&r2=642404&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
> Fri Mar 28 15:05:22 2008
> @@ -49,6 +49,8 @@
>     checkString("ab");
>     checkString("dfkljdasklsdfklasdjfklajsdfkljasdklfjasdkljfaskldjf");
>     checkString(Crypto.getRandomString(500));
> +    checkString("foo bar baz");
> +    checkString("foo\nbar\nbaz");
>   }
>
>   private void checkString(String string) throws Exception {
>
>
>


-- 
~Kevin

Re: svn commit: r642404 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/ main/java/org/apache/shindig/gadgets/http/ main/java/org/apache/shindig/social/ main/java/org/apache/shindig/social/opensocial/ main/java/or

Posted by Cassie <do...@google.com>.
Cool. That can just be mapped to the ResponseError.INTERNAL_ERROR code.
Thanks!

- Cassie


On Mon, Mar 31, 2008 at 6:52 PM, Brian Eaton <be...@google.com> wrote:

> On Mon, Mar 31, 2008 at 3:22 AM, Cassie <do...@google.com> wrote:
> >  Why do all of the social classes need throws GadgetException in their
> >  signatures? I can't see anywhere this is thrown in the current social
> code,
> >  and furthermore, the design is set up so that the service
> implementations
> >  always handle their own exceptions and return a proper error code.
> Allowing
> >  them to both return an error code and return an exception is just
> confusing.
>
> Ah, I'd missed the error handling in the original design.  There just
> needs to be some mechanism to return an error from those APIs, it
> doesn't have to be GadgetException.  If a RemoteContentFetcher were to
> throw a GadgetException, how should that exception be mapped to a
> ResponseError?
>

Re: svn commit: r642404 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/ main/java/org/apache/shindig/gadgets/http/ main/java/org/apache/shindig/social/ main/java/org/apache/shindig/social/opensocial/ main/java/or

Posted by Brian Eaton <be...@google.com>.
On Mon, Mar 31, 2008 at 3:22 AM, Cassie <do...@google.com> wrote:
>  Why do all of the social classes need throws GadgetException in their
>  signatures? I can't see anywhere this is thrown in the current social code,
>  and furthermore, the design is set up so that the service implementations
>  always handle their own exceptions and return a proper error code. Allowing
>  them to both return an error code and return an exception is just confusing.

Ah, I'd missed the error handling in the original design.  There just
needs to be some mechanism to return an error from those APIs, it
doesn't have to be GadgetException.  If a RemoteContentFetcher were to
throw a GadgetException, how should that exception be mapped to a
ResponseError?

Re: svn commit: r642404 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/ main/java/org/apache/shindig/gadgets/http/ main/java/org/apache/shindig/social/ main/java/org/apache/shindig/social/opensocial/ main/java/or

Posted by Cassie <do...@google.com>.
One comment on the original cl:

Why do all of the social classes need throws GadgetException in their
signatures? I can't see anywhere this is thrown in the current social code,
and furthermore, the design is set up so that the service implementations
always handle their own exceptions and return a proper error code. Allowing
them to both return an error code and return an exception is just confusing.


Are you going to change this in the second submit?
Thanks!

- Cassie


On Sat, Mar 29, 2008 at 2:38 AM, Kevin Brown <et...@apache.org> wrote:

> Ok, this actually didn't work out as I planned. I'm going to roll this
> patch
> back and then include it with the Guice patch to make life less painful.
>
> Sorry everyone.
>