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/18 23:56:20 UTC

svn commit: r628908 [2/2] - in /incubator/shindig/trunk: config/ features/ features/core.io/ features/core/ features/dynamic-height/ features/rpc/ features/setprefs/ features/settitle/ features/views/ java/gadgets/ java/gadgets/src/main/java/org/apache...

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/OpenSocialFeatureFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/OpenSocialFeatureFactory.java?rev=628908&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/OpenSocialFeatureFactory.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/OpenSocialFeatureFactory.java Mon Feb 18 14:56:14 2008
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shindig.gadgets;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implements the opensocial-0.6 and 0.7 features
+ * DO NOT EMULATE THIS BEHAVIOR. This is a kludge to work around the need
+ * for every open social container to have their own javascript file.
+ */
+public class OpenSocialFeatureFactory extends JsLibraryFeatureFactory {
+  private final OpenSocialFeature feature;
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public GadgetFeature create() {
+    return feature;
+  }
+
+  /**
+   * Registers the opensocial feature to the given registry.
+   *
+   * This expects that syndicators are configured with an
+   * "opensocial.0.7.location" parameter that points to the location of their
+   * open social file.
+   *
+   * @param registry
+   * @param config
+   */
+  public static void register(GadgetFeatureRegistry registry,
+                              SyndicatorConfig config) {
+    Map<String, List<JsLibrary>> libs = new HashMap<String, List<JsLibrary>>();
+    for (String syndicator : config.getSyndicators()) {
+      String js = config.get(syndicator, "opensocial.0.7.location");
+      if (js != null && js != "null") {
+        JsLibrary.Type type;
+        String content;
+        if (js.startsWith("http://")) {
+          type = JsLibrary.Type.URL;
+          content = js;
+        } else if (js.startsWith("//")) {
+          type = JsLibrary.Type.URL;
+          content = js.substring(1);
+        } else if (js.startsWith("res://")) {
+          type = JsLibrary.Type.RESOURCE;
+          content = js.substring(6);
+        } else {
+          // Assume a resource path; inline js isn't allowed.
+          type = JsLibrary.Type.RESOURCE;
+          content = js;
+        }
+        JsLibrary lib = JsLibrary.create(type, content);
+        libs.put(syndicator, Arrays.asList(lib));
+      }
+    }
+
+    // Only register if we have at least one registered syndicator with the
+    // feature.
+    if (libs.size() > 0) {
+      OpenSocialFeature newFeature = new OpenSocialFeature(libs);
+      registry.register("opensocial-0.7",
+                        Arrays.asList("opensocial-reference"),
+                        new OpenSocialFeatureFactory(newFeature));
+    }
+  }
+
+  private OpenSocialFeatureFactory(OpenSocialFeature feature) {
+    this.feature = feature;
+  }
+}
+
+class OpenSocialFeature extends GadgetFeature {
+  final Map<String, List<JsLibrary>> libs;
+
+  /**
+   * @param context
+   * @return A list of all JS libraries used by this feature
+   */
+  @Override
+  public List<JsLibrary> getJsLibraries(RenderingContext context,
+                                        ProcessingOptions options) {
+    if (context == RenderingContext.GADGET && options != null) {
+      String synd = options.getSyndicator();
+      List<JsLibrary> libraries = libs.get(synd);
+      if (libraries != null) {
+        return libraries;
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void process(Gadget gadget, GadgetContext context,
+                      Map<String, String> params) {
+    ProcessingOptions options = context.getOptions();
+    String synd = options.getSyndicator();
+    List<JsLibrary> libraries = libs.get(synd);
+    if (libraries != null) {
+      for (JsLibrary library : libraries) {
+        gadget.addJsLibrary(library);
+      }
+    }
+  }
+
+  /**
+   * @param libs Maps syndicator to libs files. Only gadget-side since
+   *   currently there is no container side OS code.
+   */
+  public OpenSocialFeature(Map<String, List<JsLibrary>> libs) {
+    this.libs = libs;
+  }
+}

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ProcessingOptions.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ProcessingOptions.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ProcessingOptions.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ProcessingOptions.java Mon Feb 18 14:56:14 2008
@@ -45,4 +45,11 @@
   public String getForcedJsLibs() {
     return null;
   }
+
+  /**
+   * @return The syndicator of the current request.
+   */
+  public String getSyndicator() {
+    return SyndicatorConfig.DEFAULT_SYNDICATOR;
+  }
 }

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java?rev=628908&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SyndicatorConfig.java Mon Feb 18 14:56:14 2008
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shindig.gadgets;
+
+import org.apache.shindig.util.ResourceLoader;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Represents per-syndicator configuration for the contianer.
+ *
+ * See config/default-syndicator.js for an example configuration.
+ *
+ * We use a cascading model, so you only have to specify attributes in
+ * your config that you actually want to change.
+ */
+public class SyndicatorConfig {
+  public static final SyndicatorConfig EMPTY = new SyndicatorConfig();
+  private final Map<String, JSONObject> config;
+  public static final String SYNDICATOR_FILE_NAME = "syndicator.js";
+  public static final String DEFAULT_SYNDICATOR = "default";
+  public static final String SYNDICATOR_KEY = "gadgets.syndicator";
+  private static final Logger logger
+      = Logger.getLogger("org.apache.shindig.gadgets");
+
+  /**
+   * @return The set of all syndicators that are currently registered.
+   */
+  public Set<String> getSyndicators() {
+    return Collections.unmodifiableSet(config.keySet());
+  }
+
+  /**
+   * Attempts to fetch a parameter for the given syndicator, or the default
+   * syndicator if the specified syndicator is not supported.
+   *
+   * @param syndicator
+   * @param parameter
+   * @return A configuration parameter as a string, or null if not set.
+   */
+  public String get(String syndicator, String parameter) {
+    JSONObject syndicatorData = config.get(syndicator);
+    if (syndicatorData == null) {
+      return null;
+    }
+    Object value = syndicatorData.opt(parameter);
+    return value == null ? null : value.toString();
+  }
+
+  /**
+   * Fetches a configuration parameter as a JSON object, array, string, or
+   * number, ensuring that it can be safely passed to javascript without any
+   * additional filtering.
+   *
+   * @param syndicator
+   * @param parameter
+   * @return A configuration parameter as a JSON object or null if not set or
+   *     can't be interpreted as JSON.
+   */
+  public Object getJson(String syndicator, String parameter) {
+    JSONObject syndicatorData = config.get(syndicator);
+    if (syndicatorData == null) {
+      return null;
+    }
+    return syndicatorData.opt(parameter);
+  }
+
+  /**
+   * @param syndicator
+   * @param parameter
+   * @return A configuration parameter as a JSON object or null if not set or
+   *     can't be interpreted as JSON.
+   */
+  public JSONObject getJsonObject(String syndicator, String parameter) {
+    JSONObject syndicatorData = config.get(syndicator);
+    if (syndicatorData == null) {
+      return null;
+    }
+    return syndicatorData.optJSONObject(parameter);
+  }
+
+  /**
+   * @param syndicator
+   * @param parameter
+   * @return A configuration parameter as a JSON object or null if not set or
+   *     can't be interpreted as JSON.
+   */
+  public JSONArray getJsonArray(String syndicator, String parameter) {
+    JSONObject syndicatorData = config.get(syndicator);
+    if (syndicatorData == null) {
+      return null;
+    }
+    return syndicatorData.optJSONArray(parameter);
+  }
+
+  /**
+   * Loads syndicators from directories recursively.
+   * @param files The files to examine.
+   * @throws GadgetException
+   */
+  private void loadFiles(File[] files) throws GadgetException {
+    try {
+      for (File file : files) {
+        if (file.isDirectory()) {
+          loadFiles(file.listFiles());
+        } else if (SYNDICATOR_FILE_NAME.equals(file.getName())) {
+          loadFromString(ResourceLoader.getContent(file));
+        }
+      }
+    } catch (IOException e) {
+      throw new GadgetException(GadgetException.Code.INVALID_PATH, e);
+    }
+  }
+
+  /**
+   * Loads resources recursively.
+   * @param files The base paths to look for syndicator.xml
+   * @throws GadgetException
+   */
+  private void loadResources(String[] files)  throws GadgetException {
+    try {
+      Map<String, String> contents
+          = ResourceLoader.getContent(files, SYNDICATOR_FILE_NAME);
+      for (String entry : contents.values()) {
+        loadFromString(entry);
+      }
+    } catch (IOException e) {
+      throw new GadgetException(GadgetException.Code.INVALID_PATH, e);
+    }
+  }
+
+  /**
+   * Merges two JSON objects together (recursively), with values from "merge"
+   * replacing values from "base".
+   *
+   * @param base
+   * @param merge
+   * @return The merged object.
+   * @throws JSONException if the two objects can't be merged for some reason.
+   */
+  private JSONObject mergeObjects(JSONObject base, JSONObject merge)
+      throws JSONException {
+    // Clone the initial object (JSONObject doesn't support "clone").
+    JSONObject clone = new JSONObject(base, JSONObject.getNames(base));
+    // Walk parameter list for the merged object and merge recursively.
+    String[] fields = JSONObject.getNames(merge);
+    for (String field : fields) {
+      Object existing = clone.opt(field);
+      Object update = merge.get(field);
+      if (existing == null) {
+        // It's new custom config, not referenced in the prototype.
+        clone.put(field, update);
+      } else {
+        // Merge if object type is JSONObject.
+        if (update instanceof JSONObject &&
+            existing instanceof JSONObject) {
+          clone.put(field, mergeObjects((JSONObject)existing,
+                                        (JSONObject)update));
+        } else {
+          // Otherwise we just overwrite it.
+          clone.put(field, update);
+        }
+      }
+    }
+    return clone;
+  }
+
+  /**
+   * Processes a syndicator file.
+   * @param json
+   */
+  public void loadFromString(String json) throws GadgetException {
+    try {
+      JSONObject contents = new JSONObject(json);
+      JSONArray syndicators = contents.getJSONArray(SYNDICATOR_KEY);
+      if (syndicators.length() == 1 &&
+          DEFAULT_SYNDICATOR.equals(syndicators.get(0).toString())) {
+        config.put(DEFAULT_SYNDICATOR, contents);
+        return;
+      } else {
+        JSONObject defaultSynd = config.get(DEFAULT_SYNDICATOR);
+        if (defaultSynd == null) {
+          throw new GadgetException(GadgetException.Code.INVALID_CONFIG,
+                                    "No default config registered");
+        }
+        for (int i = 0, j = syndicators.length(); i < j; ++i) {
+          // Copy the default object and produce a new one.
+          String syndicator = syndicators.get(i).toString();
+          config.put(syndicator, mergeObjects(defaultSynd, contents));
+        }
+      }
+    } catch (JSONException e) {
+      throw new GadgetException(GadgetException.Code.INVALID_CONFIG, e);
+    }
+  }
+
+  /**
+   * Loads syndicators from the specified resource. Follows the same rules
+   * as {@code JsFeatureLoader.loadFeatures} for locating resources.
+   * This call is not thread safe, so you should only call loadSyndicators()
+   * from within the GadgetServerConfig.
+   *
+   * @param path
+   */
+  public void loadSyndicators(String path) throws GadgetException {
+    try {
+      if (path.startsWith("res://")) {
+        path = path.substring(6);
+        logger.info("Loading resources from: " + path);
+        if (path.endsWith(".txt")) {
+          loadResources(ResourceLoader.getContent(path).split("\n"));
+        } else {
+          loadResources(new String[]{path});
+        }
+      } else {
+        logger.info("Loading files from: " + path);
+        File file = new File(path);
+        loadFiles(new File[]{file});
+      }
+    } catch (IOException e) {
+      throw new GadgetException(GadgetException.Code.INVALID_PATH, e);
+    }
+  }
+
+  /**
+   * Creates a new, empty configuration.
+   *
+   * @param defaultSyndicator The default syndicators to load.
+   */
+  public SyndicatorConfig(String defaultSyndicator) throws GadgetException {
+    config = new HashMap<String, JSONObject>();
+    if (defaultSyndicator != null) {
+      loadSyndicators(defaultSyndicator);
+    }
+  }
+
+  /**
+   * Creates an unmodifiable configuration.
+   */
+  private SyndicatorConfig() {
+    config = Collections.emptyMap();
+  }
+}

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/UserPrefSubstituter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/UserPrefSubstituter.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/UserPrefSubstituter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/UserPrefSubstituter.java Mon Feb 18 14:56:14 2008
@@ -26,7 +26,7 @@
  * Substitutes user prefs into the spec.
  */
 public class UserPrefSubstituter implements GadgetFeatureFactory {
-  private final static UserPrefSubstituterFeature feature
+  private final static GadgetFeature feature
       = new UserPrefSubstituterFeature();
 
   /**
@@ -37,20 +37,15 @@
   }
 }
 
-class UserPrefSubstituterFeature implements GadgetFeature {
-
-  /**
-   * {@inheritDoc}
-   */
-  public void prepare(GadgetView gadget, GadgetContext context,
-                      Map<String, String> params) {
-  }
+class UserPrefSubstituterFeature extends GadgetFeature {
 
   /**
    * {@inheritDoc}
    */
+  @Override
   public void process(Gadget gadget, GadgetContext context,
-                      Map<String, String> params) {
+                      Map<String, String> params) throws GadgetException {
+    super.process(gadget, context, params);
     Substitutions substitutions = gadget.getSubstitutions();
     UserPrefs upValues = gadget.getUserPrefValues();
 

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultCrossServletState.java Mon Feb 18 14:56:14 2008
@@ -24,6 +24,7 @@
 import org.apache.shindig.gadgets.BasicRemoteContentFetcher;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.GadgetFeature;
 import org.apache.shindig.gadgets.GadgetFeatureFactory;
 import org.apache.shindig.gadgets.GadgetFeatureRegistry;
 import org.apache.shindig.gadgets.GadgetServer;
@@ -31,9 +32,10 @@
 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.OpenSocialFeatureFactory;
 import org.apache.shindig.gadgets.RenderingContext;
+import org.apache.shindig.gadgets.SyndicatorConfig;
 import org.apache.shindig.gadgets.UserPrefs;
 
 import java.io.UnsupportedEncodingException;
@@ -163,15 +165,23 @@
 
     // features could be null, but that would probably be a bad idea.
     String features = context.getInitParameter("features");
+    String syndicators = context.getInitParameter("syndicators");
     try {
       gadgetSigner = new BasicGadgetSigner();
+      SyndicatorConfig syndicatorConfig = new SyndicatorConfig(syndicators);
       GadgetFeatureRegistry registry = new GadgetFeatureRegistry(features);
+
+      // We'll add the opensocial-0.7 feature manually for now.
+      // TODO: Something better than this ugly hack.
+      OpenSocialFeatureFactory.register(registry, syndicatorConfig);
+
       GadgetServerConfig config =  new GadgetServerConfig()
           .setExecutor(Executors.newCachedThreadPool())
           .setMessageBundleCache(new BasicGadgetDataCache<MessageBundle>())
           .setSpecCache(new BasicGadgetDataCache<GadgetSpec>())
           .setContentFetcher(new BasicRemoteContentFetcher(1024 * 1024))
-          .setFeatureRegistry(registry);
+          .setFeatureRegistry(registry)
+          .setSyndicatorConfig(syndicatorConfig);
       gadgetServer = new GadgetServer(config);
 
       // Grab all static javascript, concatenate it together, and generate
@@ -181,12 +191,10 @@
       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());
-            }
+        GadgetFeature feature = factory.create();
+        for (RenderingContext rc : RenderingContext.values()) {
+          for (JsLibrary library : feature.getJsLibraries(rc, null)) {
+            jsBuf.append(library.getContent());
           }
         }
       }

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=628908&r1=628907&r2=628908&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 Mon Feb 18 14:56:14 2008
@@ -21,20 +21,27 @@
 import org.apache.shindig.gadgets.GadgetContentFilter;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.GadgetServer;
+import org.apache.shindig.gadgets.GadgetServerConfigReader;
 import org.apache.shindig.gadgets.GadgetSpec;
 import org.apache.shindig.gadgets.GadgetView;
 import org.apache.shindig.gadgets.JsLibrary;
 import org.apache.shindig.gadgets.ProcessingOptions;
 import org.apache.shindig.gadgets.RenderingContext;
+import org.apache.shindig.gadgets.SyndicatorConfig;
 import org.apache.shindig.gadgets.UserPrefs;
+import org.apache.shindig.gadgets.GadgetFeatureRegistry.Entry;
+import org.json.JSONException;
+import org.json.JSONObject;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -195,9 +202,17 @@
 
     // Forced libs first.
 
+    Set<String> reqs;
+
     if (forcedLibs != null) {
       String[] libs = forcedLibs.split(":");
+      reqs = new HashSet<String>();
+      for (String l : libs) {
+        reqs.add(l);
+      }
       markup.append(String.format(externFmt, servletState.getJsUrl(libs)));
+    } else {
+      reqs = gadget.getRequires().keySet();
     }
 
     if (inlineJs.length() > 0) {
@@ -207,6 +222,45 @@
 
     if (externJs.length() > 0) {
       markup.append(externJs);
+    }
+
+    // One more thing -- we have to output the gadgets js config.
+    // config *should* be handled by a feature, but unfortunately there's
+    // no way to make this feature always be the last item in the output.
+    // oh well.
+
+    GadgetServerConfigReader serverConfig
+        = servletState.getGadgetServer().getConfig();
+    SyndicatorConfig syndConf = serverConfig.getSyndicatorConfig();
+    JSONObject syndFeatures = syndConf.getJsonObject(options.getSyndicator(),
+                                                     "gadgets.features");
+
+    if (syndFeatures != null) {
+      // now we just want configuration for the features that we actually use.
+      // TODO: this is too much manual work, and we should probably just
+      // modify the gadget object to keep the list of transitive dependencies
+      Set<Entry> found = new HashSet<Entry>();
+
+      // Nothing can ever be missing at this point since that would have
+      // thrown an exception already.
+      Set<String> empty = Collections.emptySet();
+      serverConfig.getFeatureRegistry().getIncludedFeatures(reqs, found, empty);
+
+      Set<String> features = new HashSet<String>(found.size());
+      for (Entry entry : found) {
+        features.add(entry.getName());
+      }
+      String[] featArray = features.toArray(new String[features.size()]);
+
+      try {
+        JSONObject featureConfig = new JSONObject(syndFeatures, featArray);
+        markup.append("<script><!--\ngadgets.config.init(")
+              .append(featureConfig.toString())
+              .append(");\n-->\n</script>");
+      } catch (JSONException e) {
+        // shouldn't ever happen since we've already validated our JSON output.
+        throw new RuntimeException(e);
+      }
     }
 
     List<GadgetException> gadgetExceptions = new LinkedList<GadgetException>();

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpProcessingOptions.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpProcessingOptions.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpProcessingOptions.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpProcessingOptions.java Mon Feb 18 14:56:14 2008
@@ -29,10 +29,12 @@
 public class HttpProcessingOptions extends ProcessingOptions {
   private final boolean ignoreCache;
   private final String forceJsLibs;
+  private final String syndicator;
 
   public HttpProcessingOptions(HttpServletRequest req) {
     ignoreCache = getIgnoreCache(req);
     forceJsLibs = getForceJsLibs(req);
+    syndicator = getSyndicator(req);
   }
 
   /** {@inheritDoc} */
@@ -47,6 +49,15 @@
     return ignoreCache;
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public String getSyndicator() {
+    if (syndicator == null) {
+      return super.getSyndicator();
+    }
+    return syndicator;
+  }
+
   /**
    * @param req
    * @return Whether or not to ignore the cache.
@@ -65,5 +76,13 @@
    */
   protected static String getForceJsLibs(HttpServletRequest req) {
     return req.getParameter("libs");
+  }
+
+  /**
+   * @param req
+   * @return Forced JS libs, or null if no forcing is to be done.
+   */
+  protected static String getSyndicator(HttpServletRequest req) {
+    return req.getParameter("syndicator");
   }
 }

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=628908&r1=628907&r2=628908&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 Mon Feb 18 14:56:14 2008
@@ -17,10 +17,11 @@
  */
 package org.apache.shindig.gadgets.http;
 
+import org.apache.shindig.gadgets.GadgetFeature;
 import org.apache.shindig.gadgets.GadgetFeatureFactory;
 import org.apache.shindig.gadgets.GadgetFeatureRegistry;
 import org.apache.shindig.gadgets.JsLibrary;
-import org.apache.shindig.gadgets.JsLibraryFeatureFactory;
+import org.apache.shindig.gadgets.ProcessingOptions;
 import org.apache.shindig.gadgets.RenderingContext;
 
 import java.io.IOException;
@@ -57,6 +58,7 @@
       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
@@ -93,19 +95,19 @@
       Set<GadgetFeatureRegistry.Entry> done
           = new HashSet<GadgetFeatureRegistry.Entry>();
 
+      ProcessingOptions opts = new HttpProcessingOptions(req);
+
       // 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) &&
               done.containsAll(entry.getDependencies())) {
-            GadgetFeatureFactory feature = entry.getFeature();
-            if (feature instanceof JsLibraryFeatureFactory) {
-              JsLibraryFeatureFactory jsLib = (JsLibraryFeatureFactory)feature;
-              for (JsLibrary lib : jsLib.getLibraries(context)) {
-                // TODO: type url js files fail here.
-                if (lib.getType() != JsLibrary.Type.URL) {
-                  jsData.append(lib.getContent());
-                }
+            GadgetFeatureFactory factory = entry.getFeature();
+            GadgetFeature feature = factory.create();
+            for (JsLibrary lib : feature.getJsLibraries(context, opts)) {
+              // TODO: type url js files fail here.
+              if (lib.getType() != JsLibrary.Type.URL) {
+                jsData.append(lib.getContent());
               }
             }
             done.add(entry);

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcGadgetJob.java Mon Feb 18 14:56:14 2008
@@ -55,9 +55,9 @@
                                         RenderingContext.CONTAINER,
                                         new JsonRpcProcessingOptions(context));
     } catch (URISyntaxException e) {
-      throw new RpcException("Bad url");
+      throw new RpcException(gadget, "Bad url");
     } catch (GadgetServer.GadgetProcessException e) {
-      throw new RpcException("Failed to process gadget.", e);
+      throw new RpcException(gadget, e);
     }
   }
 

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/JsonRpcRequest.java Mon Feb 18 14:56:14 2008
@@ -99,23 +99,27 @@
         out.append("gadgets", gadgetJson);
       } catch (InterruptedException e) {
         throw new RpcException("Incomplete processing", e);
-      } catch (ExecutionException e) {
-        throw new RpcException("Incomplete processing", e);
-      } catch (RuntimeException rte) {
-        if (!(rte.getCause() instanceof RpcException)) {
-          throw rte;
+      } catch (ExecutionException ee) {
+        if (!(ee.getCause() instanceof RpcException)) {
+          throw new RpcException("Incomplete processing", ee);
         }
-        RpcException e = (RpcException)rte.getCause();
+        RpcException e = (RpcException)ee.getCause();
         // Just one gadget failed; mark it as such.
         try {
+          JsonRpcGadget gadget = e.getGadget();
+
+          if (gadget == null) {
+            throw e;
+          }
+
           JSONObject errorObj = new JSONObject();
-          errorObj.put("url", e.getGadget().getUrl())
-                  .put("moduleId", e.getGadget().getModuleId());
+          errorObj.put("url", gadget.getUrl())
+                  .put("moduleId", gadget.getModuleId());
           if (e.getCause() instanceof GadgetServer.GadgetProcessException) {
             GadgetServer.GadgetProcessException gpe
                 = (GadgetServer.GadgetProcessException)e.getCause();
             for (GadgetException ge : gpe.getComponents()) {
-              errorObj.append("errors", e.getMessage());
+              errorObj.append("errors", ge.getMessage());
             }
           } else {
             errorObj.append("errors", e.getMessage());

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcException.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcException.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcException.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/RpcException.java Mon Feb 18 14:56:14 2008
@@ -43,4 +43,14 @@
     super(cause);
     this.gadget = gadget;
   }
+
+  public RpcException(JsonRpcGadget gadget, String message) {
+    super(message);
+    this.gadget = gadget;
+  }
+
+  public RpcException(JsonRpcGadget gadget, String message, Throwable cause) {
+    super(message, cause);
+    this.gadget = gadget;
+  }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/InputStreamConsumer.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/InputStreamConsumer.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/InputStreamConsumer.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/InputStreamConsumer.java Mon Feb 18 14:56:14 2008
@@ -82,9 +82,8 @@
    */
   public static String readToString(InputStream is, int maxBytes)
       throws IOException {
-    byte[] bytes = readToByteArray(is, maxBytes);
     try {
-      return new String(bytes, "UTF-8");
+      return new String(readToByteArray(is, maxBytes), "UTF-8");
     } catch (UnsupportedEncodingException e) {
       // UTF-8 is required by the Java spec.
       throw new RuntimeException("UTF-8 not supported!", e);

Added: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/ResourceLoader.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/ResourceLoader.java?rev=628908&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/ResourceLoader.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/util/ResourceLoader.java Mon Feb 18 14:56:14 2008
@@ -0,0 +1,127 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Logger;
+
+/**
+ * Handles loading contents from resource and file system files.
+ */
+public class ResourceLoader {
+
+  private static final Logger logger
+    = Logger.getLogger("org.apache.shindig.util");
+
+  /**
+   * Reads the contents of a resource as a string.
+   *
+   * @param resource
+   * @return Contents of the resource.
+   * @throws IOException
+   */
+  public static String getContent(String resource)
+      throws IOException, FileNotFoundException {
+    ClassLoader cl = ResourceLoader.class.getClassLoader();
+    InputStream is = cl.getResourceAsStream(resource);
+    if (is == null) {
+      throw new FileNotFoundException("Can not locate resource: " + resource);
+    }
+
+    return InputStreamConsumer.readToString(is);
+  }
+
+  /**
+   * Loads resources recursively and returns the contents of all matching
+   * files.
+   *
+   * @param paths The base paths to look for the desired files.
+   * @param file The name of the files to actually return content for.
+   * @return A map of file paths to their contents.
+   *
+   * @throws IOException
+   */
+  public static Map<String, String> getContent(String[] paths, String file)
+      throws IOException {
+    ClassLoader cl = ResourceLoader.class.getClassLoader();
+    Map<String, String> out = new HashMap<String, String>();
+
+    for (String path : paths) {
+      logger.info("Looking for " + file + " in " + path);
+      Enumeration<URL> mappedResources = cl.getResources(path);
+      while (mappedResources.hasMoreElements()) {
+        URL resourceUrl =  mappedResources.nextElement();
+        if ("file".equals(resourceUrl.getProtocol())) {
+          try {
+            File f = new File(resourceUrl.toURI());
+            out.put(path, getContent(f));
+          } catch (URISyntaxException e) {
+            logger.warning("Unable to load file " + resourceUrl.toString());
+          }
+        } else {
+          URLConnection urlConnection = resourceUrl.openConnection();
+          List<String> fullPaths = new LinkedList<String>();
+          if (urlConnection instanceof JarURLConnection) {
+            JarURLConnection jarUrlConn = (JarURLConnection)urlConnection;
+            JarFile jar = jarUrlConn.getJarFile();
+
+            Enumeration<JarEntry> jarEntries = jar.entries();
+            while (jarEntries.hasMoreElements()) {
+              JarEntry jarEntry =  jarEntries.nextElement();
+              if (jarEntry.getName().startsWith(path) &&
+                  jarEntry.getName().endsWith(file)) {
+                fullPaths.add(jarEntry.getName());
+              }
+            }
+          }
+          for (String res : fullPaths) {
+            out.put(res, getContent(res));
+          }
+        }
+      }
+    }
+    return Collections.unmodifiableMap(out);
+  }
+
+  /**
+   * @param file
+   * @return The contents of the file (assumed to be UTF-8).
+   * @throws IOException
+   */
+  public static String getContent(File file) throws IOException {
+    return InputStreamConsumer.readToString(new FileInputStream(file));
+  }
+}

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=628908&r1=628907&r2=628908&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 Mon Feb 18 14:56:14 2008
@@ -28,6 +28,10 @@
     <param-value>res://features/features.txt</param-value>
   </context-param>
   <context-param>
+    <param-name>syndicators</param-name>
+    <param-value>res://syndicators/default/syndicator.js</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>

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetSpecTestFixture.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetSpecTestFixture.java?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetSpecTestFixture.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetSpecTestFixture.java Mon Feb 18 14:56:14 2008
@@ -34,15 +34,17 @@
   private static final String DATETIME_TITLE = "Hello, World!";
   private static final String DATETIME_CONTENT = "Goodbye, World!";
 
-  public static final String DATETIME_URI_STRING = "http://www.google.com/ig/modules/datetime.xml";
+  public static final String DATETIME_URI_STRING
+      = "http://www.google.com/ig/modules/datetime.xml";
   public static final URI DATETIME_URI;
   public static final int DATETIME_MODULE_ID = 1;
   public static final GadgetView.ID DATETIME_ID;
-  public static final String DATETIME_XML = "<?xml version=\"1.0\"?>" +
-                                     "<Module>" +
-                                     "  <ModulePrefs title=\"" + DATETIME_TITLE + "\"/>" +
-                                     "  <Content type=\"html\">" + DATETIME_CONTENT + "</Content>" +
-                                     "</Module>";
+  public static final String DATETIME_XML
+      = "<?xml version=\"1.0\"?>" +
+        "<Module>" +
+        "  <ModulePrefs title=\"" + DATETIME_TITLE + "\"/>" +
+        "  <Content type=\"html\">" + DATETIME_CONTENT + "</Content>" +
+        "</Module>";
 
   public static final GadgetSpec DATETIME_SPEC =
       new GadgetSpec() {

Added: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SyndicatorConfigTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SyndicatorConfigTest.java?rev=628908&view=auto
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SyndicatorConfigTest.java (added)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SyndicatorConfigTest.java Mon Feb 18 14:56:14 2008
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shindig.gadgets;
+
+import static org.apache.shindig.gadgets.SyndicatorConfig.DEFAULT_SYNDICATOR;
+import static org.apache.shindig.gadgets.SyndicatorConfig.SYNDICATOR_KEY;
+
+import junit.framework.TestCase;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ *
+ */
+public class SyndicatorConfigTest extends TestCase {
+  private SyndicatorConfig config;
+
+  private static final String TOP_LEVEL_NAME = "Top level name";
+  private static final String TOP_LEVEL_VALUE = "Top level value";
+
+  private static final String NESTED_KEY = "ne$ted";
+  private static final String NESTED_NAME = "Nested name";
+  private static final String NESTED_VALUE = "Nested value";
+  private static final String NESTED_ALT_VALUE = "Nested value alt";
+
+  private static final String CHILD_SYNDICATOR = "child";
+
+  private static final String ARRAY_NAME = "array value";
+  private static final String[] ARRAY_VALUE = new String[]{"Hello", "World"};
+  private static final String ARRAY_ALT_VALUE = "Not an array";
+
+  @Override
+  public void setUp() throws Exception {
+    config = new SyndicatorConfig(null);
+    // We use a JSON Object here to guarantee that we're well formed up front.
+    JSONObject json = new JSONObject();
+    json.put(SYNDICATOR_KEY, new String[]{DEFAULT_SYNDICATOR});
+    json.put(TOP_LEVEL_NAME, TOP_LEVEL_VALUE);
+    json.put(ARRAY_NAME, ARRAY_VALUE);
+
+    // small nested data.
+    JSONObject nested = new JSONObject();
+    nested.put(NESTED_NAME, NESTED_VALUE);
+
+    json.put(NESTED_KEY, nested);
+
+    config.loadFromString(json.toString());
+  }
+
+  public void testBasic() throws Exception {
+    // check to make sure that the default config was processed correctly.
+    assertEquals(1, config.getSyndicators().size());
+    for (String synd : config.getSyndicators()) {
+      assertEquals(DEFAULT_SYNDICATOR, synd);
+    }
+
+    String value = config.get(DEFAULT_SYNDICATOR, TOP_LEVEL_NAME);
+    assertEquals(TOP_LEVEL_VALUE, value);
+
+    JSONObject nested = config.getJsonObject(DEFAULT_SYNDICATOR, NESTED_KEY);
+
+    String nestedValue = nested.getString(NESTED_NAME);
+
+    assertEquals(NESTED_VALUE, nestedValue);
+  }
+
+  public void testCascade() throws Exception {
+    JSONObject json = new JSONObject();
+    json.put(SYNDICATOR_KEY, new String[]{CHILD_SYNDICATOR});
+    json.put(ARRAY_NAME, ARRAY_ALT_VALUE);
+
+    // small nested data.
+    JSONObject nested = new JSONObject();
+    nested.put(NESTED_NAME, NESTED_ALT_VALUE);
+
+    json.put(NESTED_KEY, nested);
+
+    config.loadFromString(json.toString());
+
+    String value = config.get(CHILD_SYNDICATOR, TOP_LEVEL_NAME);
+    assertEquals(TOP_LEVEL_VALUE, value);
+
+    JSONObject nestedObj = config.getJsonObject(CHILD_SYNDICATOR, NESTED_KEY);
+    String nestedValue = nestedObj.getString(NESTED_NAME);
+    assertEquals(NESTED_ALT_VALUE, nestedValue);
+
+    String arrayValue = config.get(CHILD_SYNDICATOR, ARRAY_NAME);
+    assertEquals(ARRAY_ALT_VALUE, arrayValue);
+
+    // Verify that the parent value wasn't overwritten as well.
+
+    JSONArray defaultArrayTest = config.getJsonArray(DEFAULT_SYNDICATOR,
+                                                      ARRAY_NAME);
+    JSONArray defaultArray = new JSONArray(ARRAY_VALUE);
+    assertEquals(defaultArrayTest.toString(), defaultArray.toString());
+  }
+}

Modified: incubator/shindig/trunk/javascript/container/gadgets.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/gadgets.js?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/gadgets.js (original)
+++ incubator/shindig/trunk/javascript/container/gadgets.js Mon Feb 18 14:56:14 2008
@@ -223,22 +223,22 @@
  */
 gadgets.IfrGadgetService = function() {
   gadgets.GadgetService.call(this);
-  gadgets.ifpc_.registerService('resize_iframe', this.setHeight);
-  gadgets.ifpc_.registerService('set_pref', this.setUserPref);
-  gadgets.ifpc_.registerService('set_title', this.setTitle);
+  gadgets.rpc.register('resize_iframe', this.setHeight);
+  gadgets.rpc.register('set_pref', this.setUserPref);
+  gadgets.rpc.register('set_title', this.setTitle);
 };
 
 gadgets.IfrGadgetService.inherits(gadgets.GadgetService);
 
-gadgets.IfrGadgetService.prototype.setHeight = function(elementId, height) {
-  var element = document.getElementById(elementId);
+gadgets.IfrGadgetService.prototype.setHeight = function(height) {
+  var element = document.getElementById(this.f);
   if (element) {
     element.style.height = height + 'px';
   }
 };
 
-gadgets.IfrGadgetService.prototype.setTitle = function(gadget, title) {
-  var element = document.getElementById(gadget + '_title');
+gadgets.IfrGadgetService.prototype.setTitle = function(title) {
+  var element = document.getElementById(this.f + '_title');
   if (element) {
     element.innerHTML = title.replace(/&/g, '&amp;').replace(/</g, '&lt;');
   }
@@ -252,12 +252,12 @@
  * @param {String} value Value of user preference
  * More names and values may follow
  */
-gadgets.IfrGadgetService.prototype.setUserPref = function(gadgetFrameId) {
+gadgets.IfrGadgetService.prototype.setUserPref = function() {
   // Quick hack to extract the gadget id from module id
-  var id = parseInt(gadgetFrameId.match(/_([0-9]+)$/)[1], 10);
+  var id = parseInt(this.f.match(/_([0-9]+)$/)[1], 10);
   var gadget = gadgets.container.getGadget(id);
   var prefs = gadget.getUserPrefs();
-  for (var i = 2; i < arguments.length; i += 2) {
+  for (var i = 0, j = arguments.length; i < j; i += 2) {
     prefs[arguments[i]] = arguments[i + 1];
   }
   gadget.setUserPrefs(prefs);
@@ -433,14 +433,14 @@
 
 gadgets.IfrGadget = function(opt_params) {
   gadgets.Gadget.call(this, opt_params);
-  this.serverBase_ = 'http://www.gmodules.com/ig/'; // default gadget server
+  this.serverBase_ = '../../' // default gadget server
 };
 
 gadgets.IfrGadget.inherits(gadgets.Gadget);
 
 gadgets.IfrGadget.prototype.GADGET_IFRAME_PREFIX_ = 'remote_iframe_';
 
-gadgets.IfrGadget.prototype.SYND = 'shindig';
+gadgets.IfrGadget.prototype.SYND = 'default';
 
 gadgets.IfrGadget.prototype.cssClassGadget = 'gadgets-gadget';
 gadgets.IfrGadget.prototype.cssClassTitleBar = 'gadgets-gadget-title-bar';
@@ -498,8 +498,7 @@
 gadgets.IfrGadget.prototype.getIframeUrl = function() {
   return this.serverBase_ + 'ifr?url=' +
       encodeURIComponent(this.specUrl) + '&synd=' + this.SYND + '&mid=' +
-      this.id + '&parent=' + encodeURIComponent(gadgets.container.parentUrl_) +
-      '&ogc=' + document.location.host + this.getUserPrefsParams();
+      this.id + this.getUserPrefsParams();
 };
 
 gadgets.IfrGadget.prototype.getUserPrefsParams = function() {

Modified: incubator/shindig/trunk/javascript/container/sample-rpc.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample-rpc.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample-rpc.html (original)
+++ incubator/shindig/trunk/javascript/container/sample-rpc.html Mon Feb 18 14:56:14 2008
@@ -23,7 +23,6 @@
 </style>
 </head>
 <body>
-<script src="../../js/core.js"></script>
 <script>
   function makeXhr() {
     if (window.XMLHttpRequest) {
@@ -41,19 +40,24 @@
     var gadgetList = obj.gadgets;
     var features = {};
     for (var i = 0, gadget; gadget = gadgetList[i]; ++i) {
-      for (var j = 0, feature; feature = gadget.features[i]; ++i) {
+      var feats = gadget.features || [];
+      for (var j = 0, feature; feature = feats[j]; ++j) {
         features[feature] = true;
       }
     }
     var libs = [];
     for (var lib in features) {libs.push(lib);}
     libs.sort();
-    libs = libs.join("");
+    libs = libs.join(":");
     for (var i = 0, gadget; gadget = gadgetList[i]; ++i) {
       var newGadget = document.createElement("div");
-      newGadget.innerHTML = ['<h2>', gadget.title, '</h2>',
-        '<iframe src="', gadget.content, '&libs=', libs ,'" id="remote_iframe_', gadget.moduleId, '"></iframe>'
-      ].join("");
+      if (gadget.errors && gadget.errors.length > 0) {
+        newGadget.innerHTML = ["Unable to process gadget: ", gadget.url, ". Errors: <pre>", gadget.errors.join("\n"), "</pre>"].join("");
+      } else {
+        newGadget.innerHTML = ['<h2>', gadget.title, '</h2>',
+          '<iframe src="', gadget.content, '&libs=', libs ,'" id="remote_iframe_', gadget.moduleId, '"></iframe>'
+        ].join("");
+      }
       newGadget.className = "gadget";
       document.body.appendChild(newGadget);
     }
@@ -78,6 +82,10 @@
       {
         url: "http://www.labpixies.com/campaigns/todo/todo.xml",
         moduleId: 2
+      },
+      {
+        url: "http://www.example.org/fake/fake/fake.xml",
+        moduleId: 3
       }
     ]
   };

Modified: incubator/shindig/trunk/javascript/container/sample1.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample1.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample1.html (original)
+++ incubator/shindig/trunk/javascript/container/sample1.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: Simple Container</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">

Modified: incubator/shindig/trunk/javascript/container/sample2.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample2.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample2.html (original)
+++ incubator/shindig/trunk/javascript/container/sample2.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: Dynamic Height</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">

Modified: incubator/shindig/trunk/javascript/container/sample3.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample3.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample3.html (original)
+++ incubator/shindig/trunk/javascript/container/sample3.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: Container with FloatLeft Layout</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">

Modified: incubator/shindig/trunk/javascript/container/sample4.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample4.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample4.html (original)
+++ incubator/shindig/trunk/javascript/container/sample4.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: set-pref support</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">

Modified: incubator/shindig/trunk/javascript/container/sample5.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample5.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample5.html (original)
+++ incubator/shindig/trunk/javascript/container/sample5.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: set-pref support</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">
@@ -17,7 +16,6 @@
 
   gadgets.container.setParentUrl('ifpc_relay.html');
   var gadget = gadgets.container.createGadget({specUrl: specUrl0});
-  gadget.setServerBase('http://localhost:8080/gadgets/'); 
   gadgets.container.addGadget(gadget);
 };
 

Modified: incubator/shindig/trunk/javascript/container/sample6.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample6.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample6.html (original)
+++ incubator/shindig/trunk/javascript/container/sample6.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: dynamic-height support</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">
@@ -17,7 +16,6 @@
 
   gadgets.container.setParentUrl('ifpc_relay.html');
   var gadget = gadgets.container.createGadget({specUrl: specUrl0});
-  gadget.setServerBase('http://localhost:8080/gadgets/'); 
   gadgets.container.addGadget(gadget);
 };
 

Modified: incubator/shindig/trunk/javascript/container/sample7.html
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/container/sample7.html?rev=628908&r1=628907&r2=628908&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/container/sample7.html (original)
+++ incubator/shindig/trunk/javascript/container/sample7.html Mon Feb 18 14:56:14 2008
@@ -4,8 +4,7 @@
 <title>Sample: settitle support</title>
 <!-- default container look and feel -->
 <link rel="stylesheet" href="gadgets.css">
-<script type="text/javascript" src="json.js"></script>
-<script type="text/javascript" src="ifpc.js"></script>
+<script type="text/javascript" src="../../js/rpc.js?c=1"></script>
 <script type="text/javascript" src="cookies.js"></script>
 <script type="text/javascript" src="gadgets.js"></script>
 <script type="text/javascript">
@@ -17,7 +16,6 @@
 
   gadgets.container.setParentUrl('ifpc_relay.html');
   var gadget = gadgets.container.createGadget({specUrl: specUrl0});
-  gadget.setServerBase('http://localhost:8080/gadgets/'); 
   gadgets.container.addGadget(gadget);
 };