You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2008/02/08 00:18:34 UTC
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/src/te...
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();