You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by aw...@apache.org on 2009/02/24 01:03:55 UTC
svn commit: r747227 - in /incubator/shindig/trunk: features/
features/opensocial-base/ features/opensocial-data-context/
features/opensocial-data/ features/opensocial-reference/
java/gadgets/src/main/java/org/apache/shindig/gadgets/ java/gadgets/src/ma...
Author: awiner
Date: Tue Feb 24 00:03:55 2009
New Revision: 747227
URL: http://svn.apache.org/viewvc?rev=747227&view=rev
Log:
SHINDIG-739: Data pipelining (in part)
- Extract DataContext api into an opensocial-data-context feature, depended on by opensocial-data
- If server-side data pipelining succeeds completely, remove the opensocial-data feature and add the opensocial-data-context feature instead
- Rewrite DataContext to hide implementation better, and write test
- Add support for registerListener('*', ...) per spec
- Tweak other opensocial-related tests to work in JSUnit (not relying on 'window' variable)
- Fix name of os:MakeRequest element (now os:HttpRequest per spec)
Added:
incubator/shindig/trunk/features/opensocial-data-context/
incubator/shindig/trunk/features/opensocial-data-context/datacontext.js
incubator/shindig/trunk/features/opensocial-data-context/datacontexttest.js
incubator/shindig/trunk/features/opensocial-data-context/feature.xml
Modified:
incubator/shindig/trunk/features/features.txt
incubator/shindig/trunk/features/opensocial-base/jsonactivitytest.js
incubator/shindig/trunk/features/opensocial-data/data.js
incubator/shindig/trunk/features/opensocial-data/feature.xml
incubator/shindig/trunk/features/opensocial-reference/activitytest.js
incubator/shindig/trunk/features/opensocial-reference/opensocial.js
incubator/shindig/trunk/features/pom.xml
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriter.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriterTest.java
Modified: incubator/shindig/trunk/features/features.txt
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/features.txt?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/features.txt (original)
+++ incubator/shindig/trunk/features/features.txt Tue Feb 24 00:03:55 2009
@@ -16,6 +16,7 @@
features/opensocial-base/feature.xml
features/opensocial-current/feature.xml
features/opensocial-data/feature.xml
+features/opensocial-data-context/feature.xml
features/opensocial-jsonrpc/feature.xml
features/opensocial-reference/feature.xml
features/opensocial-rest/feature.xml
Modified: incubator/shindig/trunk/features/opensocial-base/jsonactivitytest.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-base/jsonactivitytest.js?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-base/jsonactivitytest.js (original)
+++ incubator/shindig/trunk/features/opensocial-base/jsonactivitytest.js Tue Feb 24 00:03:55 2009
@@ -17,7 +17,6 @@
*/
var gadgets = gadgets || {};
-var opensocial = opensocial || {};
function JsonActivityTest(name) {
TestCase.call(this, name);
Added: incubator/shindig/trunk/features/opensocial-data-context/datacontext.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-data-context/datacontext.js?rev=747227&view=auto
==============================================================================
--- incubator/shindig/trunk/features/opensocial-data-context/datacontext.js (added)
+++ incubator/shindig/trunk/features/opensocial-data-context/datacontext.js Tue Feb 24 00:03:55 2009
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+/**
+ * @fileoverview Implements the global implicit data context for containers.
+ */
+
+var opensocial = opensocial || {};
+
+/**
+ * @type {Object} The namespace declaration for this file.
+ */
+opensocial.data = opensocial.data || {};
+
+var osd = opensocial.data;
+
+/**
+ * @type {Object} Global DataContext to contain requested data sets.
+ */
+osd.DataContext = function() {
+ var listeners = [];
+ var dataSets = {};
+
+ /**
+ * Checks if the data for a map of keys is available.
+ * @param {Object<string, ?>} An map of keys to check.
+ * @return {boolean} Data for all the keys is present.
+ */
+ var isDataReady = function(keys) {
+ if (keys['*']) {
+ return true;
+ }
+
+ for (var key in keys) {
+ if (typeof dataSets[key] === 'undefined') {
+ return false;
+ }
+ }
+ return true;
+ };
+
+
+ /**
+ * Fires a listener for a key, but only if the data is ready for other
+ * keys this listener is bound to.
+ * @param {Object} listener The listener object.
+ * @param {string} key The key that this listener is being fired for.
+ */
+ var maybeFireListener = function(listener, key) {
+ if (isDataReady(listener.keys)) {
+ listener.callback(key);
+ }
+ };
+
+
+ /**
+ * Scans all active listeners and fires off any callbacks that inserting this
+ * key satisfies.
+ * @param {string} key The key that was updated.
+ * @private
+ */
+ var fireCallbacks = function(key) {
+ for (var i = 0; i < listeners.length; ++i) {
+ var listener = listeners[i];
+ if (listener.keys[key] || listener.keys['*']) {
+ maybeFireListener(listener, key);
+ }
+ }
+ };
+
+
+ return {
+ /**
+ * Map of existing data. This is used externally by both the
+ * opensocial-data and opensocial-templates feature, hence is
+ * not hidden.
+ */
+ dataSets_ : dataSets,
+
+
+ /**
+ * Registers a callback listener for a given set of keys.
+ * @param {string|Array.<string>} keys Key or set of keys to listen on.
+ * @param {Function(string)} callback Function to call when a listener is fired.
+ * TODO: Should return a value that can later be used to return
+ * a value.
+ */
+ registerListener : function(keys, callback) {
+ var listener = {keys : {}, callback : callback};
+
+ if (typeof keys === 'string') {
+ listener.keys[keys] = true;
+ } else {
+ for (var i = 0; i < keys.length; i++) {
+ listener.keys[keys[i]] = true;
+ }
+ }
+
+ listeners.push(listener);
+
+ // Check to see if this one should fire immediately.
+ if (keys !== '*' && isDataReady(listener.keys)) {
+ window.setTimeout(function() {
+ listener.callback()
+ }, 1);
+ }
+ },
+
+
+ /**
+ * Retrieve a data set for a given key.
+ * @param {string} key Key for the requested data set.
+ * @return {Object} The data set object.
+ */
+ getDataSet : function(key) {
+ return dataSets[key];
+ },
+
+
+ /**
+ * Puts a data set into the global DataContext object. Fires listeners
+ * if they are satisfied by the associated key being inserted.
+ *
+ * Note that if this is passed a ResponseItem object, it will crack it open
+ * and extract the JSON payload of the wrapped API Object. This includes
+ * iterating over an array of API objects and extracting their JSON into a
+ * simple array structure.
+ *
+ * @param {string} key The key to associate with this object.
+ * @param {ResponseItem|Object} obj The data object.
+ */
+ putDataSet : function(key, obj) {
+ var data = obj;
+ if (typeof data === 'undefined' || data === null) {
+ return;
+ }
+
+ // NOTE: This is ugly, but required since we need to get access
+ // to the JSON/Array payload of API responses.
+ // This will crack the actual API objects and extract their JSON payloads.
+ // TODO: this code block is not described by the spec, and should be removed.
+ // Developers using ResponseItems should call getData() themselves.
+ if (data.getData) {
+ data = data.getData();
+ if (data.array_) {
+ var out = [];
+ for (var i = 0; i < data.array_.length; i++) {
+ out.push(data.array_[i].fields_);
+ }
+ data = out;
+ } else {
+ data = data.fields_ || data;
+ }
+ }
+
+ dataSets[key] = data;
+ fireCallbacks(key);
+ },
+ }
+}();
+
+
+/**
+ * Accessor to the shared, global DataContext.
+ */
+osd.getDataContext = function() {
+ return opensocial.data.DataContext;
+};
+
Added: incubator/shindig/trunk/features/opensocial-data-context/datacontexttest.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-data-context/datacontexttest.js?rev=747227&view=auto
==============================================================================
--- incubator/shindig/trunk/features/opensocial-data-context/datacontexttest.js (added)
+++ incubator/shindig/trunk/features/opensocial-data-context/datacontexttest.js Tue Feb 24 00:03:55 2009
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ *
+ * Unittests for the opensocial-data-context feature.
+ */
+function DataContextTest(name) {
+ TestCase.call(this, name);
+}
+
+DataContextTest.inherits(TestCase);
+
+DataContextTest.prototype.setUp = function() {
+};
+
+DataContextTest.prototype.tearDown = function() {
+ var dataSets = osd.getDataContext().dataSets_;
+ for (var key in dataSets) {
+ if (dataSets.hasOwnProperty(key)) {
+ delete dataSets[key];
+ }
+ }
+};
+
+DataContextTest.prototype.testPutDataSet = function() {
+ var context = osd.getDataContext();
+
+ context.putDataSet('key', 'value');
+ this.assertEquals('value', context.getDataSet('key'));
+
+ // Test that putting null and undefined don't change the value.
+ // TODO: this seems wrong; why not support removing data?
+ context.putDataSet('key', null);
+ this.assertEquals('value', context.getDataSet('key'));
+
+ context.putDataSet('key', undefined);
+ this.assertEquals('value', context.getDataSet('key'));
+};
+
+
+/**
+ * Test registerListener()
+ */
+DataContextTest.prototype.testRegisterListener = function() {
+ var context = osd.getDataContext();
+ var listenerCalledWithKey = null;
+ var that = this;
+ var listener = function(key) {
+ listenerCalledWithKey = key;
+ that.assertNotNull(key);
+ };
+
+ context.registerListener('key', listener);
+ this.assertNull(listenerCalledWithKey);
+
+ context.putDataSet('other', 1);
+ this.assertNull(listenerCalledWithKey);
+
+ context.putDataSet('key', 2);
+ this.assertEquals('key', listenerCalledWithKey);
+
+ listenerCalledWithKey = null;
+ context.putDataSet('key', 3);
+ this.assertEquals('key', listenerCalledWithKey);
+}
+
+
+
+/**
+ * Test registerListener()
+ */
+DataContextTest.prototype.testRegisterListenerWithArray = function() {
+ var context = osd.getDataContext();
+ var listenerCalledWithKey = null;
+ var that = this;
+ var listener = function(key) {
+ listenerCalledWithKey = key;
+ that.assertNotNull(key);
+ };
+
+ context.registerListener(['one', 'two'], listener);
+ this.assertNull(listenerCalledWithKey);
+
+ context.putDataSet('one', 1);
+ this.assertNull(listenerCalledWithKey);
+
+ context.putDataSet('two', 2);
+ this.assertEquals('two', listenerCalledWithKey);
+
+ context.putDataSet('one', 3);
+ this.assertEquals('one', listenerCalledWithKey);
+}
+
+
+/**
+ * Test registerListener() with '*'
+ */
+DataContextTest.prototype.testRegisterListenerWithStar = function() {
+ var context = osd.getDataContext();
+ var listenerCalledWithKey = null;
+ var that = this;
+ var listener = function(key) {
+ listenerCalledWithKey = key;
+ that.assertNotNull(key);
+ };
+
+ context.registerListener('*', listener);
+ this.assertNull(listenerCalledWithKey);
+
+ context.putDataSet('one', 1);
+ this.assertEquals('one', listenerCalledWithKey);
+
+ context.putDataSet('two', 2);
+ this.assertEquals('two', listenerCalledWithKey);
+}
\ No newline at end of file
Added: incubator/shindig/trunk/features/opensocial-data-context/feature.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-data-context/feature.xml?rev=747227&view=auto
==============================================================================
--- incubator/shindig/trunk/features/opensocial-data-context/feature.xml (added)
+++ incubator/shindig/trunk/features/opensocial-data-context/feature.xml Tue Feb 24 00:03:55 2009
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<feature>
+ <name>opensocial-data-context</name>
+ <gadget>
+ <script src="datacontext.js"></script>
+ </gadget>
+</feature>
Modified: incubator/shindig/trunk/features/opensocial-data/data.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-data/data.js?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-data/data.js (original)
+++ incubator/shindig/trunk/features/opensocial-data/data.js Tue Feb 24 00:03:55 2009
@@ -25,15 +25,6 @@
* URL parameter support.
*/
-var opensocial = window['opensocial'] || function() {};
-
-/**
- * @type {Object} The namespace declaration for this file.
- */
-opensocial.data = opensocial.data || {};
-
-var osd = opensocial.data;
-
/**
* @type {string} The key attribute constant.
*/
@@ -213,109 +204,6 @@
};
-/**
- * @type {Object} Global DataContext to contain requested data sets.
- */
-osd.DataContext = {};
-
-osd.DataContext.listeners_ = [];
-
-osd.DataContext.dataSets_ = {};
-
-/**
- * Registers a callback listener for a given set of keys.
- * @param {string|Array.<string>} keys Key or set of keys to listen on.
- * @param {Function(string)} callback Function to call when a listener is fired.
- * TODO: Should return a value that can later be used to return
- * a value.
- */
-osd.DataContext.registerListener = function(keys, callback) {
- var listener = {};
- listener.keys = {};
-
- if (typeof(keys) == 'object') {
- for (var i in keys) {
- listener.keys[keys[i]] = true;
- }
- } else {
- listener.keys[keys] = true;
- }
-
- listener.callback = callback;
- opensocial.data.DataContext.listeners_.push(listener);
-
- // Check to see if this one should fire immediately.
- if (osd.DataContext.isDataReady(listener.keys)) {
- window.setTimeout(function() {
- listener.callback()
- }, 1);
- }
-};
-
-
-/**
- * Retrieve a data set for a given key.
- * @param {string} key Key for the requested data set.
- * @return {Object} The data set object.
- */
-osd.DataContext.getDataSet = function(key) {
- return opensocial.data.DataContext.dataSets_[key];
-};
-
-
-/**
- * Checks if the data for a map of keys is available.
- * @param {Object<string, ?>} An map of keys to check.
- * @return {boolean} Data for all the keys is present.
- */
-osd.DataContext.isDataReady = function(keys) {
- for (var key in keys) {
- if (osd.DataContext.getDataSet(key) == null) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Puts a data set into the global DataContext object. Fires listeners
- * if they are satisfied by the associated key being inserted.
- *
- * Note that if this is passed a ResponseItem object, it will crack it open
- * and extract the JSON payload of the wrapped API Object. This includes
- * iterating over an array of API objects and extracting their JSON into a
- * simple array structure.
- *
- * @param {string} key The key to associate with this object.
- * @param {ResponseItem|Object} obj The data object.
- */
-osd.DataContext.putDataSet = function(key, obj) {
- var data = obj;
- if (typeof(data) == "undefined" || data === null) {
- return;
- }
-
- // NOTE: This is ugly, but required since we need to get access
- // to the JSON/Array payload of API responses.
- // This will crack the actual API objects and extract their JSON payloads.
- if (data.getData) {
- data = data.getData();
- if (data.array_) {
- var out = [];
- for (var i = 0; i < data.array_.length; i++) {
- out.push(data.array_[i].fields_);
- }
- data = out;
- } else {
- data = data.fields_ || data;
- }
- }
-
- opensocial.data.DataContext.dataSets_[key] = data;
- opensocial.data.DataContext.fireCallbacks_(key);
-};
-
/**
* Evaluates a JS expression against the DataContext.
@@ -329,44 +217,6 @@
/**
- * Fires a listener for a key, but only if the data is ready for other
- * keys this listener is bound to.
- * @param {Object} listener The listener object.
- * @param {string} key The key that this listener is being fired for.
- */
-osd.DataContext.maybeFireListener_ = function(listener, key) {
- if (osd.DataContext.isDataReady(listener.keys)) {
- listener.callback(key);
- }
-};
-
-
-/**
- * Scans all active listeners and fires off any callbacks that inserting this
- * key satisfies.
- * @param {string} key The key that was updated.
- * @private
- */
-osd.DataContext.fireCallbacks_ = function(key) {
- for (var i = 0; i < opensocial.data.DataContext.listeners_.length; ++i) {
- var listener = opensocial.data.DataContext.listeners_[i];
- if (listener.keys[key] != null) {
- opensocial.data.DataContext.maybeFireListener_(listener, key);
- }
- }
-};
-
-
-/**
- * Accessor to the static DataContext object. At a later date multiple
- * DataContexts may be used.
- */
-osd.getDataContext = function() {
- return opensocial.data.DataContext;
-};
-
-
-/**
* @type {Object} Map of currently registered RequestDescriptors (by key).
* @private
*/
@@ -695,7 +545,7 @@
opensocial.data.addToCurrentAPIRequest(req, descriptor.key);
});
- osd.registerRequestHandler("os:DataRequest", function(descriptor) {
+ osd.registerRequestHandler("os:HttpRequest", function(descriptor) {
var href = descriptor.getAttribute('href');
var format = descriptor.getAttribute('format') || "json";
var params = {};
Modified: incubator/shindig/trunk/features/opensocial-data/feature.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-data/feature.xml?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-data/feature.xml (original)
+++ incubator/shindig/trunk/features/opensocial-data/feature.xml Tue Feb 24 00:03:55 2009
@@ -19,6 +19,7 @@
-->
<feature>
<name>opensocial-data</name>
+ <dependency>opensocial-data-context</dependency>
<dependency>opensocial-0.8</dependency>
<dependency>xmlutil</dependency>
<gadget>
Modified: incubator/shindig/trunk/features/opensocial-reference/activitytest.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-reference/activitytest.js?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-reference/activitytest.js (original)
+++ incubator/shindig/trunk/features/opensocial-reference/activitytest.js Tue Feb 24 00:03:55 2009
@@ -17,7 +17,6 @@
*/
var gadgets = gadgets || {};
-var opensocial = opensocial || {};
function ActivityTest(name) {
TestCase.call(this, name);
Modified: incubator/shindig/trunk/features/opensocial-reference/opensocial.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-reference/opensocial.js?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/opensocial-reference/opensocial.js (original)
+++ incubator/shindig/trunk/features/opensocial-reference/opensocial.js Tue Feb 24 00:03:55 2009
@@ -36,7 +36,7 @@
* @private
* @constructor (note: a constructor for JsDoc purposes)
*/
-var opensocial = window['opensocial'] || {};
+var opensocial = opensocial || {};
/**
Modified: incubator/shindig/trunk/features/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/pom.xml?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/features/pom.xml (original)
+++ incubator/shindig/trunk/features/pom.xml Tue Feb 24 00:03:55 2009
@@ -80,6 +80,7 @@
<source>core.io/io.js</source>
<source>setprefs/setprefs.js</source>
<source>views/views.js</source>
+ <source>opensocial-data-context/datacontext.js</source>
<source>opensocial-reference/opensocial.js</source>
<source>opensocial-reference/activity.js</source>
<source>opensocial-reference/address.js</source>
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/Gadget.java Tue Feb 24 00:03:55 2009
@@ -23,6 +23,10 @@
import org.apache.shindig.gadgets.spec.View;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
/**
* Intermediary representation of all state associated with processing
@@ -33,6 +37,9 @@
private GadgetSpec spec;
private Collection<PreloadedData> preloads;
private View currentView;
+ private Set<String> addedFeatures;
+ private Set<String> removedFeatures;
+
/**
* @param context The request that the gadget is being processed for.
*/
@@ -91,4 +98,37 @@
public LocaleSpec getLocale() {
return spec.getModulePrefs().getLocale(context.getLocale());
}
+
+
+ public void addFeature(String name) {
+ if (addedFeatures == null) {
+ addedFeatures = Sets.newHashSet();
+ }
+
+ addedFeatures.add(name);
+ }
+
+ public void removeFeature(String name) {
+ if (removedFeatures == null) {
+ removedFeatures = Sets.newHashSet();
+ }
+
+ removedFeatures.add(name);
+ }
+
+ public Set<String> getAddedFeatures() {
+ if (addedFeatures == null) {
+ return Collections.<String>emptySet();
+ }
+
+ return addedFeatures;
+ }
+
+ public Set<String> getRemovedFeatures() {
+ if (removedFeatures == null) {
+ return Collections.<String>emptySet();
+ }
+
+ return removedFeatures;
+ }
}
\ No newline at end of file
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/RenderingContentRewriter.java Tue Feb 24 00:03:55 2009
@@ -41,7 +41,6 @@
import org.apache.shindig.gadgets.rewrite.MutableContent;
import org.apache.shindig.gadgets.rewrite.RewriterResults;
import org.apache.shindig.gadgets.spec.Feature;
-import org.apache.shindig.gadgets.spec.GadgetSpec;
import org.apache.shindig.gadgets.spec.LocaleSpec;
import org.apache.shindig.gadgets.spec.MessageBundle;
import org.apache.shindig.gadgets.spec.ModulePrefs;
@@ -214,7 +213,6 @@
// TODO: If there isn't any js in the document, we can skip this. Unfortunately, that means
// both script tags (easy to detect) and event handlers (much more complex).
GadgetContext context = gadget.getContext();
- GadgetSpec spec = gadget.getSpec();
String forcedLibs = context.getParameter("libs");
// List of libraries we need
@@ -248,7 +246,7 @@
// Inline any libs that weren't forced. The ugly context switch between inline and external
// Js is needed to allow both inline and external scripts declared in feature.xml.
String container = context.getContainer();
- Collection<GadgetFeature> features = getFeatures(spec, forced);
+ Collection<GadgetFeature> features = getFeatures(gadget, forced);
// Precalculate the maximum length in order to avoid excessive garbage generation.
int size = 0;
@@ -304,13 +302,16 @@
* @param forced Forced libraries; added in addition to those found in the spec. Defaults to
* "core".
*/
- private Collection<GadgetFeature> getFeatures(GadgetSpec spec, Collection<String> forced)
+ private Collection<GadgetFeature> getFeatures(Gadget gadget, Collection<String> forced)
throws GadgetException {
- Map<String, Feature> features = spec.getModulePrefs().getFeatures();
+ Map<String, Feature> features = gadget.getSpec().getModulePrefs().getFeatures();
Set<String> libs = Sets.newHashSet(features.keySet());
if (!forced.isEmpty()) {
libs.addAll(forced);
}
+
+ libs.removeAll(gadget.getRemovedFeatures());
+ libs.addAll(gadget.getAddedFeatures());
Set<String> unsupported = Sets.newHashSet();
Collection<GadgetFeature> feats = featureRegistry.getFeatures(libs, unsupported);
Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriter.java?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriter.java Tue Feb 24 00:03:55 2009
@@ -206,6 +206,19 @@
head.appendChild(pipelineScript);
MutableContent.notifyEdit(doc);
+ boolean allBatchesCompleted = true;
+ for (PipelineState pipeline : pipelines) {
+ if (pipeline.batch != null) {
+ allBatchesCompleted = false;
+ break;
+ }
+ }
+
+ if (allBatchesCompleted) {
+ gadget.addFeature("opensocial-data-context");
+ gadget.removeFeature("opensocial-data");
+ }
+
return RewriterResults.notCacheable();
}
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java Tue Feb 24 00:03:55 2009
@@ -273,6 +273,43 @@
}
@Test
+ public void featuresNotInjectedWhenRemoved() throws Exception {
+ String gadgetXml =
+ "<Module><ModulePrefs title=''>" +
+ " <Require feature='foo'/>" +
+ "</ModulePrefs>" +
+ "<Content type='html'/>" +
+ "</Module>";
+
+ Gadget gadget = makeGadgetWithSpec(gadgetXml);
+ gadget.removeFeature("foo");
+
+ featureRegistry.addInline("foo", "foo_content();");
+
+ String rewritten = rewrite(gadget, "");
+
+ assertFalse("Removed script still inlined.", rewritten.contains("foo_content();"));
+ }
+
+ @Test
+ public void featuresInjectedWhenAdded() throws Exception {
+ String gadgetXml =
+ "<Module><ModulePrefs title=''>" +
+ "</ModulePrefs>" +
+ "<Content type='html'/>" +
+ "</Module>";
+
+ Gadget gadget = makeGadgetWithSpec(gadgetXml);
+ gadget.addFeature("foo");
+
+ featureRegistry.addInline("foo", "foo_content();");
+
+ String rewritten = rewrite(gadget, "");
+
+ assertTrue("Added script not inlined.", rewritten.contains("foo_content();"));
+ }
+
+ @Test
public void mixedExternalAndInline() throws Exception {
String gadgetXml =
"<Module><ModulePrefs title=''>" +
Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriterTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriterTest.java?rev=747227&r1=747226&r2=747227&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriterTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/PipelineDataContentRewriterTest.java Tue Feb 24 00:03:55 2009
@@ -56,6 +56,7 @@
import java.util.concurrent.Executors;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
/**
* Test of PipelineDataContentRewriter.
@@ -143,6 +144,9 @@
assertTrue(batchCapture.getValue().getSocialPreloads().containsKey("me"));
assertTrue(batchCapture.getValue().getHttpPreloads().containsKey("json"));
+
+ assertEquals(ImmutableSet.of("opensocial-data"), gadget.getRemovedFeatures());
+ assertEquals(ImmutableSet.of("opensocial-data-context"), gadget.getAddedFeatures());
control.verify();
}
@@ -204,6 +208,9 @@
// Check the evaluated person request
JSONObject personRequest = (JSONObject) secondBatch.getValue().getSocialPreloads().get("me");
assertEquals("canonical", personRequest.getJSONObject("params").getJSONArray("userId").get(0));
+
+ assertEquals(ImmutableSet.of("opensocial-data"), gadget.getRemovedFeatures());
+ assertEquals(ImmutableSet.of("opensocial-data-context"), gadget.getAddedFeatures());
}
@Test
@@ -227,6 +234,9 @@
// And the os-data elements should be present
assertTrue("os-data was deleted",
content.getContent().indexOf("type=\"text/os-data\"") > 0);
+
+ assertEquals(ImmutableSet.<String>of(), gadget.getRemovedFeatures());
+ assertEquals(ImmutableSet.<String>of(), gadget.getAddedFeatures());
}
/** Match a batch with the specified count of social and HTTP data items */