You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2010/01/26 00:35:06 UTC

svn commit: r903014 - in /incubator/wookie/trunk: scripts/derby/ scripts/mysql/ src-tests/org/apache/wookie/tests/ src/ src/org/apache/wookie/beans/ src/org/apache/wookie/feature/ src/org/apache/wookie/server/

Author: scottbw
Date: Mon Jan 25 23:35:06 2010
New Revision: 903014

URL: http://svn.apache.org/viewvc?rev=903014&view=rev
Log:
Added loading of features based on the content of a feature.properties file at server startup. This looks up features based on IRI and classname and adds them to the DB. Tests are included, as is the default feature.properties file. This removes the necessity for setting up features directly in SQL and so the relevant line has been removed from each of the DB setup scripts. This changeset implements WOOKIE-99.

Added:
    incubator/wookie/trunk/src-tests/org/apache/wookie/tests/FeatureLoaderTest.java
    incubator/wookie/trunk/src/features.properties
    incubator/wookie/trunk/src/org/apache/wookie/feature/FeatureLoader.java
Modified:
    incubator/wookie/trunk/scripts/derby/widgetdb.sql
    incubator/wookie/trunk/scripts/mysql/widgetdb.sql
    incubator/wookie/trunk/src/org/apache/wookie/beans/ServerFeature.java
    incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java

Modified: incubator/wookie/trunk/scripts/derby/widgetdb.sql
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/scripts/derby/widgetdb.sql?rev=903014&r1=903013&r2=903014&view=diff
==============================================================================
--- incubator/wookie/trunk/scripts/derby/widgetdb.sql (original)
+++ incubator/wookie/trunk/scripts/derby/widgetdb.sql Mon Jan 25 23:35:06 2010
@@ -10,5 +10,4 @@
 INSERT INTO WidgetType VALUES (1,1,'unsupported');
 INSERT INTO WidgetIcon VALUES (1,'/wookie/shared/images/defaultwidget.png',80,80,'en',1);
 INSERT INTO Whitelist VALUES (1,'http://127.0.0.1'),(2,'http://localhost'),(3,'http://feeds.bbc.co.uk/weather/feeds/rss');
-INSERT INTO ServerFeature VALUES (1,'org.apache.wookie.feature.wave.WaveAPIImpl','http://wave.google.com'),(2,'org.apache.wookie.feature.polling.impl.WookiePollingImpl','http://www.getwookie.org/usefeature/polling'), (3,'org.apache.wookie.feature.conformance.Test','feature:a9bb79c1');
 INSERT INTO ApiKey VALUES (1,'TEST','test@127.0.0.1')
\ No newline at end of file

Modified: incubator/wookie/trunk/scripts/mysql/widgetdb.sql
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/scripts/mysql/widgetdb.sql?rev=903014&r1=903013&r2=903014&view=diff
==============================================================================
--- incubator/wookie/trunk/scripts/mysql/widgetdb.sql (original)
+++ incubator/wookie/trunk/scripts/mysql/widgetdb.sql Mon Jan 25 23:35:06 2010
@@ -236,5 +236,4 @@
 INSERT INTO `WidgetType` VALUES (1,1,'unsupported');
 INSERT INTO `WidgetIcon` VALUES (1,'/wookie/shared/images/defaultwidget.png',80,80,'en',1);
 INSERT INTO `Whitelist` VALUES (1,'http://127.0.0.1'),(2,'http://localhost'),(3,'http://feeds.bbc.co.uk/weather/feeds/rss');
-INSERT INTO `ServerFeature` VALUES (1,'http://wave.google.com','org.apache.wookie.feature.wave.WaveAPIImpl'),(2,'http://www.getwookie.org/usefeature/polling','org.apache.wookie.feature.polling.impl.WookiePollingImpl'),(3,'feature:a9bb79c1','org.apache.wookie.feature.conformance.Test');
 INSERT INTO `ApiKey` VALUES (1,'TEST','test@127.0.0.1');
\ No newline at end of file

Added: incubator/wookie/trunk/src-tests/org/apache/wookie/tests/FeatureLoaderTest.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/FeatureLoaderTest.java?rev=903014&view=auto
==============================================================================
--- incubator/wookie/trunk/src-tests/org/apache/wookie/tests/FeatureLoaderTest.java (added)
+++ incubator/wookie/trunk/src-tests/org/apache/wookie/tests/FeatureLoaderTest.java Mon Jan 25 23:35:06 2010
@@ -0,0 +1,118 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wookie.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import org.apache.wookie.beans.ServerFeature;
+import org.apache.wookie.feature.FeatureLoader;
+
+
+public class FeatureLoaderTest {
+	
+	@Test(expected=Exception.class)
+	public void nullTest() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature(null, null);
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void nullTest2() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature(null, "fail");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void nullTest3() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("fail:", null);
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void badClass() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("fail:", "org.apache.wookie.NoSuchClass");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void badClass2() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("fail:", "");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void badClass3() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("fail:", "org.apache.wookie.beans.Name");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void badName() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("FAIL", "org.apache.wookie.feature.conformance.Test");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+	
+	@Test(expected=Exception.class)
+	public void badName2() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("", "org.apache.wookie.feature.conformance.Test");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}	
+	
+	@Test(expected=Exception.class)
+	public void mismatch() throws Exception{
+		@SuppressWarnings("unused")
+		ServerFeature sf = FeatureLoader.createFeature("fail:", "org.apache.wookie.feature.conformance.Test");
+        // Uh-oh! No exception was thrown so we 
+        // better make this test fail!
+        fail("should've thrown an exception!");
+	}
+
+	@Test
+	public void valid(){
+		try {
+			ServerFeature sf = FeatureLoader.createFeature("feature:a9bb79c1", "org.apache.wookie.feature.conformance.Test");
+			assertEquals(sf.getFeatureName(), "feature:a9bb79c1");
+			assertEquals(sf.getClassName(), "org.apache.wookie.feature.conformance.Test");
+		} catch (Exception e) {
+			fail("Couldn't create valid feature");
+		}
+	}
+
+}

Added: incubator/wookie/trunk/src/features.properties
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/features.properties?rev=903014&view=auto
==============================================================================
--- incubator/wookie/trunk/src/features.properties (added)
+++ incubator/wookie/trunk/src/features.properties Mon Jan 25 23:35:06 2010
@@ -0,0 +1,6 @@
+# Features to be installed at runtime
+# Uses the format className:IRI
+org.apache.wookie.feature.wave.WaveAPIImpl=http://wave.google.com
+org.apache.wookie.feature.polling.Polling=http://www.getwookie.org/usefeature/polling
+# This is only used for running the W3C Packaging & Configuration conformance test suite
+#org.apache.wookie.feature.conformance.Test=feature:a9bb79c1
\ No newline at end of file

Modified: incubator/wookie/trunk/src/org/apache/wookie/beans/ServerFeature.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/beans/ServerFeature.java?rev=903014&r1=903013&r2=903014&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/beans/ServerFeature.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/beans/ServerFeature.java Mon Jan 25 23:35:06 2010
@@ -40,6 +40,10 @@
 		if (features == null || features.length != 1) return null;
 		return features[0];
 	}
+	
+	public static ServerFeature[] findAll(){
+		 return (ServerFeature[]) findAll(ServerFeature.class);
+	}
 
 	/**
 	 * @return the className

Added: incubator/wookie/trunk/src/org/apache/wookie/feature/FeatureLoader.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/feature/FeatureLoader.java?rev=903014&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/feature/FeatureLoader.java (added)
+++ incubator/wookie/trunk/src/org/apache/wookie/feature/FeatureLoader.java Mon Jan 25 23:35:06 2010
@@ -0,0 +1,114 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wookie.feature;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.log4j.Logger;
+import org.apache.wookie.beans.ServerFeature;
+import org.apache.wookie.util.IRIValidator;
+import org.apache.wookie.util.hibernate.DBManagerFactory;
+import org.apache.wookie.util.hibernate.IDBManager;
+
+import java.util.Iterator;
+
+/**
+ * Loads installed features when server is initialized
+ *
+ */
+public class FeatureLoader {
+
+	static Logger _logger = Logger.getLogger(FeatureLoader.class.getName());
+
+	/**
+	 * Loads features based on the properties configuration supplied
+	 * @param config
+	 */
+	@SuppressWarnings("unchecked")
+	public static void loadFeatures(PropertiesConfiguration config){
+		final IDBManager dbManager = DBManagerFactory.getDBManager();
+		dbManager.beginTransaction();
+		
+		// Remove existing features
+		for (ServerFeature sf: ServerFeature.findAll()){
+			sf.delete();
+		}
+		
+		// Add features in properties configuration
+		Iterator i = config.getKeys();
+		while (i.hasNext()){
+			String klass = (String) i.next();
+			String name = config.getString(klass);
+			try {
+				ServerFeature sf = createFeature(name, klass);
+				// Only install it if there isn't an existing
+				// feature with the same name
+				if (ServerFeature.findByName(name) == null){
+					sf.save();
+					_logger.info("Installed feature:"+name);					
+				} else {
+					_logger.error("Error installing feature: "+name+" was already installed");
+				}
+
+			} catch (Exception e) {
+				_logger.error("Error installing feature:"+e.getMessage());
+			}
+		}
+		dbManager.commitTransaction();
+	}
+
+	/**
+	 * Returns a valid ServerFeature for the supplied parameters, or throws
+	 * an exception if the feature specified is not a valid ServerFeature.
+	 * @param name the name of the feature, which must be a valid IRI
+	 * @param klass the Class name of the feature, which must implement the IFeature interface
+	 */
+	@SuppressWarnings("unchecked")
+	public static ServerFeature createFeature(String name, String klass) throws Exception{
+		// Are required parameters missing?
+		if (name == null || klass == null){
+			throw new Exception("Invalid feature");
+		}
+		// Does the class exist?
+		Class theClass;
+		try {
+			theClass = Class.forName(klass);
+		} catch (Exception e) {
+			throw new Exception("Invalid feature: class not found");
+		}
+		// Does the class implement IFeature?
+		boolean implementsFeature = false;
+		Class[] interfaces = theClass.getInterfaces();
+		if (interfaces != null) {
+			if (interfaces.length > 0){
+				if (interfaces[0].getName().equals("org.apache.wookie.feature.IFeature")) implementsFeature = true;
+			}
+		}
+		if (!implementsFeature) throw new Exception("Invalid feature: class is not a Feature class");
+		
+		// Does the feature name match that in the class?
+		if (!((IFeature) theClass.newInstance()).getName().equals(name)) throw new Exception("Invalid feature: feature name supplied and name in the class do not match");;
+
+		// Is the feature name a valid IRI?
+		if (!IRIValidator.isValidIRI(name)){
+			throw new Exception("Invalid feature: name is not a valid IRI");			
+		}
+		
+		// All is well, create the SF and return it
+		ServerFeature sf = new ServerFeature();
+		sf.setClassName(klass);
+		sf.setFeatureName(name);
+		return sf;
+	}
+
+}

Modified: incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java?rev=903014&r1=903013&r2=903014&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/ContextListener.java Mon Jan 25 23:35:06 2010
@@ -27,6 +27,7 @@
 import org.apache.wookie.beans.Widget;
 import org.apache.wookie.exceptions.BadManifestException;
 import org.apache.wookie.exceptions.BadWidgetZipFileException;
+import org.apache.wookie.feature.FeatureLoader;
 import org.apache.wookie.manager.impl.WidgetAdminManager;
 import org.apache.wookie.manifestmodel.IManifestModel;
 import org.apache.wookie.util.WgtWatcher;
@@ -106,6 +107,22 @@
 				_logger.info("Using default open social properties, configure your local server using: " + localOpenSocialPropsFile.toString());
 			}
 			context.setAttribute("opensocial", (Configuration) opensocialConfiguration);
+			
+			/*
+			 * Load installed features
+			 */
+			PropertiesConfiguration featuresConfiguration;
+			File localFeaturesPropsFile = new File(System.getProperty("user.dir") + File.separator + "local.features.properties");
+			if (localFeaturesPropsFile.exists()) {
+				featuresConfiguration = new PropertiesConfiguration(localFeaturesPropsFile);
+				_logger.info("Loading local features file: " + localOpenSocialPropsFile.toString());
+			} else {
+				featuresConfiguration = new PropertiesConfiguration("features.properties");
+				featuresConfiguration.setFile(localFeaturesPropsFile);
+				featuresConfiguration.save();
+				_logger.info("Loading default features, configure your local server using: " + localFeaturesPropsFile.toString());
+			}
+			FeatureLoader.loadFeatures(featuresConfiguration);
 		} 
 		catch (ConfigurationException ex) {
 			_logger.error("ConfigurationException thrown: "+ ex.toString());