You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by jc...@apache.org on 2011/10/11 22:19:41 UTC
svn commit: r1182068 - in /incubator/rave/trunk:
rave-components/rave-commons/src/main/java/org/apache/rave/exception/
rave-components/rave-commons/src/main/java/org/apache/rave/persistence/
rave-components/rave-commons/src/main/java/org/apache/rave/pe...
Author: jcian
Date: Tue Oct 11 20:19:40 2011
New Revision: 1182068
URL: http://svn.apache.org/viewvc?rev=1182068&view=rev
Log:
RAVE-34: Implement AppData
https://issues.apache.org/jira/browse/RAVE-34
Added:
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/exception/DataSerializationException.java
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/model/ApplicationData.java
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/ApplicationDataRepository.java
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository.java
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/SimplePersonService.java
incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/repository/JpaApplicationDataRepositoryTest.java
Modified:
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/Repository.java
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/jpa/AbstractJpaRepository.java
incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/persistence/jpa/AbstractJpaRepositoryTest.java
incubator/rave/trunk/rave-shindig/pom.xml
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultAppDataService.java
incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultPersonService.java
incubator/rave/trunk/rave-shindig/src/main/resources/META-INF/persistence.xml
incubator/rave/trunk/rave-shindig/src/main/resources/initial_data.sql
incubator/rave/trunk/rave-shindig/src/main/resources/rave-shindig-applicationContext.xml
incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/service/AppDataServiceTest.java
incubator/rave/trunk/rave-shindig/src/test/resources/test_data.sql
Added: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/exception/DataSerializationException.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/exception/DataSerializationException.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/exception/DataSerializationException.java (added)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/exception/DataSerializationException.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,36 @@
+/*
+ * 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.rave.exception;
+
+public class DataSerializationException extends RuntimeException {
+ public DataSerializationException() {
+ }
+
+ public DataSerializationException(String message) {
+ super(message);
+ }
+
+ public DataSerializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DataSerializationException(Throwable cause) {
+ super(cause);
+ }
+}
Modified: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/Repository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/Repository.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/Repository.java (original)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/Repository.java Tue Oct 11 20:19:40 2011
@@ -27,7 +27,7 @@ public interface Repository<T> {
* Gets the type of the object served by the repository
* @return a {@link Class} representing the type of object
*/
- Class<T> getType();
+ Class<? extends T> getType();
/**
* Gets the specified object from the persistence context by its id
Modified: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/jpa/AbstractJpaRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/jpa/AbstractJpaRepository.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/jpa/AbstractJpaRepository.java (original)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/persistence/jpa/AbstractJpaRepository.java Tue Oct 11 20:19:40 2011
@@ -36,14 +36,14 @@ public abstract class AbstractJpaReposit
@PersistenceContext
protected EntityManager manager;
- private final Class<T> type;
+ private final Class<? extends T> type;
- protected AbstractJpaRepository(Class<T> type) {
+ protected AbstractJpaRepository(Class<? extends T> type) {
this.type = type;
}
@Override
- public Class<T> getType() {
+ public Class<? extends T> getType() {
return type;
}
Modified: incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/persistence/jpa/AbstractJpaRepositoryTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/persistence/jpa/AbstractJpaRepositoryTest.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/persistence/jpa/AbstractJpaRepositoryTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/persistence/jpa/AbstractJpaRepositoryTest.java Tue Oct 11 20:19:40 2011
@@ -53,7 +53,7 @@ public class AbstractJpaRepositoryTest {
@Test
public void getType() {
- assertThat(repository.getType(), is(equalTo(TestEntity.class)));
+ assertThat((Class<TestEntity>) repository.getType(), is(equalTo(TestEntity.class)));
}
@Test
Modified: incubator/rave/trunk/rave-shindig/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/pom.xml?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/pom.xml (original)
+++ incubator/rave/trunk/rave-shindig/pom.xml Tue Oct 11 20:19:40 2011
@@ -157,8 +157,10 @@
<artifactId>openjpa-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
- <includes>org/apache/rave/gadgets/oauth/model/*.class,
+ <includes>
+ org/apache/rave/gadgets/oauth/model/*.class,
org/apache/rave/opensocial/model/*.class,
+ org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository$JpaSerializableApplicationData.class,
org/apache/shindig/social/opensocial/jpa/*.class
</includes>
<excludes>
@@ -201,8 +203,7 @@
</mapping>
<mapping>
<sourceFolder>src/main/resources</sourceFolder>
- <destinationFolder>@../rave-portal/target/tomcat6x/webapps/ROOT/WEB-INF/classes
- </destinationFolder>
+ <destinationFolder>@../rave-portal/target/tomcat6x/webapps/ROOT/WEB-INF/classes</destinationFolder>
</mapping>
</mappings>
</configuration>
Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/model/ApplicationData.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/model/ApplicationData.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/model/ApplicationData.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/model/ApplicationData.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,102 @@
+/*
+ * 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.rave.opensocial.model;
+
+import org.apache.rave.persistence.BasicEntity;
+
+import javax.persistence.*;
+import java.util.Map;
+
+@Entity
+@Table(name = "application_data")
+@NamedQueries(value = {
+ @NamedQuery(name = ApplicationData.FIND_BY_USER_IDS_AND_APP_ID, query = "select a from ApplicationData a " +
+ "where a.userId IN :" + ApplicationData.USER_IDS_PARAM + " AND a.appUrl = :" + ApplicationData.APP_URL_PARAM),
+ @NamedQuery(name = ApplicationData.FIND_BY_USER_ID_AND_APP_ID, query = "select a from ApplicationData a " +
+ "where a.userId = :" + ApplicationData.USER_ID_PARAM + " AND a.appUrl = :" + ApplicationData.APP_URL_PARAM)
+})
+public class ApplicationData implements BasicEntity {
+ public static final String FIND_BY_USER_IDS_AND_APP_ID = "ApplicationData.findByUserIdsAndAppId";
+ public static final String FIND_BY_USER_ID_AND_APP_ID = "ApplicationData.findByUserIdAndAppId";
+
+ public static final String USER_IDS_PARAM = "userIds";
+ public static final String USER_ID_PARAM = "userId";
+ public static final String APP_URL_PARAM = "appUrl";
+
+ /**
+ * The internal object ID used for references to this object.
+ */
+ @Id
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "applicationDataIdGenerator")
+ @TableGenerator(name = "applicationDataIdGenerator", table = "RAVE_SHINDIG_SEQUENCES", pkColumnName = "SEQ_NAME",
+ valueColumnName = "SEQ_COUNT", pkColumnValue = "application_data", allocationSize = 1, initialValue = 1)
+ @Column(name = "entity_id")
+ private Long entityId;
+
+ @Column(name = "user_id")
+ private String userId;
+
+ @Column(name = "app_url")
+ private String appUrl;
+
+ @Transient
+ private Map<String, String> data;
+
+ public ApplicationData() {
+ }
+
+ public ApplicationData(Long entityId, String userId, String appUrl, Map<String, String> data) {
+ this.entityId = entityId;
+ this.userId = userId;
+ this.appUrl = appUrl;
+ this.data = data;
+ }
+
+ public Long getEntityId() {
+ return entityId;
+ }
+
+ public void setEntityId(Long entityId) {
+ this.entityId = entityId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getAppUrl() {
+ return appUrl;
+ }
+
+ public void setAppUrl(String appUrl) {
+ this.appUrl = appUrl;
+ }
+
+ public Map<String, String> getData() {
+ return data;
+ }
+
+ public void setData(Map<String, String> data) {
+ this.data = data;
+ }
+}
Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/ApplicationDataRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/ApplicationDataRepository.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/ApplicationDataRepository.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/ApplicationDataRepository.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,45 @@
+/*
+ * 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.rave.opensocial.repository;
+
+import org.apache.rave.opensocial.model.ApplicationData;
+import org.apache.rave.persistence.Repository;
+
+import java.util.List;
+
+public interface ApplicationDataRepository extends Repository<ApplicationData> {
+
+ /**
+ * Gets the application data for the given users and application
+ *
+ * @param userIds The users
+ * @param appId The application
+ * @return The application data for the specified users, or an empty list if none is found
+ */
+ List<ApplicationData> getApplicationData(List<String> userIds, String appId);
+
+ /**
+ * Gets the application data for the given user and application
+ *
+ * @param personId The user
+ * @param appId The application
+ * @return The application data, or null if not found
+ */
+ ApplicationData getApplicationData(String personId, String appId);
+}
Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/repository/impl/JpaApplicationDataRepository.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,151 @@
+/*
+ * 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.rave.opensocial.repository.impl;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.rave.exception.DataSerializationException;
+import org.apache.rave.opensocial.model.ApplicationData;
+import org.apache.rave.opensocial.repository.ApplicationDataRepository;
+import org.apache.rave.persistence.jpa.AbstractJpaRepository;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Lob;
+import javax.persistence.TypedQuery;
+import java.util.*;
+
+import static org.apache.rave.persistence.jpa.util.JpaUtil.getSingleResult;
+
+@Repository
+public class JpaApplicationDataRepository extends AbstractJpaRepository<ApplicationData>
+ implements ApplicationDataRepository {
+
+ public JpaApplicationDataRepository() {
+ super(JpaSerializableApplicationData.class);
+ }
+
+ @Override
+ public List<ApplicationData> getApplicationData(List<String> userIds, String appId) {
+ //if the call is only looking for data for a single user use the more efficient single user variant transparently
+ if (userIds.size() == 1) {
+ List<ApplicationData> data = new ArrayList<ApplicationData>();
+ ApplicationData applicationData = getApplicationData(userIds.get(0), appId);
+ if (applicationData != null) {
+ data.add(applicationData);
+ }
+ return data;
+ }
+
+ TypedQuery<JpaSerializableApplicationData> query = manager.createNamedQuery(ApplicationData.FIND_BY_USER_IDS_AND_APP_ID,
+ JpaSerializableApplicationData.class);
+ query.setParameter(ApplicationData.USER_IDS_PARAM, userIds);
+ query.setParameter(ApplicationData.APP_URL_PARAM, appId);
+ List<JpaSerializableApplicationData> results = query.getResultList();
+ for (JpaSerializableApplicationData applicationData : results) {
+ applicationData.deserializeData();
+ }
+ return new ArrayList<ApplicationData>(results);
+ }
+
+ @Override
+ public ApplicationData getApplicationData(String personId, String appId) {
+ TypedQuery<JpaSerializableApplicationData> query = manager.createNamedQuery(ApplicationData.FIND_BY_USER_ID_AND_APP_ID,
+ JpaSerializableApplicationData.class);
+ query.setParameter(ApplicationData.USER_ID_PARAM, personId);
+ query.setParameter(ApplicationData.APP_URL_PARAM, appId);
+ JpaSerializableApplicationData applicationData = getSingleResult(query.getResultList());
+ if (applicationData != null) {
+ applicationData.deserializeData();
+ }
+ return applicationData;
+ }
+
+ @Override
+ public ApplicationData get(long id) {
+ JpaSerializableApplicationData applicationData = (JpaSerializableApplicationData) super.get(id);
+ if (applicationData != null) {
+ applicationData.deserializeData();
+ }
+ return applicationData;
+ }
+
+ @Override
+ @Transactional
+ public ApplicationData save(ApplicationData applicationData) {
+ JpaSerializableApplicationData jpaSerializableApplicationData = getJpaSerializableApplicationData(applicationData);
+ jpaSerializableApplicationData.serializeData();
+ return super.save(jpaSerializableApplicationData);
+ }
+
+ private JpaSerializableApplicationData getJpaSerializableApplicationData(ApplicationData applicationData) {
+ if (applicationData instanceof JpaSerializableApplicationData) {
+ return (JpaSerializableApplicationData) applicationData;
+ }
+
+ return new JpaSerializableApplicationData(applicationData.getEntityId(), applicationData.getUserId(),
+ applicationData.getAppUrl(), applicationData.getData());
+ }
+
+ /**
+ * This class is here so that the details of the persistence strategy in use for serializing the appdata map to a
+ * JSON string doesnt end up being reflected in any public API of the ApplicationData object itself.
+ * <p/>
+ * This allows the public API of this repository to deal in clean ApplicationData models, but under the covers it
+ * uses this model for the actual persistence to the database.
+ */
+ @Entity
+ public static class JpaSerializableApplicationData extends ApplicationData {
+ @Lob
+ @Column(name = "serialized_data")
+ private String serializedData;
+
+ public JpaSerializableApplicationData() {
+ super();
+ }
+
+ public JpaSerializableApplicationData(Long entityId, String userId, String appUrl, Map<String, String> data) {
+ super(entityId, userId, appUrl, data);
+ }
+
+ public void serializeData() {
+ serializedData = new JSONObject(this.getData()).toString();
+ }
+
+ public void deserializeData() {
+ try {
+ Map<String, String> data = new HashMap<String, String>();
+ if (StringUtils.isNotBlank(serializedData)) {
+ JSONObject jsonObject = new JSONObject(serializedData);
+ Iterator keys = jsonObject.keys();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ data.put(key, (String) jsonObject.get(key));
+ }
+ }
+ this.setData(data);
+ } catch (JSONException e) {
+ throw new DataSerializationException("Exception caught while deserializing data: " + serializedData, e);
+ }
+ }
+ }
+}
\ No newline at end of file
Added: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/SimplePersonService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/SimplePersonService.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/SimplePersonService.java (added)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/SimplePersonService.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,41 @@
+/*
+ * 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.rave.opensocial.service;
+
+import org.apache.rave.opensocial.model.Person;
+import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.social.opensocial.spi.CollectionOptions;
+import org.apache.shindig.social.opensocial.spi.GroupId;
+import org.apache.shindig.social.opensocial.spi.UserId;
+
+import java.util.List;
+import java.util.Set;
+
+public interface SimplePersonService {
+ /**
+ * Returns a list of people that correspond to the passed in person ids.
+ *
+ * @param userIds A set of users
+ * @param groupId The group
+ * @param collectionOptions How to filter, sort and paginate the collection being fetched
+ * @param token The gadget token
+ * @return a list of people
+ */
+ List<Person> getPeople(Set<UserId> userIds, GroupId groupId, CollectionOptions collectionOptions, SecurityToken token);
+}
Modified: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultAppDataService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultAppDataService.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultAppDataService.java (original)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultAppDataService.java Tue Oct 11 20:19:40 2011
@@ -19,37 +19,260 @@
package org.apache.rave.opensocial.service.impl;
+import org.apache.commons.lang.StringUtils;
+import org.apache.rave.opensocial.model.ApplicationData;
+import org.apache.rave.opensocial.model.Person;
+import org.apache.rave.opensocial.repository.ApplicationDataRepository;
+import org.apache.rave.opensocial.service.SimplePersonService;
+import org.apache.rave.service.LockService;
import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.common.util.ImmediateFuture;
import org.apache.shindig.protocol.DataCollection;
import org.apache.shindig.protocol.ProtocolException;
import org.apache.shindig.social.opensocial.spi.AppDataService;
import org.apache.shindig.social.opensocial.spi.GroupId;
import org.apache.shindig.social.opensocial.spi.UserId;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.Future;
+import java.util.concurrent.locks.Lock;
/**
- *
+ * Implementation of the {@link AppDataService} SPI.
*/
@Service
-public class DefaultAppDataService implements AppDataService{
+public class DefaultAppDataService implements AppDataService {
+ private final SimplePersonService personService;
+ private final LockService lockService;
+ private final ApplicationDataRepository applicationDataRepository;
+ /**
+ * These are the only visibility rules I can find in the OpenSocial specification regarding visibility of appdata:
+ * <p/>
+ * "This data store can be read by anyone who can see the gadget, but only the VIEWER's data is writable."
+ * <p/>
+ * So those are the only rules that this implementation currently enforces.
+ */
+
+ @Autowired
+ public DefaultAppDataService(SimplePersonService personService, LockService lockService,
+ ApplicationDataRepository applicationDataRepository) {
+ this.personService = personService;
+ this.lockService = lockService;
+ this.applicationDataRepository = applicationDataRepository;
+ }
+
+ /**
+ * Retrieves app data for the specified user list and group.
+ *
+ * @param userIds A set of UserIds
+ * @param groupId The group
+ * @param appId The application ID
+ * @param fields The fields to filter the data by - empty set implies no filter
+ * @param token The security token
+ * @return The data fetched
+ */
@Override
- public Future<DataCollection> getPersonData(Set<UserId> userIds, GroupId groupId, String appId, Set<String> fields, SecurityToken token) throws ProtocolException {
- throw new ProtocolException(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
+ public Future<DataCollection> getPersonData(Set<UserId> userIds, GroupId groupId, String appId, Set<String> fields,
+ SecurityToken token) throws ProtocolException {
+ //make sure the request conforms to the OpenSocial visibility rules
+ List<String> personIds = validateReadRequest(userIds, groupId, appId, token);
+
+ //fetch their appdata, convert it to a DataCollection and return it
+ List<ApplicationData> applicationData = applicationDataRepository.getApplicationData(personIds, appId);
+ DataCollection dataCollection = convertAppDataMapToDataCollection(personIds, applicationData, fields);
+ return ImmediateFuture.newInstance(dataCollection);
}
+ /**
+ * Deletes data for the specified user and group.
+ *
+ * @param userId The user
+ * @param groupId The group
+ * @param appId The application ID
+ * @param fields The fields to delete - empty set implies all fields
+ * @param token The security token
+ * @return an error if one occurs
+ */
@Override
- public Future<Void> deletePersonData(UserId userId, GroupId groupId, String appId, Set<String> fields, SecurityToken token) throws ProtocolException {
- throw new ProtocolException(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
+ public Future<Void> deletePersonData(UserId userId, GroupId groupId, String appId, Set<String> fields,
+ SecurityToken token) throws ProtocolException {
+ //make sure the request conforms to the OpenSocial visibility rules
+ String personId = validateWriteRequest(userId, groupId, appId, token);
+
+ //lock on this user and this application to avoid any potential concurrency issues
+ Lock lock = getApplicationDataLock(personId, appId);
+ try {
+ lock.lock();
+
+ //get the application data for this user and application
+ ApplicationData applicationData = applicationDataRepository.getApplicationData(personId, appId);
+
+ //if there is no data, there's nothing to delete, so we're done...
+ if (applicationData == null || applicationData.getData() == null) {
+ return ImmediateFuture.newInstance(null);
+ }
+
+ //remove the fields specified -- empty field set implies remove all, otherwise remove just the fields specified
+ Map<String, String> data = applicationData.getData();
+ if (fields == null || fields.size() == 0) {
+ data.clear();
+ } else {
+ data.keySet().removeAll(fields);
+ }
+
+ //save our changes and return
+ applicationDataRepository.save(applicationData);
+ } finally {
+ lock.unlock();
+ lockService.returnLock(lock);
+ }
+ return ImmediateFuture.newInstance(null);
}
+ /**
+ * Updates app data for the specified user and group with the new values.
+ *
+ * @param userId The user
+ * @param groupId The group
+ * @param appId The application ID
+ * @param fields The fields to update. Empty set implies that all fields that should be persisted have been
+ * provided in the values map (completely replace current appData with new data). A key in the
+ * fields set without a corresponding key in the values map implies a delete of that field.
+ * A key in the values map not present in the fields set is a bad request.
+ * @param values The values to set
+ * @param token The security token
+ * @return an error if one occurs
+ */
@Override
- public Future<Void> updatePersonData(UserId userId, GroupId groupId, String appId, Set<String> fields, Map<String, String> values, SecurityToken token) throws ProtocolException {
- throw new ProtocolException(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
+ public Future<Void> updatePersonData(UserId userId, GroupId groupId, String appId, Set<String>
+ fields, Map<String, String> values, SecurityToken token) throws ProtocolException {
+ //make sure the request conforms to the OpenSocial visibility rules
+ String personId = validateWriteRequest(userId, groupId, appId, token);
+
+ //lock on this user and this application to avoid any potential concurrency issues
+ Lock lock = getApplicationDataLock(personId, appId);
+ try {
+ lock.lock();
+ //get the application data for this user and application
+ ApplicationData applicationData = applicationDataRepository.getApplicationData(personId, appId);
+
+ //if there is no data, create an empty object to store the data in that we'll save when we're done
+ if (applicationData == null) {
+ applicationData = new ApplicationData(null, personId, appId, new HashMap<String, String>());
+ }
+
+ //if the fields parameter is empty, we can just use the values map directly since this is a full update
+ if (fields == null || fields.size() == 0) {
+ applicationData.setData(values);
+ }
+ //if there are keys in the values map that aren't in the fields set, its a bad request
+ else if (!fields.containsAll(values.keySet())) {
+ throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, "Fields parameter must either be empty or contain keys " +
+ "for all name value pairs sent in request.");
+ }
+ //we have a partial update - we know that the fields set contains keys for all the entries in the values
+ //map (due to the check above), so we can just enumerate over it now to finish our work. So we want to remove
+ //any fields found in the fields set that are not found in the values map and update the rest.
+ else {
+ Map<String, String> data = applicationData.getData();
+ for (String field : fields) {
+ //if this field is not in the values map, its a delete
+ if (!values.containsKey(field)) {
+ data.remove(field);
+ } else {
+ //its an update
+ data.put(field, values.get(field));
+ }
+ }
+ }
+
+ //save our changes and return
+ applicationDataRepository.save(applicationData);
+ } finally {
+ lock.unlock();
+ lockService.returnLock(lock);
+ }
+ return ImmediateFuture.newInstance(null);
+ }
+
+ private List<String> validateReadRequest(Set<UserId> userIds, GroupId groupId, String appId, SecurityToken token) {
+ //if the appId in the token matches the appId parameter, then we know the user "can see the gadget"
+ validateAppIdMatches(appId, token);
+
+ //get the people we're supposed to be fetching data for
+ List<Person> people = personService.getPeople(userIds, groupId, null, token);
+ return convertPeopleToUserIds(people);
+ }
+
+ private String validateWriteRequest(UserId userId, GroupId groupId, String appId, SecurityToken token) {
+ //do the read level validation first
+ Set<UserId> userIds = new HashSet<UserId>(Arrays.asList(userId));
+ List<String> personIds = validateReadRequest(userIds, groupId, appId, token);
+
+ //and now check the write level validation which is "only the VIEWER's data is writable"
+ if (personIds.size() != 1 || !personIds.get(0).equalsIgnoreCase(token.getViewerId())) {
+ throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, "Writing appdata for anyone but the " +
+ "current viewer is forbidden.");
+ }
+
+ return personIds.get(0);
+ }
+
+ private void validateAppIdMatches(String appId, SecurityToken token) {
+ if (StringUtils.isBlank(appId) || !appId.equalsIgnoreCase(token.getAppId())) {
+ throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, "Requesting appdata for a different " +
+ "application is forbidden.");
+ }
+ }
+
+ private List<String> convertPeopleToUserIds(List<Person> people) {
+ List<String> ids = new ArrayList<String>(people.size());
+ for (Person person : people) {
+ ids.add(String.valueOf(person.getEntityId()));
+ }
+ return ids;
+ }
+
+ private Lock getApplicationDataLock(String personId, String appId) {
+ return lockService.borrowLock("ApplicationData", new StringBuilder(personId).append("-").append(appId).toString());
+ }
+
+ private DataCollection convertAppDataMapToDataCollection(List<String> personIds, List<ApplicationData> applicationData,
+ Set<String> fields) {
+ //create the map that we'll use to associate users with their appdata
+ Map<String, Map<String, String>> dataCollectionMap = new HashMap<String, Map<String, String>>();
+
+ //enumerate the data we have mapping it back to the owner
+ for (ApplicationData data : applicationData) {
+ //create a map for our return values
+ Map<String, String> returnData = new HashMap<String, String>();
+ //if there isn't a set of fields to filter on return all user data, otherwise filter to the specified fields
+ if (fields == null || fields.size() == 0) {
+ returnData.putAll(data.getData());
+ } else {
+ //otherwise filter the values
+ for (Map.Entry<String, String> userDataEntry : data.getData().entrySet()) {
+ if (fields.contains(userDataEntry.getKey())) {
+ returnData.put(userDataEntry.getKey(), userDataEntry.getValue());
+ }
+ }
+ }
+
+ //put an entry in the data collection mapping the user and their appdata
+ dataCollectionMap.put(data.getUserId(), returnData);
+ }
+
+ //now enumerate all of the personIds to be sure we have some data in the map for them, and if not, add empty data
+ for (String personId : personIds) {
+ if (!dataCollectionMap.containsKey(personId)) {
+ dataCollectionMap.put(personId, new HashMap<String, String>());
+ }
+ }
+
+ return new DataCollection(dataCollectionMap);
}
-}
+}
\ No newline at end of file
Modified: incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultPersonService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultPersonService.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultPersonService.java (original)
+++ incubator/rave/trunk/rave-shindig/src/main/java/org/apache/rave/opensocial/service/impl/DefaultPersonService.java Tue Oct 11 20:19:40 2011
@@ -21,6 +21,7 @@ package org.apache.rave.opensocial.servi
import com.google.common.collect.Lists;
import org.apache.rave.opensocial.repository.PersonRepository;
+import org.apache.rave.opensocial.service.SimplePersonService;
import org.apache.rave.util.CollectionUtils;
import org.apache.shindig.auth.SecurityToken;
import org.apache.shindig.common.util.ImmediateFuture;
@@ -44,7 +45,7 @@ import java.util.concurrent.Future;
* Implementation of the {@link PersonService} SPI
*/
@Service
-public class DefaultPersonService implements PersonService {
+public class DefaultPersonService implements PersonService, SimplePersonService {
private final PersonRepository repository;
@@ -60,7 +61,7 @@ public class DefaultPersonService implem
Set<String> fields,
SecurityToken token) throws ProtocolException {
- List<org.apache.rave.opensocial.model.Person> people = getPeopleFromRepository(userIds, groupId, token, collectionOptions);
+ List<org.apache.rave.opensocial.model.Person> people = getPeople(userIds, groupId, collectionOptions, token);
return ImmediateFuture.newInstance(new RestfulCollection<Person>(convertPeople(people, fields)));
}
@@ -69,10 +70,10 @@ public class DefaultPersonService implem
return ImmediateFuture.newInstance(convertPerson(getPersonForId(id, token), fields));
}
- private List<org.apache.rave.opensocial.model.Person> getPeopleFromRepository(Set<UserId> userIds,
- GroupId groupId,
- SecurityToken token,
- CollectionOptions collectionOptions) {
+ @Override
+ public List<org.apache.rave.opensocial.model.Person> getPeople(Set<UserId> userIds, GroupId groupId,
+ CollectionOptions collectionOptions,
+ SecurityToken token) {
switch (groupId.getType()) {
case all:
return getUniqueListOfConnectedPeople(userIds, collectionOptions, token);
@@ -118,13 +119,13 @@ public class DefaultPersonService implem
String filter = collectionOptions == null ? null : collectionOptions.getFilter();
List<org.apache.rave.opensocial.model.Person> current;
//Currently ignoring TOP FRIENDS as it hasn't been defined what a top friend is
- if(filter == null || filter.equals(PersonService.ALL_FILTER) || filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
+ if (filter == null || filter.equals(PersonService.ALL_FILTER) || filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
current = repository.findFriends(userId);
- } else if(filter.equals(PersonService.HAS_APP_FILTER)) {
+ } else if (filter.equals(PersonService.HAS_APP_FILTER)) {
current = repository.findFriends(userId, appId);
- } else if(filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
+ } else if (filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
current = repository.findFriendsWithFriend(userId, collectionOptions.getFilterValue());
//Represents the default case (filter by field)
@@ -142,13 +143,13 @@ public class DefaultPersonService implem
List<org.apache.rave.opensocial.model.Person> current;
//Currently ignoring TOP FRIENDS as it hasn't been defined what a top friend is
- if(filter == null || filter.equals(PersonService.ALL_FILTER) ||filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
+ if (filter == null || filter.equals(PersonService.ALL_FILTER) || filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
current = repository.findAllConnectedPeople(userId);
- } else if(filter.equals(PersonService.HAS_APP_FILTER)) {
+ } else if (filter.equals(PersonService.HAS_APP_FILTER)) {
current = repository.findAllConnectedPeople(userId, appId);
- } else if(filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
+ } else if (filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
current = repository.findAllConnectedPeopleWithFriend(userId, collectionOptions.getFilterValue());
//Represents the default case (filter by field)
@@ -165,13 +166,13 @@ public class DefaultPersonService implem
String filter = collectionOptions == null ? null : collectionOptions.getFilter();
List<org.apache.rave.opensocial.model.Person> current;
- if(filter == null || filter.equals(PersonService.ALL_FILTER) || filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
+ if (filter == null || filter.equals(PersonService.ALL_FILTER) || filter.equals(PersonService.TOP_FRIENDS_FILTER)) {
current = repository.findByGroup(groupId);
- } else if(filter.equals(PersonService.HAS_APP_FILTER)) {
+ } else if (filter.equals(PersonService.HAS_APP_FILTER)) {
current = repository.findByGroup(groupId, appId);
- } else if(filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
+ } else if (filter.equals(PersonService.IS_WITH_FRIENDS_FILTER)) {
current = repository.findByGroupWithFriend(groupId, collectionOptions.getFilterValue());
//Represents the default case (filter by field)
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=1182068&r1=1182067&r2=1182068&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 Oct 11 20:19:40 2011
@@ -34,6 +34,8 @@
<class>org.apache.rave.opensocial.model.PersonProperty</class>
<class>org.apache.rave.opensocial.model.PersonAssociation</class>
<class>org.apache.rave.opensocial.model.Url</class>
+ <class>org.apache.rave.opensocial.model.ApplicationData</class>
+ <class>org.apache.rave.opensocial.repository.impl.JpaApplicationDataRepository$JpaSerializableApplicationData</class>
<class>org.apache.rave.gadgets.oauth.model.OAuthTokenInfo</class>
<class>org.apache.rave.gadgets.oauth.model.OAuthConsumerStore</class>
Modified: incubator/rave/trunk/rave-shindig/src/main/resources/initial_data.sql
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/resources/initial_data.sql?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/resources/initial_data.sql (original)
+++ incubator/rave/trunk/rave-shindig/src/main/resources/initial_data.sql Tue Oct 11 20:19:40 2011
@@ -17,6 +17,7 @@
set @token_info_seq = 'token_info';
set @oauth_consumer_store_seq = 'oauth_consumer_store';
+set @application_data_seq = 'application_data';
set @person_seq = 'person';
set @person_association_seq = 'person_association';
set @groups_seq = 'groups';
@@ -25,6 +26,7 @@ set @group_members_seq = 'group_members'
CREATE TABLE IF NOT EXISTS RAVE_SHINDIG_SEQUENCES (seq_name VARCHAR(255) PRIMARY KEY NOT NULL, seq_count BIGINT(19));
INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@token_info_seq, 1);
INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@oauth_consumer_store_seq, 1);
+INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@application_data_seq, 1);
INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@person_seq, 1);
INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@person_association_seq, 1);
INSERT INTO RAVE_SHINDIG_SEQUENCES(seq_name, seq_count) values (@groups_seq, 1);
Modified: incubator/rave/trunk/rave-shindig/src/main/resources/rave-shindig-applicationContext.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/main/resources/rave-shindig-applicationContext.xml?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/main/resources/rave-shindig-applicationContext.xml (original)
+++ incubator/rave/trunk/rave-shindig/src/main/resources/rave-shindig-applicationContext.xml Tue Oct 11 20:19:40 2011
@@ -22,9 +22,11 @@
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- make the the rave.shindig.properties props available to autowire injectors, location of the properties can
be overridden by setting a system property "rave-shindig.override.properties" -->
@@ -37,8 +39,10 @@
<!-- bean post-processor for JPA annotations -->
<context:annotation-config/>
- <context:component-scan base-package="org.apache.rave" annotation-config="true"/>
+ <!-- enable the use of the @AspectJ style of Spring AOP -->
+ <aop:aspectj-autoproxy />
+ <context:component-scan base-package="org.apache.rave" annotation-config="true"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
@@ -46,7 +50,6 @@
<tx:annotation-driven transaction-manager="transactionManager"/>
-
<bean id="entityManagerFactory"
class="org.apache.rave.persistence.jpa.PopulatedLocalContainerEntityManagerFactory">
<property name="persistenceUnitName" value="raveShindigPersistenceUnit"/>
@@ -74,7 +77,6 @@
<property name="password" value="${rave-shindig.dataSource.password}"/>
</bean>
-
<bean id="oAuthStore" class="org.apache.rave.gadgets.oauth.inject.DefaultOAuthStore">
<constructor-arg name="defaultCallbackUrl" value="${shindig.signing.global-callback-url}"/>
<constructor-arg name="pathToPrivateKey" value="${shindig.signing.key-file}"/>
Added: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/repository/JpaApplicationDataRepositoryTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/repository/JpaApplicationDataRepositoryTest.java?rev=1182068&view=auto
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/repository/JpaApplicationDataRepositoryTest.java (added)
+++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/repository/JpaApplicationDataRepositoryTest.java Tue Oct 11 20:19:40 2011
@@ -0,0 +1,151 @@
+/*
+ * 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.rave.opensocial.repository;
+
+import org.apache.rave.opensocial.model.ApplicationData;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:rave-shindig-test-applicationContext.xml",
+ "classpath:rave-shindig-test-dataContext.xml"})
+public class JpaApplicationDataRepositoryTest {
+ @PersistenceContext
+ private EntityManager manager;
+
+ @Autowired
+ private ApplicationDataRepository repository;
+
+ private static final String VALID_USER_ID = "12345";
+ private static final String VALID_APPLICATION_ID = "http://example.com/gadget.xml";
+ private static final String SECOND_VALID_APPLICATION_ID = "http://example.com/gadget2.xml";
+ private static final Long VALID_APPLICATION_DATA_ID = 1L;
+
+ private Map<String, String> validApplicationDataMap;
+
+ @Before
+ public void setup() {
+ validApplicationDataMap = new HashMap<String, String>();
+ validApplicationDataMap.put("color", "blue");
+ validApplicationDataMap.put("speed", "fast");
+ validApplicationDataMap.put("state", "MA");
+ }
+
+ @Test
+ public void get_valid() {
+ ApplicationData applicationData = repository.get(VALID_APPLICATION_DATA_ID);
+ validateApplicationData(applicationData);
+ }
+
+ @Test
+ public void get_invalid() {
+ ApplicationData applicationData = repository.get(-1L);
+ assertThat(applicationData, is(nullValue()));
+ }
+
+ @Test
+ public void getApplicationData_byUserIdAndApplicationId_valid() {
+ ApplicationData applicationData = repository.getApplicationData(VALID_USER_ID, VALID_APPLICATION_ID);
+ validateApplicationData(applicationData);
+ }
+
+ @Test
+ public void getApplicationData_byUserIdAndApplicationId_invalid() {
+ ApplicationData applicationData = repository.getApplicationData("-1", VALID_APPLICATION_ID);
+ assertThat(applicationData, is(nullValue()));
+ }
+
+ @Test
+ public void getApplicationData_byUserIdsAndApplicationId_valid() {
+ List<ApplicationData> applicationData = repository.getApplicationData(Arrays.asList(VALID_USER_ID),
+ VALID_APPLICATION_ID);
+ validateApplicationData(applicationData.get(0));
+ }
+
+ @Test
+ public void getApplicationData_byUserIdsAndApplicationId_invalid() {
+ List<ApplicationData> applicationData = repository.getApplicationData(Arrays.asList("-1"),
+ VALID_APPLICATION_ID);
+ assertThat(applicationData, not(nullValue()));
+ assertThat(applicationData.size(), is(equalTo(0)));
+ }
+
+ @Test
+ public void getApplicationData_byUserIdsAndApplicationId_multipleUserIds_valid() {
+ List<ApplicationData> applicationData = repository.getApplicationData(Arrays.asList(VALID_USER_ID, "NO-DATA-USER"),
+ VALID_APPLICATION_ID);
+ //Since there is no appdata in the database for "NO-DATA-USER" we should only get back one result
+ assertThat(applicationData.size(), is(equalTo(1)));
+ validateApplicationData(applicationData.get(0));
+ }
+
+ @Test
+ @Transactional
+ @Rollback(true)
+ public void save_newEntity() {
+ ApplicationData applicationData = new ApplicationData(null, VALID_USER_ID, SECOND_VALID_APPLICATION_ID,
+ validApplicationDataMap);
+
+ ApplicationData saved = repository.save(applicationData);
+ manager.flush();
+ assertThat(saved.getEntityId(), is(notNullValue()));
+ }
+
+ @Test
+ @Transactional
+ @Rollback(true)
+ public void save_existingEntity() {
+ ApplicationData applicationData = new ApplicationData(VALID_APPLICATION_DATA_ID, VALID_USER_ID,
+ VALID_APPLICATION_ID, new HashMap<String, String>());
+
+ ApplicationData saved = repository.save(applicationData);
+ manager.flush();
+ assertThat(saved, is(not(sameInstance(applicationData))));
+ assertThat(saved.getEntityId(), is(equalTo(applicationData.getEntityId())));
+ }
+
+ private void validateApplicationData(ApplicationData applicationData) {
+ assertThat(applicationData, is(not(nullValue())));
+ assertThat(applicationData.getEntityId(), is(equalTo(VALID_APPLICATION_DATA_ID)));
+ assertThat(applicationData.getUserId(), is(equalTo(VALID_USER_ID)));
+ assertThat(applicationData.getAppUrl(), is(equalTo(VALID_APPLICATION_ID)));
+
+ Map<String, String> actualData = applicationData.getData();
+ for (Map.Entry<String, String> entry : validApplicationDataMap.entrySet()) {
+ assertEquals(entry.getValue(), actualData.get(entry.getKey()));
+ }
+ }
+}
Modified: incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/service/AppDataServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/service/AppDataServiceTest.java?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/service/AppDataServiceTest.java (original)
+++ incubator/rave/trunk/rave-shindig/src/test/java/org/apache/rave/opensocial/service/AppDataServiceTest.java Tue Oct 11 20:19:40 2011
@@ -19,8 +19,380 @@
package org.apache.rave.opensocial.service;
-/**
- */
+import org.apache.rave.opensocial.model.ApplicationData;
+import org.apache.rave.opensocial.model.Person;
+import org.apache.rave.opensocial.repository.ApplicationDataRepository;
+import org.apache.rave.opensocial.service.impl.DefaultAppDataService;
+import org.apache.rave.service.LockService;
+import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.protocol.DataCollection;
+import org.apache.shindig.protocol.ProtocolException;
+import org.apache.shindig.social.opensocial.spi.AppDataService;
+import org.apache.shindig.social.opensocial.spi.GroupId;
+import org.apache.shindig.social.opensocial.spi.UserId;
+import org.easymock.Capture;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
public class AppDataServiceTest {
+ private SimplePersonService personService;
+ private LockService lockService;
+ private ApplicationDataRepository appDataRepository;
+ private AppDataService appDataService;
+
+ private static final String VALID_OWNER_ID = "12345";
+ private static final String VALID_VIEWER_ID = "12345";
+ private static final String VALID_USER_ID = "12345";
+ private static final String VALID_APPLICATION_ID = "http://example.com/gadget.xml";
+ private static final Long VALID_APPLICATION_DATA_ID = 1L;
+ private static final Long VALID_MODULE_ID = 1l;
+
+ private Map<String, String> validApplicationDataMap;
+ private ApplicationData validApplicationData;
+
+ private Person validPerson;
+
+ @Before
+ public void setup() {
+ personService = createMock(SimplePersonService.class);
+ lockService = createMock(LockService.class);
+ appDataRepository = createMock(ApplicationDataRepository.class);
+ appDataService = new DefaultAppDataService(personService, lockService, appDataRepository);
+
+ validApplicationDataMap = new HashMap<String, String>();
+ validApplicationDataMap.put("color", "blue");
+ validApplicationDataMap.put("speed", "fast");
+ validApplicationDataMap.put("state", "MA");
+ validApplicationData = new ApplicationData(VALID_APPLICATION_DATA_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ validApplicationDataMap);
+
+ validPerson = new Person();
+ validPerson.setEntityId(Long.valueOf(VALID_VIEWER_ID));
+ }
+
+ @Test
+ public void getPersonData_validRequest_hasAppData() throws Exception {
+ testGetPersonData(validApplicationData.getData().keySet(), VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ validApplicationData, validApplicationData.getData());
+ }
+
+ @Test
+ public void getPersonData_validRequest_noAppData() throws Exception {
+ testGetPersonData(validApplicationData.getData().keySet(), VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ null, new HashMap<String, String>());
+ }
+
+ @Test
+ public void getPersonData_validRequest_hasAppData_nullFields() throws Exception {
+ testGetPersonData(null, VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ validApplicationData, validApplicationData.getData());
+ }
+
+ @Test
+ public void getPersonData_validRequest_hasAppData_emptyFields() throws Exception {
+ testGetPersonData(new HashSet<String>(), VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ validApplicationData, validApplicationData.getData());
+ }
+
+ @Test
+ public void getPersonData_validRequest_hasAppData_partialFields() throws Exception {
+ HashMap<String, String> expectedData = new HashMap<String, String>(validApplicationDataMap);
+ expectedData.remove("color");
+
+ testGetPersonData(expectedData.keySet(), VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID,
+ validApplicationData, expectedData);
+ }
+
+ @Test(expected = ProtocolException.class)
+ public void getPersonData_invalidRequest_wrongApplication() throws Exception {
+ testGetPersonData(validApplicationData.getData().keySet(), VALID_OWNER_ID, VALID_VIEWER_ID,
+ "http://example.com/wrong.xml", validApplicationData, validApplicationData.getData());
+ }
+
+ @Test
+ public void deletePersonData_validRequest_clearAllDataWithAllFields() throws Exception {
+ Set<String> fieldsToDelete = new HashSet<String>(validApplicationData.getData().keySet());
+
+ testDeletePersonData(fieldsToDelete, new HashMap<String, String>());
+ }
+
+ @Test
+ public void deletePersonData_validRequest_clearAllDataWithNullFields() throws Exception {
+ testDeletePersonData(null, new HashMap<String, String>());
+ }
+
+ @Test
+ public void deletePersonData_validRequest_clearAllDataWithEmptyFields() throws Exception {
+ testDeletePersonData(new HashSet<String>(), new HashMap<String, String>());
+ }
+
+ @Test
+ public void deletePersonData_validRequest_clearSomeData() throws Exception {
+ Set<String> fieldsToDelete = new HashSet<String>(validApplicationData.getData().keySet());
+ fieldsToDelete.remove("color");
+ HashMap<String, String> expectedApplicationDataAfterDelete = new HashMap<String, String>(validApplicationData.getData());
+ for (String fieldToDelete : fieldsToDelete) {
+ expectedApplicationDataAfterDelete.remove(fieldToDelete);
+ }
+
+ testDeletePersonData(fieldsToDelete, expectedApplicationDataAfterDelete);
+ }
+
+ @Test(expected = ProtocolException.class)
+ public void deletePersonData_invalidRequest_wrongViewer() throws Exception {
+ testDeletePersonData("11111", "11111", new HashSet<String>(), new HashMap<String, String>(),
+ validApplicationData);
+ }
+
+ @Test
+ public void deletePersonData_validRequest_nullApplicationData() throws Exception {
+ testDeletePersonDataNoAppDataExpected(null);
+ }
+
+ @Test
+ public void deletePersonData_validRequest_emptyApplicationData() throws Exception {
+ ApplicationData applicationData = new ApplicationData();
+ testDeletePersonDataNoAppDataExpected(applicationData);
+ }
+
+
+ @Test
+ public void updatePersonData_validRequest_removeAllValues() throws Exception {
+ HashMap<String, String> values = new HashMap<String, String>();
+ testUpdatePersonData(null, values, values, validApplicationData);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_replaceAllValues_nullFields() throws Exception {
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("newKey1", "newValue1");
+ values.put("newKey2", "newValue2");
+ testUpdatePersonData(null, values, values, validApplicationData);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_replaceAllValues_emptyFields() throws Exception {
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("newKey1", "newValue1");
+ values.put("newKey2", "newValue2");
+ testUpdatePersonData(new HashSet<String>(), values, values, validApplicationData);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_appendNewValues() throws Exception {
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("newKey1", "newValue1");
+ values.put("newKey2", "newValue2");
+
+ HashMap<String, String> expectedValuesAfterUpdate = new HashMap<String, String>(validApplicationData.getData());
+ expectedValuesAfterUpdate.putAll(values);
+
+ testUpdatePersonData(values.keySet(), values, expectedValuesAfterUpdate, validApplicationData);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_appendNewValues_nullApplicationData() throws Exception {
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("newKey1", "newValue1");
+ values.put("newKey2", "newValue2");
+
+ testUpdatePersonData(values.keySet(), values, values, null);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_removeOneField() throws Exception {
+ String propertyToRemove = "color";
+ Set<String> fields = new HashSet<String>();
+ fields.add(propertyToRemove);
+
+ HashMap<String, String> expectedValuesAfterUpdate = new HashMap<String, String>(validApplicationData.getData());
+ expectedValuesAfterUpdate.remove(propertyToRemove);
+
+ testUpdatePersonData(fields, new HashMap<String, String>(), expectedValuesAfterUpdate, validApplicationData);
+ }
+
+ @Test
+ public void updatePersonData_validRequest_updateExistingField() throws Exception {
+ String propertyToUpdate = "color";
+ String updatedValue = "ZZZZZZZZZZ";
+
+ Set<String> fields = new HashSet<String>();
+ fields.add(propertyToUpdate);
+
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put(propertyToUpdate, updatedValue);
+
+ HashMap<String, String> expectedValuesAfterUpdate = new HashMap<String, String>(validApplicationData.getData());
+ expectedValuesAfterUpdate.put(propertyToUpdate, updatedValue);
+
+ testUpdatePersonData(fields, values, expectedValuesAfterUpdate, validApplicationData);
+ }
+
+ @Test(expected = ProtocolException.class)
+ public void updatePersonData_invalidRequest_invalidArguments() throws Exception {
+ Set<String> fields = new HashSet<String>();
+ fields.add("foo");
+
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("a key", "that is not present in the fields set");
+ testUpdatePersonData(fields, values, values, validApplicationData);
+ }
+
+ private void testGetPersonData(Set<String> fields, String ownerId, String viewerId, String applicationId,
+ ApplicationData applicationData, Map<String, String> expectedData) throws Exception {
+
+ Set<UserId> userIds = new HashSet<UserId>(Arrays.asList(new UserId(UserId.Type.userId, VALID_USER_ID)));
+
+ SecurityToken securityToken = getMockSecurityToken(ownerId, viewerId, applicationId, VALID_MODULE_ID);
+
+ List<Person> users = Arrays.asList(validPerson);
+ GroupId groupId = new GroupId(GroupId.Type.self, "@self");
+ expect(personService.getPeople(userIds, groupId, null, securityToken)).andReturn(users);
+ replay(personService);
+
+ expect(appDataRepository.getApplicationData(convertPeopleToUserIds(users), applicationId)).andReturn(
+ applicationData == null ? new ArrayList<ApplicationData>() : Arrays.asList(applicationData));
+ replay(appDataRepository);
+
+ Future<DataCollection> result = appDataService.getPersonData(userIds, groupId, VALID_APPLICATION_ID, fields,
+ securityToken);
+ Map<String, String> actualData = result.get().getEntry().get(viewerId);
+ assertThat(actualData, is(not(nullValue())));
+ for (Map.Entry<String, String> entry : expectedData.entrySet()) {
+ assertEquals(entry.getValue(), actualData.get(entry.getKey()));
+ }
+ }
+
+ private void testDeletePersonData(Set<String> fieldsToDelete, HashMap<String, String> expectedApplicationDataAfterDelete) {
+ testDeletePersonData(VALID_OWNER_ID, VALID_VIEWER_ID, fieldsToDelete, expectedApplicationDataAfterDelete,
+ validApplicationData);
+ }
+
+ private void testDeletePersonData(String ownerId, String viewerId, Set<String> fieldsToDelete,
+ HashMap<String, String> expectedApplicationDataAfterDelete,
+ ApplicationData applicationData) {
+
+ UserId userId = new UserId(UserId.Type.userId, VALID_USER_ID);
+ Set<UserId> userIds = new HashSet<UserId>(Arrays.asList(userId));
+
+ SecurityToken securityToken = getMockSecurityToken(ownerId, viewerId, VALID_APPLICATION_ID, VALID_MODULE_ID);
+
+ List<Person> users = Arrays.asList(validPerson);
+ GroupId groupId = new GroupId(GroupId.Type.self, "@self");
+ expect(personService.getPeople(userIds, groupId, null, securityToken)).andReturn(users);
+ replay(personService);
+
+ expect(appDataRepository.getApplicationData(VALID_USER_ID, VALID_APPLICATION_ID)).andReturn(applicationData);
+ Capture<ApplicationData> capturedApplicationData = new Capture<ApplicationData>();
+ expect(appDataRepository.save(capture(capturedApplicationData))).andReturn(null);
+ replay(appDataRepository);
+
+ ReentrantLock lock = new ReentrantLock();
+ expect(lockService.borrowLock(anyObject(String.class), anyObject(String.class))).andReturn(lock);
+ lockService.returnLock(lock);
+ replay(lockService);
+
+ appDataService.deletePersonData(userId, groupId, VALID_APPLICATION_ID, fieldsToDelete, securityToken);
+
+ ApplicationData expectedApplicationData = new ApplicationData(applicationData.getEntityId(),
+ applicationData.getUserId(), applicationData.getAppUrl(), expectedApplicationDataAfterDelete);
+
+ ApplicationData actualApplicationData = capturedApplicationData.getValue();
+ assertEquals(expectedApplicationData.getEntityId(), actualApplicationData.getEntityId());
+ assertEquals(expectedApplicationData.getUserId(), actualApplicationData.getUserId());
+ assertEquals(expectedApplicationData.getAppUrl(), actualApplicationData.getAppUrl());
+ assertEquals(expectedApplicationData.getData(), actualApplicationData.getData());
+ }
+
+ private void testDeletePersonDataNoAppDataExpected(ApplicationData applicationData) throws InterruptedException, ExecutionException {
+
+ UserId userId = new UserId(UserId.Type.userId, VALID_USER_ID);
+ Set<UserId> userIds = new HashSet<UserId>(Arrays.asList(userId));
+
+ SecurityToken securityToken = getMockSecurityToken(VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID, VALID_MODULE_ID);
+
+ List<Person> users = Arrays.asList(validPerson);
+ GroupId groupId = new GroupId(GroupId.Type.self, "@self");
+ expect(personService.getPeople(userIds, groupId, null, securityToken)).andReturn(users);
+ replay(personService);
+
+ expect(appDataRepository.getApplicationData(VALID_USER_ID, VALID_APPLICATION_ID)).andReturn(applicationData);
+ replay(appDataRepository);
+
+ ReentrantLock lock = new ReentrantLock();
+ expect(lockService.borrowLock(anyObject(String.class), anyObject(String.class))).andReturn(lock);
+ lockService.returnLock(lock);
+ replay(lockService);
+
+ Future<Void> result = appDataService.deletePersonData(userId, groupId, VALID_APPLICATION_ID, null, securityToken);
+ assertEquals(null, result.get());
+ }
+
+ private void testUpdatePersonData(Set<String> fields, Map<String, String> values,
+ HashMap<String, String> expectedApplicationDataAfterUpdate,
+ ApplicationData applicationData) {
+
+ UserId userId = new UserId(UserId.Type.userId, VALID_USER_ID);
+ Set<UserId> userIds = new HashSet<UserId>(Arrays.asList(userId));
+
+ SecurityToken securityToken = getMockSecurityToken(VALID_OWNER_ID, VALID_VIEWER_ID, VALID_APPLICATION_ID, VALID_MODULE_ID);
+
+ List<Person> users = Arrays.asList(validPerson);
+ GroupId groupId = new GroupId(GroupId.Type.self, "@self");
+ expect(personService.getPeople(userIds, groupId, null, securityToken)).andReturn(users);
+ replay(personService);
+
+ expect(appDataRepository.getApplicationData(VALID_USER_ID, VALID_APPLICATION_ID)).andReturn(applicationData);
+ Capture<ApplicationData> capturedApplicationData = new Capture<ApplicationData>();
+ expect(appDataRepository.save(capture(capturedApplicationData))).andReturn(null);
+ replay(appDataRepository);
+
+ ReentrantLock lock = new ReentrantLock();
+ expect(lockService.borrowLock(anyObject(String.class), anyObject(String.class))).andReturn(lock);
+ lockService.returnLock(lock);
+ replay(lockService);
+
+ appDataService.updatePersonData(userId, groupId, VALID_APPLICATION_ID, fields, values, securityToken);
+
+ ApplicationData expectedApplicationData = applicationData == null ? new ApplicationData(null, VALID_USER_ID,
+ VALID_APPLICATION_ID, expectedApplicationDataAfterUpdate) :
+ new ApplicationData(applicationData.getEntityId(), applicationData.getUserId(),
+ applicationData.getAppUrl(), expectedApplicationDataAfterUpdate);
+
+ ApplicationData actualApplicationData = capturedApplicationData.getValue();
+ assertEquals(expectedApplicationData.getEntityId(), actualApplicationData.getEntityId());
+ assertEquals(expectedApplicationData.getUserId(), actualApplicationData.getUserId());
+ assertEquals(expectedApplicationData.getAppUrl(), actualApplicationData.getAppUrl());
+ assertEquals(expectedApplicationData.getData(), actualApplicationData.getData());
+ }
+
+ private SecurityToken getMockSecurityToken(String ownerId, String viewerId, String applicationId, Long moduleID) {
+ SecurityToken securityToken;
+ securityToken = createNiceMock(SecurityToken.class);
+ expect(securityToken.getOwnerId()).andReturn(ownerId);
+ expect(securityToken.getViewerId()).andReturn(viewerId);
+ expect(securityToken.getAppId()).andReturn(applicationId);
+ expect(securityToken.getModuleId()).andReturn(moduleID);
+ replay(securityToken);
+ return securityToken;
+ }
+ private List<String> convertPeopleToUserIds(List<Person> people) {
+ List<String> ids = new ArrayList<String>(people.size());
+ for (Person person : people) {
+ ids.add(String.valueOf(person.getEntityId()));
+ }
+ return ids;
+ }
}
Modified: incubator/rave/trunk/rave-shindig/src/test/resources/test_data.sql
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-shindig/src/test/resources/test_data.sql?rev=1182068&r1=1182067&r2=1182068&view=diff
==============================================================================
--- incubator/rave/trunk/rave-shindig/src/test/resources/test_data.sql (original)
+++ incubator/rave/trunk/rave-shindig/src/test/resources/test_data.sql Tue Oct 11 20:19:40 2011
@@ -16,6 +16,7 @@
-- under the License.
set @token_info_seq = 'token_info';
set @oauth_consumer_store_seq = 'oauth_consumer_store';
+set @application_data_seq = 'application_data';
set @token_info_id_1 = (SELECT seq_count FROM RAVE_SHINDIG_SEQUENCES WHERE seq_name = @token_info_seq);
INSERT INTO oauth_token_info(entity_id, access_token, token_secret, session_handle, token_expire_millis, app_url, module_id, token_name, service_name, user_id)
@@ -26,3 +27,8 @@ set @consumer_store_id_1 = (SELECT seq_c
INSERT INTO oauth_consumer_store(entity_id, gadget_uri, service_name, consumer_key, consumer_secret, key_type, key_name, callback_url)
VALUES (@consumer_store_id_1, 'http://localhost:8080/samplecontainer/examples/oauth.xml', 'Google', 'gadgetConsumer', 'gadgetSecret', 'HMAC_SYMMETRIC', 'keyName', 'http://oauth.gmodules.com/gadgets/oauthcallback');
UPDATE RAVE_SHINDIG_SEQUENCES SET seq_count = (seq_count + 1) WHERE seq_name = @oauth_consumer_store_seq;
+
+set @application_data_id_1 = (SELECT seq_count FROM RAVE_SHINDIG_SEQUENCES WHERE seq_name = @application_data_seq);
+INSERT INTO application_data(entity_id, user_id, app_url, serialized_data, dtype)
+VALUES (@application_data_id_1, '12345', 'http://example.com/gadget.xml', '{"color":"blue","speed":"fast","state":"MA"}', 'JpaApplicationDataRepository$JpaSerializableApplicationData');
+UPDATE RAVE_SHINDIG_SEQUENCES SET seq_count = (seq_count + 1) WHERE seq_name = @application_data_seq;
\ No newline at end of file