You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2008/03/28 23:05:31 UTC
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/org/apac...
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 {