View Javadoc
1   /*
2    * Copyright (C) 2003-2007 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.social.opensocial.service;
18  
19  import java.util.List;
20  import java.util.Set;
21  import java.util.concurrent.CompletableFuture;
22  import java.util.concurrent.Future;
23  
24  import javax.servlet.http.HttpServletResponse;
25  
26  import com.google.common.collect.Lists;
27  import org.apache.shindig.auth.AnonymousSecurityToken;
28  import org.apache.shindig.auth.SecurityToken;
29  import org.apache.shindig.protocol.ProtocolException;
30  import org.apache.shindig.protocol.RestfulCollection;
31  import org.apache.shindig.social.core.model.ActivityImpl;
32  import org.apache.shindig.social.opensocial.model.Activity;
33  import org.apache.shindig.social.opensocial.spi.ActivityService;
34  import org.apache.shindig.social.opensocial.spi.CollectionOptions;
35  import org.apache.shindig.social.opensocial.spi.GroupId;
36  import org.apache.shindig.social.opensocial.spi.UserId;
37  import org.exoplatform.container.PortalContainer;
38  import org.exoplatform.social.common.RealtimeListAccess;
39  import org.exoplatform.social.core.activity.model.ExoSocialActivity;
40  import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
41  import org.exoplatform.social.core.identity.model.Identity;
42  import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
43  import org.exoplatform.social.core.identity.provider.SpaceIdentityProvider;
44  import org.exoplatform.social.core.manager.ActivityManager;
45  import org.exoplatform.social.core.manager.IdentityManager;
46  
47  /**
48   * The Class ExoActivityService.
49   */
50  public class ExoActivityService extends ExoService implements ActivityService {
51  
52    /** The Constant OPENSOCIAL_PREFIX. */
53    public final static String OPENSOCIAL_PREFIX        = "opensocial:";
54  
55    /** The Constant OPENSOCIAL_PREFIX_LENGTH. */
56    public final static int    OPENSOCIAL_PREFIX_LENGTH = OPENSOCIAL_PREFIX.length();
57  
58    /*
59     * (non-Javadoc)
60     * @see
61     * org.apache.shindig.social.opensocial.spi.ActivityService#getActivities(
62     * java.util.Set, org.apache.shindig.social.opensocial.spi.GroupId,
63     * java.lang.String, java.util.Set,
64     * org.apache.shindig.social.opensocial.spi.CollectionOptions,
65     * org.apache.shindig.auth.SecurityToken)
66     */
67    public Future<RestfulCollection<Activity>> getActivities(Set<UserId> userIds,
68                                                             GroupId groupId,
69                                                             String appId,
70                                                             Set<String> fields,
71                                                             CollectionOptions options,
72                                                             SecurityToken token) throws ProtocolException {
73      List<Activity> result = Lists.newArrayList();
74  
75      PortalContainer pc = getPortalContainer(token);
76      ActivityManager am = (ActivityManager) pc.getComponentInstanceOfType(ActivityManager.class);
77  
78      try {
79        Set<Identity> idSet = getIdSet(userIds, groupId, token);
80        for (Identity id : idSet) {
81          // TODO filter by appID
82          RealtimeListAccess<ExoSocialActivity> activityListAccess = am.getActivitiesWithListAccess(id);
83          result.addAll(convertToOSActivities(activityListAccess.loadAsList(options.getFirst(), options.getMax()), fields));
84        }
85  
86        return CompletableFuture.completedFuture(new RestfulCollection<Activity>(result, 0, result.size()));
87      } catch (Exception je) {
88        throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, je.getMessage(), je);
89      }
90    }
91  
92    /*
93     * (non-Javadoc)
94     * @see
95     * org.apache.shindig.social.opensocial.spi.ActivityService#getActivities(
96     * org.apache.shindig.social.opensocial.spi.UserId,
97     * org.apache.shindig.social.opensocial.spi.GroupId, java.lang.String,
98     * java.util.Set, org.apache.shindig.social.opensocial.spi.CollectionOptions,
99     * java.util.Set, org.apache.shindig.auth.SecurityToken)
100    */
101   public Future<RestfulCollection<Activity>> getActivities(UserId userId,
102                                                            GroupId groupId,
103                                                            String appId,
104                                                            Set<String> fields,
105                                                            CollectionOptions options,
106                                                            Set<String> activityIds,
107                                                            SecurityToken token) throws ProtocolException {
108     List<Activity> result = Lists.newArrayList();
109     try {
110       if (token instanceof AnonymousSecurityToken) {
111         throw new Exception(Integer.toString(HttpServletResponse.SC_FORBIDDEN));
112       }
113 
114       PortalContainer pc = getPortalContainer(token);
115       ActivityManager am = (ActivityManager) pc.getComponentInstanceOfType(ActivityManager.class);
116 
117       String user = userId.getUserId(token);
118       Identity id = getIdentity(user, token);
119 
120       List<ExoSocialActivity> exoActivities = am.getActivitiesWithListAccess(id)
121                                                 .loadAsList(options.getFirst(), options.getMax());
122 
123       // TODO : this is not efficient, this should be done by the JCR
124       for (ExoSocialActivity exoActivity : exoActivities) {
125         if (exoActivity.getType() != null && exoActivity.getType().startsWith(OPENSOCIAL_PREFIX)) {
126           if (activityIds.contains(exoActivity.getType().substring(OPENSOCIAL_PREFIX_LENGTH)))
127             ;
128           result.add(convertToOSActivity(exoActivity, fields));
129         }
130       }
131 
132       return CompletableFuture.completedFuture(new RestfulCollection<Activity>(result, 0, result.size()));
133     } catch (Exception je) {
134       throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, je.getMessage(), je);
135     }
136   }
137 
138   /*
139    * (non-Javadoc)
140    * @see
141    * org.apache.shindig.social.opensocial.spi.ActivityService#getActivity(org
142    * .apache.shindig.social.opensocial.spi.UserId,
143    * org.apache.shindig.social.opensocial.spi.GroupId, java.lang.String,
144    * java.util.Set, java.lang.String, org.apache.shindig.auth.SecurityToken)
145    */
146   public Future<Activity> getActivity(UserId userId,
147                                       GroupId groupId,
148                                       String appId,
149                                       Set<String> fields,
150                                       String activityId,
151                                       SecurityToken token) throws ProtocolException {
152     throw new ProtocolException(HttpServletResponse.SC_NOT_IMPLEMENTED, null);
153   }
154 
155   /*
156    * (non-Javadoc)
157    * @see
158    * org.apache.shindig.social.opensocial.spi.ActivityService#deleteActivities
159    * (org.apache.shindig.social.opensocial.spi.UserId,
160    * org.apache.shindig.social.opensocial.spi.GroupId, java.lang.String,
161    * java.util.Set, org.apache.shindig.auth.SecurityToken)
162    */
163   public Future<Void> deleteActivities(UserId userId,
164                                        GroupId groupId,
165                                        String appId,
166                                        Set<String> activityIds,
167                                        SecurityToken token) throws ProtocolException {
168     throw new ProtocolException(HttpServletResponse.SC_NOT_IMPLEMENTED, null);
169   }
170 
171   /*
172    * (non-Javadoc)
173    * @see
174    * org.apache.shindig.social.opensocial.spi.ActivityService#createActivity
175    * (org.apache.shindig.social.opensocial.spi.UserId,
176    * org.apache.shindig.social.opensocial.spi.GroupId, java.lang.String,
177    * java.util.Set, org.apache.shindig.social.opensocial.model.Activity,
178    * org.apache.shindig.auth.SecurityToken)
179    */
180   public Future<Void> createActivity(UserId userId,
181                                      GroupId groupId,
182                                      String appId,
183                                      Set<String> fields,
184                                      Activity activity,
185                                      SecurityToken token) throws ProtocolException {
186     try {
187       activity.setAppId(appId); //groupId = new GroupId(GroupId.Type.groupId, "space:qsdsqd")
188 
189       ExoSocialActivity exoActivity = convertFromOSActivity(activity, fields);
190 
191 
192       if (token instanceof AnonymousSecurityToken) {
193         throw new ProtocolException(HttpServletResponse.SC_UNAUTHORIZED, " a non anonymous security token is expected");
194       }
195 
196       PortalContainer pc = getPortalContainer(token);
197       ActivityManager am = (ActivityManager) pc.getComponentInstanceOfType(ActivityManager.class);
198       IdentityManager identityManager = (IdentityManager) pc.getComponentInstanceOfType(IdentityManager.class);
199 
200       String user = userId.getUserId(token); // can be organization:name or organization:UUID
201       if (user.contains(":")) {
202         user = user.split(":")[1];
203       }
204 
205       Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, user, false);
206 
207       // identity for the stream to post on
208       Identity targetStream = userIdentity;
209 
210       /// someone posting for a space ?
211       if (groupId.getType() == GroupId.Type.objectId) {
212         String group = groupId.toString(); // can be space:name or space:UUID
213         if (group.contains(":")) {
214           group = group.split(":")[1];
215         }
216         targetStream = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, group, false);
217         // TODO : check that member is allowed to post on group or throw SC_UNAUTHORIZED
218       }
219 
220       // we need to know where to post
221       if (targetStream == null) {
222         throw new ProtocolException(HttpServletResponse.SC_FORBIDDEN, user + " is an unknown identity");
223       }
224 
225       // Define activity user if not already set
226       String activityUser = exoActivity.getUserId();
227       if (activityUser == null) {
228         exoActivity.setUserId(userIdentity.getId());
229 
230         // making sure it resolves to a valid identity
231       } else {
232         Identity activityUserIdentity = identityManager.getIdentity(activityUser);
233         if (activityUserIdentity == null) {
234           throw new ProtocolException(HttpServletResponse.SC_FORBIDDEN, activityUser + " is an unknown identity");
235         }
236       }
237 
238       am.saveActivityNoReturn(targetStream, exoActivity);
239 
240       return CompletableFuture.completedFuture(null);
241     } catch (Exception e) {
242       if (e instanceof ProtocolException) {
243         throw (ProtocolException)e;
244       }
245       throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e);
246     }
247   }
248 
249   /**
250    * Convert from os activity.
251    *
252    * @param activity the activity
253    * @param fields the fields
254    * @return the org.exoplatform.social.core.activitystream.model. activity
255    */
256   private ExoSocialActivity convertFromOSActivity(Activity activity,
257                                                                                           Set<String> fields) {
258 
259     ExoSocialActivity exoActivity = new ExoSocialActivityImpl();
260 
261     if (fields != null && !fields.isEmpty()) {
262 
263       for (String field : fields) {
264 
265         if (field.equals(Activity.Field.APP_ID.name())) {
266           exoActivity.setAppId(activity.getAppId());
267         }
268 
269         if (field.equals(Activity.Field.BODY.name())) {
270           exoActivity.setBody(activity.getBody());
271         }
272 
273         if (field.equals(Activity.Field.BODY_ID.name())) {
274           exoActivity.setBodyId(activity.getBodyId());
275         }
276 
277         if (field.equals(Activity.Field.EXTERNAL_ID.name())) {
278           exoActivity.setExternalId(activity.getExternalId());
279         }
280 
281         if (field.equals(Activity.Field.ID.name())) {
282           exoActivity.setId(activity.getId());
283         }
284 
285         if (field.equals(Activity.Field.MEDIA_ITEMS.name())) {
286           exoActivity.setMediaItems(activity.getMediaItems());
287         }
288 
289         if (field.equals(Activity.Field.POSTED_TIME.name())) {
290           exoActivity.setPostedTime(activity.getPostedTime());
291         }
292 
293         if (field.equals(Activity.Field.LAST_UPDATED.name())) {
294           exoActivity.setUpdated(activity.getUpdated());
295         }
296 
297         if (field.equals(Activity.Field.PRIORITY.name())) {
298           exoActivity.setPriority(activity.getPriority());
299         }
300 
301         if (field.equals(Activity.Field.STREAM_FAVICON_URL.name())) {
302           exoActivity.setStreamFaviconUrl(activity.getStreamFaviconUrl());
303         }
304 
305         if (field.equals(Activity.Field.STREAM_SOURCE_URL.name())) {
306           exoActivity.setStreamSourceUrl(activity.getStreamSourceUrl());
307         }
308 
309         if (field.equals(Activity.Field.STREAM_TITLE.name())) {
310           exoActivity.setStreamTitle(activity.getStreamTitle());
311         }
312 
313         if (field.equals(Activity.Field.STREAM_URL.name())) {
314           exoActivity.setStreamUrl(activity.getStreamUrl());
315         }
316 
317         if (field.equals(Activity.Field.TEMPLATE_PARAMS.name())) {
318           exoActivity.setTemplateParams(activity.getTemplateParams());
319         }
320 
321         if (field.equals(Activity.Field.TITLE.name())) {
322           exoActivity.setTitle(activity.getTitle());
323         }
324 
325         if (field.equals(Activity.Field.TITLE_ID)) {
326           exoActivity.setTitleId(activity.getTitleId());
327         }
328 
329         if (field.equals(Activity.Field.URL)) {
330           exoActivity.setUrl(activity.getUrl());
331         }
332         if (field.equals(Activity.Field.USER_ID)) {
333           exoActivity.setUserId(activity.getUserId());
334         }
335 
336       }
337 
338     } else {
339 
340       exoActivity.setAppId(activity.getAppId());
341       exoActivity.setBody(activity.getBody());
342       exoActivity.setBodyId(activity.getBodyId());
343       exoActivity.setExternalId(activity.getExternalId());
344       exoActivity.setId(activity.getId());
345       exoActivity.setMediaItems(activity.getMediaItems());
346       if (activity.getPostedTime() != null)
347         exoActivity.setPostedTime(activity.getPostedTime());
348       exoActivity.setPriority(activity.getPriority());
349       exoActivity.setStreamFaviconUrl(activity.getStreamFaviconUrl());
350       exoActivity.setStreamSourceUrl(activity.getStreamSourceUrl());
351       exoActivity.setStreamTitle(activity.getStreamTitle());
352       exoActivity.setStreamUrl(activity.getStreamUrl());
353       exoActivity.setTemplateParams(activity.getTemplateParams());
354       exoActivity.setTitle(activity.getTitle());
355       exoActivity.setTitleId(activity.getTitleId());
356       if (activity.getUpdated() != null)
357         exoActivity.setUpdated(activity.getUpdated());
358       exoActivity.setUrl(activity.getUrl());
359       exoActivity.setUserId(activity.getUserId());
360 
361     }
362     return exoActivity;
363 
364   }
365 
366   /**
367    * Convert to os activity.
368    *
369    * @param exoActivity the exo activity
370    * @param fields the fields
371    * @return the activity
372    */
373   private Activity convertToOSActivity(ExoSocialActivity exoActivity,
374                                        Set<String> fields) {
375 
376     Activity activity = new ActivityImpl();
377 
378     if (fields != null && !fields.isEmpty()) {
379 
380       for (String field : fields) {
381 
382         if (field.equals(Activity.Field.APP_ID.name())) {
383           activity.setAppId(exoActivity.getAppId());
384         }
385 
386         if (field.equals(Activity.Field.BODY.name())) {
387           activity.setBody(exoActivity.getBody());
388         }
389 
390         if (field.equals(Activity.Field.BODY_ID.name())) {
391           activity.setBodyId(exoActivity.getBodyId());
392         }
393 
394         if (field.equals(Activity.Field.EXTERNAL_ID.name())) {
395           activity.setExternalId(exoActivity.getExternalId());
396         }
397 
398         if (field.equals(Activity.Field.ID.name())) {
399           activity.setId(exoActivity.getId());
400         }
401 
402         if (field.equals(Activity.Field.MEDIA_ITEMS.name())) {
403           activity.setMediaItems(exoActivity.getMediaItems());
404         }
405 
406         if (field.equals(Activity.Field.POSTED_TIME.name())) {
407           activity.setPostedTime(exoActivity.getPostedTime());
408         }
409 
410         if (field.equals(Activity.Field.LAST_UPDATED.name())) {
411           activity.setUpdated(exoActivity.getUpdated());
412         }
413 
414         if (field.equals(Activity.Field.PRIORITY.name())) {
415           activity.setPriority(exoActivity.getPriority());
416         }
417 
418         if (field.equals(Activity.Field.STREAM_FAVICON_URL.name())) {
419           activity.setStreamFaviconUrl(exoActivity.getStreamFaviconUrl());
420         }
421 
422         if (field.equals(Activity.Field.STREAM_SOURCE_URL.name())) {
423           activity.setStreamSourceUrl(exoActivity.getStreamSourceUrl());
424         }
425 
426         if (field.equals(Activity.Field.STREAM_TITLE.name())) {
427           activity.setStreamTitle(exoActivity.getStreamTitle());
428         }
429 
430         if (field.equals(Activity.Field.STREAM_URL.name())) {
431           activity.setStreamUrl(exoActivity.getStreamUrl());
432         }
433 
434         if (field.equals(Activity.Field.TEMPLATE_PARAMS.name())) {
435           activity.setTemplateParams(exoActivity.getTemplateParams());
436         }
437 
438         if (field.equals(Activity.Field.TITLE.name())) {
439           activity.setTitle(exoActivity.getTitle());
440         }
441 
442         if (field.equals(Activity.Field.TITLE_ID)) {
443           activity.setTitleId(exoActivity.getTitleId());
444         }
445 
446         if (field.equals(Activity.Field.URL)) {
447           activity.setUrl(exoActivity.getUrl());
448         }
449         if (field.equals(Activity.Field.USER_ID)) {
450           activity.setUserId(exoActivity.getUserId());
451         }
452 
453       }
454 
455     } else {
456 
457       activity.setAppId(exoActivity.getAppId());
458       activity.setBody(exoActivity.getBody());
459       activity.setBodyId(exoActivity.getBodyId());
460       activity.setExternalId(exoActivity.getExternalId());
461       activity.setId(exoActivity.getId());
462       activity.setMediaItems(exoActivity.getMediaItems());
463       activity.setPostedTime(exoActivity.getPostedTime());
464       activity.setPriority(exoActivity.getPriority());
465       activity.setStreamFaviconUrl(exoActivity.getStreamFaviconUrl());
466       activity.setStreamSourceUrl(exoActivity.getStreamSourceUrl());
467       activity.setStreamTitle(exoActivity.getStreamTitle());
468       activity.setStreamUrl(exoActivity.getStreamUrl());
469       activity.setTemplateParams(exoActivity.getTemplateParams());
470       activity.setTitle(exoActivity.getTitle());
471       activity.setTitleId(exoActivity.getTitleId());
472       activity.setUpdated(exoActivity.getUpdated());
473       activity.setUrl(exoActivity.getUrl());
474       activity.setUserId(exoActivity.getUserId());
475     }
476     return activity;
477 
478   }
479 
480   /**
481    * Convert to os activities.
482    *
483    * @param activities the activities
484    * @param fields the fields
485    * @return the list
486    */
487   private List<Activity> convertToOSActivities(List<ExoSocialActivity> activities,
488                                                Set<String> fields) {
489     List<Activity> res = Lists.newArrayList();
490     for (ExoSocialActivity activity : activities) {
491       res.add(convertToOSActivity(activity, fields));
492     }
493     return res;
494   }
495 
496 }