You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by do...@apache.org on 2008/05/15 08:30:44 UTC
svn commit: r656517 - in /incubator/shindig/trunk/java/social-api/src:
main/java/org/apache/shindig/social/abdera/
main/java/org/apache/shindig/social/samplecontainer/
test/java/org/apache/shindig/social/abdera/
Author: doll
Date: Wed May 14 23:30:43 2008
New Revision: 656517
URL: http://svn.apache.org/viewvc?rev=656517&view=rev
Log:
SHINDIG-265
Patch from David Primmer, modified for code style fixes. This change introduces a cleaner way to write the abdera adapter classes. The next step here is to refactor the current adapter classes to use the new code.
Added:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/AbstractSocialEntityCollectionAdapter.java
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/ActivityAdapter.java
Modified:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/SocialApiProvider.java
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/abdera/SocialApiProviderTestFixture.java
Added: incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/AbstractSocialEntityCollectionAdapter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/AbstractSocialEntityCollectionAdapter.java?rev=656517&view=auto
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/AbstractSocialEntityCollectionAdapter.java (added)
+++ incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/AbstractSocialEntityCollectionAdapter.java Wed May 14 23:30:43 2008
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.shindig.social.abdera;
+
+import org.apache.shindig.common.SecurityToken;
+import org.apache.shindig.common.SecurityTokenDecoder;
+import org.apache.shindig.common.SecurityTokenException;
+import org.apache.shindig.social.opensocial.util.BeanJsonConverter;
+import org.apache.shindig.social.opensocial.util.BeanXmlConverter;
+
+import com.google.inject.Inject;
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.i18n.templates.Route;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+import org.apache.abdera.protocol.server.impl.AbstractEntityCollectionAdapter;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * By extending this class it becomes easy to build Collections which are backed
+ * by a set of Social entities - such as a person or activity.
+ *
+ * @param <T> The entity that this is backed by.
+ */
+
+public abstract class AbstractSocialEntityCollectionAdapter<T> extends
+ AbstractEntityCollectionAdapter<T> {
+
+ protected String ID_PREFIX;
+ protected Factory factory;
+ private BeanXmlConverter beanXmlConverter;
+ private BeanJsonConverter beanJsonConverter;
+ private SecurityTokenDecoder securityTokenDecoder;
+
+ public AbstractSocialEntityCollectionAdapter() {
+ ID_PREFIX = "urn:guid:";
+ factory = new Abdera().getFactory();
+ }
+
+ private enum Format {
+ JSON("json"), ATOM("atom");
+
+ private final String displayValue;
+
+ private Format(String displayValue) {
+ this.displayValue = displayValue;
+ }
+
+ public String getDisplayValue() {
+ return displayValue;
+ }
+ }
+
+ @Inject
+ public void setConverters(BeanXmlConverter beanXmlConverter,
+ BeanJsonConverter beanJsonConverter) {
+ this.beanXmlConverter = beanXmlConverter;
+ this.beanJsonConverter = beanJsonConverter;
+ }
+
+ @Inject
+ public void setSecurityTokenDecoder(SecurityTokenDecoder
+ securityTokenDecoder) {
+ this.securityTokenDecoder = securityTokenDecoder;
+ }
+
+ protected SecurityToken getSecurityToken(RequestContext request)
+ throws SecurityTokenException {
+ String token = request.getParameter("st");
+ if (token == null || token.trim().length() == 0) {
+ throw new SecurityTokenException("Missing security token");
+ }
+ return securityTokenDecoder.createToken(token);
+ }
+
+ /**
+ * returns the format (jsoc or atom) from the RequestContext obj created by
+ * Abdera from the URL request.
+ *
+ * @param request the RequestContext obj from Abdera
+ * @return the format and default to Format.JSON
+ */
+ private Format getFormatTypeFromRequest(RequestContext request) {
+ // TODO should gracefully handle introspection if format param is missing.
+ String format = request.getTarget().getParameter("format");
+
+ if (format != null && format.equals(Format.ATOM.getDisplayValue())) {
+ return Format.ATOM;
+ } else {
+ return Format.JSON;
+ }
+ }
+
+ /**
+ * @param request RequestContext
+ * @param resourceRouteVariable The route variable for the entry. So, for a
+ * route pattern of /:collection/:id, with "id" resourceRouteVariable this
+ * would null out "id" in the generated URL.
+ * @return The absolute request URI (includes server name, port, etc) URL for
+ * the collection of the entry.
+ */
+ public String getFeedIriForEntry(RequestContext request,
+ String resourceRouteVariable) {
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put(resourceRouteVariable, null);
+ String uri = request.urlFor(getRoute(request).getName(), params);
+ return request.getResolvedUri().resolve(uri).toString();
+ }
+
+ /**
+ * This assumes the target resolver was a RouteManager and returns a Route
+ * object. If it does not, it throws a NPE for now. It could also deal with a
+ * Regex resolver
+ *
+ * @param request the request
+ * @return The Route object that matched the request.
+ */
+ public Route getRoute(RequestContext request) {
+ Object matcher = request.getTarget().getMatcher();
+ if (matcher instanceof Route) {
+ return (Route) matcher;
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ @Override
+ public Object getContent(T entity, RequestContext request)
+ throws ResponseContextException {
+ Format format = getFormatTypeFromRequest(request);
+ Content content = factory.newContent();
+
+ switch (format) {
+ case ATOM:
+ content.setContentType(Content.Type.XML);
+ content.setValue(beanXmlConverter.convertToXml(entity));
+ break;
+ case JSON:
+ content.setContentType(Content.Type.TEXT);
+ content.setValue(beanJsonConverter.convertToJson(entity).toString());
+ break;
+ }
+ return content;
+ }
+
+ public abstract String getSummary(T entity) throws ResponseContextException;
+
+ /**
+ * Add the details to an entry.
+ *
+ * @param request The request context
+ * @param e The entry
+ * @param feedIri The feed IRI
+ * @param entity The object that the entry is based on.
+ */
+ @Override
+ protected String addEntryDetails(RequestContext request, Entry e,
+ IRI feedIri, T entity) throws ResponseContextException {
+ String link = getLink(entity, feedIri, request);
+
+ e.addLink(link, "self", "application/atom+xml", null, null, 0);
+ e.setId(getId(entity));
+ e.setTitle(getTitle(entity));
+ e.setUpdated(getUpdated(entity));
+ e.setSummary(getSummary(entity));
+ List<Person> authors = getAuthors(entity, request);
+ if (authors != null) {
+ for (Person a : authors) {
+ e.addAuthor(a);
+ }
+ }
+ return link;
+ }
+
+ /**
+ * Unimplemented HTTP methods
+ */
+
+ @Override
+ public ResponseContext deleteEntry(RequestContext request) {
+ return null;
+ }
+
+ @Override
+ public ResponseContext postEntry(RequestContext request) {
+ return null;
+ }
+
+ @Override
+ public ResponseContext putEntry(RequestContext request) {
+ return null;
+ }
+
+ @Override
+ public ResponseContext getFeed(RequestContext request) {
+ return null;
+ }
+}
Added: incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/ActivityAdapter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/ActivityAdapter.java?rev=656517&view=auto
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/ActivityAdapter.java (added)
+++ incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/ActivityAdapter.java Wed May 14 23:30:43 2008
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.shindig.social.abdera;
+
+import org.apache.shindig.common.BasicSecurityToken;
+import org.apache.shindig.common.SecurityToken;
+import org.apache.shindig.common.SecurityTokenException;
+import org.apache.shindig.common.crypto.BlobCrypterException;
+import org.apache.shindig.social.opensocial.ActivitiesService;
+import org.apache.shindig.social.opensocial.model.Activity;
+
+import com.google.inject.Inject;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.context.ResponseContextException;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * This Collection is backed by a set of Activity entities
+ */
+public class ActivityAdapter extends
+ AbstractSocialEntityCollectionAdapter<Activity> {
+
+ private ActivitiesService activitiesService;
+
+ @Inject
+ public ActivityAdapter(ActivitiesService activitiesService) {
+ this.activitiesService = activitiesService;
+ }
+
+ @Override
+ public Activity getEntry(String resourceName, RequestContext request)
+ throws ResponseContextException {
+ String aid = resourceName;
+ String uid = request.getTarget().getParameter("uid");
+ SecurityToken authToken = getSecurityToken(request, uid);
+ return activitiesService.getActivity(uid, aid, authToken).getResponse();
+ }
+
+ private SecurityToken getSecurityToken(RequestContext request,
+ final String viewerId) {
+ try {
+ return super.getSecurityToken(request);
+ } catch (SecurityTokenException se) {
+ // For now, if there's no st param, we'll mock one up.
+ try {
+ return new BasicSecurityToken("o", viewerId, "a", "d", "u", "m");
+ } catch (BlobCrypterException be) {
+ be.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public String getId(Activity activityObj) throws ResponseContextException {
+ return activityObj.getId();
+ }
+
+ // hoisting rule: atom:entry/atom:author/atom:uri aliases "user_id"
+ @Override
+ public List<Person> getAuthors(Activity activityObj, RequestContext request)
+ throws ResponseContextException {
+ Person author = factory.newAuthor();
+ author.setUri(ID_PREFIX + activityObj.getUserId());
+ return Arrays.asList(author);
+ }
+
+ @Override
+ public String getName(Activity activityObj) throws ResponseContextException {
+ return activityObj.getId();
+ }
+
+ // hoisting rule: atom:entry/atom:title aliases "title"
+ @Override
+ public String getTitle(Activity activityObj) throws ResponseContextException {
+ return activityObj.getTitle();
+ }
+
+ @Override
+ public Date getUpdated(Activity activityObj) throws ResponseContextException {
+ return activityObj.getUpdated();
+ }
+
+ // hoisting rule: atom:entry/atom:summary aliases "body"
+ @Override
+ public String getSummary(Activity activityObj)
+ throws ResponseContextException {
+ return activityObj.getBody();
+ }
+
+ /**
+ * Unimplemented Data methods
+ */
+ @Override
+ public void deleteEntry(String resourceName, RequestContext request)
+ throws ResponseContextException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public Iterable<Activity> getEntries(RequestContext request)
+ throws ResponseContextException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Activity postEntry(String title, IRI id, String summary, Date updated,
+ List<Person> authors, Content content, RequestContext request)
+ throws ResponseContextException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void putEntry(Activity entry, String title, Date updated,
+ List<Person> authors, String summary, Content content,
+ RequestContext request) throws ResponseContextException {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * Collection-level hoisting rules
+ */
+
+ /**
+ * The collection-level URL. Calls the getFeedIriForEntry and nulls "aid".
+ *
+ * @param request
+ * RequestContext
+ * @return The absolute request URI (includes server name, port, etc) URL
+ */
+ @Override
+ public String getHref(RequestContext request) {
+ return getFeedIriForEntry(request, "aid");
+ }
+
+ @Override
+ public String getId(RequestContext request) {
+ // TODO what really to return for the feed ID? Better data will help.
+ return getHref(request);
+ }
+
+ // hoisting rule: atom:entry/atom:source/atom:title aliases "stream_title"
+ // TODO stream_title can't be accessed right here....
+ public String getTitle(RequestContext request) {
+ return getRoute(request).getName();
+ }
+
+ // hoisting rule: atom:entry/atom:author/atom:uri aliases "user_id"
+ @Override
+ public String getAuthor(RequestContext request)
+ throws ResponseContextException {
+ return request.getTarget().getParameter("uid");
+ }
+}
Modified: incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/SocialApiProvider.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/SocialApiProvider.java?rev=656517&r1=656516&r2=656517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/SocialApiProvider.java (original)
+++ incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/abdera/SocialApiProvider.java Wed May 14 23:30:43 2008
@@ -32,7 +32,8 @@
private Provider<ActivitiesServiceAdapter> activitiesAdapterProvider;
private Provider<FriendsServiceAdapter> friendsAdapterProvider;
private Provider<DataServiceAdapter> dataAdapterProvider;
-
+ private Provider<ActivityAdapter> activityAdapterProvider;
+
/**
* The CollectionAdapter enum standardizes the names and descriptions of the
* URL templates as defined in the RESTful API spec. Each unique template has
@@ -79,12 +80,14 @@
Provider<PeopleServiceAdapter> peopleAdapterProvider,
Provider<FriendsServiceAdapter> friendsAdapterProvider,
Provider<ActivitiesServiceAdapter> activitiesAdapterProvider,
- Provider<DataServiceAdapter> dataAdapterProvider) {
+ Provider<DataServiceAdapter> dataAdapterProvider,
+ Provider<ActivityAdapter> activityAdapterProvider) {
this.peopleAdapterProvider = peopleAdapterProvider;
this.friendsAdapterProvider = friendsAdapterProvider;
this.activitiesAdapterProvider = activitiesAdapterProvider;
this.dataAdapterProvider = dataAdapterProvider;
- }
+ this.activityAdapterProvider = activityAdapterProvider;
+ }
/**
* CollectionAdapters are provided via Guice and the RouteManager wires
@@ -109,6 +112,7 @@
ActivitiesServiceAdapter activitiesAdapter
= activitiesAdapterProvider.get();
DataServiceAdapter dataAdapter = dataAdapterProvider.get();
+ ActivityAdapter activityAdapter = activityAdapterProvider.get();
// Add the RouteManager that parses incoming and builds outgoing URLs
// {uid} is assumed to be a deterministic GUID for the service
@@ -170,7 +174,7 @@
// /activities/{uid}/@self/{aid}
.addRoute(CollectionAdapter.ACTIVITY_OF_USER.toString(),
BASE + "activities/:uid/@self/:aid",
- TargetType.TYPE_ENTRY, activitiesAdapter)
+ TargetType.TYPE_ENTRY, activityAdapter)
// AppData
Modified: incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java?rev=656517&r1=656516&r2=656517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java (original)
+++ incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/samplecontainer/XmlStateFileFetcher.java Wed May 14 23:30:43 2008
@@ -9,7 +9,6 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
-
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
@@ -20,6 +19,8 @@
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -29,9 +30,6 @@
import java.util.List;
import java.util.Map;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
@Singleton
public class XmlStateFileFetcher {
private static final String DEFAULT_STATE_URL
Modified: incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/abdera/SocialApiProviderTestFixture.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/abdera/SocialApiProviderTestFixture.java?rev=656517&r1=656516&r2=656517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/abdera/SocialApiProviderTestFixture.java (original)
+++ incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/abdera/SocialApiProviderTestFixture.java Wed May 14 23:30:43 2008
@@ -39,14 +39,17 @@
public final Provider<DataServiceAdapter> dataProvider =
mock(Provider.class);
public final SocialApiProvider provider = new SocialApiProvider();
-
+ public final Provider<ActivityAdapter> activityProvider =
+ mock(Provider.class);
+
public SocialApiProviderTestFixture() {
provider.setAdapters(peopleProvider, friendsProvider, activitiesProvider,
- dataProvider);
+ dataProvider, activityProvider);
expect(activitiesProvider.get()).andReturn(null);
expect(peopleProvider.get()).andReturn(null);
expect(friendsProvider.get()).andReturn(null);
expect(dataProvider.get()).andReturn(null);
+ expect(activityProvider.get()).andReturn(null);
org.easymock.EasyMock.replay(activitiesProvider);
org.easymock.EasyMock.replay(peopleProvider);
org.easymock.EasyMock.replay(friendsProvider);