Author: scottbw
Date: Mon Mar 26 20:28:55 2012
New Revision: 1305541

URL: http://svn.apache.org/viewvc?rev=1305541&view=rev
Log:
Changed the persistence mechanism for API keys from using a database table to 
an editable configuration file similar to access policies; see WOOKIE-331. The 
REST API is unchanged.

Added:
    incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/
    incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/
    
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/ApiKeysTest.java
    incubator/wookie/trunk/src/keys
    incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKey.java
    
incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeyUtils.java
    incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeys.java
Removed:
    
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/impl/ApiKeyImpl.java
    incubator/wookie/trunk/src/org/apache/wookie/beans/IApiKey.java
    incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/impl/ApiKeyImpl.java
    incubator/wookie/trunk/src/org/apache/wookie/helpers/WidgetKeyManager.java
Modified:
    incubator/wookie/trunk/UPGRADING
    incubator/wookie/trunk/etc/ddl-schema/wookie-schema.xml
    
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java
    
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/wookie-schema.cnd
    
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/beans/AbstractPersistenceTest.java
    
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ApiKeyControllerTest.java
    incubator/wookie/trunk/src/META-INF/persistence.xml
    
incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/JPAPersistenceManager.java
    
incubator/wookie/trunk/src/org/apache/wookie/beans/util/PersistenceManagerFactory.java
    
incubator/wookie/trunk/src/org/apache/wookie/controller/ApiKeyController.java
    incubator/wookie/trunk/src/org/apache/wookie/helpers/ApiKeyHelper.java
    
incubator/wookie/trunk/src/org/apache/wookie/server/security/AuthorizationFilter.java

Modified: incubator/wookie/trunk/UPGRADING
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/UPGRADING?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- incubator/wookie/trunk/UPGRADING (original)
+++ incubator/wookie/trunk/UPGRADING Mon Mar 26 20:28:55 2012
@@ -12,6 +12,9 @@ release and so you should make sure you 
 The Services class and related classes deprecated in earlier versions of 
Wookie were removed in 0.10.0, and these
 tables can be removed from the database. There is a script in 
/scripts/migration to drop these tables.
 
+From 0.10.0 the API keys are managed using a configuration text file rather 
than in the database (as per Policies).
+This means that you should add API keys to the /keys file from the database.
+
 FROM 0.9.1 TO 0.9.2
 ===================
 

Modified: incubator/wookie/trunk/etc/ddl-schema/wookie-schema.xml
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/etc/ddl-schema/wookie-schema.xml?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- incubator/wookie/trunk/etc/ddl-schema/wookie-schema.xml (original)
+++ incubator/wookie/trunk/etc/ddl-schema/wookie-schema.xml Mon Mar 26 20:28:55 
2012
@@ -216,16 +216,6 @@
     </index>
   </table>
 
-  <table name="ApiKey">
-    <column name="id" primaryKey="true" required="true" type="INTEGER"/>
-    <column name="jpa_version" type="INTEGER"/>
-    <column name="value" required="true" size="255" type="VARCHAR"/>
-    <column name="email" required="true" size="255" type="VARCHAR"/>
-    <index name="IXApiKey1">
-      <index-column name="value"/>
-    </index>
-  </table>
-
   <table name="Feature">
     <column name="id" primaryKey="true" required="true" type="INTEGER"/>
     <column name="jpa_version" type="INTEGER"/>

Modified: 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java
 (original)
+++ 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java
 Mon Mar 26 20:28:55 2012
@@ -50,7 +50,6 @@ import org.apache.jackrabbit.ocm.mapper.
 import org.apache.jackrabbit.ocm.query.Filter;
 import org.apache.jackrabbit.ocm.query.Query;
 import org.apache.jackrabbit.ocm.query.QueryManager;
-import org.apache.wookie.beans.IApiKey;
 import org.apache.wookie.beans.IBean;
 import org.apache.wookie.beans.IDescription;
 import org.apache.wookie.beans.IFeature;
@@ -66,7 +65,6 @@ import org.apache.wookie.beans.IStartFil
 import org.apache.wookie.beans.IWidget;
 import org.apache.wookie.beans.IWidgetIcon;
 import org.apache.wookie.beans.IWidgetInstance;
-import org.apache.wookie.beans.jcr.impl.ApiKeyImpl;
 import org.apache.wookie.beans.jcr.impl.DescriptionImpl;
 import org.apache.wookie.beans.jcr.impl.FeatureImpl;
 import org.apache.wookie.beans.jcr.impl.LicenseImpl;
@@ -109,7 +107,6 @@ public class JCRPersistenceManager imple
     private static final Map<String,String> IMPLEMENTATION_FIELD_MAP = new 
HashMap<String,String>();
     static
     {
-        INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IDescription.class, DescriptionImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IFeature.class, FeatureImpl.class);
         INTERFACE_TO_CLASS_MAP.put(ILicense.class, LicenseImpl.class);
@@ -124,7 +121,6 @@ public class JCRPersistenceManager imple
         INTERFACE_TO_CLASS_MAP.put(IWidgetIcon.class, WidgetIconImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, 
WidgetInstanceImpl.class);
 
-        BEAN_INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IParticipant.class, 
ParticipantImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IWidget.class, WidgetImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, 
WidgetInstanceImpl.class);

Modified: 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/wookie-schema.cnd
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/wookie-schema.cnd?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/wookie-schema.cnd
 (original)
+++ 
incubator/wookie/trunk/modules/jcr/src/org/apache/wookie/beans/jcr/wookie-schema.cnd
 Mon Mar 26 20:28:55 2012
@@ -149,7 +149,3 @@
 
 [wookie:whitelist] > nt:base
 - wookie:fUrl (string) mandatory
-
-[wookie:apiKey] > nt:base
-- wookie:value (string) mandatory
-- wookie:email (string) mandatory

Modified: 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/beans/AbstractPersistenceTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/beans/AbstractPersistenceTest.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/beans/AbstractPersistenceTest.java
 (original)
+++ 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/beans/AbstractPersistenceTest.java
 Mon Mar 26 20:28:55 2012
@@ -21,7 +21,6 @@ import javax.naming.Context;
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
 
-import org.apache.wookie.beans.IApiKey;
 import org.apache.wookie.beans.IParticipant;
 import org.apache.wookie.beans.IPreference;
 import org.apache.wookie.beans.IWidget;
@@ -135,8 +134,7 @@ public abstract class AbstractPersistenc
         // and first existing Widget to use as the basis of a  
         // new Widget Instance
         //
-        IApiKey [] apiKeys = persistenceManager.findAll(IApiKey.class);
-        String apiKey = apiKeys[0].getValue();
+        String apiKey = "TEST";
         IWidget [] widgets = persistenceManager.findAll(IWidget.class);
         IWidget widget = widgets[0];        
         widgetGuid = widget.getGuid();
@@ -200,8 +198,6 @@ public abstract class AbstractPersistenc
         //
         // Get the widget instance created in the previous transaction
         // 
-        apiKeys = persistenceManager.findAll(IApiKey.class);
-        apiKey = apiKeys[0].getValue();
         widgets = persistenceManager.findAll(IWidget.class);
         widget = widgets[0];
         IWidgetInstance widgetInstance0 = 
persistenceManager.findWidgetInstanceByGuid(apiKey, "test", 
"test-shared-data-key", widgetGuid);

Modified: 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ApiKeyControllerTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ApiKeyControllerTest.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ApiKeyControllerTest.java
 (original)
+++ 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ApiKeyControllerTest.java
 Mon Mar 26 20:28:55 2012
@@ -33,6 +33,7 @@ import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
 import org.jdom.input.SAXBuilder;
+import org.junit.AfterClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -42,6 +43,15 @@ import org.junit.Test;
 public class ApiKeyControllerTest extends AbstractControllerTest {
 
   private static final String APIKEY_SERVICE_LOCATION_VALID = 
TEST_SERVER_LOCATION  + "keys";
+  
+  
+//  @AfterClass
+//  public static void cleanUp() throws HttpException, IOException{
+//    HttpClient client = new HttpClient();
+//    DeleteMethod del = new DeleteMethod(APIKEY_SERVICE_LOCATION_VALID + "/"  
+ "DUPLICATION_TEST");
+//    setAuthenticationCredentials(client);
+//    client.executeMethod(del);
+//  }
 
   /**
    * Attempt to get the list of API keys without having authenticated first
@@ -105,6 +115,14 @@ public class ApiKeyControllerTest extend
     code = get.getStatusCode();
     assertEquals(200, code);
     assertTrue(get.getResponseBodyAsString().contains("TEST_KEY"));
+    
+    //
+    // Remove the key
+    // 
+    client = new HttpClient();
+    DeleteMethod del = new DeleteMethod(APIKEY_SERVICE_LOCATION_VALID + "/"  + 
"TEST_KEY");
+    setAuthenticationCredentials(client);
+    client.executeMethod(del);
   }
 
   /**
@@ -116,17 +134,27 @@ public class ApiKeyControllerTest extend
   @Test
   public void removeKey() throws JDOMException, IOException {
     String id = null;
+    HttpClient client = new HttpClient();
 
     //
     // Create a new API key
     //
-    HttpClient client = new HttpClient();
+    PostMethod post = new PostMethod(APIKEY_SERVICE_LOCATION_VALID);
+    setAuthenticationCredentials(client);
+    post.setParameter("apikey", "TEST_KEY_TO_REMOVE");
+    post.setParameter("email", "[email protected]");
+    client.executeMethod(post);
+    int code = post.getStatusCode();
+    assertEquals(201, code);
+    
+    
+ 
     GetMethod get = new GetMethod(APIKEY_SERVICE_LOCATION_VALID);
     setAuthenticationCredentials(client);
     client.executeMethod(get);
-    int code = get.getStatusCode();
+    code = get.getStatusCode();
     assertEquals(200, code);
-    assertTrue(get.getResponseBodyAsString().contains("TEST_KEY"));
+    assertTrue(get.getResponseBodyAsString().contains("TEST_KEY_TO_REMOVE"));
 
     //
     // Get the ID of the key we created
@@ -134,7 +162,7 @@ public class ApiKeyControllerTest extend
     Document doc = new SAXBuilder().build(get.getResponseBodyAsStream());
     for (Object key : doc.getRootElement().getChildren()) {
       Element keyElement = (Element) key;
-      if (keyElement.getAttributeValue("value").equals("TEST_KEY")) {
+      if (keyElement.getAttributeValue("value").equals("TEST_KEY_TO_REMOVE")) {
         id = keyElement.getAttributeValue("id");
       }
     }
@@ -160,7 +188,7 @@ public class ApiKeyControllerTest extend
     code = get.getStatusCode();
     assertEquals(200, code);
     System.out.println(get.getResponseBodyAsString());
-    assertFalse(get.getResponseBodyAsString().contains("TEST_KEY"));
+    assertFalse(get.getResponseBodyAsString().contains("TEST_KEY_TO_REMOVE"));
 
   }
 

Added: 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/ApiKeysTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/ApiKeysTest.java?rev=1305541&view=auto
==============================================================================
--- 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/ApiKeysTest.java
 (added)
+++ 
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/server/security/ApiKeysTest.java
 Mon Mar 26 20:28:55 2012
@@ -0,0 +1,68 @@
+/*
+ * 
+ * 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.server.security;
+
+import static org.junit.Assert.*;
+
+import org.apache.wookie.exceptions.ResourceDuplicationException;
+import org.apache.wookie.exceptions.ResourceNotFoundException;
+import org.apache.wookie.server.security.ApiKeys;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class ApiKeysTest {
+  
+  @BeforeClass
+  public static void setup() throws ResourceDuplicationException{
+    ApiKeys.getInstance().clear();
+    ApiKeys.getInstance().addKey("KEYS_TEST_1", "[email protected]");
+  }
+  
+  @Test
+  public void getInstance(){
+    assertNotNull(ApiKeys.getInstance());
+  }
+  
+  @Test
+  public void getKeys(){
+    assertEquals(1, ApiKeys.getInstance().getKeys().length);
+    assertEquals("KEYS_TEST_1", ApiKeys.getInstance().getKeys()[0].getValue());
+  }
+  
+  @Test
+  public void addKey() throws ResourceDuplicationException, 
ResourceNotFoundException{
+    ApiKeys.getInstance().addKey("KEYS_TEST_2", "[email protected]");
+    assertEquals(2, ApiKeys.getInstance().getKeys().length);
+    ApiKeys.getInstance().removeKey("KEYS_TEST_2");
+  }
+  
+  @Test
+  public void removeKey() throws ResourceNotFoundException, 
ResourceDuplicationException{
+    // Add a key
+    ApiKeys.getInstance().addKey("KEYS_TEST_2", "[email protected]");
+    assertEquals(2, ApiKeys.getInstance().getKeys().length);
+    // Remove it
+    ApiKeys.getInstance().removeKey("KEYS_TEST_2");
+    assertEquals(1, ApiKeys.getInstance().getKeys().length);
+    assertEquals("KEYS_TEST_1", ApiKeys.getInstance().getKeys()[0].getValue());
+  }
+
+}

Modified: incubator/wookie/trunk/src/META-INF/persistence.xml
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/META-INF/persistence.xml?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- incubator/wookie/trunk/src/META-INF/persistence.xml (original)
+++ incubator/wookie/trunk/src/META-INF/persistence.xml Mon Mar 26 20:28:55 2012
@@ -20,7 +20,6 @@
 
         <non-jta-data-source>java:comp/env/jdbc/widgetdb</non-jta-data-source>
 
-        <class>org.apache.wookie.beans.jpa.impl.ApiKeyImpl</class>
         <class>org.apache.wookie.beans.jpa.impl.DescriptionImpl</class>
         <class>org.apache.wookie.beans.jpa.impl.FeatureImpl</class>
         <class>org.apache.wookie.beans.jpa.impl.LicenseImpl</class>

Added: incubator/wookie/trunk/src/keys
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/keys?rev=1305541&view=auto
==============================================================================
--- incubator/wookie/trunk/src/keys (added)
+++ incubator/wookie/trunk/src/keys Mon Mar 26 20:28:55 2012
@@ -0,0 +1,16 @@
+##
+## API Keys File
+##
+## This file is dynamically loaded by Wookie and configures
+## API keys for accessing Wookie. Each application that will
+## request widget instances must have its own API key.
+## 
+## The format of entries is key = contact email address
+##
+##
+## Example:
+##
+## mykey = [email protected]
+##
+
[email protected]
\ No newline at end of file

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/JPAPersistenceManager.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/JPAPersistenceManager.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/JPAPersistenceManager.java
 (original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/beans/jpa/JPAPersistenceManager.java
 Mon Mar 26 20:28:55 2012
@@ -47,7 +47,6 @@ import org.apache.openjpa.persistence.Op
 import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.openjpa.persistence.QueryResultCache;
 import org.apache.openjpa.persistence.StoreCache;
-import org.apache.wookie.beans.IApiKey;
 import org.apache.wookie.beans.IAuthor;
 import org.apache.wookie.beans.IBean;
 import org.apache.wookie.beans.IDescription;
@@ -64,7 +63,6 @@ import org.apache.wookie.beans.IStartFil
 import org.apache.wookie.beans.IWidget;
 import org.apache.wookie.beans.IWidgetIcon;
 import org.apache.wookie.beans.IWidgetInstance;
-import org.apache.wookie.beans.jpa.impl.ApiKeyImpl;
 import org.apache.wookie.beans.jpa.impl.AuthorImpl;
 import org.apache.wookie.beans.jpa.impl.DescriptionImpl;
 import org.apache.wookie.beans.jpa.impl.FeatureImpl;
@@ -108,7 +106,6 @@ public class JPAPersistenceManager imple
     private static final Map<String,String> DB_TYPE_TO_JPA_DICTIONARY_MAP = 
new HashMap<String,String>();
     static
     {
-        INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IDescription.class, DescriptionImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IFeature.class, FeatureImpl.class);
         INTERFACE_TO_CLASS_MAP.put(ILicense.class, LicenseImpl.class);
@@ -125,7 +122,6 @@ public class JPAPersistenceManager imple
         INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, 
WidgetInstanceImpl.class);
         INTERFACE_TO_CLASS_MAP.put(IOAuthToken.class, OAuthTokenImpl.class);
 
-        BEAN_INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IParticipant.class, 
ParticipantImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IPreference.class, 
PreferenceImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(ISharedData.class, 
SharedDataImpl.class);
@@ -133,7 +129,6 @@ public class JPAPersistenceManager imple
         BEAN_INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, 
WidgetInstanceImpl.class);
         BEAN_INTERFACE_TO_CLASS_MAP.put(IOAuthToken.class, 
OAuthTokenImpl.class);
 
-        BEAN_INTERFACE_TO_ID_FIELD_TYPE_MAP.put(IApiKey.class, Integer.class);
         BEAN_INTERFACE_TO_ID_FIELD_TYPE_MAP.put(IParticipant.class, 
Integer.class);
         BEAN_INTERFACE_TO_ID_FIELD_TYPE_MAP.put(IWidget.class, Integer.class);
         BEAN_INTERFACE_TO_ID_FIELD_TYPE_MAP.put(IWidgetInstance.class, 
Integer.class);

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/beans/util/PersistenceManagerFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/beans/util/PersistenceManagerFactory.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/beans/util/PersistenceManagerFactory.java
 (original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/beans/util/PersistenceManagerFactory.java
 Mon Mar 26 20:28:55 2012
@@ -17,7 +17,6 @@ package org.apache.wookie.beans.util;
 import java.lang.reflect.Method;
 
 import org.apache.commons.configuration.Configuration;
-import org.apache.wookie.beans.IApiKey;
 import org.apache.wookie.beans.IDescription;
 import org.apache.wookie.beans.IName;
 import org.apache.wookie.beans.IStartFile;
@@ -129,20 +128,6 @@ public class PersistenceManagerFactory
                     initializing = false;
                 }
                 
-                // ApiKey
-                if (initializing && 
(persistenceManager.findAll(IApiKey.class).length == 0))
-                {
-                    // optional: create only if initializing
-                    IApiKey apiKey = 
persistenceManager.newInstance(IApiKey.class);
-                    apiKey.setValue("TEST");
-                    apiKey.setEmail("[email protected]");
-                    persistenceManager.save(apiKey);
-                }
-                else
-                {
-                    initializing = false;
-                }
-                
                 // commit persistence manager transaction
                 try
                 {

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/controller/ApiKeyController.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/controller/ApiKeyController.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/controller/ApiKeyController.java 
(original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/controller/ApiKeyController.java 
Mon Mar 26 20:28:55 2012
@@ -18,21 +18,17 @@
 package org.apache.wookie.controller;
 
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.log4j.Logger;
-import org.apache.wookie.beans.IApiKey;
-import org.apache.wookie.beans.util.IPersistenceManager;
-import org.apache.wookie.beans.util.PersistenceManagerFactory;
 import org.apache.wookie.exceptions.InvalidParametersException;
 import org.apache.wookie.exceptions.ResourceDuplicationException;
 import org.apache.wookie.exceptions.ResourceNotFoundException;
 import org.apache.wookie.exceptions.UnauthorizedAccessException;
 import org.apache.wookie.helpers.ApiKeyHelper;
+import org.apache.wookie.server.security.ApiKeys;
 
 /**
  * Admin controller for creating, updating and listing API keys
@@ -59,9 +55,7 @@ public class ApiKeyController extends Co
   @Override
   protected void index(HttpServletRequest request, HttpServletResponse 
response)
       throws UnauthorizedAccessException, IOException {
-    IPersistenceManager persistenceManager = 
PersistenceManagerFactory.getPersistenceManager();
-    IApiKey[] apiKeys = persistenceManager.findAll(IApiKey.class);
-    returnXml(ApiKeyHelper.createXML(apiKeys),response);
+    
returnXml(ApiKeyHelper.createXML(ApiKeys.getInstance().getKeys()),response);
   }
 
   /* (non-Javadoc)
@@ -74,18 +68,13 @@ public class ApiKeyController extends Co
     String value = request.getParameter("apikey");
     String email = request.getParameter("email");
     if (value == null || email == null || value.trim().length() ==0 || 
email.trim().length() == 0) throw new InvalidParametersException();
-    IPersistenceManager persistenceManager = 
PersistenceManagerFactory.getPersistenceManager();
-    Map<String, Object> values = new HashMap<String, Object>();
-    values.put("value", value);
-    values.put("email", email);
-    if (persistenceManager.findByValues(IApiKey.class, values).length > 0){
-      throw new ResourceDuplicationException();
+    
+    try {
+      ApiKeys.getInstance().addKey(value, email);
+    } catch (Exception e) {
+      throw new ResourceDuplicationException();  
     }
     
-    IApiKey apiKey = persistenceManager.newInstance(IApiKey.class);
-    apiKey.setValue(value);
-    apiKey.setEmail(email);
-    persistenceManager.save(apiKey);
     _logger.info("New API key registered for "+email);
     return true;
   }
@@ -144,12 +133,10 @@ public class ApiKeyController extends Co
   protected boolean remove(String resourceId, HttpServletRequest request)
       throws ResourceNotFoundException, UnauthorizedAccessException,
       InvalidParametersException {
-    IPersistenceManager persistenceManager = 
PersistenceManagerFactory.getPersistenceManager();
-    IApiKey apiKey = persistenceManager.findById(IApiKey.class, resourceId);
-    if (apiKey == null) throw new ResourceNotFoundException();
-    persistenceManager.delete(apiKey);
-    _logger.info("API key deleted for "+apiKey.getEmail());
-    return true;
+    
+      ApiKeys.getInstance().removeKey(resourceId);
+      _logger.info("API key deleted: "+resourceId); 
+      return true;
   }
   
 }

Modified: incubator/wookie/trunk/src/org/apache/wookie/helpers/ApiKeyHelper.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/helpers/ApiKeyHelper.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/helpers/ApiKeyHelper.java 
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/helpers/ApiKeyHelper.java Mon 
Mar 26 20:28:55 2012
@@ -17,7 +17,7 @@
 
 package org.apache.wookie.helpers;
 
-import org.apache.wookie.beans.IApiKey;
+import org.apache.wookie.server.security.ApiKey;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.output.XMLOutputter;
@@ -32,11 +32,11 @@ public class ApiKeyHelper {
    * @param keys the keys to serialize
    * @return a String containing the XML serialization of the API keys
    */
-  public static String createXML(IApiKey[] keys){
+  public static String createXML(ApiKey[] keys){
     Document document = new Document();
     Element keysElement = new Element("keys");
 
-    for(IApiKey key: keys){
+    for(ApiKey key: keys){
       Element keyElement = new Element("key");
       keyElement.setAttribute("id", String.valueOf(key.getId()));
       keyElement.setAttribute("value", key.getValue());

Added: incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKey.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKey.java?rev=1305541&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKey.java 
(added)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKey.java 
Mon Mar 26 20:28:55 2012
@@ -0,0 +1,78 @@
+/*
+ * 
+ * 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.server.security;
+
+/**
+ * Representation of an API key, consisting of an id, a key value, and a 
contact email address
+ */
+public class ApiKey {
+  
+  private Object id;
+  private String value;
+  private String email;
+  
+  public ApiKey(){
+  }
+  
+  public ApiKey(String key, String email){
+    setValue(key);
+    setEmail(email);
+    this.id = key;
+  }
+
+  /**
+   * Get the id of the key
+   * @return
+   */
+  public Object getId() {
+    return id;
+  }
+
+  /**
+   * Get the actual Key value
+   * @return
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * Set the value 
+   * @param value
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Get contact email associated with this key
+   * @return
+   */
+  public String getEmail() {
+    return email;
+  }
+
+  /**
+   * Set the contact email address
+   * @param email
+   */
+  public void setEmail(String email) {
+    this.email = email;
+  }
+
+}

Added: 
incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeyUtils.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeyUtils.java?rev=1305541&view=auto
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeyUtils.java 
(added)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeyUtils.java 
Mon Mar 26 20:28:55 2012
@@ -0,0 +1,112 @@
+/*
+ * 
+ * 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.server.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.mail.Email;
+import org.apache.commons.mail.EmailException;
+import org.apache.commons.mail.SimpleEmail;
+import org.apache.wookie.Messages;
+import org.apache.wookie.exceptions.SystemUnavailableException;
+import org.apache.wookie.util.HashGenerator;
+import org.apache.wookie.w3c.util.RandomGUID;
+
+/**
+ * Static utility methods for API keys
+ * 
+ * (Under Wookie 0.9.x these methods were used for the "request an API key" 
function in the admin UI, and are
+ * retained here for use either in admin clients or possible future APIs)
+ */
+public class ApiKeyUtils {
+  
+  /**
+   * Generates and registers a new API key and notifies the requestor via 
email of the key values.
+   * 
+   * @param request the request to create a new API key
+   * @param email the email address of the registering party
+   * @param localizedMessages the set of localized messages
+   * @throws Exception 
+   */
+  public static void generateKey(HttpServletRequest request, String email, 
Messages localizedMessages) throws Exception {
+    
+    String hashKey = generateAPIKey(email);
+    
+    ApiKeys.getInstance().addKey(hashKey, email);
+    
+    String message = 
localizedMessages.getString("WidgetKeyManager.0")+hashKey+" \n";  
//$NON-NLS-1$//$NON-NLS-2$
+    message+="\n" + localizedMessages.getString("WidgetKeyManager.1"); 
//$NON-NLS-1$ //$NON-NLS-2$
+    
+    Configuration properties = (Configuration) 
request.getSession().getServletContext().getAttribute("properties"); 
//$NON-NLS-1$
+    
+    String server = properties.getString("widget.email.server");
+    int port = properties.getInt("widget.email.port");
+    String contact = properties.getString("widget.email.contact");
+    sendEmail(server, port, contact, email, message, 
properties.getString("widget.email.username"), 
properties.getString("widget.email.password")); //$NON-NLS-1$ //$NON-NLS-2$ 
//$NON-NLS-3$
+  }
+  
+  /**
+   * Generate a usable pseudo-random API key that will work OK in a URL
+   * @param email
+   * @return a String usable as an API key
+   * @throws SystemUnavailableException
+   */
+  public static String generateAPIKey(String email) throws 
SystemUnavailableException{
+    // generate a nonce
+    RandomGUID r = new RandomGUID();
+    String nonce = "nonce-" + r.toString();        //$NON-NLS-1$
+
+    // now use SHA hash on the nonce        
+    String hashKey = HashGenerator.getInstance().encrypt(nonce+email);  
+
+    // get rid of any chars that might upset a url...
+    hashKey = hashKey.replaceAll("=", ".eq."); //$NON-NLS-1$ //$NON-NLS-2$
+    hashKey = hashKey.replaceAll("\\?", ".qu."); //$NON-NLS-1$ //$NON-NLS-2$
+    hashKey = hashKey.replaceAll("&", ".am."); //$NON-NLS-1$ //$NON-NLS-2$
+    hashKey = hashKey.replaceAll("\\+", ".pl."); //$NON-NLS-1$ //$NON-NLS-2$
+    
+    return hashKey;
+  }
+
+  /**
+   * Send email.
+   * 
+   * @param mailserver - the SMTP mail server address
+   * @param from
+   * @param to
+   * @param message
+   * @throws Exception
+   */
+  private static void sendEmail(String mailserver, int port, String from, 
String to, String message, String username, String password) throws 
EmailException {  
+    Email email = new SimpleEmail();
+    email.setDebug(false); // true if you want to debug
+        email.setHostName(mailserver);
+        if (username != null) {
+      email.setAuthentication(username, password);
+          email.getMailSession().getProperties().put(
+             "mail.smtp.starttls.enable", "true");
+    }
+        email.setFrom(from, "Wookie Server");
+        email.setSubject("Wookie API Key");
+        email.setMsg(message);
+        email.addTo(to);
+        email.send();
+  }
+
+}

Added: incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeys.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeys.java?rev=1305541&view=auto
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeys.java 
(added)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/security/ApiKeys.java 
Mon Mar 26 20:28:55 2012
@@ -0,0 +1,203 @@
+/*
+ * 
+ * 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.server.security;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+import org.apache.log4j.Logger;
+import org.apache.wookie.exceptions.ResourceDuplicationException;
+import org.apache.wookie.exceptions.ResourceNotFoundException;
+
+/**
+ * Class for managing API Keys used to gain access to widget instances
+ *
+ */
+public class ApiKeys {
+  
+  static Logger logger = Logger.getLogger(ApiKeys.class.getName());  
+  
+  /*
+   * Lock on the configuration; commons-config isn't thread safe
+   * so we must use an explicit lock to avoid concurrency issues
+   */
+  private final Lock lock = new ReentrantLock();
+  
+  private static ApiKeys instance;
+  
+  private HashMap<String, ApiKey> keys;
+  private  PropertiesConfiguration properties;
+  private  FileChangedReloadingStrategy reloader = new 
FileChangedReloadingStrategy();
+  
+  /**
+   * Private constructor
+   */
+  private ApiKeys(){
+    try {
+      keys = new HashMap<String, ApiKey>();
+      properties = new PropertiesConfiguration("keys");
+      properties.setReloadingStrategy(reloader);
+      load();
+    } catch (ConfigurationException e) {
+      logger.error("Problem initializing the API Keys from configuration", e);
+    }
+  }
+  
+  /**
+   * Get the ApiKeys instance
+   * @return the singleton ApiKeys instance
+   */
+  public static ApiKeys getInstance() {
+    if (instance == null) instance = new ApiKeys();
+    return instance;
+  }
+  
+  /**
+   * Refresh the API keys, checking
+   * if the file needs to be reloaded
+   */
+  private void refresh(){
+    if (reloader.reloadingRequired()){
+      keys.clear();
+      load();
+      reloader.reloadingPerformed();
+    }
+  }
+  
+  /**
+   * Load the API keys from the key
+   * configuration file
+   */
+  private void load(){
+    lock.lock();
+    try {
+      properties.clear();
+      properties.load();
+         
+      @SuppressWarnings("rawtypes")
+      Iterator keys = properties.getKeys();
+      while(keys.hasNext()){
+        String key = (String)keys.next();
+        String email = properties.getString(key);
+        addKeyToCollection(key,email);
+      }
+    } catch (ConfigurationException e) {
+      logger.error("Error loading API Keys from the keys file", e);
+    } finally {
+      lock.unlock();
+    }
+  }
+  
+  /**
+   * Checks if a key exists
+   * @param key
+   * @return true if the key exists, otherwise false
+   */
+  public boolean validate(String key){
+    refresh();
+    if (keys.containsKey(key)){
+      return true;
+    }
+    return false;
+  }
+  
+  /**
+   * Get an array of all the currently installed keys
+   * @return an array of ApiKey objects
+   */
+  public ApiKey[] getKeys(){
+    refresh();
+    return keys.values().toArray(new ApiKey[keys.size()]);
+  }
+  
+  /**
+   * Internal method for adding a new key and saving the
+   * configuration properties file.
+   * @param key
+   * @param email
+   * @return true if the key was successfully added, otherwise false
+   * @throws ConfigurationException
+   */
+  private boolean addKeyToCollection(String key, String email) throws 
ConfigurationException{
+    ApiKey apiKey = new ApiKey(key, email);
+    if (keys.containsKey(apiKey.getValue())){
+      logger.debug("Duplicate key submitted for "+email);
+      return false;
+    } else {
+      // Add
+      keys.put(apiKey.getValue(), apiKey);
+      logger.debug("Key added for "+apiKey.getEmail());
+      return true;
+    }
+  }
+  
+  /**
+   * Add and save a new API key
+   * @param key
+   * @param email
+   * @throws ResourceDuplicationException if the key already exists
+   */
+  public void addKey(String key, String email) throws 
ResourceDuplicationException{
+    try {
+      if (addKeyToCollection(key, email)){
+        lock.lock();
+        try {
+          properties.addProperty(key, email);
+        } finally {
+          lock.unlock();
+        }
+      } else {
+        throw new ResourceDuplicationException();
+      }
+    } catch (ConfigurationException e) {
+      logger.error("Problem with keys properties configuration", e);
+    }
+  }
+  
+  /**
+   * Remove a key
+   * @param key
+   * @throws ResourceNotFoundException 
+   */
+  public void removeKey(String key) throws ResourceNotFoundException{
+    if (keys.containsKey(key)){
+      keys.remove(key);
+    } else {
+      throw new ResourceNotFoundException();
+    }
+  }
+  
+  /**
+   * Clear all keys
+   */
+  public void clear(){
+    keys.clear();
+    lock.lock();
+    try{
+      properties.clear();
+    } finally {
+      lock.unlock();
+    }
+  }
+
+}

Modified: 
incubator/wookie/trunk/src/org/apache/wookie/server/security/AuthorizationFilter.java
URL: 
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/security/AuthorizationFilter.java?rev=1305541&r1=1305540&r2=1305541&view=diff
==============================================================================
--- 
incubator/wookie/trunk/src/org/apache/wookie/server/security/AuthorizationFilter.java
 (original)
+++ 
incubator/wookie/trunk/src/org/apache/wookie/server/security/AuthorizationFilter.java
 Mon Mar 26 20:28:55 2012
@@ -29,9 +29,6 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.log4j.Logger;
-import org.apache.wookie.beans.IApiKey;
-import org.apache.wookie.beans.util.IPersistenceManager;
-import org.apache.wookie.beans.util.PersistenceManagerFactory;
 
 /**
  * Authorization Filter for API Requests
@@ -137,22 +134,12 @@ public class AuthorizationFilter impleme
    * @return true if the API key is registered, false otherwise
    */
   private boolean isRegistered(String apiKey){
-    
-    //
-    // Key not found
-    //
-    IPersistenceManager persistenceManager = 
PersistenceManagerFactory.getPersistenceManager();
-    IApiKey[] apiKeyBean = persistenceManager.findByValue(IApiKey.class, 
"value", apiKey);
-    if (apiKeyBean == null || apiKeyBean.length != 1) {
-      _logger.info("Invalid API key supplied: " + apiKey);
-      return false;
-    }
-
-    //
-    // Key valid
-    //
-    return true;
-    
+      if (ApiKeys.getInstance().validate(apiKey)){
+        return true;
+      } else {
+        _logger.info("Invalid API key supplied: " + apiKey);
+        return false;      
+      }
   }
 
 }


Reply via email to