You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ja...@apache.org on 2011/07/19 16:40:27 UTC

svn commit: r1148365 - in /incubator/rave/trunk: ./ rave-shindig/ rave-shindig/src/main/java/org/apache/rave/os/ rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/ rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/ rave-shindig/...

Author: jasha
Date: Tue Jul 19 14:40:21 2011
New Revision: 1148365

URL: http://svn.apache.org/viewvc?rev=1148365&view=rev
Log:
RAVE-85 implement all methods of OAuthStoreDb
add support for TokenInfo, 
move JQL handling to service's, 
add Guice module for DB handling,
add unit tests

Added:
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthModuleDb.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbProvider.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthTokenInfoDb.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/ConsumerStoreService.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/TokenInfoService.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImpl.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImpl.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/social/opensocial/jpa/openjpa/OpenJPADbModule.java
    incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/
    incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/
    incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImplTest.java
    incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImplTest.java
    incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/
    incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/persistence.xml
Modified:
    incubator/rave/trunk/pom.xml
    incubator/rave/trunk/rave-shindig/pom.xml
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/os/DatabasePopulateContextListener.java
    incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java
    incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml
    incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml
    incubator/rave/trunk/rave-shindig/src/main/webapp/WEB-INF/web.xml
    incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java

Modified: incubator/rave/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/pom.xml?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/pom.xml (original)
+++ incubator/rave/trunk/pom.xml Tue Jul 19 14:40:21 2011
@@ -61,6 +61,7 @@
         <org.openid4java.version>0.9.6</org.openid4java.version>
         <jersey-server.version>1.6</jersey-server.version>
         <jersey-spring.version>1.0</jersey-spring.version>
+        <guice.version>3.0</guice.version>
 
         <!-- Force maven-filesync-plugin rewrite the Eclipse FileSync plugin configuration with
             $mvn filesync:generate -Dmaven.filesync.override=true -->
@@ -147,6 +148,11 @@
               <version>${org.springframework.version}</version>
             </dependency>
             <dependency>
+              <groupId>com.google.inject.extensions</groupId>
+              <artifactId>guice-persist</artifactId>
+              <version>${guice.version}</version>
+            </dependency>
+            <dependency>
               <groupId>org.glassfish.web</groupId>
               <artifactId>jstl-impl</artifactId>
               <version>${jstl.version}</version>

Modified: incubator/rave/trunk/rave-shindig/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/pom.xml?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/pom.xml (original)
+++ incubator/rave/trunk/rave-shindig/pom.xml Tue Jul 19 14:40:21 2011
@@ -62,6 +62,11 @@
     </dependency>
 
     <dependency>
+      <groupId>com.google.inject.extensions</groupId>
+      <artifactId>guice-persist</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.shindig</groupId>
       <artifactId>shindig-social-api</artifactId>
       <scope>provided</scope>
@@ -98,7 +103,7 @@
     <dependency>
       <groupId>org.easymock</groupId>
       <artifactId>easymock</artifactId>
-      <scope>provided</scope>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 

Modified: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/os/DatabasePopulateContextListener.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/os/DatabasePopulateContextListener.java?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/os/DatabasePopulateContextListener.java (original)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/os/DatabasePopulateContextListener.java Tue Jul 19 14:40:21 2011
@@ -48,8 +48,9 @@ public class DatabasePopulateContextList
 
     public static EntityManager getEntityManager() {
         if (em == null) {
-            if (emf == null)
+            if (emf == null) {
                 emf = Persistence.createEntityManagerFactory(PersistenceUnitName);
+            }
             em = emf.createEntityManager();
         }
         return em;
@@ -58,8 +59,7 @@ public class DatabasePopulateContextList
 
     @Override
     public void contextInitialized(ServletContextEvent sce) {
-        String executeScriptQuery = "SELECT * FROM person";
-        String sqlScripts[] = { "initial_data.sql" };
+        String sqlScripts[] = {"initial_data.sql"};
 
         List<File> scriptLocations = new ArrayList<File>();
         for (String sqlScript : sqlScripts) {
@@ -85,7 +85,6 @@ public class DatabasePopulateContextList
         person.setNickname("hoosier");
         person.setSmoker(new EnumDb<Smoker>(Smoker.NO));
 
-        // EntityManager em = emf.createEntityManager();
         EntityManager em = getEntityManager();
         em.getTransaction().begin();
         em.persist(person);

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthModuleDb.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthModuleDb.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthModuleDb.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthModuleDb.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,43 @@
+/*
+ * 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.oauth;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.name.Names;
+import org.apache.shindig.common.crypto.BlobCrypter;
+
+/**
+ * Replacement for the {@link OAuthModuleDb} . We can't extend {@link OAuthModuleDb} and call
+ * super.configure, because Guice does not permit bindig the same thing twice.
+ * Therefore some duplicate code, but at least no changes in {@link OAuthModuleDb}
+ */
+public class OAuthModuleDb extends AbstractModule {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void configure() {
+        bind(BlobCrypter.class).annotatedWith(Names.named(OAuthFetcherConfig.OAUTH_STATE_CRYPTER))
+                .toProvider(OAuthModule.OAuthCrypterProvider.class);
+        bind(OAuthStore.class).toProvider(OAuthStoreDbProvider.class);
+        bind(OAuthRequest.class).toProvider(OAuthModule.OAuthRequestProvider.class);
+    }
+}

Modified: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java (original)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDb.java Tue Jul 19 14:40:21 2011
@@ -19,37 +19,33 @@
 
 package org.apache.shindig.gadgets.oauth;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 import net.oauth.OAuth;
 import net.oauth.OAuthConsumer;
 import net.oauth.OAuthServiceProvider;
 import net.oauth.signature.RSA_SHA1;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.rave.os.DatabasePopulateContextListener;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb;
+import org.apache.shindig.gadgets.oauth.service.ConsumerStoreService;
+import org.apache.shindig.gadgets.oauth.service.TokenInfoService;
 import org.springframework.core.io.ClassPathResource;
 
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
 /**
- * that retrieves the consumer_key, consumer_secret and key_type from the database
+ * {@link OAuthStore} that retrieves the consumer_key, consumer_secret and key_type from the database
  * <p/>
  * Usage scenario: Rave OpenSocial container is the oauth consumer
  * (oauth data are stored elsewhere, this container tries to fetch data from e.g. Google)
  */
 public class OAuthStoreDb implements OAuthStore {
-    /**
-     * This is the JPA entity manager, shared by all threads accessing this service (need to check
-     * that its really thread safe).
-     */
-    private EntityManager entityManager;
+
+    private ConsumerStoreService oAuthStoreService;
+
+    private TokenInfoService tokenInfoService;
 
     /**
      * Callback to use when no per-key callback URL is found.
@@ -64,26 +60,25 @@ public class OAuthStoreDb implements OAu
 
     public OAuthStoreDb(String defaultCallbackUrl,
                         String pathToPrivateKey,
-                        String privateKeyName) throws IOException {
-        this(defaultCallbackUrl, pathToPrivateKey, privateKeyName,
-                DatabasePopulateContextListener.getEntityManager());
-    }
-
-    public OAuthStoreDb(String defaultCallbackUrl,
-                        String pathToPrivateKey,
                         String privateKeyName,
-                        EntityManager entityManager) throws IOException {
+                        ConsumerStoreService oAuthStoreService,
+                        TokenInfoService tokenInfoService) throws IOException {
         this.defaultCallbackUrl = defaultCallbackUrl;
         this.defaultKey = loadDefaultKey(pathToPrivateKey, privateKeyName);
-        this.entityManager = entityManager;
+        this.oAuthStoreService = oAuthStoreService;
+        this.tokenInfoService = tokenInfoService;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ConsumerInfo getConsumerKeyAndSecret(SecurityToken securityToken, String serviceName,
                                                 OAuthServiceProvider provider)
             throws GadgetException {
         String gadgetUri = securityToken.getAppUrl();
-        OAuthConsumerStoreDb consumerStoreDb = findOAuthConsumerStore(gadgetUri, serviceName);
+        OAuthConsumerStoreDb consumerStoreDb = oAuthStoreService.findOAuthConsumerStore(
+                gadgetUri, serviceName);
         if (consumerStoreDb == null) {
             return null;
         }
@@ -95,21 +90,53 @@ public class OAuthStoreDb implements OAu
         return new ConsumerInfo(consumer, consumerStoreDb.getKeyName(), callbackUrl);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public TokenInfo getTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName) throws GadgetException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public TokenInfo getTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo,
+                                  String serviceName, String tokenName) throws GadgetException {
+        OAuthTokenInfoDb info = tokenInfoService.findOAuthTokenInfo(
+                securityToken.getViewerId(), securityToken.getAppUrl(),
+                OAuthTokenInfoDb.MODULE_ID, tokenName, serviceName);
+        if (info == null) {
+            return null;
+        }
+
+        return new TokenInfo(info.getAccessToken(), info.getTokenSecret(),
+                info.getSessionHandle(), info.getTokenExpireMillis());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public void setTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName, TokenInfo tokenInfo) throws GadgetException {
-        //To change body of implemented methods use File | Settings | File Templates.
+    public void setTokenInfo(SecurityToken securityToken, ConsumerInfo consumerInfo,
+                             String serviceName, String tokenName, TokenInfo tokenInfo) throws GadgetException {
+        OAuthTokenInfoDb tokenInfoDb = new OAuthTokenInfoDb(securityToken,
+                serviceName, tokenName, tokenInfo);
+        tokenInfoService.saveOAuthTokenInfo(tokenInfoDb);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public void removeToken(SecurityToken securityToken, ConsumerInfo consumerInfo, String serviceName, String tokenName) throws GadgetException {
-        //To change body of implemented methods use File | Settings | File Templates.
+    public void removeToken(SecurityToken securityToken, ConsumerInfo consumerInfo,
+                            String serviceName, String tokenName) throws GadgetException {
+        tokenInfoService.deleteOAuthTokenInfo(
+                securityToken.getViewerId(), securityToken.getAppUrl(),
+                OAuthTokenInfoDb.MODULE_ID, tokenName, serviceName);
     }
 
+    /**
+     * Loads {@link BasicOAuthStoreConsumerKeyAndSecret} needed if there is no specific consumer key and secret
+     *
+     * @param signingKeyFile location of the signing key file on the classpath or filesystem
+     * @param signingKeyName name of the signing key file
+     * @return RSA_PRIVATE key and secret read from the classpath or file system
+     * @throws IOException if the file cannot be read
+     */
     static BasicOAuthStoreConsumerKeyAndSecret loadDefaultKey(
             String signingKeyFile, String signingKeyName) throws IOException {
         InputStream inputStream = new ClassPathResource(signingKeyFile)
@@ -125,7 +152,8 @@ public class OAuthStoreDb implements OAu
      * Creates an {@link OAuthConsumer} based on the OAuth signature method
      *
      * @param provider        {@link net.oauth.OAuthServiceProvider}
-     * @param consumerStoreDb {@link org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb} persistent OAuth consumer keys & secrets
+     * @param consumerStoreDb {@link org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb}
+     *                        persistent OAuth consumer keys & secrets
      * @return {@link OAuthConsumer} if the signature method is supported
      */
     private OAuthConsumer createOAuthConsumer(OAuthServiceProvider provider,
@@ -159,19 +187,4 @@ public class OAuthStoreDb implements OAu
         return consumer;
     }
 
-    OAuthConsumerStoreDb findOAuthConsumerStore(String gadgetUri, String serviceName) {
-        if (StringUtils.isBlank(gadgetUri) || StringUtils.isBlank(serviceName)) {
-            return null;
-        }
-        Query q = entityManager.createQuery("SELECT x FROM OAuthConsumerStoreDb x " +
-                "WHERE x.gadgetUri = :gadgetUriParam and x.serviceName = :serviceNameParam");
-        q.setParameter("gadgetUriParam", gadgetUri).setParameter("serviceNameParam", serviceName);
-        q.setFirstResult(0);
-        q.setMaxResults(1);
-        List<OAuthConsumerStoreDb> results = (List<OAuthConsumerStoreDb>) q.getResultList();
-        if (CollectionUtils.isEmpty(results)) {
-            return null;
-        }
-        return results.get(0);
-    }
 }

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbProvider.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbProvider.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbProvider.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbProvider.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shindig.gadgets.oauth;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.persistence.EntityManager;
+
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.inject.spi.Message;
+import org.apache.rave.os.DatabasePopulateContextListener;
+import org.apache.shindig.gadgets.oauth.service.ConsumerStoreService;
+import org.apache.shindig.gadgets.oauth.service.TokenInfoService;
+import org.apache.shindig.gadgets.oauth.service.impl.ConsumerStoreServiceDbImpl;
+import org.apache.shindig.gadgets.oauth.service.impl.TokenInfoServiceDbImpl;
+import org.apache.shindig.social.opensocial.jpa.openjpa.OpenJPADbModule;
+
+/**
+ * {@link com.google.inject.Singleton} {@link Provider} for {@link OAuthStoreDb}
+ */
+@Singleton
+public class OAuthStoreDbProvider implements Provider<OAuthStore> {
+    private static final String OAUTH_CALLBACK_URL = "shindig.signing.global-callback-url";
+    private static final String OAUTH_SIGNING_KEY_FILE = "shindig.signing.key-file";
+    private static final String OAUTH_SIGNING_KEY_NAME = "shindig.signing.key-name";
+
+    private final OAuthStoreDb store;
+    private ConsumerStoreService consumerStoreService;
+    private TokenInfoService tokenInfoService;
+
+    @Inject
+    public OAuthStoreDbProvider(@Named(OAUTH_CALLBACK_URL) String defaultCallbackUrl,
+                                @Named(OAUTH_SIGNING_KEY_FILE) String pathToPrivateKey,
+                                @Named(OAUTH_SIGNING_KEY_NAME) String privateKeyName) {
+        super();
+        try {
+            Injector dbInjector = Guice.createInjector(new OpenJPADbModule());
+            this.store = new OAuthStoreDb(defaultCallbackUrl, pathToPrivateKey, privateKeyName,
+                    getConsumerStoreService(dbInjector), getTokenInfoService(dbInjector));
+        } catch (IOException e) {
+            throw new CreationException(Arrays.asList(
+                    new Message("Could not initialize OAuthStore " + e.getMessage())
+            ));
+        }
+    }
+
+    /**
+     * @return {@link ConsumerStoreService} that can retrieve OAuth consumer keys & secretss
+     * @param dbInjector {@link Injector} for persistence
+     */
+    protected ConsumerStoreService getConsumerStoreService(Injector dbInjector) {
+        if (consumerStoreService == null) {
+            consumerStoreService = dbInjector.getInstance(ConsumerStoreServiceDbImpl.class);
+        }
+        return consumerStoreService;
+    }
+
+    /**
+     * @return {@link TokenInfoService} that can retrieve TokenInfo from the db
+     * @param dbInjector {@link Injector} for persistence
+     */
+    protected TokenInfoService getTokenInfoService(Injector dbInjector) {
+        if (tokenInfoService == null) {
+            tokenInfoService = dbInjector.getInstance(TokenInfoServiceDbImpl.class);
+        }
+        return tokenInfoService;
+    }
+
+    /**
+     * @return {@link EntityManager} for this provider
+     */
+    protected static EntityManager getEntityManager() {
+        return DatabasePopulateContextListener.getEntityManager();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public OAuthStore get() {
+        return store;
+    }
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthTokenInfoDb.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthTokenInfoDb.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthTokenInfoDb.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/jpa/OAuthTokenInfoDb.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,174 @@
+/*
+ * 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.oauth.jpa;
+
+/**
+ * Bean for OAuth TokenInfo
+ */
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.gadgets.oauth.OAuthStore;
+import org.apache.shindig.social.opensocial.jpa.api.DbObject;
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+@Entity
+@Table(name = "oauth_token_info")
+public class OAuthTokenInfoDb implements DbObject {
+    /**
+     * @see {@link org.apache.shindig.social.core.oauth.OAuthSecurityToken#getModuleId()}
+     */
+    public static final String MODULE_ID = "NOT_USED";
+
+    @Id
+    @GeneratedValue(strategy = IDENTITY)
+    @Column(name = "oid")
+    private long objectId;
+
+    @Column(name = "access_token")
+    private String accessToken;
+
+    @Column(name = "token_secret")
+    private String tokenSecret;
+
+    @Column(name = "session_handle")
+    private String sessionHandle;
+
+    @Column(name = "token_expire_millis")
+    private long tokenExpireMillis;
+
+    @Column(name = "app_url")
+    private String appUrl;
+
+    @Column(name = "module_id")
+    private String moduleId;
+
+    @Column(name = "service_name")
+    private String serviceName;
+
+    @Column(name = "token_name")
+    private String tokenName;
+
+    @Column(name = "user_id")
+    private String userId;
+
+    public OAuthTokenInfoDb() {
+        super();
+    }
+
+    public OAuthTokenInfoDb(SecurityToken securityToken, String serviceName,
+                            String tokenName, OAuthStore.TokenInfo tokenInfo) {
+        this.setAccessToken(tokenInfo.getAccessToken());
+        this.setAppUrl(securityToken.getAppUrl());
+        this.setModuleId(MODULE_ID);
+        this.setServiceName(serviceName);
+        this.setSessionHandle(tokenInfo.getSessionHandle());
+        this.setTokenExpireMillis(tokenInfo.getTokenExpireMillis());
+        this.setTokenName(tokenName);
+        this.setTokenSecret(tokenInfo.getTokenSecret());
+        this.setUserId(securityToken.getViewerId());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long getObjectId() {
+        return objectId;
+    }
+
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    public String getTokenSecret() {
+        return tokenSecret;
+    }
+
+    public void setTokenSecret(String tokenSecret) {
+        this.tokenSecret = tokenSecret;
+    }
+
+    public String getSessionHandle() {
+        return sessionHandle;
+    }
+
+    public void setSessionHandle(String sessionHandle) {
+        this.sessionHandle = sessionHandle;
+    }
+
+    public long getTokenExpireMillis() {
+        return tokenExpireMillis;
+    }
+
+    public void setTokenExpireMillis(long tokenExpireMillis) {
+        this.tokenExpireMillis = tokenExpireMillis;
+    }
+
+    public String getAppUrl() {
+        return appUrl;
+    }
+
+    public void setAppUrl(String appUrl) {
+        this.appUrl = appUrl;
+    }
+
+    public String getModuleId() {
+        return moduleId;
+    }
+
+    public void setModuleId(String moduleId) {
+        this.moduleId = moduleId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getTokenName() {
+        return tokenName;
+    }
+
+    public void setTokenName(String tokenName) {
+        this.tokenName = tokenName;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/ConsumerStoreService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/ConsumerStoreService.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/ConsumerStoreService.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/ConsumerStoreService.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,50 @@
+/*
+ * 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.oauth.service;
+
+import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb;
+
+/**
+ * Service to handle OAuth consumer info
+ */
+public interface ConsumerStoreService {
+
+    /**
+     * Fetches {@link OAuthConsumerStoreDb} based on the gadget location and the service provider
+     *
+     * @param gadgetUri   location of the gadget definition
+     * @param serviceName name of the service provider
+     * @return {@link OAuthConsumerStoreDb} or {@literal null} if none matches the criteria
+     */
+    public OAuthConsumerStoreDb findOAuthConsumerStore(String gadgetUri, String serviceName);
+
+    /**
+     * Persists {@link OAuthConsumerStoreDb}
+     *
+     * @param consumerStoreDb {@link OAuthConsumerStoreDb} to store
+     */
+    public void save(OAuthConsumerStoreDb consumerStoreDb);
+
+    /**
+     * Removes the {@link OAuthConsumerStoreDb} from the database
+     * @param consumerStoreDb {@link OAuthConsumerStoreDb} to delete
+     */
+    public void delete(OAuthConsumerStoreDb consumerStoreDb);
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/TokenInfoService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/TokenInfoService.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/TokenInfoService.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/TokenInfoService.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,60 @@
+/*
+ * 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.oauth.service;
+
+import org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb;
+
+/**
+ * Service to handle OAuth Tokens
+ */
+public interface TokenInfoService {
+
+    /**
+     * Retrieves {@link OAuthTokenInfoDb}
+     *
+     * @param userId      unique identifier of gadget viewer
+     * @param appUrl      URL of the gadget
+     * @param moduleId    the module ID of the application
+     * @param tokenName   gadget's nickname for the token to use
+     * @param serviceName name of the service provider
+     * @return {@link OAuthTokenInfoDb} or {@literal null} if none matches the criteria
+     */
+    public OAuthTokenInfoDb findOAuthTokenInfo(String userId, String appUrl, String moduleId,
+                                               String tokenName, String serviceName);
+
+    /**
+     * Persists the {@link OAuthTokenInfoDb} to the data store
+     *
+     * @param tokenInfoDb {@link OAuthTokenInfoDb} to save
+     */
+    void saveOAuthTokenInfo(OAuthTokenInfoDb tokenInfoDb);
+
+    /**
+     * Removes the {@link OAuthTokenInfoDb}'s that match the criteria from the data store
+     *
+     * @param userId      unique identifier of the gadget viewer
+     * @param appUrl      URL of the gadget
+     * @param moduleId    the module ID of the application
+     * @param tokenName   gadget's nickname for the token to use
+     * @param serviceName name of the service provider
+     */
+    void deleteOAuthTokenInfo(String userId, String appUrl, String moduleId,
+                              String tokenName, String serviceName);
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImpl.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImpl.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImpl.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImpl.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,108 @@
+/*
+ * 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.oauth.service.impl;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import com.google.inject.Inject;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb;
+import org.apache.shindig.gadgets.oauth.service.ConsumerStoreService;
+
+/**
+ * DB (OpenJPA) implementation of {@link ConsumerStoreService}
+ */
+public class ConsumerStoreServiceDbImpl implements ConsumerStoreService {
+    private static final String GADGET_URI_PARAM = "gadgetUriParam";
+    private static final String SERVICE_NAME_PARAM = "serviceNameParam";
+
+    /**
+     * This is the JPA entity manager, shared by all threads accessing this service (need to check
+     * that its really thread safe).
+     */
+    private EntityManager entityManager;
+
+    @Inject
+    public ConsumerStoreServiceDbImpl(EntityManager entityManager) {
+        super();
+        this.entityManager = entityManager;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public OAuthConsumerStoreDb findOAuthConsumerStore(final String gadgetUri,
+                                                       final String serviceName) {
+        if (StringUtils.isBlank(gadgetUri) || StringUtils.isBlank(serviceName)) {
+            return null;
+        }
+        final Query query = getFindOAuthConsumerStoreQuery(gadgetUri, serviceName);
+        final List results = query.getResultList();
+        if (CollectionUtils.isNotEmpty(results)) {
+            return (OAuthConsumerStoreDb) results.get(0);
+        }
+        return null;
+    }
+
+    /**
+     * TODO check how we can use @Transactional
+     * {@inheritDoc}
+     */
+    @Override
+    public void save(OAuthConsumerStoreDb consumerStoreDb) {
+        entityManager.getTransaction().begin();
+        entityManager.persist(consumerStoreDb);
+        entityManager.getTransaction().commit();
+    }
+
+    /**
+     * TODO check how we can use @Transactional
+     * {@inheritDoc}
+     */
+    @Override
+    public void delete(OAuthConsumerStoreDb consumerStoreDb) {
+        entityManager.getTransaction().begin();
+        entityManager.remove(consumerStoreDb);
+        entityManager.getTransaction().commit();
+    }
+
+    /**
+     * Builds {@link Query} to find a single {@link OAuthConsumerStoreDb}
+     *
+     * @param gadgetUri   location of the gadget definition
+     * @param serviceName name of the service provider
+     * @return {@link Query}
+     */
+    Query getFindOAuthConsumerStoreQuery(final String gadgetUri, final String serviceName) {
+        StringBuilder qString = new StringBuilder();
+        qString.append("SELECT x FROM OAuthConsumerStoreDb x ");
+        qString.append("WHERE x.gadgetUri = :").append(GADGET_URI_PARAM);
+        qString.append(" and x.serviceName = :").append(SERVICE_NAME_PARAM);
+        Query q = entityManager.createQuery(qString.toString());
+        q.setParameter(GADGET_URI_PARAM, gadgetUri).setParameter(SERVICE_NAME_PARAM, serviceName);
+        q.setFirstResult(0).setMaxResults(1);
+        return q;
+    }
+
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImpl.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImpl.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImpl.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImpl.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,131 @@
+/*
+ * 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.oauth.service.impl;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import com.google.inject.Inject;
+import com.google.inject.persist.Transactional;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb;
+import org.apache.shindig.gadgets.oauth.service.TokenInfoService;
+
+/**
+ * DB (OpenJPA) implementation of {@link TokenInfoService}
+ */
+public class TokenInfoServiceDbImpl implements TokenInfoService {
+
+    private static final String USER_ID_PARAM = "userIdParam";
+    private static final String APP_URL_PARAM = "appUrlParam";
+    private static final String MODULE_ID_PARAM = "moduleIdParam";
+    private static final String TOKEN_NAME_PARAM = "tokenNameParam";
+    private static final String SERVICE_NAME_PARAM = "serviceNameParam";
+
+    /**
+     * This is the JPA entity manager, shared by all threads accessing this service (need to check
+     * that its really thread safe).
+     */
+    protected EntityManager entityManager;
+
+    @Inject
+    public TokenInfoServiceDbImpl(EntityManager entityManager) {
+        this.entityManager = entityManager;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public OAuthTokenInfoDb findOAuthTokenInfo(String userId, String appUrl,
+                                               String moduleId, String tokenName, String serviceName) {
+        final Query query = getFindOAuthTokenInfoQuery(userId, appUrl, moduleId, tokenName, serviceName);
+        final List results = query.getResultList();
+        if (CollectionUtils.isNotEmpty(results)) {
+            return (OAuthTokenInfoDb) results.get(0);
+        }
+        return null;
+    }
+
+    /**
+     * TODO find how to use @Transactional
+     * {@inheritDoc}
+     */
+    @Override
+    public void saveOAuthTokenInfo(OAuthTokenInfoDb tokenInfoDb) {
+        entityManager.getTransaction().begin();
+        if (tokenInfoDb.getObjectId() == 0L) {
+            entityManager.persist(tokenInfoDb);
+        } else {
+            entityManager.merge(tokenInfoDb);
+        }
+        entityManager.getTransaction().commit();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    @Transactional
+    public void deleteOAuthTokenInfo(String userId, String appUrl, String moduleId,
+                                     String tokenName, String serviceName) {
+        OAuthTokenInfoDb tokenInfoDb = findOAuthTokenInfo(userId, appUrl, moduleId,
+                tokenName, serviceName);
+        if (tokenInfoDb != null) {
+            entityManager.getTransaction().begin();
+            entityManager.remove(tokenInfoDb);
+            entityManager.getTransaction().commit();
+        }
+    }
+
+
+    /**
+     * Builds {@link Query} to find a single {@link OAuthTokenInfoDb}
+     *
+     * @param userId      unique identifier of a user
+     * @param appUrl      URL of the gadget
+     * @param moduleId    the module ID of the application
+     * @param tokenName   gadget's nickname for the token to use
+     * @param serviceName name of the service provider
+     * @return {@link Query}
+     */
+    Query getFindOAuthTokenInfoQuery(final String userId, final String appUrl, final String moduleId,
+                                     final String tokenName, final String serviceName) {
+        StringBuilder qString = new StringBuilder();
+        qString.append("SELECT x FROM OAuthTokenInfoDb x ");
+        qString.append("WHERE x.userId = :").append(USER_ID_PARAM);
+        qString.append(" AND x.appUrl = :").append(APP_URL_PARAM);
+        qString.append(" AND x.moduleId = :").append(MODULE_ID_PARAM);
+        qString.append(" AND x.tokenName = :").append(TOKEN_NAME_PARAM);
+        qString.append(" AND x.serviceName = :").append(SERVICE_NAME_PARAM);
+
+        Query query = entityManager.createQuery(qString.toString());
+        query.setParameter(USER_ID_PARAM, userId);
+        query.setParameter(APP_URL_PARAM, appUrl);
+        query.setParameter(MODULE_ID_PARAM, moduleId);
+        query.setParameter(TOKEN_NAME_PARAM, tokenName);
+        query.setParameter(SERVICE_NAME_PARAM, serviceName);
+        query.setFirstResult(0).setMaxResults(1);
+        return query;
+    }
+
+}

Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/social/opensocial/jpa/openjpa/OpenJPADbModule.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/social/opensocial/jpa/openjpa/OpenJPADbModule.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/social/opensocial/jpa/openjpa/OpenJPADbModule.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/shindig/social/opensocial/jpa/openjpa/OpenJPADbModule.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,65 @@
+/*
+ * 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.social.opensocial.jpa.openjpa;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+/**
+ * Guice module to provide an {@link EntityManager}
+ */
+public class OpenJPADbModule extends AbstractModule {
+    // EntityManagerFactory is thread-safe while EntityManager is not.
+    // See http://www.benmccann.com/dev-blog/hibernate-with-jpa-annotations-and-guice/
+    private static final ThreadLocal<EntityManager> ENTITY_MANAGER_CACHE
+            = new ThreadLocal<EntityManager>();
+
+    public void configure() {
+    }
+
+    /**
+     * @return {@link EntityManagerFactory} configured in META-INF/persistence.xml
+     */
+    @Provides
+    @Singleton
+    public EntityManagerFactory provideEntityManagerFactory() {
+        // TODO: read properties instead of preconfigured db connection in raveShindigPersistenceUnit
+        return Persistence.createEntityManagerFactory("raveShindigPersistenceUnit");
+    }
+
+    /**
+     * @param entityManagerFactory {@link EntityManagerFactory}
+     * @return thread-safe {@link EntityManager}
+     */
+    @Provides
+    public EntityManager provideEntityManager(EntityManagerFactory entityManagerFactory) {
+        EntityManager entityManager = ENTITY_MANAGER_CACHE.get();
+        if (entityManager == null) {
+            ENTITY_MANAGER_CACHE.set(entityManager = entityManagerFactory.createEntityManager());
+        }
+        return entityManager;
+    }
+
+}

Modified: incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml (original)
+++ incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/orm.xml Tue Jul 19 14:40:21 2011
@@ -85,4 +85,5 @@
   <entity class="org.apache.shindig.social.opensocial.jpa.ApplicationDataMapValueDb">
   </entity>
   <entity class="org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb"/>
+  <entity class="org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb"/>
 </entity-mappings>

Modified: incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml (original)
+++ incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml Tue Jul 19 14:40:21 2011
@@ -18,32 +18,21 @@
   ~ under the License.
   -->
 <persistence xmlns="http://java.sun.com/xml/ns/persistence"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
-	version="2.0">
-	<persistence-unit name="raveShindigPersistenceUnit"
-		transaction-type="RESOURCE_LOCAL">
-		<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-		<properties>
-			<property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
-			<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" />
-			<property name="openjpa.ConnectionDriverName" value="org.h2.Driver" />
-			<property name="openjpa.ConnectionURL" value="jdbc:h2:mem:portal;DB_CLOSE_DELAY=-1" />
-			<property name="openjpa.ConnectionUserName" value="sa" />
-			<property name="openjpa.ConnectionPassword" value="sa" />
-		</properties>
-	</persistence-unit>
-	
-	
-	 <persistence-unit name="raveShindigOpenJPATest" transaction-type="RESOURCE_LOCAL">
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+  version="2.0">
+  <persistence-unit name="raveShindigPersistenceUnit" transaction-type="RESOURCE_LOCAL">
     <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+    <class>org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb</class>
+    <class>org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb</class>
     <properties>
       <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
       <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" />
       <property name="openjpa.ConnectionDriverName" value="org.h2.Driver" />
-      <property name="openjpa.ConnectionURL" value="jdbc:h2:mem:portal;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=10000" />
+      <property name="openjpa.ConnectionURL" value="jdbc:h2:mem:portal;DB_CLOSE_DELAY=-1" />
       <property name="openjpa.ConnectionUserName" value="sa" />
       <property name="openjpa.ConnectionPassword" value="sa" />
     </properties>
   </persistence-unit>
+
 </persistence>

Modified: incubator/rave/trunk/rave-shindig/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/webapp/WEB-INF/web.xml?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/webapp/WEB-INF/web.xml (original)
+++ incubator/rave/trunk/rave-shindig/src/main/webapp/WEB-INF/web.xml Tue Jul 19 14:40:21 2011
@@ -34,7 +34,7 @@
       org.apache.shindig.gadgets.DefaultGuiceModule:
       org.apache.shindig.social.core.config.SocialApiGuiceModule:
       org.apache.rave.os.JPAOpenSocialModule:
-      org.apache.shindig.gadgets.oauth.OAuthModule:
+      org.apache.shindig.gadgets.oauth.OAuthModuleDb:
       org.apache.shindig.common.cache.ehcache.EhCacheModule:
       org.apache.shindig.sample.shiro.ShiroGuiceModule:
       org.apache.shindig.sample.container.SampleContainerGuiceModule:

Modified: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java?rev=1148365&r1=1148364&r2=1148365&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java (original)
+++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/OAuthStoreDbTest.java Tue Jul 19 14:40:21 2011
@@ -19,46 +19,87 @@
 
 package org.apache.shindig.gadgets.oauth;
 
+import java.io.IOException;
+import java.util.Date;
+
+import net.oauth.OAuth;
 import net.oauth.OAuthServiceProvider;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb;
+import org.apache.shindig.gadgets.oauth.service.ConsumerStoreService;
+import org.apache.shindig.gadgets.oauth.service.TokenInfoService;
 import org.apache.shindig.social.core.oauth.OAuthSecurityToken;
+import org.junit.Before;
 import org.junit.Test;
 
-import java.util.Date;
-
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 
 /**
  * Test class for {@link OAuthStoreDb}
  */
 public class OAuthStoreDbTest {
     private static final long NEXT_HOUR = 1000L * 60L * 60L;
+    private static final String GADGET_URI = "http://localhost:8080/samplecontainer/examples/oauth.xml";
+    private static final String SERVICE_NAME = "testService";
+    private static final String CONSUMER_SECRET = "gadgetSecret";
+
+    private SecurityToken token;
+    private OAuthStoreDb oAuthStoreDb;
+    private ConsumerStoreService oAuthStoreService;
+    private TokenInfoService tokenInfoService;
+
     @Test
     public void testGetConsumerKeyAndSecret() throws Exception {
-        //String userId, String appUrl, String appId, String domain,
-        //String container, Long expiresAt
-        SecurityToken token = new OAuthSecurityToken("john.doe", "http://localhost:8080/myapp",
-                "myapp", "localhost", "default", new Date().getTime() + NEXT_HOUR);
-        String serviceName = "testService";
-
-        OAuthStoreDb oAuthStoreDb = new OAuthStoreDb("http://localhost:8080","keys/oauthkey.pem",
-                "consumer-test-key");
 
         OAuthConsumerStoreDb consumerStore = new OAuthConsumerStoreDb();
-        final String gadgetUri = "http://localhost:8080/samplecontainer/examples/oauth.xml";
-        consumerStore.setGadgetUri(gadgetUri);
+        consumerStore.setGadgetUri(GADGET_URI);
         consumerStore.setConsumerKey("gadgetConsumer");
-        consumerStore.setConsumerSecret("gadgetSecret");
+        consumerStore.setConsumerSecret(CONSUMER_SECRET);
         consumerStore.setKeyType(OAuthConsumerStoreDb.KeyType.HMAC_SYMMETRIC);
 
         OAuthServiceProvider provider = new OAuthServiceProvider(null, null, null);
-        final OAuthStore.ConsumerInfo keyAndSecret = oAuthStoreDb.getConsumerKeyAndSecret(token, serviceName, provider);
-        assertNull(keyAndSecret);
 
-        
+        expect(oAuthStoreService.findOAuthConsumerStore(GADGET_URI, SERVICE_NAME))
+                .andReturn(consumerStore);
+        replay(oAuthStoreService);
+
+        final OAuthStore.ConsumerInfo keyAndSecret =
+                oAuthStoreDb.getConsumerKeyAndSecret(token, SERVICE_NAME, provider);
+        assertNotNull(keyAndSecret);
+        assertEquals(OAuth.HMAC_SHA1, keyAndSecret.getConsumer().getProperty(
+                OAuth.OAUTH_SIGNATURE_METHOD));
+
+        verify(oAuthStoreService);
+    }
+
+    @Test
+    public void testGetTokenInfo() throws Exception {
+        final String testTokenName = "testTokenName";
+
+
+        OAuthTokenInfoDb oAuthTokenInfoDb = new OAuthTokenInfoDb();
+        oAuthTokenInfoDb.setTokenName(testTokenName);
+        oAuthTokenInfoDb.setTokenSecret(CONSUMER_SECRET);
+        OAuthStore.ConsumerInfo consumerInfo = createMock(OAuthStore.ConsumerInfo.class);
+
+        expect(tokenInfoService.findOAuthTokenInfo(token.getViewerId(), token.getAppUrl(),
+                OAuthTokenInfoDb.MODULE_ID, testTokenName,
+                SERVICE_NAME)).andReturn(oAuthTokenInfoDb);
+        replay(tokenInfoService);
+
+        final OAuthStore.TokenInfo tokenInfoDb = oAuthStoreDb.getTokenInfo(token, consumerInfo,
+                SERVICE_NAME, testTokenName);
+
+        assertNotNull("Got TokenInfo", tokenInfoDb);
+        assertEquals(CONSUMER_SECRET, tokenInfoDb.getTokenSecret());
+
+        verify(tokenInfoService);
     }
 
     @Test
@@ -66,9 +107,21 @@ public class OAuthStoreDbTest {
         BasicOAuthStoreConsumerKeyAndSecret defaultKey =
                 OAuthStoreDb.loadDefaultKey("keys/oauthkey.pem", "consumer-test-key");
         assertNotNull("defaultKey", defaultKey);
-        assertEquals(BasicOAuthStoreConsumerKeyAndSecret.KeyType.RSA_PRIVATE, defaultKey.getKeyType());
+        assertEquals(BasicOAuthStoreConsumerKeyAndSecret.KeyType.RSA_PRIVATE,
+                defaultKey.getKeyType());
         assertEquals("consumer-test-key", defaultKey.getKeyName());
         final String keyFileContents = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANXjbMKL9N+9950V7QaDhr7JbF5uJtFgsiCsRjYDT9SaVCaNk2zXRXzqj2acKpAthV0R+4cVeWBN0mDL8CE/Rjo0r+9375DrSpi+jb+hnhYTGfiGbpJrUfCxlOXrvdsw4kZpLVKaj8wZFPb11Cnl5s1QBpPGWs1ij/qj/V04xRwXAgMBAAECgYEA0jXUPFgE8KjpZQ+Zhl9Z3MRlp2Em8XzRVF88GfWjTdXngoR+MehYuO5mxXgSNOUoP1JfHGI0ijux2cRVWrevMdO+0bkezMmgWlBTAqgoidwauX+0NyIRJOOG0anggmSrrf8jocjDLp7ZEhVjmtMzvys6P4RyFaNKXNyxK7J1/LECQQD/fB8vKvenzm9NNEdQyap3d0LYqWd/47NiOCCoS8K/DGVVIZiQQigUOi3ZTY6LV2Eb2RtwRnwBXMsKuQUTHZGDAkEA1lHU2OYGYP7SMu+fxzwFRNx0DrXWqIe0XFQX6EDRbk5H/eKgVt1tER8Mbin/z5utvXXiGJAj6+Eop6uqNPUq3QJAWbFZwVV0XJU8vf38i4BBOG/GKApRK7Tk5TaPQIZYeHoBmUGSLhMLvw4tynxP7tteXEh8OY6FOnU5UyphfbSDwQJBAIC0oesjsH79aMQ4DS77x3pEHdpbry6EWHb99WF/04W3sxovx/SCgyY+DBv4UuydZCgcLAxuO3RDQkP3Hn8xIG0CQQC9keRoDlA7RkwCXq76vEzLUqWiRSeHbXkaniSp7/xqzlw1IeMTtzoqMcJAulNr9W+vKKBYtE3sjXLcmO/CvWk/";
         assertEquals(keyFileContents, defaultKey.getConsumerSecret());
     }
+
+    @Before
+    public void setup() throws IOException {
+        token = new OAuthSecurityToken("john.doe", GADGET_URI,
+                "myapp", "localhost", "default", new Date().getTime() + NEXT_HOUR);
+        tokenInfoService = createMock(TokenInfoService.class);
+        oAuthStoreService = createMock(ConsumerStoreService.class);
+        
+        oAuthStoreDb = new OAuthStoreDb("http://localhost:8080", "keys/oauthkey.pem",
+                "consumer-test-key", oAuthStoreService, tokenInfoService);
+    }
 }

Added: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImplTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImplTest.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImplTest.java (added)
+++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/ConsumerStoreServiceDbImplTest.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,86 @@
+/*
+ * 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.oauth.service.impl;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb;
+import org.apache.shindig.gadgets.oauth.service.ConsumerStoreService;
+import org.apache.shindig.social.opensocial.jpa.openjpa.OpenJPADbModule;
+import org.junit.Before;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+/**
+ * Test for {@link ConsumerStoreServiceDbImpl}
+ */
+public class ConsumerStoreServiceDbImplTest {
+    private static final String GADGET_URI = "http://localhost:8080/samplecontainer/examples/oauth.xml";
+    private static final String SERVICE_NAME = "testService";
+    private static final String CONSUMER_SECRET = "gadgetSecret";
+    private static final String NEW_SERVICE_NAME = "new_service_name";
+
+    private ConsumerStoreService service;
+
+    @Before
+    public void setUp() throws Exception {
+        Injector injector = Guice.createInjector(new OpenJPADbModule());
+        service = injector.getInstance(ConsumerStoreServiceDbImpl.class);
+
+    }
+
+    @Test
+    public void testCrudOperations() throws Exception {
+        assertNull("Empty DB", service.findOAuthConsumerStore(GADGET_URI, SERVICE_NAME));
+        
+        OAuthConsumerStoreDb consumerStore = new OAuthConsumerStoreDb();
+        consumerStore.setGadgetUri(GADGET_URI);
+        consumerStore.setConsumerKey("gadgetConsumer");
+        consumerStore.setConsumerSecret(CONSUMER_SECRET);
+        consumerStore.setKeyType(OAuthConsumerStoreDb.KeyType.HMAC_SYMMETRIC);
+        consumerStore.setServiceName(SERVICE_NAME);
+
+        service.save(consumerStore);
+
+        OAuthConsumerStoreDb consumerStoreDb = service.findOAuthConsumerStore(
+                GADGET_URI, SERVICE_NAME);
+        assertEquals("Saved 1 item", consumerStore, consumerStoreDb);
+        
+        long savedId = consumerStoreDb.getObjectId();
+        consumerStoreDb.setServiceName(NEW_SERVICE_NAME);
+
+        service.save(consumerStoreDb);
+
+        assertNull("updated service name", service.findOAuthConsumerStore(
+                GADGET_URI, SERVICE_NAME));
+
+        assertEquals("No new id", savedId, service.findOAuthConsumerStore(
+                GADGET_URI, NEW_SERVICE_NAME).getObjectId());
+
+        service.delete(consumerStoreDb);
+
+        assertNull("updated service name", service.findOAuthConsumerStore(
+                GADGET_URI, NEW_SERVICE_NAME));
+
+    }
+
+}

Added: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImplTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImplTest.java?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImplTest.java (added)
+++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/shindig/gadgets/oauth/service/impl/TokenInfoServiceDbImplTest.java Tue Jul 19 14:40:21 2011
@@ -0,0 +1,88 @@
+/*
+ * 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.oauth.service.impl;
+
+import java.util.Date;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.gadgets.oauth.OAuthStore;
+import org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb;
+import org.apache.shindig.gadgets.oauth.service.TokenInfoService;
+import org.apache.shindig.social.core.oauth.OAuthSecurityToken;
+import org.apache.shindig.social.opensocial.jpa.openjpa.OpenJPADbModule;
+import org.junit.Before;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+/**
+ * Test class for {@link TokenInfoServiceDbImpl}
+ */
+public class TokenInfoServiceDbImplTest {
+    private TokenInfoService service;
+    private static final long EXPIRE_TIME = new Date().getTime() + 1000L + 60L + 60L;
+
+    @Before
+    public void setUp() throws Exception {
+        Injector injector = Guice.createInjector(new OpenJPADbModule());
+        service = injector.getInstance(TokenInfoServiceDbImpl.class);
+
+    }
+
+    @Test
+    public void testCrudOperations() throws Exception {
+        assertNull("Empty db", service.findOAuthTokenInfo("userId", "appUrl",
+                OAuthTokenInfoDb.MODULE_ID, "tokenName", "serviceName"));
+
+        OAuthStore.TokenInfo oAuthTokenInfo = new OAuthStore.TokenInfo("accessToken",
+                "tokenSecret", "sessionHandle", EXPIRE_TIME);
+
+        SecurityToken securityToken = new OAuthSecurityToken("userId", "appUrl",
+                "appId", "domain", "container", EXPIRE_TIME);
+
+        OAuthTokenInfoDb tokenInfo = new OAuthTokenInfoDb(securityToken, "serviceName",
+                "tokenName", oAuthTokenInfo);
+
+        service.saveOAuthTokenInfo(tokenInfo);
+        OAuthTokenInfoDb tokenInfoDb = service.findOAuthTokenInfo("userId", "appUrl",
+                OAuthTokenInfoDb.MODULE_ID, "tokenName", "serviceName");
+        assertEquals("Found in db", tokenInfo, tokenInfoDb);
+
+        long tokenInfoId = tokenInfoDb.getObjectId();
+
+        tokenInfoDb.setTokenName("newTokenName");
+        service.saveOAuthTokenInfo(tokenInfoDb);
+        assertNull("Cannot find with old criteria", service.findOAuthTokenInfo(
+                "userId", "appUrl", OAuthTokenInfoDb.MODULE_ID, "tokenName", "serviceName"));
+        assertEquals("Same id after update", tokenInfoId,
+                service.findOAuthTokenInfo("userId", "appUrl", OAuthTokenInfoDb.MODULE_ID,
+                        "newTokenName", "serviceName").getObjectId());
+
+        service.deleteOAuthTokenInfo("userId", "appUrl", OAuthTokenInfoDb.MODULE_ID, "newTokenName",
+                "serviceName");
+        assertNull("Empty db", service.findOAuthTokenInfo(
+                "userId", "appUrl", OAuthTokenInfoDb.MODULE_ID, "newTokenName", "serviceName"));
+
+    }
+
+}

Added: incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/persistence.xml?rev=1148365&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/persistence.xml (added)
+++ incubator/rave/trunk/rave-shindig/src/test/resources/META-INF/persistence.xml Tue Jul 19 14:40:21 2011
@@ -0,0 +1,39 @@
+<!--
+  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.
+  -->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+  version="2.0">
+
+  <!-- Test config -->
+  <persistence-unit name="raveShindigPersistenceUnit" transaction-type="RESOURCE_LOCAL">
+    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+    <class>org.apache.shindig.gadgets.oauth.jpa.OAuthConsumerStoreDb</class>
+    <class>org.apache.shindig.gadgets.oauth.jpa.OAuthTokenInfoDb</class>
+    <properties>
+      <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
+      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
+      <property name="openjpa.ConnectionDriverName" value="org.h2.Driver"/>
+      <property name="openjpa.ConnectionURL" value="jdbc:h2:mem:portal;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=10000"/>
+      <property name="openjpa.ConnectionUserName" value="sa"/>
+      <property name="openjpa.ConnectionPassword" value="sa"/>
+    </properties>
+  </persistence-unit>
+
+</persistence>