You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by Cassie <do...@apache.org> on 2008/02/08 02:33:28 UTC
Re: svn commit: r619684 - in /incubator/shindig/trunk: features/core/ java/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ java/gadgets/src/main/webapp/WEB-INF/ java/gadgets/
Just a quick thought - did you test the samplecontainer? It seems like
moving things into /files might affect it.
Thanks.
- Cassie
On Thu, Feb 7, 2008 at 3:18 PM, <et...@apache.org> wrote:
> Author: etnu
> Date: Thu Feb 7 15:18:30 2008
> New Revision: 619684
>
> URL: http://svn.apache.org/viewvc?rev=619684&view=rev
> Log:
> - Merged in changes from SHINDIG-51 and prepared code for merging
> SHINDIG-35
> - Fixed caching behavior in JsServlet; files will now be cached
> indefinitely and a cache busting token must be appended to get the new
> version.
> - Added placeholder for RpcServlet for SHINDIG-25.
> - Fixed static files path in pom.xml to be compatible with the jar-based
> build (no longer places all files into the root; now files are in
> /gadgets/files/). This may
> require updating some of the static files, but currently examples all
> seem to work.
> - Cleaned up a spec deviation in gadgets.io (did not properly handle
> POST_DATA) and collapsed "enums" to their simplest form.
>
>
> Added:
>
> 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/RpcServlet.java
> Modified:
> incubator/shindig/trunk/features/core/io.js
> incubator/shindig/trunk/java/gadgets/pom.xml
>
> 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/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/ProxyHandler.java
>
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.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/GadgetServerTest.java
>
> Modified: incubator/shindig/trunk/features/core/io.js
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core/io.js?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> --- incubator/shindig/trunk/features/core/io.js (original)
> +++ incubator/shindig/trunk/features/core/io.js Thu Feb 7 15:18:30 2008
> @@ -82,37 +82,37 @@
> case "FEED":
> resp.data = gadgets.json.parse(resp.text);
> if (!resp.data) {
> - resp.errors = ["failed to parse JSON"];
> + resp.errors.push("failed to parse JSON");
> resp.data = null;
> }
> break;
> - case "DOM":
> - var dom;
> - if (window.ActiveXObject) {
> - dom = new ActiveXObject("Microsoft.XMLDOM");
> - dom.async = false;
> - dom.validateOnParse = false;
> - dom.resolveExternals = false;
> - if (!dom.loadXML(resp.text)) {
> - resp.errors = ["failed to parse XML"];
> + case "DOM":
> + var dom;
> + if (window.ActiveXObject) {
> + dom = new ActiveXObject("Microsoft.XMLDOM");
> + dom.async = false;
> + dom.validateOnParse = false;
> + dom.resolveExternals = false;
> + if (!dom.loadXML(resp.text)) {
> + resp.errors.push("failed to parse XML");
> + } else {
> + resp.data = dom;
> + }
> } else {
> - resp.data = dom;
> + var parser = new DOMParser();
> + dom = parser.parseFromString(resp.text, "text/xml");
> + if ("parsererror" == dom.documentElement.nodeName) {
> + resp.errors.push("failed to parse XML");
> + } else {
> + resp.data = dom;
> + }
> }
> - } else {
> - var parser = new DOMParser();
> - dom = parser.parseFromString(resp.text, "text/xml");
> - if ("parsererror" == dom.documentElement.nodeName) {
> - resp.errors = ["failed to parse XML"];
> - } else {
> - resp.data = dom;
> - }
> - }
> - break;
> - default:
> - resp.data = resp.text;
> - break;
> - }
> - callback(resp);
> + break;
> + default:
> + resp.data = resp.text;
> + break;
> + }
> + callback(resp);
> }
>
> return /** @scope gadgets.io */ {
> @@ -145,10 +145,8 @@
> encodeURIComponent(url));
>
> // Check if authorization is requested
> - if (opt_params && opt_params.AUTHORIZATION &&
> - gadgets.io.AuthorizationType
> [opt_params.AUTHORIZATION.toUpperCase()]
> - != gadgets.io.AuthorizationType.NONE) {
> - newUrl += "&authz=" + opt_params.AUTHORIZATION.toLowerCase();
> + if (params.AUTHORIZATION && params.AUTHORIZATION !== "NONE") {
> + newUrl += "&authz=" + params.AUTHORIZATION.toLowerCase();
> // Add the security-token if available
> if (gadgets.util.getUrlParameters()["st"]) {
> newUrl += "&st=" + gadgets.util.getUrlParameters()["st"];
> @@ -160,10 +158,11 @@
> xhr.onreadystatechange = gadgets.util.makeClosure(null,
> processResponse, url, callback, params, xhr);
> }
> - if (params.METHOD == "POST") {
> - xhr.setRequestHeader('Content-Type',
> 'application/x-www-form-urlencoded');
> - if (params.postData) {
> - xhr.send("postData=" + encodeURIComponent(params.postData));
> + if (params.METHOD === "POST") {
> + xhr.setRequestHeader('Content-Type',
> + 'application/x-www-form-urlencoded');
> + if (params.POST_DATA) {
> + xhr.send("postData=" + encodeURIComponent(params.POST_DATA));
> } else {
> xhr.send("postData=");
> }
> @@ -225,189 +224,25 @@
> };
> }();
>
> -// TODO: This can all be removed after the spec is published. This is
> only
> -// here to satisfy documentation requirements.
> -
> -/**
> - * @static
> - * @class
> - * Used by the
> - * <a href="gadgets.io.html#makeRequest">
> - * <code>gadgets.io.makeRequest()</code></a> method.
> - * @name gadgets.io.RequestParameters
> - */
> -gadgets.io.RequestParameters = {
> - /**
> - * The method to use when fetching content from the URL;
> - * defaults to <code>MethodType.GET</a></code>.
> - * Specified as a
> - * <a href="gadgets.io.MethodType.html">MethodType</a>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - METHOD : 'METHOD',
> -
> - /**
> - * The type of content that lives at the URL;
> - * defaults to <code>ContentType.HTML</code>.
> - * Specified as a
> - * <a href="gadgets.io.ContentType.html">
> - * ContentType</a>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - CONTENT_TYPE : "CONTENT_TYPE",
> -
> - /**
> - * The data to send to the URL using the POST method;
> - * defaults to null.
> - * Specified as a <code>String</code>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - POST_DATA : "POST_DATA",
> -
> - /**
> - * The HTTP headers to send to the URL;
> - * defaults to null.
> - * Specified as a <code>Map.<String,String></code>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - HEADERS : "HEADERS",
> -
> - /**
> - * The type of authentication to use when fetching the content;
> - * defaults to <code>AuthorizationType.NONE</code>.
> - * Specified as an
> - * <a href="gadgets.io.AuthorizationType.html">
> - * AuthorizationType</a>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - AUTHORIZATION : 'AUTHORIZATION',
> -
> -
> - /**
> - * If the content is a feed, the number of entries to fetch;
> - * defaults to 3.
> - * Specified as a <code>Number</code>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - NUM_ENTRIES : 'NUM_ENTRIES',
> -
> - /**
> - * If the content is a feed, whether to fetch summaries for that feed;
> - * defaults to false.
> - * Specified as a <code>Boolean</code>.
> - *
> - * @member gadgets.io.RequestParameters
> - */
> - GET_SUMMARIES : 'GET_SUMMARIES'
> -};
> -
> -
> -/**
> - * @static
> - * @class
> - * Used by
> - * <a href="gadgets.io.RequestParameters.html">
> - * RequestParameters</a>.
> - * @name gadgets.io.MethodType
> - */
> -gadgets.io.MethodType = {
> - /**
> - * The default type.
> - * @member gadgets.io.MethodType
> - */
> - GET : 'GET',
> -
> - /**
> - * Not supported by all containers.
> - * @member gadgets.io.MethodType
> - */
> - POST : 'POST',
> -
> - /**
> - * Not supported by all containers.
> - * @member gadgets.io.MethodType
> - */
> - PUT : 'PUT',
> -
> - /**
> - * Not supported by all containers.
> - * @member gadgets.io.MethodType
> - */
> - DELETE : 'DELETE',
> -
> - /**
> - * Not supported by all containers.
> - * @member gadgets.io.MethodType
> - */
> - HEAD : 'HEAD'
> -};
> -
> -
> -/**
> - * @static
> - * @class
> - * Used by
> - * <a href="gadgets.io.RequestParameters.html">
> - * RequestParameters</a>.
> - * @name gadgets.io.ContentType
> - */
> -gadgets.io.ContentType = {
> - /**
> - * Returns text; used for fetching HTML.
> - * @member gadgets.io.ContentType
> - */
> - TEXT : 'TEXT',
> -
> - /**
> - * Returns a DOM object; used for fetching XML.
> - * @member gadgets.io.ContentType
> - */
> - DOM : 'DOM',
> -
> - /**
> - * Returns a JSON object.
> - * @member gadgets.io.ContentType
> - */
> - JSON : 'JSON',
> -
> - /**
> - * Returns a JSON representation of a feed.
> - * @member gadgets.io.ContentType
> - */
> - FEED : 'FEED'
> -};
> -
> -
> -/**
> - * @static
> - * @class
> - * Used by
> - * <a href="gadgets.io.RequestParameters.html">
> - * RequestParameters</a>.
> - * @name gadgets.io.AuthorizationType
> - */
> -gadgets.io.AuthorizationType = {
> - /**
> - * No authorization.
> - * @member gadgets.io.AuthorizationType
> - */
> - NONE : 'NONE',
> -
> - /**
> - * The request will be signed by the container.
> - * @member gadgets.io.AuthorizationType
> - */
> - SIGNED : 'SIGNED',
> -
> - /**
> - * The container will use full authentication.
> - * @member gadgets.io.AuthorizationType
> - */
> - AUTHENTICATED : 'AUTHENTICATED'
> -};
> +gadgets.io.RequestParameters = gadgets.util.makeEnum([
> + "METHOD",
> + "CONTENT_TYPE",
> + "POST_DATA",
> + "HEADERS",
> + "AUTHORIZATION",
> + "NUM_ENTRIES",
> + "GET_SUMMARIES"
> +]);
> +
> +// PUT, DELETE, and HEAD not supported currently.
> +gadgets.io.MethodType = gadgets.util.makeEnum([
> + "GET", "POST", "PUT", "DELETE", "HEAD"
> +]);
> +
> +gadgets.io.ContentType = gadgets.util.makeEnum([
> + "TEXT", "DOM", "JSON", "FEED"
> +]);
> +
> +gadgets.io.AuthorizationType = gadgets.util.makeEnum([
> + "NONE", "SIGNED", "AUTHENTICATED"
> +]);
> \ No newline at end of file
>
> Modified: incubator/shindig/trunk/java/gadgets/pom.xml
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/pom.xml?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/pom.xml (original)
> +++ incubator/shindig/trunk/java/gadgets/pom.xml Thu Feb 7 15:18:30 2008
> @@ -28,6 +28,7 @@
> <resource>
> <!-- this is relative to the pom.xml directory -->
> <directory>../../javascript/</directory>
> + <targetPath>files</targetPath>
> <includes>
> <include>**/*.*</include>
> </includes>
>
> 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=619684&r1=619683&r2=619684&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
> Thu Feb 7 15:18:30 2008
> @@ -146,6 +146,13 @@
> }
>
> /**
> + * @return All registered features.
> + */
> + public Map<String, Entry> getAllFeatures() {
> + return Collections.unmodifiableMap(features);
> + }
> +
> + /**
> * Attempts to retrieve all the {@code GadgetFeature} classes specified
> * in the {@code needed} list. Those that are found are returned in
> * {@code resultsFound}, while the names of those that are missing are
>
> 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=619684&r1=619683&r2=619684&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
> Thu Feb 7 15:18:30 2008
> @@ -22,39 +22,21 @@
> import java.net.MalformedURLException;
> import java.util.ArrayList;
> import java.util.Arrays;
> +import java.util.Collections;
> import java.util.HashSet;
> import java.util.LinkedList;
> import java.util.List;
> import java.util.Locale;
> import java.util.Map;
> import java.util.Set;
> -import java.util.Collections;
> import java.util.concurrent.Callable;
> import java.util.concurrent.CompletionService;
> import java.util.concurrent.ExecutionException;
> -import java.util.concurrent.Executor;
> import java.util.concurrent.ExecutorCompletionService;
> import java.util.concurrent.Future;
> -import java.util.logging.Logger;
> -import java.util.logging.Level;
>
> public class GadgetServer {
> - private final GadgetServerConfig config;
> -
> - private static final Logger logger
> - = Logger.getLogger("org.apache.shindig.gadgets");
> -
> - /**
> - * Creates a GadgetServer without a config.
> - *
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - * @param executor
> - */
> - @Deprecated
> - public GadgetServer(Executor executor) {
> - config = new GadgetServerConfig();
> - config.setExecutor(executor);
> - }
> + private final GadgetServerConfigReader config;
>
> /**
> * Creates a GadgetServer using the provided configuration.
> @@ -72,51 +54,11 @@
> Check.notNull(configuration.getContentFetcher(),
> "ContentFetcher is required.");
>
> - config = new GadgetServerConfig();
> + config = new GadgetServerConfigReader();
> config.copyFrom(configuration);
> }
>
> /**
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - */
> - @Deprecated
> - public void setSpecCache(GadgetDataCache<GadgetSpec> specCache) {
> - config.setSpecCache(specCache);
> - }
> -
> - /**
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - */
> - @Deprecated
> - public void setMessageBundleCache(GadgetDataCache<MessageBundle> cache)
> {
> - config.setMessageBundleCache(cache);
> - }
> -
> - /**
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - */
> - @Deprecated
> - public void setContentFetcher(RemoteContentFetcher fetcher) {
> - config.setContentFetcher(fetcher);
> - }
> -
> - /**
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - */
> - @Deprecated
> - public void setGadgetFeatureRegistry(GadgetFeatureRegistry registry) {
> - config.setFeatureRegistry(registry);
> - }
> -
> - /**
> - * @deprecated Replaced by {@link
> #GadgetServer(GadgetServerConfigReader)}.
> - */
> - @Deprecated
> - public void setGadgetBlacklist(GadgetBlacklist gadgetBlacklist) {
> - config.setGadgetBlacklist(gadgetBlacklist);
> - }
> -
> - /**
> * @return A read-only view of the server's configuration.
> */
> public GadgetServerConfigReader getConfig() {
> @@ -140,22 +82,6 @@
> RenderingContext rctx,
> ProcessingOptions options)
> throws GadgetProcessException {
> - // TODO: Remove dep checks when GadgetServer(Executor) is removed.
> - if (config.getSpecCache() == null) {
> - throw new GadgetProcessException(
> GadgetException.Code.MISSING_SPEC_CACHE);
> - }
> - if (config.getMessageBundleCache() == null ) {
> - throw new GadgetProcessException(
> - GadgetException.Code.MISSING_MESSAGE_BUNDLE_CACHE);
> - }
> - if (config.getContentFetcher() == null) {
> - throw new GadgetProcessException(
> - GadgetException.Code.MISSING_REMOTE_OBJECT_FETCHER);
> - }
> - if (config.getFeatureRegistry() == null) {
> - throw new GadgetProcessException(
> - GadgetException.Code.MISSING_FEATURE_REGISTRY);
> - }
>
> // Queue/tree of all jobs to be run for successful processing
> GadgetContext gc = new GadgetContext(config.getContentFetcher(),
> @@ -242,8 +168,6 @@
> }
>
> if (gadgetException != null) {
> - logger.log(Level.SEVERE, gadgetException.getCode().toString(),
> gadgetException);
> -
> // Add to list of all exceptions caught, clear jobs, and continue
> // to aggressively catch as many exceptions as possible. Since
> // tasks are running anyway, we may as well get their results in
> @@ -320,7 +244,8 @@
>
> private WorkflowContext(GadgetContext context) {
> this.context = context;
> - this.depsDone = Collections.synchronizedSet(new
> HashSet<WorkflowDependency>());
> + this.depsDone
> + = Collections.synchronizedSet(new
> HashSet<WorkflowDependency>());
> this.jobsToRun = new WorkflowJobList(this);
> }
> }
> @@ -431,8 +356,9 @@
> Map<String, GadgetSpec.FeatureSpec> requires = wc.gadget.getRequires
> ();
> Set<String> needed = new HashSet<String>(requires.size());
> Set<String> optionalNames = new HashSet<String>();
> -
> - for (Map.Entry<String, GadgetSpec.FeatureSpec> entry :
> requires.entrySet()) {
> +
> + for (Map.Entry<String, GadgetSpec.FeatureSpec> entry :
> + requires.entrySet()) {
> needed.add(entry.getKey());
> if (entry.getValue().isOptional()) {
> optionalNames.add(entry.getKey());
>
> Added:
> 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=619684&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> (added)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> Thu Feb 7 15:18:30 2008
> @@ -0,0 +1,107 @@
> +/*
> + * 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.http;
> +
> +import org.apache.shindig.gadgets.Gadget;
> +import org.apache.shindig.gadgets.GadgetServer;
> +import org.apache.shindig.gadgets.GadgetSigner;
> +
> +import java.util.logging.Logger;
> +
> +import javax.servlet.ServletConfig;
> +import javax.servlet.ServletContext;
> +import javax.servlet.ServletException;
> +import javax.servlet.http.HttpServletRequest;
> +
> +/**
> + * Loads shared configuration and creates appropriate class instances for
> + * sharing amongst servlets.
> + */
> +public abstract class CrossServletState {
> + private static final Logger logger
> + = Logger.getLogger("org.apache.shindig.gadgets");
> + /**
> + * @param config
> + * @return A CrossServletState appropriate for the given ServletConfig
> + * @throws ServletException
> + */
> + public static synchronized CrossServletState get(ServletConfig config)
> + throws ServletException {
> + ServletContext context = config.getServletContext();
> + // Check to see if the context has already been created. If it has,
> + // just return.
> + CrossServletState state
> + = (CrossServletState)context.getAttribute("servlet-data");
> +
> + if (state == null) {
> + String dataClass = context.getInitParameter("servlet-data-class");
> + if (dataClass == null) {
> + throw new ServletException("servlet-data-class is missing.");
> + }
> + logger.info("Loading CrossServletState: " + dataClass);
> + try {
> + state =
> (CrossServletState)Class.forName(dataClass).newInstance();
> + state.init(context);
> + context.setAttribute("servlet-data", state);
> + } catch (InstantiationException ie) {
> + throw new ServletException(ie);
> + } catch (IllegalAccessException iae) {
> + throw new ServletException(iae);
> + } catch (ClassNotFoundException cnfe) {
> + throw new ServletException(cnfe);
> + }
> + }
> + return state;
> + }
> +
> + /**
> + * @return A GadgetServer instance that is fully configured and
> + * ready to be used to process gadgets.
> + */
> + public abstract GadgetServer getGadgetServer();
> +
> + /**
> + * @param req The request that a signing token is needed for.
> + * @return A unique GadgetSigner for the request
> + */
> + public abstract GadgetSigner getGadgetSigner(HttpServletRequest req);
> +
> + /**
> + * Constructs a url for retrieving javascript for the given
> + * set of features.
> + *
> + * @param features
> + * @return The url to retrieve the appropriate JS.
> + */
> + public abstract String getJsUrl(String[] features);
> +
> + /**
> + * Constructs a url for generating an iframe for the given gadget.
> + * This only applies for RPC calls that must generate an iframe.
> + */
> + public abstract String getIframeUrl(Gadget gadget, HttpServletRequest
> req);
> +
> + /**
> + * Initializes this handler using the provided implementation.
> + * @param context
> + * @throws ServletException
> + */
> + protected abstract void init(ServletContext context) throws
> ServletException;
> +}
>
> Added:
> 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=619684&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> (added)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> Thu Feb 7 15:18:30 2008
> @@ -0,0 +1,192 @@
> +/*
> + * 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.http;
> +
> +import org.apache.shindig.gadgets.BasicGadgetDataCache;
> +import org.apache.shindig.gadgets.BasicGadgetSigner;
> +import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> +import org.apache.shindig.gadgets.Gadget;
> +import org.apache.shindig.gadgets.GadgetException;
> +import org.apache.shindig.gadgets.GadgetFeatureFactory;
> +import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> +import org.apache.shindig.gadgets.GadgetServer;
> +import org.apache.shindig.gadgets.GadgetServerConfig;
> +import org.apache.shindig.gadgets.GadgetSigner;
> +import org.apache.shindig.gadgets.GadgetSpec;
> +import org.apache.shindig.gadgets.JsLibrary;
> +import org.apache.shindig.gadgets.JsLibraryFeatureFactory;
> +import org.apache.shindig.gadgets.MessageBundle;
> +import org.apache.shindig.gadgets.RenderingContext;
> +
> +import java.io.UnsupportedEncodingException;
> +import java.net.URLEncoder;
> +import java.security.MessageDigest;
> +import java.security.NoSuchAlgorithmException;
> +import java.util.Map;
> +import java.util.concurrent.Executors;
> +
> +import javax.servlet.ServletContext;
> +import javax.servlet.ServletException;
> +import javax.servlet.http.HttpServletRequest;
> +
> +/**
> + * A handler which uses all of the basic versions of classes.
> + */
> +public class DefaultCrossServletState extends CrossServletState {
> +
> + private GadgetServer gadgetServer;
> + private GadgetSigner gadgetSigner;
> + private String jsPath;
> + private String iframePath;
> + private String jsCacheParam;
> +
> + private static final String DEFAULT_JS_PREFIX = "/gadgets/js/";
> + private static final String DEFAULT_IFRAME_PREFIX = "/gadgets/ifr?";
> +
> + /**
> + * {@inheritDoc}
> + */
> + @Override
> + public GadgetServer getGadgetServer() {
> + return gadgetServer;
> + }
> +
> + /**
> + * {@inheritDoc}
> + * Just returns the same gadget signer no matter the request.
> + */
> + @Override
> + public GadgetSigner getGadgetSigner(HttpServletRequest req) {
> + return gadgetSigner;
> + }
> +
> + /**
> + * {@inheritDoc}
> + */
> + @Override
> + public String getIframeUrl(Gadget gadget, HttpServletRequest req) {
> + // We don't have any meaningful data in the current request anyway,
> so
> + // we'll just do this statically.
> + StringBuilder buf = new StringBuilder();
> + try {
> + buf.append(iframePath)
> + .append("url=")
> + .append(
> + URLEncoder.encode(gadget.getId
> ().getURI().toString(),"UTF-8"));
> + } catch (UnsupportedEncodingException e) {
> + throw new RuntimeException("UTF-8 Not supported!", e);
> + }
> +
> + // TODO: extract user prefs, current view, etc. from <req>. Currently
> + // consumers of the response are on their own for this.
> + return buf.toString();
> + }
> +
> + /**
> + * {@inheritDoc}
> + */
> + @Override
> + public String getJsUrl(String[] features) {
> + StringBuilder buf = new StringBuilder();
> + buf.append(jsPath);
> + if (features == null || features.length == 0) {
> + buf.append("core");
> + } else {
> + boolean firstDone = false;
> + for (String feature : features) {
> + if (firstDone) {
> + buf.append(":");
> + } else {
> + firstDone = true;
> + }
> + buf.append(feature);
> + }
> + }
> + buf.append(".js?v=").append(jsCacheParam);
> + return buf.toString();
> + }
> +
> + /**
> + * {@inheritDoc}
> + */
> + @Override
> + protected void init(ServletContext context) throws ServletException {
> + jsPath = context.getInitParameter("js-service-path");
> + if (jsPath == null) {
> + jsPath = DEFAULT_JS_PREFIX;
> + }
> +
> + iframePath = context.getInitParameter("iframe-path");
> + if (iframePath == null) {
> + iframePath = DEFAULT_IFRAME_PREFIX;
> + }
> +
> + // features could be null, but that would probably be a bad idea.
> + String features = context.getInitParameter("features");
> + try {
> + gadgetSigner = new BasicGadgetSigner();
> + GadgetFeatureRegistry registry = new
> GadgetFeatureRegistry(features);
> + GadgetServerConfig config = new GadgetServerConfig()
> + .setExecutor(Executors.newCachedThreadPool())
> + .setMessageBundleCache(new
> BasicGadgetDataCache<MessageBundle>())
> + .setSpecCache(new BasicGadgetDataCache<GadgetSpec>())
> + .setContentFetcher(new BasicRemoteContentFetcher(1024 * 1024))
> + .setFeatureRegistry(registry);
> + gadgetServer = new GadgetServer(config);
> +
> + // Grab all static javascript, concatenate it together, and
> generate
> + // an md5. This becomes the cache busting suffix for javascript
> files.
> + StringBuilder jsBuf = new StringBuilder();
> +
> + for (Map.Entry<String, GadgetFeatureRegistry.Entry> entry :
> + registry.getAllFeatures().entrySet()) {
> + GadgetFeatureFactory factory = entry.getValue().getFeature();
> + if (factory instanceof JsLibraryFeatureFactory) {
> + JsLibraryFeatureFactory lib = (JsLibraryFeatureFactory)factory;
> + for (RenderingContext rc : RenderingContext.values()) {
> + for (JsLibrary library : lib.getLibraries(rc)) {
> + jsBuf.append(library.getContent());
> + }
> + }
> + }
> + }
> + MessageDigest md;
> + try {
> + md = MessageDigest.getInstance("MD5");
> + } catch (NoSuchAlgorithmException noMD5) {
> + try {
> + md = MessageDigest.getInstance("SHA");
> + } catch (NoSuchAlgorithmException noSha) {
> + throw new ServletException("No suitable MessageDigest found!");
> + }
> + }
> + byte[] hash = md.digest(jsBuf.toString().getBytes());
> + // Convert to hex. This might be a waste of bytes (32) -- could be
> + // replaced with a base64 implementation.
> + StringBuffer hexString = new StringBuffer();
> + for (byte b : hash) {
> + hexString.append(Integer.toHexString(0xFF & b));
> + }
> + jsCacheParam = hexString.toString();
> + } catch (GadgetException e) {
> + throw new ServletException(e);
> + }
> + }
> +}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> Thu Feb 7 15:18:30 2008
> @@ -13,18 +13,13 @@
> */
> package org.apache.shindig.gadgets.http;
>
> -import org.apache.shindig.gadgets.BasicGadgetDataCache;
> -import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> import org.apache.shindig.gadgets.Gadget;
> import org.apache.shindig.gadgets.GadgetContentFilter;
> import org.apache.shindig.gadgets.GadgetException;
> -import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> import org.apache.shindig.gadgets.GadgetServer;
> -import org.apache.shindig.gadgets.GadgetServerConfig;
> import org.apache.shindig.gadgets.GadgetSpec;
> import org.apache.shindig.gadgets.GadgetView;
> import org.apache.shindig.gadgets.JsLibrary;
> -import org.apache.shindig.gadgets.MessageBundle;
> import org.apache.shindig.gadgets.ProcessingOptions;
> import org.apache.shindig.gadgets.RenderingContext;
> import org.apache.shindig.gadgets.UserPrefs;
> @@ -39,11 +34,11 @@
> import java.util.LinkedList;
> import java.util.List;
> import java.util.Map;
> -import java.util.Set;
> -import java.util.concurrent.Executors;
> +import java.util.logging.Level;
> +import java.util.logging.Logger;
>
> import javax.servlet.ServletConfig;
> -import javax.servlet.ServletContext;
> +import javax.servlet.ServletException;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> @@ -52,63 +47,17 @@
> * Servlet for rendering Gadgets, typically in an IFRAME.
> */
> public class GadgetRenderingServlet extends HttpServlet {
> - private final GadgetServer gadgetServer;
> - private final GadgetServerConfig serverConfig;
> - private String jsServicePath;
> + private CrossServletState servletState;
> private static final String CAJA_PARAM = "caja";
> private static final String USERPREF_PARAM_PREFIX = "up_";
> private static final String LIBS_PARAM_NAME = "libs";
> - private static final String JS_FILE_SUFFIX = ".js";
> - public static final String DEFAULT_JS_SERVICE_PATH = "js/";
> + private static final Logger logger
> + = Logger.getLogger("org.apache.shindig.gadgets");
>
> - /**
> - * Creates a {@code GadgetRenderingServlet} with default executor,
> - * caches, etc.
> - *
> - * Note that features aren't loaded until init() is called.
> - *
> - * @throws GadgetException If something went wrong during
> configuration.
> - */
> - public GadgetRenderingServlet() throws GadgetException {
> - serverConfig = new GadgetServerConfig()
> - .setExecutor(Executors.newCachedThreadPool())
> - .setMessageBundleCache(new BasicGadgetDataCache<MessageBundle>())
> - .setSpecCache(new BasicGadgetDataCache<GadgetSpec>())
> - .setContentFetcher(new BasicRemoteContentFetcher(1024 * 1024))
> - .setFeatureRegistry(new GadgetFeatureRegistry(null));
> - gadgetServer = new GadgetServer(serverConfig);
> - }
> -
> - /**
> - * Creates a servlet using a pre-configured server. Using this method
> - * will cause init to ignore feature loading parameters.
> - * @param server
> - */
> - public GadgetRenderingServlet(GadgetServer server) {
> - gadgetServer = server;
> - // Set this to null to indicate that all configuration has been done
> - // custom.
> - serverConfig = null;
> - }
>
> @Override
> - public void init(ServletConfig config) {
> - ServletContext context = config.getServletContext();
> - String jsPath = context.getInitParameter("js-service-path");
> - if (jsPath == null) {
> - jsPath = DEFAULT_JS_SERVICE_PATH;
> - }
> - jsServicePath = jsPath;
> - if (serverConfig != null) {
> - // Using the default server.
> - String features = context.getInitParameter("features");
> - try {
> - serverConfig.getFeatureRegistry().registerFeatures(features);
> - } catch (GadgetException e) {
> - e.printStackTrace();
> - System.exit(1);
> - }
> - }
> + public void init(ServletConfig config) throws ServletException {
> + servletState = CrossServletState.get(config);
> }
>
> @Override
> @@ -153,11 +102,9 @@
> String view = req.getParameter("view");
> view = (view == null || view.length() == 0) ? GadgetSpec.DEFAULT_VIEW: view;
> try {
> - gadget = gadgetServer.processGadget(gadgetId,
> - getPrefsFromRequest(req),
> - context.getLocale(),
> - RenderingContext.GADGET,
> - options);
> + gadget = servletState.getGadgetServer().processGadget(gadgetId,
> + getPrefsFromRequest(req), context.getLocale(),
> + RenderingContext.GADGET, options);
> outputGadget(gadget, view, options, contentFilters, resp);
> } catch (GadgetServer.GadgetProcessException e) {
> outputErrors(e, resp);
> @@ -188,12 +135,6 @@
> case URL:
> outputUrlGadget(gadget, options, resp);
> break;
> - // default makes no sense here, as this is an enum, we want to insure
> that
> - // we cover all cases of the enum, so leave it out.
> -// default:
> -// resp.sendError(HttpServletResponse.SC_BAD_REQUEST,
> -// "Unexpected reror: unknown gadget type");
> -// break;
> }
> }
>
> @@ -218,6 +159,7 @@
>
> StringBuilder markup = new StringBuilder();
> markup.append("<html><head>");
> + // TODO: This is so wrong.
> markup.append("<style type=\"text/css\">" +
> "body,td,div,span,p{font-family:arial,sans-serif;}" +
> "a {color:#0000cc;}a:visited {color:#551a8b;}" +
> @@ -228,6 +170,7 @@
> StringBuilder externJs = new StringBuilder();
> StringBuilder inlineJs = new StringBuilder();
> String externFmt = "<script src=\"%s\"></script>\n";
> + String forcedLibs = options.getForcedJsLibs();
>
> for (JsLibrary library : gadget.getJsLibraries()) {
> JsLibrary.Type type = library.getType();
> @@ -239,18 +182,17 @@
> inlineJs.append(library.getContent()).append('\n');
> } else {
> // FILE or RESOURCE
> - if (options.getForcedJsLibs() == null) {
> + if (forcedLibs == null) {
> inlineJs.append(library.getContent()).append('\n');
> } // otherwise it was already included by options.forceJsLibs.
> }
> }
>
> // Forced libs first.
> - if (options.getForcedJsLibs() != null) {
> - markup.append(String.format(externFmt,
> - DEFAULT_JS_SERVICE_PATH +
> - options.getForcedJsLibs() +
> - JS_FILE_SUFFIX));
> +
> + if (forcedLibs != null) {
> + String[] libs = forcedLibs.split(":");
> + markup.append(String.format(externFmt, servletState.getJsUrl
> (libs)));
> }
>
> if (inlineJs.length() > 0) {
> @@ -280,7 +222,7 @@
> }
> }
> }
> -
> +
> if (gadgetExceptions.size() > 0) {
> throw new GadgetServer.GadgetProcessException(gadgetExceptions);
> }
> @@ -294,28 +236,31 @@
>
> private void outputUrlGadget(Gadget gadget,
> ProcessingOptions options, HttpServletResponse resp) throws
> IOException {
> - // UserPrefs portion of query string to tack on
> // TODO: generalize this as injectedArgs on Gadget object
> +
> + // Preserve existing query string parameters.
> + URI redirURI = gadget.getContentHref();
> + StringBuilder query = new StringBuilder(redirURI.getQuery());
> +
> // TODO: userprefs on the fragment rather than query string
> - String prefsQuery = getPrefsQueryString(gadget.getUserPrefValues());
> - String libsQuery = null;
> + query.append(getPrefsQueryString(gadget.getUserPrefValues()));
>
> - if (options.getForcedJsLibs() == null) {
> - libsQuery = getLibsQueryString(gadget.getRequires().keySet());
> + String[] libs;
> + String forcedLibs = options.getForcedJsLibs();
> + if (forcedLibs == null) {
> + libs = (String[])gadget.getRequires().keySet().toArray();
> } else {
> - libsQuery = DEFAULT_JS_SERVICE_PATH +
> - options.getForcedJsLibs() +
> - JS_FILE_SUFFIX;
> + libs = forcedLibs.split(":");
> }
> + appendLibsToQuery(libs, query);
>
> - URI redirURI = gadget.getContentHref();
> try {
> redirURI = new URI(redirURI.getScheme(),
> redirURI.getUserInfo(),
> redirURI.getHost(),
> redirURI.getPort(),
> redirURI.getPath(),
> - redirURI.getQuery() + prefsQuery + libsQuery,
> + query.toString(),
> redirURI.getFragment());
> } catch (URISyntaxException e) {
> // Not really ever going to happen; input values are already OK.
> @@ -337,6 +282,10 @@
> markup.append(' ');
> markup.append(error.getMessage());
> markup.append('\n');
> +
> + // Log the errors here for now. We might want different severity
> levels
> + // for different error codes.
> + logger.log(Level.INFO, "Failed to render gadget", error);
> }
> markup.append("</pre>");
> markup.append("</body></html>");
> @@ -363,9 +312,9 @@
> buf.append('&');
> try {
> buf.append(USERPREF_PARAM_PREFIX)
> - .append(URLEncoder.encode(prefEntry.getKey(), "UTF8"))
> - .append('=')
> - .append(URLEncoder.encode(prefEntry.getValue(), "UTF8"));
> + .append(URLEncoder.encode(prefEntry.getKey(), "UTF8"))
> + .append("=")
> + .append(URLEncoder.encode(prefEntry.getValue(), "UTF8"));
> } catch (UnsupportedEncodingException e) {
> // If UTF8 is somehow not supported, we may as well bail.
> // Not a whole lot we can do without such support.
> @@ -375,26 +324,16 @@
> return buf.toString();
> }
>
> - private String getLibsQueryString(Set<String> features) {
> - StringBuilder buf = new StringBuilder();
> - buf.append('&').append(LIBS_PARAM_NAME).append('=');
> - buf.append(jsServicePath);
> - if (features.size() == 0) {
> - buf.append("core");
> - } else {
> - boolean first = true;
> - for (String feature : features) {
> - if (first) {
> - first = false;
> - } else {
> - buf.append(':');
> - }
> - buf.append(feature);
> - }
> - }
> - buf.append(JS_FILE_SUFFIX);
> -
> - return buf.toString();
> + /**
> + * Appends libs to the query string.
> + * @param libs
> + * @param query
> + */
> + private void appendLibsToQuery(String[] libs, StringBuilder query) {
> + query.append("&")
> + .append(LIBS_PARAM_NAME)
> + .append("=")
> + .append(servletState.getJsUrl(libs));
> }
>
> /**
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> Thu Feb 7 15:18:30 2008
> @@ -13,7 +13,6 @@
> */
> package org.apache.shindig.gadgets.http;
>
> -import org.apache.shindig.gadgets.GadgetException;
> import org.apache.shindig.gadgets.GadgetFeatureFactory;
> import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> import org.apache.shindig.gadgets.JsLibrary;
> @@ -26,7 +25,7 @@
> import java.util.Set;
>
> import javax.servlet.ServletConfig;
> -import javax.servlet.ServletContext;
> +import javax.servlet.ServletException;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> @@ -36,42 +35,24 @@
> * Used by type=URL gadgets in loading JavaScript resources.
> */
> public class JsServlet extends HttpServlet {
> - private GadgetFeatureRegistry registry = null;
> -
> - /**
> - * Create a JsServlet using a pre-configured feature registry.
> - * @param registry
> - */
> - public JsServlet(GadgetFeatureRegistry registry) {
> - this.registry = registry;
> - }
> -
> - /**
> - * Creates a JsServlet without a default registry; the registry will be
> - * created automatically when init is called.
> - */
> - public JsServlet() {
> - registry = null;
> - }
> + private CrossServletState servletState;
> + private static final long START_TIME = System.currentTimeMillis();
>
> @Override
> - public void init(ServletConfig config) {
> - ServletContext context = config.getServletContext();
> -
> - if (registry == null) {
> - String features = context.getInitParameter("features");
> - try {
> - registry = new GadgetFeatureRegistry(features);
> - } catch (GadgetException e) {
> - e.printStackTrace();
> - throw new RuntimeException(e);
> - }
> - }
> + public void init(ServletConfig config) throws ServletException {
> + servletState = CrossServletState.get(config);
> }
>
> @Override
> protected void doGet(HttpServletRequest req, HttpServletResponse resp)
> throws IOException {
> + // If an If-Modified-Since header is ever provided, we always say
> + // not modified. This is because when there actually is a change,
> + // cache busting should occur.
> + if (req.getHeader("If-Modified-Since") != null) {
> + resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
> + return;
> + }
> // Use the last component as filename; prefix is ignored
> String uri = req.getRequestURI();
> // We only want the file name part. There will always be at least 1
> slash
> @@ -94,6 +75,8 @@
> = new HashSet<GadgetFeatureRegistry.Entry>();
> Set<String> missing = new HashSet<String>();
>
> + GadgetFeatureRegistry registry
> + = servletState.getGadgetServer
> ().getConfig().getFeatureRegistry();
> if (registry.getIncludedFeatures(needed, found, missing)) {
> String containerParam = req.getParameter("c");
> RenderingContext context;
> @@ -105,6 +88,8 @@
>
> Set<GadgetFeatureRegistry.Entry> done
> = new HashSet<GadgetFeatureRegistry.Entry>();
> +
> + // TODO: This doesn't work correctly under JDK 1.5, but it does
> under 1.6
> do {
> for (GadgetFeatureRegistry.Entry entry : found) {
> if (!done.contains(entry) &&
> @@ -145,8 +130,15 @@
> * @param response The HTTP response
> */
> private void setCachingHeaders(HttpServletResponse response) {
> - response.setHeader("Cache-Control", "public,max-age=2592000");
> - response.setDateHeader("Expires", System.currentTimeMillis()
> - + 2592000000L);
> +
> + // Most browsers accept this. 2030 is the last round year before
> + // the end of time.
> + response.setHeader("Expires", "Tue, 01 Jan 2030 00:00:01 GMT");
> +
> + // IE seems to need this (10 years should be enough).
> + response.setHeader("Cache-Control", "public,max-age=315360000");
> +
> + // Firefox requires this for certain cases.
> + response.setDateHeader("Last-Modified", START_TIME);
> }
> }
>
> 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=619684&r1=619683&r2=619684&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
> Thu Feb 7 15:18:30 2008
> @@ -18,7 +18,6 @@
> */
> package org.apache.shindig.gadgets.http;
>
> -import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> import org.apache.shindig.gadgets.GadgetException;
> import org.apache.shindig.gadgets.GadgetSigner;
> import org.apache.shindig.gadgets.GadgetToken;
> @@ -48,13 +47,9 @@
> private static final int TWO_HOURS_IN_MS = 7200000;
> private static final int ONE_HOUR_IN_SECS = 3600;
> private static final int MAX_PROXY_SIZE = 1024 * 1024;
> -
> +
> private final RemoteContentFetcher fetcher;
>
> - public ProxyHandler() {
> - this(new BasicRemoteContentFetcher(MAX_PROXY_SIZE));
> - }
> -
> public ProxyHandler(RemoteContentFetcher fetcher) {
> this.fetcher = fetcher;
> }
> @@ -203,7 +198,9 @@
> private GadgetToken extractAndValidateToken(HttpServletRequest request,
> GadgetSigner signer) throws ServletException {
> try {
> - if (signer == null) return null;
> + if (signer == null) {
> + return null;
> + }
> String token = request.getParameter("st");
> if (token == null) {
> token = "";
> @@ -229,7 +226,7 @@
>
> /**
> * Sign a URL with a GadgetToken if needed
> - * @return
> + * @return
> */
> private URL signUrl(URL originalUrl, GadgetToken token,
> HttpServletRequest request) throws ServletException {
> @@ -238,7 +235,7 @@
> !"signed".equals(request.getParameter("authz"))) {
> return originalUrl;
> }
> - return token.signUrl(originalUrl, "GET", // TODO: request.getMethod
> ()
> + return token.signUrl(originalUrl, "GET", // TODO: request.getMethod
> ()
> request.getParameterMap());
> } catch (GadgetException ge) {
> throw new ServletException(ge);
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> Thu Feb 7 15:18:30 2008
> @@ -18,28 +18,38 @@
> */
> package org.apache.shindig.gadgets.http;
>
> -import org.apache.shindig.gadgets.BasicGadgetSigner;
> -import org.apache.shindig.gadgets.GadgetSigner;
> +import org.apache.shindig.gadgets.GadgetServerConfigReader;
>
> import java.io.IOException;
>
> +import javax.servlet.ServletConfig;
> import javax.servlet.ServletException;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
>
> public class ProxyServlet extends HttpServlet {
> - private final GadgetSigner signer;
> - private final ProxyHandler handler;
> + private CrossServletState servletState;
> + private ProxyHandler proxyHandler;
> +
> + @Override
> + public void init(ServletConfig config) throws ServletException {
> + servletState = CrossServletState.get(config);
> + GadgetServerConfigReader serverConfig
> + = servletState.getGadgetServer().getConfig();
> + proxyHandler = new ProxyHandler(serverConfig.getContentFetcher());
> + }
>
> @Override
> protected void doGet(HttpServletRequest request, HttpServletResponse
> response)
> throws ServletException, IOException {
> String output = request.getParameter("output");
> if ("js".equals(output)) {
> - handler.fetchJson(request, response, signer);
> + proxyHandler.fetchJson(
> + request, response, servletState.getGadgetSigner(request));
> } else {
> - handler.fetch(request, response, signer);
> + proxyHandler.fetch(
> + request, response, servletState.getGadgetSigner(request));
> }
> }
>
> @@ -48,22 +58,5 @@
> throws ServletException, IOException {
> // Currently they are identical
> doGet(request, response);
> - }
> -
> - /**
> - * Constructs a ProxyServlet with the default (non-secure)
> GadgetSigner.
> - */
> - public ProxyServlet() {
> - this(new BasicGadgetSigner(), new ProxyHandler());
> - }
> -
> - /**
> - * Creates a ProxyServlet using the specified GadgetSigner.
> - * @param signer Used to sign and verify requests
> - * @param handler Used to fetch proxied content
> - */
> - public ProxyServlet(GadgetSigner signer, ProxyHandler handler) {
> - this.signer = signer;
> - this.handler = handler;
> }
> }
>
> Added:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java?rev=619684&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> (added)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> Thu Feb 7 15:18:30 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.http;
> +
> +import java.io.IOException;
> +
> +import javax.servlet.ServletConfig;
> +import javax.servlet.ServletException;
> +import javax.servlet.http.HttpServlet;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +
> +/**
> + * Handles RPC metadata requests.
> + */
> +public class RpcServlet extends HttpServlet {
> + private CrossServletState state;
> +
> + @Override
> + protected void doGet(HttpServletRequest request, HttpServletResponse
> response)
> + throws ServletException, IOException {
> + }
> +
> + @Override
> + public void init(ServletConfig config) throws ServletException {
> + state = CrossServletState.get(config);
> + }
> +
> + public RpcServlet() {
> + }
> +}
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> --- incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> (original)
> +++ incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> Thu Feb 7 15:18:30 2008
> @@ -19,48 +19,63 @@
> "http://java.sun.com/dtd/web-app_2_3.dtd">
>
> <web-app>
> - <!-- configuration -->
> - <context-param>
> - <param-name>features</param-name>
> - <param-value>res://features/features.txt</param-value>
> - </context-param>
> -
> - <!-- Render a Gadget -->
> - <servlet>
> - <servlet-name>xml-to-html</servlet-name>
> - <servlet-class>
> - org.apache.shindig.gadgets.http.GadgetRenderingServlet
> - </servlet-class>
> - </servlet>
> -
> - <!-- Proxy -->
> - <servlet>
> - <servlet-name>proxy</servlet-name>
> - <servlet-class>
> - org.apache.shindig.gadgets.http.ProxyServlet
> - </servlet-class>
> - </servlet>
> -
> -
> - <!-- javascript serving -->
> - <servlet>
> - <servlet-name>js</servlet-name>
> - <servlet-class>org.apache.shindig.gadgets.http.JsServlet
> </servlet-class>
> - </servlet>
> -
> - <servlet-mapping>
> - <servlet-name>js</servlet-name>
> - <url-pattern>/js/*</url-pattern>
> - </servlet-mapping>
> -
> - <servlet-mapping>
> - <servlet-name>proxy</servlet-name>
> - <url-pattern>/proxy</url-pattern>
> - </servlet-mapping>
> -
> - <servlet-mapping>
> - <servlet-name>xml-to-html</servlet-name>
> - <url-pattern>/ifr</url-pattern>
> - </servlet-mapping>
> -
> + <!-- configuration -->
> + <context-param>
> + <param-name>features</param-name>
> + <param-value>res://features/features.txt</param-value>
> + </context-param>
> + <context-param>
> + <param-name>servlet-data-class</param-name>
> + <param-value>org.apache.shindig.gadgets.http.DefaultCrossServletState
> </param-value>
> + </context-param>
> +
> + <!-- Render a Gadget -->
> + <servlet>
> + <servlet-name>xml-to-html</servlet-name>
> + <servlet-class>
> + org.apache.shindig.gadgets.http.GadgetRenderingServlet
> + </servlet-class>
> + </servlet>
> +
> + <!-- Proxy -->
> + <servlet>
> + <servlet-name>proxy</servlet-name>
> + <servlet-class>
> + org.apache.shindig.gadgets.http.ProxyServlet
> + </servlet-class>
> + </servlet>
> +
> + <!-- Metadata RPC -->
> + <servlet>
> + <servlet-name>rpc</servlet-name>
> + <servlet-class>
> + org.apache.shindig.gadgets.http.RpcServlet
> + </servlet-class>
> + </servlet>
> +
> + <!-- javascript serving -->
> + <servlet>
> + <servlet-name>js</servlet-name>
> + <servlet-class>org.apache.shindig.gadgets.http.JsServlet
> </servlet-class>
> + </servlet>
> +
> + <servlet-mapping>
> + <servlet-name>js</servlet-name>
> + <url-pattern>/js/*</url-pattern>
> + </servlet-mapping>
> +
> + <servlet-mapping>
> + <servlet-name>proxy</servlet-name>
> + <url-pattern>/proxy</url-pattern>
> + </servlet-mapping>
> +
> + <servlet-mapping>
> + <servlet-name>xml-to-html</servlet-name>
> + <url-pattern>/ifr</url-pattern>
> + </servlet-mapping>
> +
> + <servlet-mapping>
> + <servlet-name>rpc</servlet-name>
> + <url-pattern>/rpc</url-pattern>
> + </servlet-mapping>
> </web-app>
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java?rev=619684&r1=619683&r2=619684&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> Thu Feb 7 15:18:30 2008
> @@ -27,29 +27,48 @@
> import static org.easymock.EasyMock.expect;
> import static org.easymock.EasyMock.isA;
>
> -import java.util.concurrent.Executor;
> import java.util.concurrent.Executors;
>
> public class GadgetServerTest extends EasyMockTestCase {
> - final Executor executor = Executors.newCachedThreadPool();
> - final GadgetServer gadgetServer;
> + GadgetServer gadgetServer;
> final RemoteContentFetcher fetcher = mock(RemoteContentFetcher.class);
> @SuppressWarnings(value="unchecked")
> final GadgetDataCache<GadgetSpec> specCache = mock(GadgetDataCache.class
> );
> @SuppressWarnings(value="unchecked")
> final GadgetDataCache<MessageBundle> bundleCache = mock(
> GadgetDataCache.class);
>
> - public GadgetServerTest() throws GadgetException {
> - // TODO: need to test for configuration errors.
> - gadgetServer = new GadgetServer(new GadgetServerConfig()
> - .setExecutor(executor)
> - .setSpecCache(specCache)
> - .setMessageBundleCache(bundleCache)
> - .setFeatureRegistry(new GadgetFeatureRegistry(null))
> - .setContentFetcher(fetcher));
> + void initServer(GadgetServerConfigReader customConfig) throws
> GadgetException {
> + GadgetServerConfig config = new GadgetServerConfig();
> +
> + if (customConfig != null) {
> + config.copyFrom(customConfig);
> + }
> +
> + if (config.getExecutor() == null) {
> + config.setExecutor(Executors.newCachedThreadPool());
> + }
> +
> + if (config.getSpecCache() == null) {
> + config.setSpecCache(specCache);
> + }
> +
> + if (config.getMessageBundleCache() == null) {
> + config.setMessageBundleCache(bundleCache);
> + }
> +
> + if (config.getFeatureRegistry() == null) {
> + config.setFeatureRegistry(new GadgetFeatureRegistry(null));
> + }
> +
> + if (config.getContentFetcher() == null) {
> + config.setContentFetcher(fetcher);
> + }
> +
> + gadgetServer = new GadgetServer(config);
> }
>
> public void testGadgetSpecNotInCache() throws Exception {
> + initServer(null);
> RemoteContent results = new RemoteContent(200,
> DATETIME_XML.getBytes(), null);
> ProcessingOptions options = new ProcessingOptions();
>
> @@ -65,6 +84,7 @@
> }
>
> public void testGadgetSpecInCache() throws Exception {
> + initServer(null);
> expect(specCache.get
> (eq(DATETIME_URI_STRING))).andReturn(DATETIME_SPEC);
> replay();
>
> @@ -75,6 +95,7 @@
> }
>
> public void testBasicGadget() throws Exception {
> + initServer(null);
> RemoteContent results = new RemoteContent(200,
> DATETIME_XML.getBytes(), null);
> ProcessingOptions options = new ProcessingOptions();
>
> @@ -93,8 +114,7 @@
>
> public void testBlacklistedGadget() throws Exception {
> GadgetBlacklist blacklist = mock(GadgetBlacklist.class);
> - gadgetServer.setGadgetBlacklist(blacklist);
> -
> + initServer(new GadgetServerConfig().setGadgetBlacklist(blacklist));
> expect(specCache.get(eq(DATETIME_URI_STRING))).andReturn(null);
> expect(blacklist.isBlacklisted(eq(DATETIME_URI))).andReturn(true);
> replay();
>
>
>
Re: svn commit: r619684 - in /incubator/shindig/trunk: features/core/ java/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ java/gadgets/src/main/webapp/WEB-INF/ java/gadgets/
Posted by Kevin Brown <et...@google.com>.
On Feb 7, 2008 5:33 PM, Cassie <do...@apache.org> wrote:
> Just a quick thought - did you test the samplecontainer? It seems like
> moving things into /files might affect it.
> Thanks.
>
> - Cassie
Yes, we have to update a couple of those files as well to make sure it's
consistent across the board. I'll go through all the files and submit
changes tonight if nobody beats me to it.
>
>
> On Thu, Feb 7, 2008 at 3:18 PM, <et...@apache.org> wrote:
>
> > Author: etnu
> > Date: Thu Feb 7 15:18:30 2008
> > New Revision: 619684
> >
> > URL: http://svn.apache.org/viewvc?rev=619684&view=rev
> > Log:
> > - Merged in changes from SHINDIG-51 and prepared code for merging
> > SHINDIG-35
> > - Fixed caching behavior in JsServlet; files will now be cached
> > indefinitely and a cache busting token must be appended to get the new
> > version.
> > - Added placeholder for RpcServlet for SHINDIG-25.
> > - Fixed static files path in pom.xml to be compatible with the jar-based
> > build (no longer places all files into the root; now files are in
> > /gadgets/files/). This may
> > require updating some of the static files, but currently examples all
> > seem to work.
> > - Cleaned up a spec deviation in gadgets.io (did not properly handle
> > POST_DATA) and collapsed "enums" to their simplest form.
> >
> >
> > Added:
> >
> >
> 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/RpcServlet.java
> > Modified:
> > incubator/shindig/trunk/features/core/io.js
> > incubator/shindig/trunk/java/gadgets/pom.xml
> >
> >
> 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/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/ProxyHandler.java
> >
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.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/GadgetServerTest.java
> >
> > Modified: incubator/shindig/trunk/features/core/io.js
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core/io.js?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > --- incubator/shindig/trunk/features/core/io.js (original)
> > +++ incubator/shindig/trunk/features/core/io.js Thu Feb 7 15:18:30 2008
> > @@ -82,37 +82,37 @@
> > case "FEED":
> > resp.data = gadgets.json.parse(resp.text);
> > if (!resp.data) {
> > - resp.errors = ["failed to parse JSON"];
> > + resp.errors.push("failed to parse JSON");
> > resp.data = null;
> > }
> > break;
> > - case "DOM":
> > - var dom;
> > - if (window.ActiveXObject) {
> > - dom = new ActiveXObject("Microsoft.XMLDOM");
> > - dom.async = false;
> > - dom.validateOnParse = false;
> > - dom.resolveExternals = false;
> > - if (!dom.loadXML(resp.text)) {
> > - resp.errors = ["failed to parse XML"];
> > + case "DOM":
> > + var dom;
> > + if (window.ActiveXObject) {
> > + dom = new ActiveXObject("Microsoft.XMLDOM");
> > + dom.async = false;
> > + dom.validateOnParse = false;
> > + dom.resolveExternals = false;
> > + if (!dom.loadXML(resp.text)) {
> > + resp.errors.push("failed to parse XML");
> > + } else {
> > + resp.data = dom;
> > + }
> > } else {
> > - resp.data = dom;
> > + var parser = new DOMParser();
> > + dom = parser.parseFromString(resp.text, "text/xml");
> > + if ("parsererror" == dom.documentElement.nodeName) {
> > + resp.errors.push("failed to parse XML");
> > + } else {
> > + resp.data = dom;
> > + }
> > }
> > - } else {
> > - var parser = new DOMParser();
> > - dom = parser.parseFromString(resp.text, "text/xml");
> > - if ("parsererror" == dom.documentElement.nodeName) {
> > - resp.errors = ["failed to parse XML"];
> > - } else {
> > - resp.data = dom;
> > - }
> > - }
> > - break;
> > - default:
> > - resp.data = resp.text;
> > - break;
> > - }
> > - callback(resp);
> > + break;
> > + default:
> > + resp.data = resp.text;
> > + break;
> > + }
> > + callback(resp);
> > }
> >
> > return /** @scope gadgets.io */ {
> > @@ -145,10 +145,8 @@
> > encodeURIComponent(url));
> >
> > // Check if authorization is requested
> > - if (opt_params && opt_params.AUTHORIZATION &&
> > - gadgets.io.AuthorizationType
> > [opt_params.AUTHORIZATION.toUpperCase()]
> > - != gadgets.io.AuthorizationType.NONE) {
> > - newUrl += "&authz=" + opt_params.AUTHORIZATION.toLowerCase();
> > + if (params.AUTHORIZATION && params.AUTHORIZATION !== "NONE") {
> > + newUrl += "&authz=" + params.AUTHORIZATION.toLowerCase();
> > // Add the security-token if available
> > if (gadgets.util.getUrlParameters()["st"]) {
> > newUrl += "&st=" + gadgets.util.getUrlParameters()["st"];
> > @@ -160,10 +158,11 @@
> > xhr.onreadystatechange = gadgets.util.makeClosure(null,
> > processResponse, url, callback, params, xhr);
> > }
> > - if (params.METHOD == "POST") {
> > - xhr.setRequestHeader('Content-Type',
> > 'application/x-www-form-urlencoded');
> > - if (params.postData) {
> > - xhr.send("postData=" + encodeURIComponent(params.postData));
> > + if (params.METHOD === "POST") {
> > + xhr.setRequestHeader('Content-Type',
> > + 'application/x-www-form-urlencoded');
> > + if (params.POST_DATA) {
> > + xhr.send("postData=" + encodeURIComponent(params.POST_DATA));
> > } else {
> > xhr.send("postData=");
> > }
> > @@ -225,189 +224,25 @@
> > };
> > }();
> >
> > -// TODO: This can all be removed after the spec is published. This is
> > only
> > -// here to satisfy documentation requirements.
> > -
> > -/**
> > - * @static
> > - * @class
> > - * Used by the
> > - * <a href="gadgets.io.html#makeRequest">
> > - * <code>gadgets.io.makeRequest()</code></a> method.
> > - * @name gadgets.io.RequestParameters
> > - */
> > -gadgets.io.RequestParameters = {
> > - /**
> > - * The method to use when fetching content from the URL;
> > - * defaults to <code>MethodType.GET</a></code>.
> > - * Specified as a
> > - * <a href="gadgets.io.MethodType.html">MethodType</a>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - METHOD : 'METHOD',
> > -
> > - /**
> > - * The type of content that lives at the URL;
> > - * defaults to <code>ContentType.HTML</code>.
> > - * Specified as a
> > - * <a href="gadgets.io.ContentType.html">
> > - * ContentType</a>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - CONTENT_TYPE : "CONTENT_TYPE",
> > -
> > - /**
> > - * The data to send to the URL using the POST method;
> > - * defaults to null.
> > - * Specified as a <code>String</code>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - POST_DATA : "POST_DATA",
> > -
> > - /**
> > - * The HTTP headers to send to the URL;
> > - * defaults to null.
> > - * Specified as a <code>Map.<String,String></code>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - HEADERS : "HEADERS",
> > -
> > - /**
> > - * The type of authentication to use when fetching the content;
> > - * defaults to <code>AuthorizationType.NONE</code>.
> > - * Specified as an
> > - * <a href="gadgets.io.AuthorizationType.html">
> > - * AuthorizationType</a>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - AUTHORIZATION : 'AUTHORIZATION',
> > -
> > -
> > - /**
> > - * If the content is a feed, the number of entries to fetch;
> > - * defaults to 3.
> > - * Specified as a <code>Number</code>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - NUM_ENTRIES : 'NUM_ENTRIES',
> > -
> > - /**
> > - * If the content is a feed, whether to fetch summaries for that
> feed;
> > - * defaults to false.
> > - * Specified as a <code>Boolean</code>.
> > - *
> > - * @member gadgets.io.RequestParameters
> > - */
> > - GET_SUMMARIES : 'GET_SUMMARIES'
> > -};
> > -
> > -
> > -/**
> > - * @static
> > - * @class
> > - * Used by
> > - * <a href="gadgets.io.RequestParameters.html">
> > - * RequestParameters</a>.
> > - * @name gadgets.io.MethodType
> > - */
> > -gadgets.io.MethodType = {
> > - /**
> > - * The default type.
> > - * @member gadgets.io.MethodType
> > - */
> > - GET : 'GET',
> > -
> > - /**
> > - * Not supported by all containers.
> > - * @member gadgets.io.MethodType
> > - */
> > - POST : 'POST',
> > -
> > - /**
> > - * Not supported by all containers.
> > - * @member gadgets.io.MethodType
> > - */
> > - PUT : 'PUT',
> > -
> > - /**
> > - * Not supported by all containers.
> > - * @member gadgets.io.MethodType
> > - */
> > - DELETE : 'DELETE',
> > -
> > - /**
> > - * Not supported by all containers.
> > - * @member gadgets.io.MethodType
> > - */
> > - HEAD : 'HEAD'
> > -};
> > -
> > -
> > -/**
> > - * @static
> > - * @class
> > - * Used by
> > - * <a href="gadgets.io.RequestParameters.html">
> > - * RequestParameters</a>.
> > - * @name gadgets.io.ContentType
> > - */
> > -gadgets.io.ContentType = {
> > - /**
> > - * Returns text; used for fetching HTML.
> > - * @member gadgets.io.ContentType
> > - */
> > - TEXT : 'TEXT',
> > -
> > - /**
> > - * Returns a DOM object; used for fetching XML.
> > - * @member gadgets.io.ContentType
> > - */
> > - DOM : 'DOM',
> > -
> > - /**
> > - * Returns a JSON object.
> > - * @member gadgets.io.ContentType
> > - */
> > - JSON : 'JSON',
> > -
> > - /**
> > - * Returns a JSON representation of a feed.
> > - * @member gadgets.io.ContentType
> > - */
> > - FEED : 'FEED'
> > -};
> > -
> > -
> > -/**
> > - * @static
> > - * @class
> > - * Used by
> > - * <a href="gadgets.io.RequestParameters.html">
> > - * RequestParameters</a>.
> > - * @name gadgets.io.AuthorizationType
> > - */
> > -gadgets.io.AuthorizationType = {
> > - /**
> > - * No authorization.
> > - * @member gadgets.io.AuthorizationType
> > - */
> > - NONE : 'NONE',
> > -
> > - /**
> > - * The request will be signed by the container.
> > - * @member gadgets.io.AuthorizationType
> > - */
> > - SIGNED : 'SIGNED',
> > -
> > - /**
> > - * The container will use full authentication.
> > - * @member gadgets.io.AuthorizationType
> > - */
> > - AUTHENTICATED : 'AUTHENTICATED'
> > -};
> > +gadgets.io.RequestParameters = gadgets.util.makeEnum([
> > + "METHOD",
> > + "CONTENT_TYPE",
> > + "POST_DATA",
> > + "HEADERS",
> > + "AUTHORIZATION",
> > + "NUM_ENTRIES",
> > + "GET_SUMMARIES"
> > +]);
> > +
> > +// PUT, DELETE, and HEAD not supported currently.
> > +gadgets.io.MethodType = gadgets.util.makeEnum([
> > + "GET", "POST", "PUT", "DELETE", "HEAD"
> > +]);
> > +
> > +gadgets.io.ContentType = gadgets.util.makeEnum([
> > + "TEXT", "DOM", "JSON", "FEED"
> > +]);
> > +
> > +gadgets.io.AuthorizationType = gadgets.util.makeEnum([
> > + "NONE", "SIGNED", "AUTHENTICATED"
> > +]);
> > \ No newline at end of file
> >
> > Modified: incubator/shindig/trunk/java/gadgets/pom.xml
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/pom.xml?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > --- incubator/shindig/trunk/java/gadgets/pom.xml (original)
> > +++ incubator/shindig/trunk/java/gadgets/pom.xml Thu Feb 7 15:18:30
> 2008
> > @@ -28,6 +28,7 @@
> > <resource>
> > <!-- this is relative to the pom.xml directory -->
> > <directory>../../javascript/</directory>
> > + <targetPath>files</targetPath>
> > <includes>
> > <include>**/*.*</include>
> > </includes>
> >
> > 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=619684&r1=619683&r2=619684&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
> > Thu Feb 7 15:18:30 2008
> > @@ -146,6 +146,13 @@
> > }
> >
> > /**
> > + * @return All registered features.
> > + */
> > + public Map<String, Entry> getAllFeatures() {
> > + return Collections.unmodifiableMap(features);
> > + }
> > +
> > + /**
> > * Attempts to retrieve all the {@code GadgetFeature} classes
> specified
> > * in the {@code needed} list. Those that are found are returned in
> > * {@code resultsFound}, while the names of those that are missing are
> >
> > 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=619684&r1=619683&r2=619684&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
> > Thu Feb 7 15:18:30 2008
> > @@ -22,39 +22,21 @@
> > import java.net.MalformedURLException;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > +import java.util.Collections;
> > import java.util.HashSet;
> > import java.util.LinkedList;
> > import java.util.List;
> > import java.util.Locale;
> > import java.util.Map;
> > import java.util.Set;
> > -import java.util.Collections;
> > import java.util.concurrent.Callable;
> > import java.util.concurrent.CompletionService;
> > import java.util.concurrent.ExecutionException;
> > -import java.util.concurrent.Executor;
> > import java.util.concurrent.ExecutorCompletionService;
> > import java.util.concurrent.Future;
> > -import java.util.logging.Logger;
> > -import java.util.logging.Level;
> >
> > public class GadgetServer {
> > - private final GadgetServerConfig config;
> > -
> > - private static final Logger logger
> > - = Logger.getLogger("org.apache.shindig.gadgets");
> > -
> > - /**
> > - * Creates a GadgetServer without a config.
> > - *
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - * @param executor
> > - */
> > - @Deprecated
> > - public GadgetServer(Executor executor) {
> > - config = new GadgetServerConfig();
> > - config.setExecutor(executor);
> > - }
> > + private final GadgetServerConfigReader config;
> >
> > /**
> > * Creates a GadgetServer using the provided configuration.
> > @@ -72,51 +54,11 @@
> > Check.notNull(configuration.getContentFetcher(),
> > "ContentFetcher is required.");
> >
> > - config = new GadgetServerConfig();
> > + config = new GadgetServerConfigReader();
> > config.copyFrom(configuration);
> > }
> >
> > /**
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - */
> > - @Deprecated
> > - public void setSpecCache(GadgetDataCache<GadgetSpec> specCache) {
> > - config.setSpecCache(specCache);
> > - }
> > -
> > - /**
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - */
> > - @Deprecated
> > - public void setMessageBundleCache(GadgetDataCache<MessageBundle>
> cache)
> > {
> > - config.setMessageBundleCache(cache);
> > - }
> > -
> > - /**
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - */
> > - @Deprecated
> > - public void setContentFetcher(RemoteContentFetcher fetcher) {
> > - config.setContentFetcher(fetcher);
> > - }
> > -
> > - /**
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - */
> > - @Deprecated
> > - public void setGadgetFeatureRegistry(GadgetFeatureRegistry registry)
> {
> > - config.setFeatureRegistry(registry);
> > - }
> > -
> > - /**
> > - * @deprecated Replaced by {@link
> > #GadgetServer(GadgetServerConfigReader)}.
> > - */
> > - @Deprecated
> > - public void setGadgetBlacklist(GadgetBlacklist gadgetBlacklist) {
> > - config.setGadgetBlacklist(gadgetBlacklist);
> > - }
> > -
> > - /**
> > * @return A read-only view of the server's configuration.
> > */
> > public GadgetServerConfigReader getConfig() {
> > @@ -140,22 +82,6 @@
> > RenderingContext rctx,
> > ProcessingOptions options)
> > throws GadgetProcessException {
> > - // TODO: Remove dep checks when GadgetServer(Executor) is removed.
> > - if (config.getSpecCache() == null) {
> > - throw new GadgetProcessException(
> > GadgetException.Code.MISSING_SPEC_CACHE);
> > - }
> > - if (config.getMessageBundleCache() == null ) {
> > - throw new GadgetProcessException(
> > - GadgetException.Code.MISSING_MESSAGE_BUNDLE_CACHE);
> > - }
> > - if (config.getContentFetcher() == null) {
> > - throw new GadgetProcessException(
> > - GadgetException.Code.MISSING_REMOTE_OBJECT_FETCHER);
> > - }
> > - if (config.getFeatureRegistry() == null) {
> > - throw new GadgetProcessException(
> > - GadgetException.Code.MISSING_FEATURE_REGISTRY);
> > - }
> >
> > // Queue/tree of all jobs to be run for successful processing
> > GadgetContext gc = new GadgetContext(config.getContentFetcher(),
> > @@ -242,8 +168,6 @@
> > }
> >
> > if (gadgetException != null) {
> > - logger.log(Level.SEVERE, gadgetException.getCode().toString(),
> > gadgetException);
> > -
> > // Add to list of all exceptions caught, clear jobs, and
> continue
> > // to aggressively catch as many exceptions as possible. Since
> > // tasks are running anyway, we may as well get their results in
> > @@ -320,7 +244,8 @@
> >
> > private WorkflowContext(GadgetContext context) {
> > this.context = context;
> > - this.depsDone = Collections.synchronizedSet(new
> > HashSet<WorkflowDependency>());
> > + this.depsDone
> > + = Collections.synchronizedSet(new
> > HashSet<WorkflowDependency>());
> > this.jobsToRun = new WorkflowJobList(this);
> > }
> > }
> > @@ -431,8 +356,9 @@
> > Map<String, GadgetSpec.FeatureSpec> requires =
> wc.gadget.getRequires
> > ();
> > Set<String> needed = new HashSet<String>(requires.size());
> > Set<String> optionalNames = new HashSet<String>();
> > -
> > - for (Map.Entry<String, GadgetSpec.FeatureSpec> entry :
> > requires.entrySet()) {
> > +
> > + for (Map.Entry<String, GadgetSpec.FeatureSpec> entry :
> > + requires.entrySet()) {
> > needed.add(entry.getKey());
> > if (entry.getValue().isOptional()) {
> > optionalNames.add(entry.getKey());
> >
> > Added:
> >
> 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=619684&view=auto
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> > (added)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/CrossServletState.java
> > Thu Feb 7 15:18:30 2008
> > @@ -0,0 +1,107 @@
> > +/*
> > + * 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.http;
> > +
> > +import org.apache.shindig.gadgets.Gadget;
> > +import org.apache.shindig.gadgets.GadgetServer;
> > +import org.apache.shindig.gadgets.GadgetSigner;
> > +
> > +import java.util.logging.Logger;
> > +
> > +import javax.servlet.ServletConfig;
> > +import javax.servlet.ServletContext;
> > +import javax.servlet.ServletException;
> > +import javax.servlet.http.HttpServletRequest;
> > +
> > +/**
> > + * Loads shared configuration and creates appropriate class instances
> for
> > + * sharing amongst servlets.
> > + */
> > +public abstract class CrossServletState {
> > + private static final Logger logger
> > + = Logger.getLogger("org.apache.shindig.gadgets");
> > + /**
> > + * @param config
> > + * @return A CrossServletState appropriate for the given
> ServletConfig
> > + * @throws ServletException
> > + */
> > + public static synchronized CrossServletState get(ServletConfig
> config)
> > + throws ServletException {
> > + ServletContext context = config.getServletContext();
> > + // Check to see if the context has already been created. If it has,
> > + // just return.
> > + CrossServletState state
> > + = (CrossServletState)context.getAttribute("servlet-data");
> > +
> > + if (state == null) {
> > + String dataClass = context.getInitParameter
> ("servlet-data-class");
> > + if (dataClass == null) {
> > + throw new ServletException("servlet-data-class is missing.");
> > + }
> > + logger.info("Loading CrossServletState: " + dataClass);
> > + try {
> > + state =
> > (CrossServletState)Class.forName(dataClass).newInstance();
> > + state.init(context);
> > + context.setAttribute("servlet-data", state);
> > + } catch (InstantiationException ie) {
> > + throw new ServletException(ie);
> > + } catch (IllegalAccessException iae) {
> > + throw new ServletException(iae);
> > + } catch (ClassNotFoundException cnfe) {
> > + throw new ServletException(cnfe);
> > + }
> > + }
> > + return state;
> > + }
> > +
> > + /**
> > + * @return A GadgetServer instance that is fully configured and
> > + * ready to be used to process gadgets.
> > + */
> > + public abstract GadgetServer getGadgetServer();
> > +
> > + /**
> > + * @param req The request that a signing token is needed for.
> > + * @return A unique GadgetSigner for the request
> > + */
> > + public abstract GadgetSigner getGadgetSigner(HttpServletRequest req);
> > +
> > + /**
> > + * Constructs a url for retrieving javascript for the given
> > + * set of features.
> > + *
> > + * @param features
> > + * @return The url to retrieve the appropriate JS.
> > + */
> > + public abstract String getJsUrl(String[] features);
> > +
> > + /**
> > + * Constructs a url for generating an iframe for the given gadget.
> > + * This only applies for RPC calls that must generate an iframe.
> > + */
> > + public abstract String getIframeUrl(Gadget gadget,
> HttpServletRequest
> > req);
> > +
> > + /**
> > + * Initializes this handler using the provided implementation.
> > + * @param context
> > + * @throws ServletException
> > + */
> > + protected abstract void init(ServletContext context) throws
> > ServletException;
> > +}
> >
> > Added:
> >
> 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=619684&view=auto
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> > (added)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
> > Thu Feb 7 15:18:30 2008
> > @@ -0,0 +1,192 @@
> > +/*
> > + * 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.http;
> > +
> > +import org.apache.shindig.gadgets.BasicGadgetDataCache;
> > +import org.apache.shindig.gadgets.BasicGadgetSigner;
> > +import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> > +import org.apache.shindig.gadgets.Gadget;
> > +import org.apache.shindig.gadgets.GadgetException;
> > +import org.apache.shindig.gadgets.GadgetFeatureFactory;
> > +import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> > +import org.apache.shindig.gadgets.GadgetServer;
> > +import org.apache.shindig.gadgets.GadgetServerConfig;
> > +import org.apache.shindig.gadgets.GadgetSigner;
> > +import org.apache.shindig.gadgets.GadgetSpec;
> > +import org.apache.shindig.gadgets.JsLibrary;
> > +import org.apache.shindig.gadgets.JsLibraryFeatureFactory;
> > +import org.apache.shindig.gadgets.MessageBundle;
> > +import org.apache.shindig.gadgets.RenderingContext;
> > +
> > +import java.io.UnsupportedEncodingException;
> > +import java.net.URLEncoder;
> > +import java.security.MessageDigest;
> > +import java.security.NoSuchAlgorithmException;
> > +import java.util.Map;
> > +import java.util.concurrent.Executors;
> > +
> > +import javax.servlet.ServletContext;
> > +import javax.servlet.ServletException;
> > +import javax.servlet.http.HttpServletRequest;
> > +
> > +/**
> > + * A handler which uses all of the basic versions of classes.
> > + */
> > +public class DefaultCrossServletState extends CrossServletState {
> > +
> > + private GadgetServer gadgetServer;
> > + private GadgetSigner gadgetSigner;
> > + private String jsPath;
> > + private String iframePath;
> > + private String jsCacheParam;
> > +
> > + private static final String DEFAULT_JS_PREFIX = "/gadgets/js/";
> > + private static final String DEFAULT_IFRAME_PREFIX = "/gadgets/ifr?";
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + @Override
> > + public GadgetServer getGadgetServer() {
> > + return gadgetServer;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + * Just returns the same gadget signer no matter the request.
> > + */
> > + @Override
> > + public GadgetSigner getGadgetSigner(HttpServletRequest req) {
> > + return gadgetSigner;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + @Override
> > + public String getIframeUrl(Gadget gadget, HttpServletRequest req) {
> > + // We don't have any meaningful data in the current request anyway,
> > so
> > + // we'll just do this statically.
> > + StringBuilder buf = new StringBuilder();
> > + try {
> > + buf.append(iframePath)
> > + .append("url=")
> > + .append(
> > + URLEncoder.encode(gadget.getId
> > ().getURI().toString(),"UTF-8"));
> > + } catch (UnsupportedEncodingException e) {
> > + throw new RuntimeException("UTF-8 Not supported!", e);
> > + }
> > +
> > + // TODO: extract user prefs, current view, etc. from <req>.
> Currently
> > + // consumers of the response are on their own for this.
> > + return buf.toString();
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + @Override
> > + public String getJsUrl(String[] features) {
> > + StringBuilder buf = new StringBuilder();
> > + buf.append(jsPath);
> > + if (features == null || features.length == 0) {
> > + buf.append("core");
> > + } else {
> > + boolean firstDone = false;
> > + for (String feature : features) {
> > + if (firstDone) {
> > + buf.append(":");
> > + } else {
> > + firstDone = true;
> > + }
> > + buf.append(feature);
> > + }
> > + }
> > + buf.append(".js?v=").append(jsCacheParam);
> > + return buf.toString();
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + @Override
> > + protected void init(ServletContext context) throws ServletException {
> > + jsPath = context.getInitParameter("js-service-path");
> > + if (jsPath == null) {
> > + jsPath = DEFAULT_JS_PREFIX;
> > + }
> > +
> > + iframePath = context.getInitParameter("iframe-path");
> > + if (iframePath == null) {
> > + iframePath = DEFAULT_IFRAME_PREFIX;
> > + }
> > +
> > + // features could be null, but that would probably be a bad idea.
> > + String features = context.getInitParameter("features");
> > + try {
> > + gadgetSigner = new BasicGadgetSigner();
> > + GadgetFeatureRegistry registry = new
> > GadgetFeatureRegistry(features);
> > + GadgetServerConfig config = new GadgetServerConfig()
> > + .setExecutor(Executors.newCachedThreadPool())
> > + .setMessageBundleCache(new
> > BasicGadgetDataCache<MessageBundle>())
> > + .setSpecCache(new BasicGadgetDataCache<GadgetSpec>())
> > + .setContentFetcher(new BasicRemoteContentFetcher(1024 *
> 1024))
> > + .setFeatureRegistry(registry);
> > + gadgetServer = new GadgetServer(config);
> > +
> > + // Grab all static javascript, concatenate it together, and
> > generate
> > + // an md5. This becomes the cache busting suffix for javascript
> > files.
> > + StringBuilder jsBuf = new StringBuilder();
> > +
> > + for (Map.Entry<String, GadgetFeatureRegistry.Entry> entry :
> > + registry.getAllFeatures().entrySet()) {
> > + GadgetFeatureFactory factory = entry.getValue().getFeature();
> > + if (factory instanceof JsLibraryFeatureFactory) {
> > + JsLibraryFeatureFactory lib =
> (JsLibraryFeatureFactory)factory;
> > + for (RenderingContext rc : RenderingContext.values()) {
> > + for (JsLibrary library : lib.getLibraries(rc)) {
> > + jsBuf.append(library.getContent());
> > + }
> > + }
> > + }
> > + }
> > + MessageDigest md;
> > + try {
> > + md = MessageDigest.getInstance("MD5");
> > + } catch (NoSuchAlgorithmException noMD5) {
> > + try {
> > + md = MessageDigest.getInstance("SHA");
> > + } catch (NoSuchAlgorithmException noSha) {
> > + throw new ServletException("No suitable MessageDigest
> found!");
> > + }
> > + }
> > + byte[] hash = md.digest(jsBuf.toString().getBytes());
> > + // Convert to hex. This might be a waste of bytes (32) -- could
> be
> > + // replaced with a base64 implementation.
> > + StringBuffer hexString = new StringBuffer();
> > + for (byte b : hash) {
> > + hexString.append(Integer.toHexString(0xFF & b));
> > + }
> > + jsCacheParam = hexString.toString();
> > + } catch (GadgetException e) {
> > + throw new ServletException(e);
> > + }
> > + }
> > +}
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/GadgetRenderingServlet.java
> > Thu Feb 7 15:18:30 2008
> > @@ -13,18 +13,13 @@
> > */
> > package org.apache.shindig.gadgets.http;
> >
> > -import org.apache.shindig.gadgets.BasicGadgetDataCache;
> > -import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> > import org.apache.shindig.gadgets.Gadget;
> > import org.apache.shindig.gadgets.GadgetContentFilter;
> > import org.apache.shindig.gadgets.GadgetException;
> > -import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> > import org.apache.shindig.gadgets.GadgetServer;
> > -import org.apache.shindig.gadgets.GadgetServerConfig;
> > import org.apache.shindig.gadgets.GadgetSpec;
> > import org.apache.shindig.gadgets.GadgetView;
> > import org.apache.shindig.gadgets.JsLibrary;
> > -import org.apache.shindig.gadgets.MessageBundle;
> > import org.apache.shindig.gadgets.ProcessingOptions;
> > import org.apache.shindig.gadgets.RenderingContext;
> > import org.apache.shindig.gadgets.UserPrefs;
> > @@ -39,11 +34,11 @@
> > import java.util.LinkedList;
> > import java.util.List;
> > import java.util.Map;
> > -import java.util.Set;
> > -import java.util.concurrent.Executors;
> > +import java.util.logging.Level;
> > +import java.util.logging.Logger;
> >
> > import javax.servlet.ServletConfig;
> > -import javax.servlet.ServletContext;
> > +import javax.servlet.ServletException;
> > import javax.servlet.http.HttpServlet;
> > import javax.servlet.http.HttpServletRequest;
> > import javax.servlet.http.HttpServletResponse;
> > @@ -52,63 +47,17 @@
> > * Servlet for rendering Gadgets, typically in an IFRAME.
> > */
> > public class GadgetRenderingServlet extends HttpServlet {
> > - private final GadgetServer gadgetServer;
> > - private final GadgetServerConfig serverConfig;
> > - private String jsServicePath;
> > + private CrossServletState servletState;
> > private static final String CAJA_PARAM = "caja";
> > private static final String USERPREF_PARAM_PREFIX = "up_";
> > private static final String LIBS_PARAM_NAME = "libs";
> > - private static final String JS_FILE_SUFFIX = ".js";
> > - public static final String DEFAULT_JS_SERVICE_PATH = "js/";
> > + private static final Logger logger
> > + = Logger.getLogger("org.apache.shindig.gadgets");
> >
> > - /**
> > - * Creates a {@code GadgetRenderingServlet} with default executor,
> > - * caches, etc.
> > - *
> > - * Note that features aren't loaded until init() is called.
> > - *
> > - * @throws GadgetException If something went wrong during
> > configuration.
> > - */
> > - public GadgetRenderingServlet() throws GadgetException {
> > - serverConfig = new GadgetServerConfig()
> > - .setExecutor(Executors.newCachedThreadPool())
> > - .setMessageBundleCache(new
> BasicGadgetDataCache<MessageBundle>())
> > - .setSpecCache(new BasicGadgetDataCache<GadgetSpec>())
> > - .setContentFetcher(new BasicRemoteContentFetcher(1024 * 1024))
> > - .setFeatureRegistry(new GadgetFeatureRegistry(null));
> > - gadgetServer = new GadgetServer(serverConfig);
> > - }
> > -
> > - /**
> > - * Creates a servlet using a pre-configured server. Using this method
> > - * will cause init to ignore feature loading parameters.
> > - * @param server
> > - */
> > - public GadgetRenderingServlet(GadgetServer server) {
> > - gadgetServer = server;
> > - // Set this to null to indicate that all configuration has been
> done
> > - // custom.
> > - serverConfig = null;
> > - }
> >
> > @Override
> > - public void init(ServletConfig config) {
> > - ServletContext context = config.getServletContext();
> > - String jsPath = context.getInitParameter("js-service-path");
> > - if (jsPath == null) {
> > - jsPath = DEFAULT_JS_SERVICE_PATH;
> > - }
> > - jsServicePath = jsPath;
> > - if (serverConfig != null) {
> > - // Using the default server.
> > - String features = context.getInitParameter("features");
> > - try {
> > - serverConfig.getFeatureRegistry().registerFeatures(features);
> > - } catch (GadgetException e) {
> > - e.printStackTrace();
> > - System.exit(1);
> > - }
> > - }
> > + public void init(ServletConfig config) throws ServletException {
> > + servletState = CrossServletState.get(config);
> > }
> >
> > @Override
> > @@ -153,11 +102,9 @@
> > String view = req.getParameter("view");
> > view = (view == null || view.length() == 0) ?
> GadgetSpec.DEFAULT_VIEW: view;
> > try {
> > - gadget = gadgetServer.processGadget(gadgetId,
> > - getPrefsFromRequest(req),
> > - context.getLocale(),
> > - RenderingContext.GADGET,
> > - options);
> > + gadget = servletState.getGadgetServer().processGadget(gadgetId,
> > + getPrefsFromRequest(req), context.getLocale(),
> > + RenderingContext.GADGET, options);
> > outputGadget(gadget, view, options, contentFilters, resp);
> > } catch (GadgetServer.GadgetProcessException e) {
> > outputErrors(e, resp);
> > @@ -188,12 +135,6 @@
> > case URL:
> > outputUrlGadget(gadget, options, resp);
> > break;
> > - // default makes no sense here, as this is an enum, we want to
> insure
> > that
> > - // we cover all cases of the enum, so leave it out.
> > -// default:
> > -// resp.sendError(HttpServletResponse.SC_BAD_REQUEST,
> > -// "Unexpected reror: unknown gadget type");
> > -// break;
> > }
> > }
> >
> > @@ -218,6 +159,7 @@
> >
> > StringBuilder markup = new StringBuilder();
> > markup.append("<html><head>");
> > + // TODO: This is so wrong.
> > markup.append("<style type=\"text/css\">" +
> > "body,td,div,span,p{font-family:arial,sans-serif;}" +
> > "a {color:#0000cc;}a:visited {color:#551a8b;}" +
> > @@ -228,6 +170,7 @@
> > StringBuilder externJs = new StringBuilder();
> > StringBuilder inlineJs = new StringBuilder();
> > String externFmt = "<script src=\"%s\"></script>\n";
> > + String forcedLibs = options.getForcedJsLibs();
> >
> > for (JsLibrary library : gadget.getJsLibraries()) {
> > JsLibrary.Type type = library.getType();
> > @@ -239,18 +182,17 @@
> > inlineJs.append(library.getContent()).append('\n');
> > } else {
> > // FILE or RESOURCE
> > - if (options.getForcedJsLibs() == null) {
> > + if (forcedLibs == null) {
> > inlineJs.append(library.getContent()).append('\n');
> > } // otherwise it was already included by options.forceJsLibs.
> > }
> > }
> >
> > // Forced libs first.
> > - if (options.getForcedJsLibs() != null) {
> > - markup.append(String.format(externFmt,
> > - DEFAULT_JS_SERVICE_PATH +
> > - options.getForcedJsLibs() +
> > - JS_FILE_SUFFIX));
> > +
> > + if (forcedLibs != null) {
> > + String[] libs = forcedLibs.split(":");
> > + markup.append(String.format(externFmt, servletState.getJsUrl
> > (libs)));
> > }
> >
> > if (inlineJs.length() > 0) {
> > @@ -280,7 +222,7 @@
> > }
> > }
> > }
> > -
> > +
> > if (gadgetExceptions.size() > 0) {
> > throw new GadgetServer.GadgetProcessException(gadgetExceptions);
> > }
> > @@ -294,28 +236,31 @@
> >
> > private void outputUrlGadget(Gadget gadget,
> > ProcessingOptions options, HttpServletResponse resp) throws
> > IOException {
> > - // UserPrefs portion of query string to tack on
> > // TODO: generalize this as injectedArgs on Gadget object
> > +
> > + // Preserve existing query string parameters.
> > + URI redirURI = gadget.getContentHref();
> > + StringBuilder query = new StringBuilder(redirURI.getQuery());
> > +
> > // TODO: userprefs on the fragment rather than query string
> > - String prefsQuery = getPrefsQueryString(gadget.getUserPrefValues
> ());
> > - String libsQuery = null;
> > + query.append(getPrefsQueryString(gadget.getUserPrefValues()));
> >
> > - if (options.getForcedJsLibs() == null) {
> > - libsQuery = getLibsQueryString(gadget.getRequires().keySet());
> > + String[] libs;
> > + String forcedLibs = options.getForcedJsLibs();
> > + if (forcedLibs == null) {
> > + libs = (String[])gadget.getRequires().keySet().toArray();
> > } else {
> > - libsQuery = DEFAULT_JS_SERVICE_PATH +
> > - options.getForcedJsLibs() +
> > - JS_FILE_SUFFIX;
> > + libs = forcedLibs.split(":");
> > }
> > + appendLibsToQuery(libs, query);
> >
> > - URI redirURI = gadget.getContentHref();
> > try {
> > redirURI = new URI(redirURI.getScheme(),
> > redirURI.getUserInfo(),
> > redirURI.getHost(),
> > redirURI.getPort(),
> > redirURI.getPath(),
> > - redirURI.getQuery() + prefsQuery + libsQuery,
> > + query.toString(),
> > redirURI.getFragment());
> > } catch (URISyntaxException e) {
> > // Not really ever going to happen; input values are already OK.
> > @@ -337,6 +282,10 @@
> > markup.append(' ');
> > markup.append(error.getMessage());
> > markup.append('\n');
> > +
> > + // Log the errors here for now. We might want different severity
> > levels
> > + // for different error codes.
> > + logger.log(Level.INFO, "Failed to render gadget", error);
> > }
> > markup.append("</pre>");
> > markup.append("</body></html>");
> > @@ -363,9 +312,9 @@
> > buf.append('&');
> > try {
> > buf.append(USERPREF_PARAM_PREFIX)
> > - .append(URLEncoder.encode(prefEntry.getKey(), "UTF8"))
> > - .append('=')
> > - .append(URLEncoder.encode(prefEntry.getValue(),
> "UTF8"));
> > + .append(URLEncoder.encode(prefEntry.getKey(), "UTF8"))
> > + .append("=")
> > + .append(URLEncoder.encode(prefEntry.getValue(), "UTF8"));
> > } catch (UnsupportedEncodingException e) {
> > // If UTF8 is somehow not supported, we may as well bail.
> > // Not a whole lot we can do without such support.
> > @@ -375,26 +324,16 @@
> > return buf.toString();
> > }
> >
> > - private String getLibsQueryString(Set<String> features) {
> > - StringBuilder buf = new StringBuilder();
> > - buf.append('&').append(LIBS_PARAM_NAME).append('=');
> > - buf.append(jsServicePath);
> > - if (features.size() == 0) {
> > - buf.append("core");
> > - } else {
> > - boolean first = true;
> > - for (String feature : features) {
> > - if (first) {
> > - first = false;
> > - } else {
> > - buf.append(':');
> > - }
> > - buf.append(feature);
> > - }
> > - }
> > - buf.append(JS_FILE_SUFFIX);
> > -
> > - return buf.toString();
> > + /**
> > + * Appends libs to the query string.
> > + * @param libs
> > + * @param query
> > + */
> > + private void appendLibsToQuery(String[] libs, StringBuilder query) {
> > + query.append("&")
> > + .append(LIBS_PARAM_NAME)
> > + .append("=")
> > + .append(servletState.getJsUrl(libs));
> > }
> >
> > /**
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsServlet.java
> > Thu Feb 7 15:18:30 2008
> > @@ -13,7 +13,6 @@
> > */
> > package org.apache.shindig.gadgets.http;
> >
> > -import org.apache.shindig.gadgets.GadgetException;
> > import org.apache.shindig.gadgets.GadgetFeatureFactory;
> > import org.apache.shindig.gadgets.GadgetFeatureRegistry;
> > import org.apache.shindig.gadgets.JsLibrary;
> > @@ -26,7 +25,7 @@
> > import java.util.Set;
> >
> > import javax.servlet.ServletConfig;
> > -import javax.servlet.ServletContext;
> > +import javax.servlet.ServletException;
> > import javax.servlet.http.HttpServlet;
> > import javax.servlet.http.HttpServletRequest;
> > import javax.servlet.http.HttpServletResponse;
> > @@ -36,42 +35,24 @@
> > * Used by type=URL gadgets in loading JavaScript resources.
> > */
> > public class JsServlet extends HttpServlet {
> > - private GadgetFeatureRegistry registry = null;
> > -
> > - /**
> > - * Create a JsServlet using a pre-configured feature registry.
> > - * @param registry
> > - */
> > - public JsServlet(GadgetFeatureRegistry registry) {
> > - this.registry = registry;
> > - }
> > -
> > - /**
> > - * Creates a JsServlet without a default registry; the registry will
> be
> > - * created automatically when init is called.
> > - */
> > - public JsServlet() {
> > - registry = null;
> > - }
> > + private CrossServletState servletState;
> > + private static final long START_TIME = System.currentTimeMillis();
> >
> > @Override
> > - public void init(ServletConfig config) {
> > - ServletContext context = config.getServletContext();
> > -
> > - if (registry == null) {
> > - String features = context.getInitParameter("features");
> > - try {
> > - registry = new GadgetFeatureRegistry(features);
> > - } catch (GadgetException e) {
> > - e.printStackTrace();
> > - throw new RuntimeException(e);
> > - }
> > - }
> > + public void init(ServletConfig config) throws ServletException {
> > + servletState = CrossServletState.get(config);
> > }
> >
> > @Override
> > protected void doGet(HttpServletRequest req, HttpServletResponse resp)
> > throws IOException {
> > + // If an If-Modified-Since header is ever provided, we always say
> > + // not modified. This is because when there actually is a change,
> > + // cache busting should occur.
> > + if (req.getHeader("If-Modified-Since") != null) {
> > + resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
> > + return;
> > + }
> > // Use the last component as filename; prefix is ignored
> > String uri = req.getRequestURI();
> > // We only want the file name part. There will always be at least 1
> > slash
> > @@ -94,6 +75,8 @@
> > = new HashSet<GadgetFeatureRegistry.Entry>();
> > Set<String> missing = new HashSet<String>();
> >
> > + GadgetFeatureRegistry registry
> > + = servletState.getGadgetServer
> > ().getConfig().getFeatureRegistry();
> > if (registry.getIncludedFeatures(needed, found, missing)) {
> > String containerParam = req.getParameter("c");
> > RenderingContext context;
> > @@ -105,6 +88,8 @@
> >
> > Set<GadgetFeatureRegistry.Entry> done
> > = new HashSet<GadgetFeatureRegistry.Entry>();
> > +
> > + // TODO: This doesn't work correctly under JDK 1.5, but it does
> > under 1.6
> > do {
> > for (GadgetFeatureRegistry.Entry entry : found) {
> > if (!done.contains(entry) &&
> > @@ -145,8 +130,15 @@
> > * @param response The HTTP response
> > */
> > private void setCachingHeaders(HttpServletResponse response) {
> > - response.setHeader("Cache-Control", "public,max-age=2592000");
> > - response.setDateHeader("Expires", System.currentTimeMillis()
> > - + 2592000000L);
> > +
> > + // Most browsers accept this. 2030 is the last round year before
> > + // the end of time.
> > + response.setHeader("Expires", "Tue, 01 Jan 2030 00:00:01 GMT");
> > +
> > + // IE seems to need this (10 years should be enough).
> > + response.setHeader("Cache-Control", "public,max-age=315360000");
> > +
> > + // Firefox requires this for certain cases.
> > + response.setDateHeader("Last-Modified", START_TIME);
> > }
> > }
> >
> > 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=619684&r1=619683&r2=619684&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
> > Thu Feb 7 15:18:30 2008
> > @@ -18,7 +18,6 @@
> > */
> > package org.apache.shindig.gadgets.http;
> >
> > -import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
> > import org.apache.shindig.gadgets.GadgetException;
> > import org.apache.shindig.gadgets.GadgetSigner;
> > import org.apache.shindig.gadgets.GadgetToken;
> > @@ -48,13 +47,9 @@
> > private static final int TWO_HOURS_IN_MS = 7200000;
> > private static final int ONE_HOUR_IN_SECS = 3600;
> > private static final int MAX_PROXY_SIZE = 1024 * 1024;
> > -
> > +
> > private final RemoteContentFetcher fetcher;
> >
> > - public ProxyHandler() {
> > - this(new BasicRemoteContentFetcher(MAX_PROXY_SIZE));
> > - }
> > -
> > public ProxyHandler(RemoteContentFetcher fetcher) {
> > this.fetcher = fetcher;
> > }
> > @@ -203,7 +198,9 @@
> > private GadgetToken extractAndValidateToken(HttpServletRequest
> request,
> > GadgetSigner signer) throws ServletException {
> > try {
> > - if (signer == null) return null;
> > + if (signer == null) {
> > + return null;
> > + }
> > String token = request.getParameter("st");
> > if (token == null) {
> > token = "";
> > @@ -229,7 +226,7 @@
> >
> > /**
> > * Sign a URL with a GadgetToken if needed
> > - * @return
> > + * @return
> > */
> > private URL signUrl(URL originalUrl, GadgetToken token,
> > HttpServletRequest request) throws ServletException {
> > @@ -238,7 +235,7 @@
> > !"signed".equals(request.getParameter("authz"))) {
> > return originalUrl;
> > }
> > - return token.signUrl(originalUrl, "GET", // TODO:
> request.getMethod
> > ()
> > + return token.signUrl(originalUrl, "GET", // TODO:
> request.getMethod
> > ()
> > request.getParameterMap());
> > } catch (GadgetException ge) {
> > throw new ServletException(ge);
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ProxyServlet.java
> > Thu Feb 7 15:18:30 2008
> > @@ -18,28 +18,38 @@
> > */
> > package org.apache.shindig.gadgets.http;
> >
> > -import org.apache.shindig.gadgets.BasicGadgetSigner;
> > -import org.apache.shindig.gadgets.GadgetSigner;
> > +import org.apache.shindig.gadgets.GadgetServerConfigReader;
> >
> > import java.io.IOException;
> >
> > +import javax.servlet.ServletConfig;
> > import javax.servlet.ServletException;
> > import javax.servlet.http.HttpServlet;
> > import javax.servlet.http.HttpServletRequest;
> > import javax.servlet.http.HttpServletResponse;
> >
> > public class ProxyServlet extends HttpServlet {
> > - private final GadgetSigner signer;
> > - private final ProxyHandler handler;
> > + private CrossServletState servletState;
> > + private ProxyHandler proxyHandler;
> > +
> > + @Override
> > + public void init(ServletConfig config) throws ServletException {
> > + servletState = CrossServletState.get(config);
> > + GadgetServerConfigReader serverConfig
> > + = servletState.getGadgetServer().getConfig();
> > + proxyHandler = new ProxyHandler(serverConfig.getContentFetcher());
> > + }
> >
> > @Override
> > protected void doGet(HttpServletRequest request, HttpServletResponse
> > response)
> > throws ServletException, IOException {
> > String output = request.getParameter("output");
> > if ("js".equals(output)) {
> > - handler.fetchJson(request, response, signer);
> > + proxyHandler.fetchJson(
> > + request, response, servletState.getGadgetSigner(request));
> > } else {
> > - handler.fetch(request, response, signer);
> > + proxyHandler.fetch(
> > + request, response, servletState.getGadgetSigner(request));
> > }
> > }
> >
> > @@ -48,22 +58,5 @@
> > throws ServletException, IOException {
> > // Currently they are identical
> > doGet(request, response);
> > - }
> > -
> > - /**
> > - * Constructs a ProxyServlet with the default (non-secure)
> > GadgetSigner.
> > - */
> > - public ProxyServlet() {
> > - this(new BasicGadgetSigner(), new ProxyHandler());
> > - }
> > -
> > - /**
> > - * Creates a ProxyServlet using the specified GadgetSigner.
> > - * @param signer Used to sign and verify requests
> > - * @param handler Used to fetch proxied content
> > - */
> > - public ProxyServlet(GadgetSigner signer, ProxyHandler handler) {
> > - this.signer = signer;
> > - this.handler = handler;
> > }
> > }
> >
> > Added:
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java?rev=619684&view=auto
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> > (added)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcServlet.java
> > Thu Feb 7 15:18:30 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.http;
> > +
> > +import java.io.IOException;
> > +
> > +import javax.servlet.ServletConfig;
> > +import javax.servlet.ServletException;
> > +import javax.servlet.http.HttpServlet;
> > +import javax.servlet.http.HttpServletRequest;
> > +import javax.servlet.http.HttpServletResponse;
> > +
> > +/**
> > + * Handles RPC metadata requests.
> > + */
> > +public class RpcServlet extends HttpServlet {
> > + private CrossServletState state;
> > +
> > + @Override
> > + protected void doGet(HttpServletRequest request, HttpServletResponse
> > response)
> > + throws ServletException, IOException {
> > + }
> > +
> > + @Override
> > + public void init(ServletConfig config) throws ServletException {
> > + state = CrossServletState.get(config);
> > + }
> > +
> > + public RpcServlet() {
> > + }
> > +}
> >
> > Modified:
> > incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > --- incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> > (original)
> > +++ incubator/shindig/trunk/java/gadgets/src/main/webapp/WEB-INF/web.xml
> > Thu Feb 7 15:18:30 2008
> > @@ -19,48 +19,63 @@
> > "http://java.sun.com/dtd/web-app_2_3.dtd">
> >
> > <web-app>
> > - <!-- configuration -->
> > - <context-param>
> > - <param-name>features</param-name>
> > - <param-value>res://features/features.txt</param-value>
> > - </context-param>
> > -
> > - <!-- Render a Gadget -->
> > - <servlet>
> > - <servlet-name>xml-to-html</servlet-name>
> > - <servlet-class>
> > - org.apache.shindig.gadgets.http.GadgetRenderingServlet
> > - </servlet-class>
> > - </servlet>
> > -
> > - <!-- Proxy -->
> > - <servlet>
> > - <servlet-name>proxy</servlet-name>
> > - <servlet-class>
> > - org.apache.shindig.gadgets.http.ProxyServlet
> > - </servlet-class>
> > - </servlet>
> > -
> > -
> > - <!-- javascript serving -->
> > - <servlet>
> > - <servlet-name>js</servlet-name>
> > - <servlet-class>org.apache.shindig.gadgets.http.JsServlet
> > </servlet-class>
> > - </servlet>
> > -
> > - <servlet-mapping>
> > - <servlet-name>js</servlet-name>
> > - <url-pattern>/js/*</url-pattern>
> > - </servlet-mapping>
> > -
> > - <servlet-mapping>
> > - <servlet-name>proxy</servlet-name>
> > - <url-pattern>/proxy</url-pattern>
> > - </servlet-mapping>
> > -
> > - <servlet-mapping>
> > - <servlet-name>xml-to-html</servlet-name>
> > - <url-pattern>/ifr</url-pattern>
> > - </servlet-mapping>
> > -
> > + <!-- configuration -->
> > + <context-param>
> > + <param-name>features</param-name>
> > + <param-value>res://features/features.txt</param-value>
> > + </context-param>
> > + <context-param>
> > + <param-name>servlet-data-class</param-name>
> > + <param-value>
> org.apache.shindig.gadgets.http.DefaultCrossServletState
> > </param-value>
> > + </context-param>
> > +
> > + <!-- Render a Gadget -->
> > + <servlet>
> > + <servlet-name>xml-to-html</servlet-name>
> > + <servlet-class>
> > + org.apache.shindig.gadgets.http.GadgetRenderingServlet
> > + </servlet-class>
> > + </servlet>
> > +
> > + <!-- Proxy -->
> > + <servlet>
> > + <servlet-name>proxy</servlet-name>
> > + <servlet-class>
> > + org.apache.shindig.gadgets.http.ProxyServlet
> > + </servlet-class>
> > + </servlet>
> > +
> > + <!-- Metadata RPC -->
> > + <servlet>
> > + <servlet-name>rpc</servlet-name>
> > + <servlet-class>
> > + org.apache.shindig.gadgets.http.RpcServlet
> > + </servlet-class>
> > + </servlet>
> > +
> > + <!-- javascript serving -->
> > + <servlet>
> > + <servlet-name>js</servlet-name>
> > + <servlet-class>org.apache.shindig.gadgets.http.JsServlet
> > </servlet-class>
> > + </servlet>
> > +
> > + <servlet-mapping>
> > + <servlet-name>js</servlet-name>
> > + <url-pattern>/js/*</url-pattern>
> > + </servlet-mapping>
> > +
> > + <servlet-mapping>
> > + <servlet-name>proxy</servlet-name>
> > + <url-pattern>/proxy</url-pattern>
> > + </servlet-mapping>
> > +
> > + <servlet-mapping>
> > + <servlet-name>xml-to-html</servlet-name>
> > + <url-pattern>/ifr</url-pattern>
> > + </servlet-mapping>
> > +
> > + <servlet-mapping>
> > + <servlet-name>rpc</servlet-name>
> > + <url-pattern>/rpc</url-pattern>
> > + </servlet-mapping>
> > </web-app>
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java?rev=619684&r1=619683&r2=619684&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetServerTest.java
> > Thu Feb 7 15:18:30 2008
> > @@ -27,29 +27,48 @@
> > import static org.easymock.EasyMock.expect;
> > import static org.easymock.EasyMock.isA;
> >
> > -import java.util.concurrent.Executor;
> > import java.util.concurrent.Executors;
> >
> > public class GadgetServerTest extends EasyMockTestCase {
> > - final Executor executor = Executors.newCachedThreadPool();
> > - final GadgetServer gadgetServer;
> > + GadgetServer gadgetServer;
> > final RemoteContentFetcher fetcher = mock(RemoteContentFetcher.class);
> > @SuppressWarnings(value="unchecked")
> > final GadgetDataCache<GadgetSpec> specCache = mock(
> GadgetDataCache.class
> > );
> > @SuppressWarnings(value="unchecked")
> > final GadgetDataCache<MessageBundle> bundleCache = mock(
> > GadgetDataCache.class);
> >
> > - public GadgetServerTest() throws GadgetException {
> > - // TODO: need to test for configuration errors.
> > - gadgetServer = new GadgetServer(new GadgetServerConfig()
> > - .setExecutor(executor)
> > - .setSpecCache(specCache)
> > - .setMessageBundleCache(bundleCache)
> > - .setFeatureRegistry(new GadgetFeatureRegistry(null))
> > - .setContentFetcher(fetcher));
> > + void initServer(GadgetServerConfigReader customConfig) throws
> > GadgetException {
> > + GadgetServerConfig config = new GadgetServerConfig();
> > +
> > + if (customConfig != null) {
> > + config.copyFrom(customConfig);
> > + }
> > +
> > + if (config.getExecutor() == null) {
> > + config.setExecutor(Executors.newCachedThreadPool());
> > + }
> > +
> > + if (config.getSpecCache() == null) {
> > + config.setSpecCache(specCache);
> > + }
> > +
> > + if (config.getMessageBundleCache() == null) {
> > + config.setMessageBundleCache(bundleCache);
> > + }
> > +
> > + if (config.getFeatureRegistry() == null) {
> > + config.setFeatureRegistry(new GadgetFeatureRegistry(null));
> > + }
> > +
> > + if (config.getContentFetcher() == null) {
> > + config.setContentFetcher(fetcher);
> > + }
> > +
> > + gadgetServer = new GadgetServer(config);
> > }
> >
> > public void testGadgetSpecNotInCache() throws Exception {
> > + initServer(null);
> > RemoteContent results = new RemoteContent(200,
> > DATETIME_XML.getBytes(), null);
> > ProcessingOptions options = new ProcessingOptions();
> >
> > @@ -65,6 +84,7 @@
> > }
> >
> > public void testGadgetSpecInCache() throws Exception {
> > + initServer(null);
> > expect(specCache.get
> > (eq(DATETIME_URI_STRING))).andReturn(DATETIME_SPEC);
> > replay();
> >
> > @@ -75,6 +95,7 @@
> > }
> >
> > public void testBasicGadget() throws Exception {
> > + initServer(null);
> > RemoteContent results = new RemoteContent(200,
> > DATETIME_XML.getBytes(), null);
> > ProcessingOptions options = new ProcessingOptions();
> >
> > @@ -93,8 +114,7 @@
> >
> > public void testBlacklistedGadget() throws Exception {
> > GadgetBlacklist blacklist = mock(GadgetBlacklist.class);
> > - gadgetServer.setGadgetBlacklist(blacklist);
> > -
> > + initServer(new GadgetServerConfig().setGadgetBlacklist(blacklist));
> > expect(specCache.get(eq(DATETIME_URI_STRING))).andReturn(null);
> > expect(blacklist.isBlacklisted(eq(DATETIME_URI))).andReturn(true);
> > replay();
> >
> >
> >
>