You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by Santiago Gala <sa...@gmail.com> on 2008/04/03 20:23:09 UTC
Re: svn commit: r644123 [1/3] - in /incubator/shindig/trunk:
features/core.io/ java/gadgets/ java/gadgets/conf/
java/gadgets/src/main/java/org/apache/shindig/gadgets/
java/gadgets/src/main/java/org/apache/shindig/gadgets/http/
java/gadgets/src/main/java/or...
quite possibly a small oversight after applying the patch, but
$ find . -name .svn -prune -or -type f -empty -print
./java/gadgets/src/test/java/org/apache/shindig/gadgets/http/GadgetRendererTest.java
./java/gadgets/src/test/java/org/apache/shindig/gadgets/http/JsonRpcRequestTest.java
./java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java
./java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.java
./java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java
./java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java
:) (I am not sure it is not a working copy problem here)
Regards
Santiago
El jue, 03-04-2008 a las 00:40 +0000, etnu@apache.org escribió:
> Author: etnu
> Date: Wed Apr 2 17:40:05 2008
> New Revision: 644123
>
> URL: http://svn.apache.org/viewvc?rev=644123&view=rev
> Log:
> Wiring up Guice support as discussed in SHINDIG-152.
>
> This is a very significant change for anyone who has maintained customized implementations of any of the core Shindig classes, but it greatly simplifies the task of extending te server.
>
> This patch also incorporates Brian Eaton's signing interface improvements discussed in SHINDIG-157.
>
>
> Added:
> incubator/shindig/trunk/java/gadgets/conf/
> incubator/shindig/trunk/java/gadgets/conf/gadgets.properties
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetTokenDecoder.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/CachedContentFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DefaultGuiceModule.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetTokenDecoder.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/PreloadFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcherFactory.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingTask.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GuiceServletContextListener.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpGuiceModule.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/InjectedServlet.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcHandler.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxiedContentFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/UrlGenerator.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/GadgetRenderingTaskTest.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpTestFixture.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/JsonRpcHandlerTest.java
> Removed:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSigner.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DataFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSigner.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/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/test/java/org/apache/shindig/gadgets/SignedFetchRequestSignerTest.java
> Modified:
> incubator/shindig/trunk/features/core.io/io.js
> incubator/shindig/trunk/java/gadgets/pom.xml
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetToken.java
> 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/Gadget.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetToken.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/MessageBundleFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContent.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/RenderingContext.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderer.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetContext.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.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/gadgets/http/ProxyServlet.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/social/GadgetDataServlet.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/samplecontainer/XmlStateFileFetcher.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/BlobCrypter.java
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/ResourceLoader.java
> incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> 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/GadgetServerTest.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/http/GadgetRendererTest.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/JsonRpcRequestTest.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/gadgets/spec/ModulePrefsTest.java
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/util/BlobCrypterTest.java
>
> Modified: incubator/shindig/trunk/features/core.io/io.js
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core.io/io.js?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/features/core.io/io.js (original)
> +++ incubator/shindig/trunk/features/core.io/io.js Wed Apr 2 17:40:05 2008
> @@ -193,10 +193,10 @@
> * false otherwise
> */
> function respondWithPreload(postData, params, callback) {
> - if (gadgets.io.preloaded && gadgets.io.preloaded[postData.url]) {
> - var preload = gadgets.io.preloaded[postData.url];
> + if (gadgets.io.preloaded_ && gadgets.io.preloaded_[postData.url]) {
> + var preload = gadgets.io.preloaded_[postData.url];
> if (postData.httpMethod == "GET" && postData.authz == "none") {
> - delete gadgets.io.preloaded[postData.url];
> + delete gadgets.io.preloaded_[postData.url];
> if (preload.rc !== 200) {
> callback({errors : ["Error " + preload.rc]});
> } else {
> @@ -349,4 +349,4 @@
>
> gadgets.io.AuthorizationType = gadgets.util.makeEnum([
> "NONE", "SIGNED", "AUTHENTICATED"
> -]);
> \ No newline at end of file
> +]);
>
> Added: incubator/shindig/trunk/java/gadgets/conf/gadgets.properties
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/conf/gadgets.properties?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/conf/gadgets.properties (added)
> +++ incubator/shindig/trunk/java/gadgets/conf/gadgets.properties Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,9 @@
> +features.default=res://features/features.txt
> +syndicators.default=res://syndicators/default/syndicator.js
> +blacklist.file=
> +urls.iframe.prefix=/gadgets/ifr?
> +urls.js.prefix=/gadgets/js/
> +signing.key-name=
> +signing.key-file=
> +
> +
>
> Modified: incubator/shindig/trunk/java/gadgets/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/pom.xml?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/pom.xml (original)
> +++ incubator/shindig/trunk/java/gadgets/pom.xml Wed Apr 2 17:40:05 2008
> @@ -153,13 +153,6 @@
> <directory>../../features</directory>
> </resource>
> <resource>
> - <targetPath>syndicators/default</targetPath>
> - <directory>../../config</directory>
> - <includes>
> - <include>syndicator.js</include>
> - </includes>
> - </resource>
> - <resource>
> <!-- duplicated here for the jar build. -->
> <!-- TODO: Eliminate duplicate copies in WAR output -->
> <!-- this is relative to the pom.xml directory -->
> @@ -169,6 +162,16 @@
> <include>**/*.*</include>
> </includes>
> </resource>
> + <resource>
> + <targetPath>syndicators/default</targetPath>
> + <directory>../../config</directory>
> + <includes>
> + <include>syndicator.js</include>
> + </includes>
> + </resource>
> + <resource>
> + <directory>conf</directory>
> + </resource>
> </resources>
> </build>
> <repositories>
> @@ -229,7 +232,12 @@
> <version>20080229</version>
> <scope>compile</scope>
> </dependency>
> - <dependency>
> + <dependency>
> + <groupId>com.google.code.guice</groupId>
> + <artifactId>guice</artifactId>
> + <version>1.0</version>
> + </dependency>
> + <dependency>
> <groupId>commons-lang</groupId>
> <artifactId>commons-lang</artifactId>
> <version>2.3</version>
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetBlacklist.java Wed Apr 2 17:40:05 2008
> @@ -17,6 +17,9 @@
> */
> package org.apache.shindig.gadgets;
>
> +import com.google.inject.Inject;
> +import com.google.inject.name.Named;
> +
> import java.io.BufferedReader;
> import java.io.File;
> import java.io.FileReader;
> @@ -71,7 +74,15 @@
> public BasicGadgetBlacklist(File blacklistFile) throws IOException {
> exactMatches = new HashSet<String>();
> regexpMatches = new ArrayList<Pattern>();
> - parseBlacklist(blacklistFile);
> + if (blacklistFile.exists()) {
> + parseBlacklist(blacklistFile);
> + }
> + }
> +
> + @Inject
> + public BasicGadgetBlacklist(@Named("blacklist.file") String file)
> + throws IOException {
> + this(new File(file));
> }
>
> private void parseBlacklist(File blacklistFile) throws IOException {
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetToken.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetToken.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetToken.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetToken.java Wed Apr 2 17:40:05 2008
> @@ -27,24 +27,24 @@
> /**
> * Primitive token implementation that uses stings as tokens.
> */
> -class BasicGadgetToken implements GadgetToken {
> +public class BasicGadgetToken implements GadgetToken {
> /** serialized form of the token */
> private final String token;
> -
> +
> /** data from the token */
> private final Map<String, String> tokenData;
> -
> +
> /** tool to use for signing and encrypting the token */
> private BlobCrypter crypter = new BlobCrypter(INSECURE_KEY);
> -
> +
> private static final byte[] INSECURE_KEY =
> { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
> -
> +
> private static final String OWNER_KEY = "o";
> private static final String APP_KEY = "a";
> private static final String VIEWER_KEY = "v";
> private static final String DOMAIN_KEY = "d";
> -
> +
> /**
> * {@inheritDoc}
> */
> @@ -56,14 +56,14 @@
> * Generates a token from an input string
> * @param token String form of token
> * @param maxAge max age of the token (in seconds)
> - * @throws BlobCrypterException
> + * @throws BlobCrypterException
> */
> public BasicGadgetToken(String token, int maxAge)
> - throws BlobCrypterException {
> + throws BlobCrypterException {
> this.token = token;
> this.tokenData = crypter.unwrap(token, maxAge);
> }
> -
> +
> public BasicGadgetToken(String owner, String viewer, String app,
> String domain) throws BlobCrypterException {
> tokenData = new HashMap<String, String>(5,1);
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetTokenDecoder.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetTokenDecoder.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetTokenDecoder.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetTokenDecoder.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,48 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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 org.apache.shindig.util.BlobCrypterException;
> +
> +/**
> + * A GadgetTokenDecoder implementation that just provides dummy data to satisfy
> + * tests and API calls. Do not use this for any security applications.
> + */
> +public class BasicGadgetTokenDecoder implements GadgetTokenDecoder {
> +
> + /**
> + * {@inheritDoc}
> + *
> + * Returns a token with some faked out values.
> + */
> + public GadgetToken createToken(String stringToken) throws GadgetException {
> + try {
> + String[] tokens = stringToken.split(":");
> + return new BasicGadgetToken(tokens[0], tokens[1], tokens[2], tokens[3]);
> + } catch (BlobCrypterException e) {
> + throw new GadgetException(GadgetException.Code.INVALID_GADGET_TOKEN, e);
> + }
> + }
> +
> + /**
> + * Creates a signer with 24 hour token expiry
> + */
> + public BasicGadgetTokenDecoder() {
> + }
> +}
>
> 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=644123&r1=644122&r2=644123&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 Wed Apr 2 17:40:05 2008
> @@ -19,19 +19,28 @@
>
> import org.apache.shindig.util.InputStreamConsumer;
>
> +import com.google.inject.Singleton;
> +
> import java.io.FileNotFoundException;
> import java.io.IOException;
> +import java.io.InputStream;
> import java.net.HttpURLConnection;
> import java.net.URLConnection;
> import java.util.List;
> import java.util.Map;
> +import java.util.zip.GZIPInputStream;
> +import java.util.zip.Inflater;
> +import java.util.zip.InflaterInputStream;
>
> /**
> * Implementation of a {@code RemoteObjectFetcher} using standard java.net
> - * classes.
> + * classes. Only one instance of this should be present at any time, so we
> + * annotate it as a Singleton to resolve Guice injection limitations.
> */
> -public class BasicRemoteContentFetcher implements RemoteContentFetcher {
> +@Singleton
> +public class BasicRemoteContentFetcher extends RemoteContentFetcher {
> private static final int CONNECT_TIMEOUT_MS = 5000;
> + private static final int DEFAULT_MAX_OBJECT_SIZE = 1024 * 1024;
>
> private final int maxObjSize;
>
> @@ -41,10 +50,18 @@
> * @param maxObjSize Maximum size, in bytes, of object to fetch
> */
> public BasicRemoteContentFetcher(int maxObjSize) {
> + super(null);
> this.maxObjSize = maxObjSize;
> }
>
> /**
> + * Creates a new fetcher using the default maximum object size.
> + */
> + public BasicRemoteContentFetcher() {
> + this(DEFAULT_MAX_OBJECT_SIZE);
> + }
> +
> + /**
> * Initializes the connection.
> *
> * @param request
> @@ -56,6 +73,7 @@
> URLConnection fetcher;
> fetcher = request.getUri().toURL().openConnection();
> fetcher.setConnectTimeout(CONNECT_TIMEOUT_MS);
> + fetcher.setRequestProperty("Accept-Encoding", "gzip, deflate");
> if (fetcher instanceof HttpURLConnection) {
> ((HttpURLConnection)fetcher).setInstanceFollowRedirects(true);
> Map<String, List<String>> reqHeaders = request.getAllHeaders();
> @@ -96,12 +114,25 @@
> } else {
> responseCode = RemoteContent.SC_OK;
> }
> - byte[] body = InputStreamConsumer.readToByteArray(
> - fetcher.getInputStream(), maxObjSize);
> +
> + String encoding = fetcher.getContentEncoding();
> + InputStream is = null;
> + // Create the appropriate stream wrapper based on the encoding type.
> + if (encoding == null) {
> + is = fetcher.getInputStream();
> + } else if (encoding.equalsIgnoreCase("gzip")) {
> + is = new GZIPInputStream(fetcher.getInputStream());
> + } else if (encoding.equalsIgnoreCase("deflate")) {
> + Inflater inflater = new Inflater(true);
> + is = new InflaterInputStream(fetcher.getInputStream(), inflater);
> + }
> +
> + byte[] body = InputStreamConsumer.readToByteArray(is, maxObjSize);
> return new RemoteContent(responseCode, body, headers);
> }
>
> /** {@inheritDoc} */
> + @Override
> public RemoteContent fetch(RemoteContentRequest request) {
> try {
> URLConnection fetcher = getConnection(request);
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/CachedContentFetcher.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/CachedContentFetcher.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/CachedContentFetcher.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/CachedContentFetcher.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,57 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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 com.google.inject.Inject;
> +import com.google.inject.Singleton;
> +
> +import java.net.URI;
> +import java.util.HashMap;
> +import java.util.Map;
> +
> +/**
> + * Caches the results of a request indefinitely.
> + *
> + * Currently just uses a map for the cache. This means it will grow infinitely.
> + */
> +@Singleton
> +public class CachedContentFetcher extends RemoteContentFetcher {
> +
> + private final Map<URI, RemoteContent> cache;
> +
> + /** {@inheritDoc} */
> + @Override
> + public RemoteContent fetch(RemoteContentRequest request)
> + throws GadgetException {
> + RemoteContent result = cache.get(request.getUri());
> + if (result == null) {
> + result = nextFetcher.fetch(request);
> + synchronized (cache) {
> + cache.put(request.getUri(),result);
> + }
> + }
> + return result;
> + }
> +
> + @Inject
> + public CachedContentFetcher(RemoteContentFetcher nextFetcher) {
> + super(nextFetcher);
> + cache = new HashMap<URI, RemoteContent>();
> + }
> +}
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DefaultGuiceModule.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DefaultGuiceModule.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DefaultGuiceModule.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/DefaultGuiceModule.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,92 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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 org.apache.shindig.util.ResourceLoader;
> +
> +import com.google.inject.AbstractModule;
> +import com.google.inject.CreationException;
> +import com.google.inject.Scopes;
> +import com.google.inject.name.Names;
> +import com.google.inject.spi.Message;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.util.Arrays;
> +import java.util.Properties;
> +import java.util.concurrent.Executor;
> +import java.util.concurrent.Executors;
> +
> +/**
> + * Creates a module to supply all of the Basic* classes
> + */
> +public class DefaultGuiceModule extends AbstractModule {
> + private final Properties properties;
> + private final static String DEFAULT_PROPERTIES = "gadgets.properties";
> +
> + /** {@inheritDoc} */
> + @Override
> + protected void configure() {
> + Names.bindProperties(this.binder(), properties);
> +
> + bind(RemoteContentFetcher.class).to(BasicRemoteContentFetcher.class);
> +
> + bind(RemoteContentFetcher.class)
> + .annotatedWith(GadgetSpecFetcher.class)
> + .to(CachedContentFetcher.class);
> + bind(RemoteContentFetcher.class)
> + .annotatedWith(MessageBundleFetcher.class)
> + .to(CachedContentFetcher.class);
> +
> + // This is redundant because Guice doesn't handle generic fall through
> + // for non-annotated types.
> + bind(RemoteContentFetcher.class)
> + .annotatedWith(PreloadFetcher.class)
> + .to(BasicRemoteContentFetcher.class);
> +
> + bind(GadgetBlacklist.class).to(BasicGadgetBlacklist.class);
> + bind(GadgetTokenDecoder.class).to(BasicGadgetTokenDecoder.class);
> + bind(SigningFetcherFactory.class);
> + bind(Executor.class).toInstance(Executors.newCachedThreadPool());
> +
> + bind(SyndicatorConfig.class).in(Scopes.SINGLETON);
> + bind(GadgetFeatureRegistry.class).in(Scopes.SINGLETON);
> + bind(GadgetServer.class).in(Scopes.SINGLETON);
> + }
> +
> + public DefaultGuiceModule(Properties properties) {
> + this.properties = properties;
> + }
> +
> + /**
> + * Creates module with standard properties.
> + */
> + public DefaultGuiceModule() {
> + Properties properties = null;
> + try {
> + InputStream is = ResourceLoader.openResource(DEFAULT_PROPERTIES);
> + properties = new Properties();
> + properties.load(is);
> + } catch (IOException e) {
> + throw new CreationException(Arrays.asList(
> + new Message("Unable to load properties: " + DEFAULT_PROPERTIES)));
> + }
> + this.properties = properties;
> + }
> +}
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java Wed Apr 2 17:40:05 2008
> @@ -34,14 +34,6 @@
> * and is modified in parallel by a number of {@code GadgetFeature}
> * processors, in an order defined by their dependencies, in
> * {@code GadgetServer}.
> - *
> - * Upon completion of processing, a {@code Gadget} is serialized as appropriate
> - * to whatever output format is appropriate (eg. as gadget content in an
> - * IFRAME), potentially with post-processing such as HTML whitespace
> - * compression or HTML+JS (Caja) rewriting applied.
> - *
> - * "Hangman" variable substitutions (eg. __MSG_foo__) are performed as needed
> - * and transparently for fields that support this functionality.
> */
> public class Gadget {
> private final GadgetContext context;
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetFeatureRegistry.java Wed Apr 2 17:40:05 2008
> @@ -17,10 +17,12 @@
> */
> package org.apache.shindig.gadgets;
>
> +import com.google.inject.Inject;
> +import com.google.inject.name.Named;
> +
> import java.util.Collections;
> import java.util.HashMap;
> import java.util.HashSet;
> -import java.util.LinkedList;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
> @@ -35,66 +37,33 @@
> * registry.register("my-feature", null, new MyFeatureFactory());
> */
> public class GadgetFeatureRegistry {
> - private final Map<String, Entry> features = new HashMap<String, Entry>();
> - private final Map<String, Entry> core = new HashMap<String, Entry>();
> + private final Map<String, Entry> features;
> + private final Map<String, Entry> core;
>
> // Caches the transitive dependencies to enable faster lookups.
> private final Map<Set<String>, Set<Entry>> transitiveDeps
> = new HashMap<Set<String>, Set<Entry>>();
>
> - private boolean coreDone = false;
> -
> - private final RemoteContentFetcher fetcher;
> + private boolean graphComplete = false;
>
> private final static Logger logger
> = Logger.getLogger("org.apache.shindig.gadgets");
>
> /**
> - * Creates the gadget feature registry and loads an initial set of features.
> - * Any 'core' features loaded at this point will automatically become
> - * dependencies for every other feature.
> - * @param featurePath
> - * @param fetcher
> - */
> - public GadgetFeatureRegistry(String featurePath, RemoteContentFetcher fetcher)
> - throws GadgetException {
> - this.fetcher = fetcher;
> - registerFeatures(featurePath);
> - }
> -
> - /**
> - * Recursively loads a set of features from a path in the filesystem or
> - * from the classpath.
> + * Creates a new feature registry and loads the specified features.
> *
> - * @param featurePath Path to the directory that contains feature xml files.
> - */
> - public void registerFeatures(String featurePath) throws GadgetException {
> - if (featurePath == null) {
> - return;
> - }
> -
> - List<String> coreDeps = new LinkedList<String>();
> - JsFeatureLoader loader = new JsFeatureLoader(fetcher);
> - Set<Entry> jsFeatures = loader.loadFeatures(featurePath, this);
> -
> - if (!coreDone) {
> - for (Entry entry : jsFeatures) {
> - if (entry.name.startsWith("core") || entry.name.equals("core")) {
> - coreDeps.add(entry.getName());
> - core.put(entry.getName(), entry);
> - }
> - }
> -
> - logger.info("Core dependencies: " + coreDeps);
> -
> - // Make sure non-core features depend on core.
> - for (Entry entry : jsFeatures) {
> - if (!entry.name.startsWith("core") && !entry.name.equals("core")) {
> - entry.deps.addAll(core.keySet());
> - }
> - }
> -
> - coreDone = true;
> + * @param contentFetcher
> + * @param featureFiles
> + * @throws GadgetException
> + */
> + @Inject
> + public GadgetFeatureRegistry(@Named("features.default") String featureFiles,
> + RemoteContentFetcher contentFetcher) throws GadgetException {
> + features = new HashMap<String, Entry>();
> + core = new HashMap<String, Entry>();
> + if (featureFiles != null) {
> + JsFeatureLoader loader = new JsFeatureLoader(contentFetcher);
> + loader.loadFeatures(featureFiles, this);
> }
> }
>
> @@ -105,7 +74,9 @@
> *
> * Names are freeform, but it is strongly suggested that they are
> * namespaced, optionally (yet often usefully) in Java package-notation ie.
> - * 'com.google.gadgets.skins'.
> + * 'org.example.FooFeature'
> + *
> + * May never be invoked after calling getIncludedFeatures.
> *
> * @param name Name of the feature to register, ideally using the conventions
> * described
> @@ -116,26 +87,33 @@
> */
> public Entry register(String name, List<String> deps,
> GadgetFeatureFactory feature) {
> + if (graphComplete) {
> + throw new IllegalStateException("registerFeatures should never be " +
> + "invoked after calling getIncludedFeatures");
> + }
> logger.info("Registering feature: " + name + " with deps " + deps);
> Entry entry = new Entry(name, deps, feature, this);
> - if (coreDone) {
> + if (isCore(entry)) {
> + core.put(name, entry);
> + for (Entry e : features.values()) {
> + e.deps.add(name);
> + }
> + } else {
> entry.deps.addAll(core.keySet());
> }
> features.put(name, entry);
> - validateFeatureGraph();
> return entry;
> }
>
> /**
> - * Traverses the graph traversed by the registered features, validating
> - * that it comprises a directed acyclic graph in which all features'
> - * dependencies are provided.
> - *
> - * If the graph is not acyclic, it cannot be used to create a workflow. If
> - * any dependencies are missing, {@code Gadget} rendering may be incomplete.
> + * @param entry
> + * @return True if the entry is "core" (a dependency of all other features)
> */
> - private static void validateFeatureGraph() {
> - // TODO: ensure that features form a DAG and that all deps are provided
> + private boolean isCore(Entry entry) {
> + if (entry.name.startsWith("core") || entry.name.equals("core")) {
> + return true;
> + }
> + return false;
> }
>
> /**
> @@ -158,6 +136,7 @@
> public boolean getIncludedFeatures(Set<String> needed,
> Set<Entry> resultsFound,
> Set<String> resultsMissing) {
> + graphComplete = true;
> if (needed.size() == 0) {
> // Shortcut for gadgets that don't have any explicit dependencies.
> resultsFound.addAll(core.values());
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java Wed Apr 2 17:40:05 2008
> @@ -22,7 +22,8 @@
> import org.apache.shindig.gadgets.spec.LocaleSpec;
> import org.apache.shindig.gadgets.spec.MessageBundle;
> import org.apache.shindig.gadgets.spec.Preload;
> -import org.apache.shindig.util.Check;
> +
> +import com.google.inject.Inject;
>
> import java.util.HashMap;
> import java.util.HashSet;
> @@ -32,39 +33,42 @@
> import java.util.Set;
> import java.util.concurrent.Callable;
> import java.util.concurrent.CompletionService;
> +import java.util.concurrent.Executor;
> import java.util.concurrent.ExecutorCompletionService;
> import java.util.concurrent.Future;
>
> +/**
> + * Primary gadget processing facility. Converts an input Context into an output
> + * Gadget
> + */
> public class GadgetServer {
> - private final GadgetServerConfigReader config;
> -
> - /**
> - * Creates a GadgetServer using the provided configuration.
> - *
> - * @param configuration
> - * @throws IllegalArgumentException When missing required fields aren't set.
> - */
> - public GadgetServer(GadgetServerConfigReader configuration) {
> - Check.notNull(configuration.getExecutor(), "Executor is required.");
> - Check.notNull(configuration.getFeatureRegistry(),
> - "FeatureRegistry is required.");
> - Check.notNull(configuration.getGadgetSpecFetcher(),
> - "GadgetSpecFetcher is required");
> - Check.notNull(configuration.getMessageBundleFetcher(),
> - "MessageBundleFetcher is required.");
> - Check.notNull(configuration.getContentFetcher(),
> - "ContentFetcher is required.");
> - Check.notNull(configuration.getSyndicatorConfig(),
> - "SyndicatorConfig is required");
> - config = new GadgetServerConfigReader();
> - config.copyFrom(configuration);
> - }
> + private final Executor executor;
> + private final GadgetFeatureRegistry registry;
> + private final GadgetBlacklist blacklist;
> + private final RemoteContentFetcher preloadFetcher;
> + private final RemoteContentFetcher gadgetSpecFetcher;
> + private final RemoteContentFetcher messageBundleFetcher;
>
> /**
> - * @return A read-only view of the server's configuration.
> + * @param executor
> + * @param registry
> + * @param blacklist
> + * @param gadgetSpecFetcher
> + * @param messageBundleFetcher
> */
> - public GadgetServerConfigReader getConfig() {
> - return config;
> + @Inject
> + public GadgetServer(Executor executor,
> + GadgetFeatureRegistry registry,
> + GadgetBlacklist blacklist,
> + @PreloadFetcher RemoteContentFetcher preloadFetcher,
> + @GadgetSpecFetcher RemoteContentFetcher gadgetSpecFetcher,
> + @MessageBundleFetcher RemoteContentFetcher messageBundleFetcher) {
> + this.executor = executor;
> + this.registry = registry;
> + this.blacklist = blacklist;
> + this.preloadFetcher = preloadFetcher;
> + this.gadgetSpecFetcher = gadgetSpecFetcher;
> + this.messageBundleFetcher = messageBundleFetcher;
> }
>
> /**
> @@ -75,13 +79,15 @@
> * @throws GadgetException
> */
> public Gadget processGadget(GadgetContext context) throws GadgetException {
> - if (config.getGadgetBlacklist() != null) {
> - if (config.getGadgetBlacklist().isBlacklisted(context.getUrl())) {
> - throw new GadgetException(GadgetException.Code.BLACKLISTED_GADGET);
> - }
> + if (blacklist.isBlacklisted(context.getUrl())) {
> + throw new GadgetException(GadgetException.Code.BLACKLISTED_GADGET);
> }
> - GadgetSpec spec = config.getGadgetSpecFetcher().fetch(context.getUrl(),
> - context.getIgnoreCache());
> +
> + RemoteContentRequest request = RemoteContentRequest.getRequest(
> + context.getUrl(), context.getIgnoreCache());
> + RemoteContent response = gadgetSpecFetcher.fetch(request);
> + GadgetSpec spec
> + = new GadgetSpec(context.getUrl(), response.getResponseAsString());
> return createGadgetFromSpec(spec, context);
> }
>
> @@ -94,9 +100,10 @@
> */
> private MessageBundle getBundle(LocaleSpec localeSpec, GadgetContext context)
> throws GadgetException {
> - MessageBundle bundle;
> - bundle = config.getMessageBundleFetcher().fetch(
> + RemoteContentRequest request = RemoteContentRequest.getRequest(
> localeSpec.getMessages(), context.getIgnoreCache());
> + RemoteContent response = messageBundleFetcher.fetch(request);
> + MessageBundle bundle = new MessageBundle(response.getResponseAsString());
> return bundle;
> }
>
> @@ -178,17 +185,22 @@
> Map<GadgetFeatureRegistry.Entry, GadgetFeature> tasks)
> throws GadgetException {
>
> - // Immediately enqueue all the preloads
> - CompletionService<RemoteContent> preloadProcessor
> - = new ExecutorCompletionService<RemoteContent>(config.getExecutor());
> - for (Preload preload : gadget.getSpec().getModulePrefs().getPreloads()) {
> - gadget.getPreloadMap().put(preload,
> - preloadProcessor.submit(
> - new PreloadTask(preload, getConfig().getContentFetcher())));
> + // Immediately enqueue all the preloads. We don't block on preloads because
> + // we want them to run in parallel
> + RenderingContext renderContext = gadget.getContext().getRenderingContext();
> + if (RenderingContext.GADGET.equals(renderContext)) {
> + CompletionService<RemoteContent> preloadProcessor
> + = new ExecutorCompletionService<RemoteContent>(executor);
> + for (Preload preload : gadget.getSpec().getModulePrefs().getPreloads()) {
> + PreloadTask task = new PreloadTask(preload, preloadFetcher);
> + Future<RemoteContent> future = preloadProcessor.submit(task);
> + gadget.getPreloadMap().put(preload, future);
> + }
> }
>
> + // TODO: This seems pointless if nothing is actually using it.
> CompletionService<GadgetException> featureProcessor
> - = new ExecutorCompletionService<GadgetException>(config.getExecutor());
> + = new ExecutorCompletionService<GadgetException>(executor);
> // FeatureTask is OK has a hash key because we want actual instances, not
> // names.
> GadgetContext context = gadget.getContext();
> @@ -251,8 +263,7 @@
> Set<GadgetFeatureRegistry.Entry> dependencies
> = new HashSet<GadgetFeatureRegistry.Entry>(features.size());
> Set<String> unsupported = new HashSet<String>();
> - config.getFeatureRegistry().getIncludedFeatures(features.keySet(),
> - dependencies, unsupported);
> + registry.getIncludedFeatures(features.keySet(), dependencies, unsupported);
>
> for (String missing : unsupported) {
> Feature feature = features.get(missing);
> @@ -319,7 +330,11 @@
>
> public RemoteContent call() {
> RemoteContentRequest request = new RemoteContentRequest(preload.getHref());
> - return fetcher.fetch(request);
> + try {
> + return fetcher.fetch(request);
> + } catch (GadgetException e) {
> + return RemoteContent.ERROR;
> + }
> }
>
> public PreloadTask(Preload preload, RemoteContentFetcher fetcher) {
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfig.java Wed Apr 2 17:40:05 2008
> @@ -1,88 +0,0 @@
> -/**
> - * Licensed to the Apache Software Foundation (ASF) under one
> - * or more contributor license agreements. See the NOTICE file
> - * distributed with this work for additional information
> - * regarding copyright ownership. The ASF licenses this file
> - * to you 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 org.apache.shindig.gadgets.spec.GadgetSpec;
> -import org.apache.shindig.gadgets.spec.MessageBundle;
> -
> -import java.util.concurrent.Executor;
> -
> -/**
> - * Stores configuration data for a GadgetServer.
> - *
> - * The main purpose of this class is to allow for better readability of
> - * GadgetServer ctor parameters and to simplify interacting with its components.
> - *
> - *
> - *
> - * Usage:
> - *
> - * <code>
> - * GadgetServer server = new GadgetServer(new GadgetServerConfig()
> - * .setRemoteContentFetcher(new BasicRemoteContentFetcher())
> - * .setGadgetCache(new BasicGadgetDataCache<GadgetSpec>())
> - * .setOtherProperties(...));
> - * </code>
> - *
> - * Any missing data will result in GadgetServer throwing an IllegalArgsException
> - * unless noted as "optional" here.
> - */
> -public class GadgetServerConfig extends GadgetServerConfigReader {
> -
> - public GadgetServerConfig setExecutor(Executor executor) {
> - this.executor = executor;
> - return this;
> - }
> -
> - public GadgetServerConfig setFeatureRegistry(
> - GadgetFeatureRegistry featureRegistry) {
> - this.featureRegistry = featureRegistry;
> - return this;
> - }
> -
> - public GadgetServerConfig setGadgetSpecFetcher(
> - DataFetcher<GadgetSpec> gadgetSpecFetcher) {
> - this.gadgetSpecFetcher = gadgetSpecFetcher;
> - return this;
> - }
> -
> - public GadgetServerConfig setMessageBundleFetcher(
> - DataFetcher<MessageBundle> messageBundleFetcher) {
> - this.messageBundleFetcher = messageBundleFetcher;
> - return this;
> - }
> -
> - public GadgetServerConfig setContentFetcher(
> - RemoteContentFetcher contentFetcher) {
> - this.contentFetcher = contentFetcher;
> - return this;
> - }
> -
> - // Optional
> -
> - public GadgetServerConfig setGadgetBlacklist(
> - GadgetBlacklist gadgetBlacklist) {
> - this.gadgetBlacklist = gadgetBlacklist;
> - return this;
> - }
> -
> - public GadgetServerConfig setSyndicatorConfig(SyndicatorConfig config) {
> - syndicatorConfig = config;
> - return this;
> - }
> -}
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServerConfigReader.java Wed Apr 2 17:40:05 2008
> @@ -1,96 +0,0 @@
> -/**
> - * Licensed to the Apache Software Foundation (ASF) under one
> - * or more contributor license agreements. See the NOTICE file
> - * distributed with this work for additional information
> - * regarding copyright ownership. The ASF licenses this file
> - * to you 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 org.apache.shindig.gadgets.spec.GadgetSpec;
> -import org.apache.shindig.gadgets.spec.MessageBundle;
> -
> -import java.util.concurrent.Executor;
> -
> -/**
> - * Stores configuration data for a GadgetServer.
> - *
> - * The main purpose of this class is to allow for better readability of
> - * GadgetServer ctor parameters and to simplify interacting with its components.
> - *
> - * Works in conjunction with {@code GadgetServerConfig} to create immutable
> - * configuration objects. Note that members are still potentially mutable.
> - *
> - */
> -public class GadgetServerConfigReader {
> -
> - protected Executor executor;
> -
> - public Executor getExecutor() {
> - return executor;
> - }
> -
> - protected GadgetFeatureRegistry featureRegistry;
> -
> - public GadgetFeatureRegistry getFeatureRegistry() {
> - return featureRegistry;
> - }
> -
> - protected DataFetcher<GadgetSpec> gadgetSpecFetcher;
> -
> - public DataFetcher<GadgetSpec> getGadgetSpecFetcher() {
> - return gadgetSpecFetcher;
> - }
> -
> - protected DataFetcher<MessageBundle> messageBundleFetcher;
> -
> - public DataFetcher<MessageBundle> getMessageBundleFetcher() {
> - return messageBundleFetcher;
> - }
> -
> - protected RemoteContentFetcher contentFetcher;
> -
> - public RemoteContentFetcher getContentFetcher() {
> - return contentFetcher;
> - }
> -
> - protected GadgetBlacklist gadgetBlacklist;
> -
> - public GadgetBlacklist getGadgetBlacklist() {
> - return gadgetBlacklist;
> - }
> -
> - protected SyndicatorConfig syndicatorConfig;
> -
> - public SyndicatorConfig getSyndicatorConfig() {
> - if (syndicatorConfig == null) {
> - return SyndicatorConfig.EMPTY;
> - }
> - return syndicatorConfig;
> - }
> -
> - /**
> - * Copies all fields from {@code base} into this instance.
> - * @param base
> - */
> - public void copyFrom(GadgetServerConfigReader base) {
> - // We use the getters here just in case any methods were overridden.
> - executor = base.getExecutor();
> - featureRegistry = base.getFeatureRegistry();
> - contentFetcher = base.getContentFetcher();
> - gadgetSpecFetcher = base.getGadgetSpecFetcher();
> - messageBundleFetcher = base.getMessageBundleFetcher();
> - gadgetBlacklist = base.getGadgetBlacklist();
> - syndicatorConfig = base.getSyndicatorConfig();
> - }
> -}
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFetcher.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFetcher.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFetcher.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFetcher.java Wed Apr 2 17:40:05 2008
> @@ -19,62 +19,15 @@
>
> package org.apache.shindig.gadgets;
>
> -import org.apache.shindig.gadgets.spec.GadgetSpec;
> +import com.google.inject.BindingAnnotation;
>
> -import java.net.URI;
> -import java.util.HashMap;
> -import java.util.Map;
> -import java.util.logging.Logger;
> -
> -/**
> - * Spec retrieval implementation that retrieves specs by the following:
> - *
> - * - Consulting the in-memory cache (just a Map)
> - * - If not found, making a RemoteContentRequest for the spec
> - * - Parsing spec
> - * - Storing to the cache
> - */
> -public class GadgetSpecFetcher implements DataFetcher<GadgetSpec> {
> - private final RemoteContentFetcher fetcher;
> - private final Map<URI, GadgetSpec> cache;
> -
> - private final static Logger logger
> - = Logger.getLogger("org.apache.shindig.gadgets");
> -
> - /** {@inheritDoc} */
> - public void invalidate(URI url) {
> - synchronized (cache) {
> - cache.remove(url);
> - }
> - }
> -
> - /** {@inheritDoc} */
> - public GadgetSpec fetch(URI url, boolean forceReload) throws GadgetException {
> - GadgetSpec spec = null;
> - if (!forceReload) {
> - spec = cache.get(url);
> - }
> - if (spec == null) {
> - RemoteContentRequest request = new RemoteContentRequest(url);
> - RemoteContent response = fetcher.fetch(request);
> -
> - if (response.getHttpStatusCode() == RemoteContent.SC_OK) {
> - spec = new GadgetSpec(url, response.getResponseAsString());
> - cache.put(url, spec);
> - } else {
> - String error = "Unable to get content from " + url.toString();
> - throw new GadgetException(
> - GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT, error);
> - }
> - }
> - return spec;
> - }
> -
> - /**
> - * @param fetcher The fetcher to use for remote resource retrieval.
> - */
> - public GadgetSpecFetcher(RemoteContentFetcher fetcher) {
> - this.fetcher = fetcher;
> - cache = new HashMap<URI, GadgetSpec>();
> - }
> +import java.lang.annotation.ElementType;
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Retention(RetentionPolicy.RUNTIME)
> +@Target({ElementType.FIELD, ElementType.PARAMETER})
> +@BindingAnnotation
> +public @interface GadgetSpecFetcher {
> }
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetToken.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetToken.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetToken.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetToken.java Wed Apr 2 17:40:05 2008
> @@ -20,7 +20,7 @@
>
> /**
> * An abstract representation of a signing token.
> - * Use in conjunction with @code GadgetSigner.
> + * Use in conjunction with @code GadgetTokenDecoder.
> */
> public interface GadgetToken {
>
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetTokenDecoder.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetTokenDecoder.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetTokenDecoder.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetTokenDecoder.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,34 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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;
> +
> +/**
> + * Handles verification of gadget security tokens.
> + */
> +public interface GadgetTokenDecoder {
> +
> + /**
> + * Decrypts and verifies a gadget security token to return a gadget token.
> + *
> + * @param tokenString String representation of the token to be created.
> + * @return The token representation of the input data.
> + * @throws GadgetException If tokenString is not a valid token
> + */
> + public GadgetToken createToken(String tokenString) throws GadgetException;
> +}
>
> 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=644123&r1=644122&r2=644123&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 Wed Apr 2 17:40:05 2008
> @@ -26,7 +26,11 @@
>
> import java.io.File;
> import java.io.IOException;
> -import java.util.*;
> +import java.util.EnumMap;
> +import java.util.HashMap;
> +import java.util.LinkedList;
> +import java.util.List;
> +import java.util.Map;
> import java.util.logging.Logger;
>
> /**
> @@ -59,18 +63,18 @@
> * in the text file. If path is prefixed with res://, the file
> * is treated as a resource, and all references are assumed to be
> * resources as well.
> - * @return A list of the newly loaded features.
> * @throws GadgetException
> */
> - public Set<GadgetFeatureRegistry.Entry> loadFeatures(String path,
> - GadgetFeatureRegistry registry) throws GadgetException {
> + public void loadFeatures(String path, GadgetFeatureRegistry registry)
> + throws GadgetException {
> List<ParsedFeature> features = new LinkedList<ParsedFeature>();
> try {
> if (path.startsWith("res://")) {
> path = path.substring(6);
> logger.info("Loading resources from: " + path);
> if (path.endsWith(".txt")) {
> - loadResources(ResourceLoader.getContent(path).split("[\r\n]+"), features);
> + loadResources(ResourceLoader.getContent(path).split("[\r\n]+"),
> + features);
> } else {
> loadResources(new String[]{path}, features);
> }
> @@ -83,14 +87,11 @@
> throw new GadgetException(GadgetException.Code.INVALID_PATH, e);
> }
>
> - Set<GadgetFeatureRegistry.Entry> entries
> - = new HashSet<GadgetFeatureRegistry.Entry>();
> for (ParsedFeature feature : features) {
> JsLibraryFeatureFactory factory
> = new JsLibraryFeatureFactory(feature.libraries);
> - entries.add(registry.register(feature.name, feature.deps, factory));
> + registry.register(feature.name, feature.deps, factory);
> }
> - return entries;
> }
>
> /**
> @@ -213,7 +214,8 @@
>
> NodeList gadgets = doc.getElementsByTagName("gadget");
> for (int i = 0, j = gadgets.getLength(); i < j; ++i) {
> - processContext(feature, (Element)gadgets.item(i), RenderingContext.GADGET);
> + processContext(feature, (Element)gadgets.item(i),
> + RenderingContext.GADGET);
> }
>
> NodeList containers = doc.getElementsByTagName("container");
> @@ -236,9 +238,11 @@
> * @param feature
> * @param context
> * @param renderingContext
> + * @throws GadgetException
> */
> 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");
> @@ -298,7 +302,8 @@
> final List<String> deps;
>
> public ParsedFeature() {
> - libraries = new EnumMap<RenderingContext, Map<String, List<JsLibrary>>>(RenderingContext.class);
> + libraries = new EnumMap<RenderingContext, Map<String, List<JsLibrary>>>(
> + RenderingContext.class);
> deps = new LinkedList<String>();
> }
>
>
> 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=644123&r1=644122&r2=644123&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 Wed Apr 2 17:40:05 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/MessageBundleFetcher.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFetcher.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFetcher.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFetcher.java Wed Apr 2 17:40:05 2008
> @@ -19,63 +19,15 @@
>
> package org.apache.shindig.gadgets;
>
> -import org.apache.shindig.gadgets.spec.MessageBundle;
> +import com.google.inject.BindingAnnotation;
>
> -import java.net.URI;
> -import java.util.HashMap;
> -import java.util.Map;
> -import java.util.logging.Logger;
> -
> -/**
> - * Message bundle retrieval implementation that retrieves by the following:
> - *
> - * - Consulting the in-memory cache (just a Map)
> - * - If not found, making a RemoteContentRequest for the bundle
> - * - Parsing bundle
> - * - Storing to the cache
> - */
> -public class MessageBundleFetcher implements DataFetcher<MessageBundle> {
> - private final RemoteContentFetcher fetcher;
> - private final Map<URI, MessageBundle> cache;
> -
> - private final static Logger logger
> - = Logger.getLogger("org.apache.shindig.gadgets");
> -
> - /** {@inheritDoc} */
> - public void invalidate(URI url) {
> - synchronized (cache) {
> - cache.remove(url);
> - }
> - }
> -
> - /** {@inheritDoc} */
> - public MessageBundle fetch(URI url, boolean forceReload)
> - throws GadgetException {
> - MessageBundle bundle = null;
> - if (!forceReload) {
> - bundle = cache.get(url);
> - }
> - if (bundle == null) {
> - RemoteContentRequest request = new RemoteContentRequest(url);
> - RemoteContent response = fetcher.fetch(request);
> -
> - if (response.getHttpStatusCode() == RemoteContent.SC_OK) {
> - bundle = new MessageBundle(response.getResponseAsString());
> - cache.put(url, bundle);
> - } else {
> - String error = "Unable to get content from " + url.toString();
> - throw new GadgetException(
> - GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT, error);
> - }
> - }
> - return bundle;
> - }
> -
> - /**
> - * @param fetcher The fetcher to use for remote resource retrieval.
> - */
> - public MessageBundleFetcher(RemoteContentFetcher fetcher) {
> - this.fetcher = fetcher;
> - cache = new HashMap<URI, MessageBundle>();
> - }
> +import java.lang.annotation.ElementType;
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Retention(RetentionPolicy.RUNTIME)
> +@Target({ElementType.FIELD, ElementType.PARAMETER})
> +@BindingAnnotation
> +public @interface MessageBundleFetcher {
> }
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/PreloadFetcher.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/PreloadFetcher.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/PreloadFetcher.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/PreloadFetcher.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,33 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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 com.google.inject.BindingAnnotation;
> +
> +import java.lang.annotation.ElementType;
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Retention(RetentionPolicy.RUNTIME)
> +@Target({ElementType.FIELD, ElementType.PARAMETER})
> +@BindingAnnotation
> +public @interface PreloadFetcher {
> +}
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContent.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContent.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContent.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RemoteContent.java Wed Apr 2 17:40:05 2008
> @@ -89,6 +89,16 @@
> }
>
> /**
> + * Simple constructor for setting a basic response from a string. Mostly used
> + * for testing.
> + *
> + * @param body
> + */
> + public RemoteContent(String body) {
> + this(SC_OK, body.getBytes(), null);
> + }
> +
> + /**
> * Attempts to determine the encoding of the body. If it can't be determined,
> * we use DEFAULT_ENCODING instead.
> * @return The detected encoding or DEFAULT_ENCODING.
>
> 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=644123&r1=644122&r2=644123&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 Wed Apr 2 17:40:05 2008
> @@ -18,11 +18,30 @@
> 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=644123&r1=644122&r2=644123&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 Wed Apr 2 17:40:05 2008
> @@ -21,6 +21,7 @@
>
> import java.io.ByteArrayInputStream;
> import java.io.InputStream;
> +import java.io.UnsupportedEncodingException;
> import java.net.URI;
> import java.util.ArrayList;
> import java.util.Arrays;
> @@ -33,9 +34,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?
> */
> @@ -50,6 +48,19 @@
> }
>
> /**
> + * @return The post body as a string, assuming UTF-8 encoding.
> + * TODO: We should probably tolerate other encodings, based on the
> + * Content-Type header.
> + */
> + public String getPostBodyAsString() {
> + try {
> + return new String(postBody, "UTF-8");
> + } catch (UnsupportedEncodingException e) {
> + return "";
> + }
> + }
> +
> + /**
> * Retrieves the total length of the post body.
> *
> * @return The length of the post body.
> @@ -121,6 +132,18 @@
> }
>
> /**
> + * Creates a simple GET request
> + *
> + * @param uri
> + * @param ignoreCache
> + */
> + public static RemoteContentRequest getRequest(URI uri, boolean ignoreCache) {
> + Options options = new Options();
> + options.ignoreCache = ignoreCache;
> + return new RemoteContentRequest(uri, options);
> + }
> +
> + /**
> *
> * @param method
> * @param uri
> @@ -165,6 +188,22 @@
> }
>
> /**
> + * Creates a new request to a different URL using all request data from
> + * an existing request.
> + *
> + * @param uri
> + * @param base The base request to copy data from.
> + */
> + public RemoteContentRequest(URI uri, RemoteContentRequest base) {
> + this.uri = uri;
> + this.method = base.method;
> + this.options = base.options;
> + this.headers = base.headers;
> + this.contentType = base.contentType;
> + this.postBody = base.postBody;
> + }
> +
> + /**
> * Basic GET request.
> *
> * @param uri
> @@ -285,6 +324,10 @@
> }
>
> public static final Options DEFAULT_OPTIONS = new Options();
> + public static final Options IGNORE_CACHE_OPTIONS = new Options();
> + static {
> + IGNORE_CACHE_OPTIONS.ignoreCache = true;
> + }
>
> /**
> * Bag of options for making a request.
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RenderingContext.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RenderingContext.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RenderingContext.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/RenderingContext.java Wed Apr 2 17:40:05 2008
> @@ -18,6 +18,15 @@
> package org.apache.shindig.gadgets;
>
> public enum RenderingContext {
> + // Used when rendering gadgets (iframes or inline).
> + // TODO: rename this to "RENDER_GADGET"?
> GADGET,
> - CONTAINER
> +
> + // Used when rendering container data (not a gadget render)
> + CONTAINER,
> +
> + // Used when retrieving metadata about a gadget. Processing is generally
> + // identical to processing under GADGET, but some operations may be safely
> + // skipped, such as preload processing.
> + METADATA
> }
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,284 @@
> +/*
> + * 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 org.apache.shindig.util.Crypto;
> +import org.apache.shindig.util.TimeSource;
> +
> +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.URI;
> +import java.net.URISyntaxException;
> +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 SigningFetcher extends RemoteContentFetcher {
> +
> + 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 final 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 final Object privateKeyObject;
> +
> + /**
> + * The name of the key, included in the fetch to help with key rotation.
> + */
> + protected final String keyName;
> +
> + /**
> + * Constructor for subclasses that don't want this code to use their
> + * keys.
> + */
> + protected SigningFetcher(RemoteContentFetcher next, GadgetToken authToken) {
> + this(next, 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 static SigningFetcher makeFromPrivateKey(RemoteContentFetcher next,
> + GadgetToken authToken, String keyName, PrivateKey privateKey) {
> + return new SigningFetcher(next, 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 static SigningFetcher makeFromB64PrivateKey(RemoteContentFetcher next,
> + GadgetToken authToken, String keyName, String privateKey) {
> + return new SigningFetcher(next, 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 static SigningFetcher makeFromPrivateKeyBytes(
> + RemoteContentFetcher next, GadgetToken authToken, String keyName,
> + byte[] privateKey) {
> + return new SigningFetcher(next, authToken, keyName, privateKey);
> + }
> +
> + protected SigningFetcher(RemoteContentFetcher next, GadgetToken authToken,
> + String keyName, Object privateKeyObject) {
> + super(next);
> + this.authToken = authToken;
> + this.keyName = keyName;
> + this.privateKeyObject = privateKeyObject;
> + }
> +
> + @Override
> + public RemoteContent fetch(RemoteContentRequest request)
> + throws GadgetException {
> + RemoteContentRequest signed = signRequest(request);
> + return nextFetcher.fetch(signed);
> + }
> +
> + private RemoteContentRequest signRequest(RemoteContentRequest req)
> + throws GadgetException {
> + try {
> + // Parse the request into parameters for OAuth signing, stripping out
> + // any OAuth or OpenSocial parameters injected by the client
> + URI resource = req.getUri();
> + String query = resource.getRawQuery();
> + resource = removeQuery(resource);
> + List<OAuth.Parameter> queryParams = sanitize(OAuth.decodeForm(query));
> + String postStr = req.getPostBodyAsString();
> + List<OAuth.Parameter> postParams = sanitize(OAuth.decodeForm(postStr));
> + List<OAuth.Parameter> msgParams = new ArrayList<OAuth.Parameter>();
> + msgParams.addAll(queryParams);
> + msgParams.addAll(postParams);
> +
> + addOpenSocialParams(msgParams);
> +
> + 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(req.getMethod(), 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);
> + }
> + }
> + // Careful here; the OAuth form encoding scheme is slightly different than
> + // the normal form encoding scheme, so we have to use the OAuth library
> + // formEncode method. The java.net.URI code makes it difficult to insert
> + // a pre-encoded query string, so we use URL instead.
> + String finalQuery = OAuth.formEncode(newQuery);
> + URL url = new URL(
> + resource.getScheme(),
> + resource.getHost(),
> + resource.getPort(),
> + resource.getRawPath() + "?" + finalQuery);
> + return new RemoteContentRequest(url.toURI(), req);
> + } catch (Exception e) {
> + throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR, e);
> + }
> + }
> +
> + private URI removeQuery(URI resource) throws URISyntaxException {
> + return new URI(
> + resource.getScheme(),
> + null, // user info
> + resource.getHost(),
> + resource.getPort(),
> + resource.getRawPath(),
> + null, // query
> + null); // fragment
> + }
> +
> +
> + 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());
> + }
> +}
>
> Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcherFactory.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcherFactory.java?rev=644123&view=auto
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcherFactory.java (added)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcherFactory.java Wed Apr 2 17:40:05 2008
> @@ -0,0 +1,71 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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 org.apache.shindig.util.InputStreamConsumer;
> +import org.apache.shindig.util.ResourceLoader;
> +
> +import com.google.inject.Inject;
> +import com.google.inject.name.Named;
> +
> +import java.io.IOException;
> +
> +/**
> + * Produces Signing content fetchers for input tokens.
> + */
> +public class SigningFetcherFactory {
> + private final String keyName;
> + private final String privateKey;
> +
> + /**
> + * Produces a signing fetcher that will sign requests and delegate actual
> + * network retrieval to the {@code networkFetcher}
> + *
> + * @param networkFetcher The fetcher that will be doing actual work.
> + * @param token The gadget token used for extracting signing parameters.
> + * @return The signing fetcher.
> + */
> + public RemoteContentFetcher getSigningFetcher(
> + RemoteContentFetcher networkFetcher, GadgetToken token) {
> + return SigningFetcher.makeFromB64PrivateKey(
> + networkFetcher, token, keyName, privateKey);
> + }
> +
> + /**
> + * @param keyName The key name (may be null) used in the signature.
> + * @param keyFile The file containing your private key for signing requests.
> + */
> + @Inject
> + public SigningFetcherFactory(@Named("signing.key-name") String keyName,
> + @Named("signing.key-file") String keyFile) {
> + if (keyName == null || keyName.length() == 0) {
> + this.keyName = null;
> + } else {
> + this.keyName = keyName;
> + }
> + String privateKey = null;
> + try {
> + privateKey
> + = InputStreamConsumer.readToString(ResourceLoader.open(keyFile));
> + } catch (IOException e) {
> + privateKey = "";
> + }
> + this.privateKey = privateKey;
> + }
> +}
>
> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java
> URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java?rev=644123&r1=644122&r2=644123&view=diff
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java Wed Apr 2 17:40:05 2008
> @@ -21,6 +21,9 @@
>
> import org.apache.shindig.util.ResourceLoader;
>
> +import com.google.inject.Inject;
> +import com.google.inject.name.Named;
> +
> import org.json.JSONArray;
> import org.json.JSONException;
> import org.json.JSONObject;
> @@ -45,7 +48,6 @@
> * your config that you actually want to change.
> */
> public class SyndicatorConfig {
> - public static final SyndicatorConfig EMPTY = new SyndicatorConfig();
> private final Map<String, JSONObject> config;
> public static final String DEFAULT_SYNDICATOR = "default";
> public static final String SYNDICATOR_KEY = "gadgets.syndicator";
> @@ -168,6 +170,7 @@
> private void loadResources(String[] files) throws GadgetException {
> try {
> for (String entry : files) {
> + logger.info("Reading syndicator config: " + entry);
> String content = ResourceLoader.getContent(entry);
> loadFromString(content);
> }
> @@ -212,8 +215,9 @@
> for (String field : fields) {
> Object existing = clone.opt(field);
> Object update = merge.get(field);
> - if (existing == null) {
> - // It's new custom config, not referenced in the prototype.
> + if (existing == null || update == null) {
> + // It's new custom config, not referenced in the prototype, or
> + // it's removing a pre-configured value.
> clone.put(field, update);
> } else {
> // Merge if object type is JSONObject.
> @@ -290,20 +294,13 @@
>
> /**
> * Creates a new, empty configuration.
> - *
> - * @param defaultSyndicator The default syndicators to load.
> */
> - public SyndicatorConfig(String defaultSyndicator) throws GadgetException {
> + @Inject
> + public SyndicatorConfig(@Named("syndicators.default") String syndicators)
> + throws GadgetException {
> config = new HashMap<String, JSONObject>();
> - if (defaultSyndicator != null) {
> - loadSyndicators(defaultSyndicator);
> + if (syndicators != null) {
> + loadSyndicators(syndicators);
> }
> - }
> -
> - /**
> - * Creates an unmodifiable configuration.
> - */
> - private SyndicatorConfig() {
> - config = Collections.emptyMap();
> }
> }
>
>
--
Santiago Gala
http://memojo.com/~sgala/blog/