View Javadoc
1   /*
2    * Copyright (C) 2003-2011 eXo Platform SAS.
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU Affero General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (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 Affero General Public License for more details.
13   *
14   * You should have received a copy of the GNU Affero General Public License
15   * along with this program. If not, see <http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.social.service.rest;
18  
19  import java.io.IOException;
20  import java.net.MalformedURLException;
21  import java.net.URI;
22  import java.net.URL;
23  import java.net.URLConnection;
24  import java.net.URLDecoder;
25  import java.text.SimpleDateFormat;
26  import java.util.Date;
27  import java.util.TimeZone;
28  import java.util.regex.Pattern;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.ws.rs.WebApplicationException;
32  import javax.ws.rs.core.MediaType;
33  import javax.ws.rs.core.Response;
34  import javax.ws.rs.core.Response.Status;
35  import javax.ws.rs.core.UriInfo;
36  
37  import org.exoplatform.commons.utils.CommonsUtils;
38  import org.exoplatform.container.ExoContainerContext;
39  import org.exoplatform.container.PortalContainer;
40  import org.exoplatform.services.rest.impl.EnvironmentContext;
41  import org.exoplatform.services.security.ConversationState;
42  import org.exoplatform.services.security.IdentityConstants;
43  import org.exoplatform.social.core.activity.model.ActivityStream;
44  import org.exoplatform.social.core.activity.model.ExoSocialActivity;
45  import org.exoplatform.social.core.identity.model.Identity;
46  import org.exoplatform.social.core.identity.model.Profile;
47  import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
48  import org.exoplatform.social.core.identity.provider.SpaceIdentityProvider;
49  import org.exoplatform.social.core.manager.ActivityManager;
50  import org.exoplatform.social.core.manager.IdentityManager;
51  import org.exoplatform.social.core.manager.RelationshipManager;
52  import org.exoplatform.social.core.service.LinkProvider;
53  import org.exoplatform.social.core.space.spi.SpaceService;
54  import org.exoplatform.social.service.rest.api.models.IdentityRestOut;
55  import org.exoplatform.social.service.rest.api.models.ProfileRestOut;
56  
57  /**
58   * Util.java: utility class for rest <br>.
59   *
60   * @author hoatle
61   * @since  Jan 5, 2009
62   */
63  public final class Util {
64    
65    private static final Pattern URL_PATTERN = Pattern
66        .compile("^(?i)" +
67        "(" +
68          "((?:(?:ht)tp(?:s?)\\:\\/\\/)?" +                                                       // protolcol
69          "(?:\\w+:\\w+@)?" +                                                                       // username password
70          "(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +  // IPAddress
71          "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|" +     // IPAddress
72          "(?:(?:[-\\p{L}\\p{Digit}\\+\\$\\-\\*\\=]+\\.)+" +
73          "(?:[a-z]{2,}))))|" +                                                                     //Domain
74          "(?:(?:(?:ht)tp(?:s?)\\:\\/\\/)(?:\\w+:\\w+@)?(?:[-\\p{L}\\p{Digit}\\+\\$\\-\\*\\=]+))" + // Protocol with hostname
75        ")" +
76        "(?::[\\d]{1,5})?" +                                                                        // port
77        "(?:[\\/|\\?|\\#].*)?$");                                                               // path and query
78  
79    /**
80     * Prevents constructing a new instance.
81     */
82    private Util() {
83    }
84  
85    /**
86     * Checks a url is in a valid form or not.
87     * 
88     * @param link
89     * @return
90     */
91    public static boolean isValidURL(String link) {
92      if (link == null || link.length() == 0) return false;
93      return URL_PATTERN.matcher(link).matches();
94    }
95    
96    /**
97     * Gets the response object constructed from the provided params.
98     *
99     * @param entity the identity
100    * @param uriInfo the uri request info
101    * @param mediaType the media type to be returned
102    * @param status the status code
103    * @return response the response object
104    */
105   public static Response getResponse(Object entity, UriInfo uriInfo, MediaType mediaType, Response.Status status) {
106     Response resp = Response.created(uriInfo.getAbsolutePath())
107                    .entity(entity)
108                    .type(mediaType.toString() + "; charset=utf-8")
109                    .status(status)
110                    .build();
111     
112     return resp;
113   }
114   /**
115    * Gets mediaType from string format.
116    * Currently supports json and xml only.
117    *
118    * @param format
119    * @return mediaType of matched or throw BAD_REQUEST exception
120    * @throws WebApplicationException
121    * @deprecated User {@link #getMediaType(String, String[])} instead.
122    *             Will be removed by 1.3.x
123    */
124   @Deprecated
125   public static MediaType getMediaType(String format) throws WebApplicationException {
126     if (format.equals("json")) {
127       return MediaType.APPLICATION_JSON_TYPE;
128     } else if(format.equals("xml")) {
129       return MediaType.APPLICATION_XML_TYPE;
130     }
131     throw new WebApplicationException(Response.Status.BAD_REQUEST);
132   }
133 
134 
135   /**
136    * Gets the media type from an expected format string (usually the input) and an array of supported format strings.
137    * If expectedFormat is not found in the supported format array, Status.UNSUPPORTED_MEDIA_TYPE is thrown.
138    * The supported format must include one of those format: json, xml, atom or rss, otherwise Status.NOT_ACCEPTABLE
139    * could be thrown.
140    *
141    * @param expectedFormat the expected input format
142    * @param supportedFormats the supported format array
143    * @return the associated media type
144    */
145   public static MediaType getMediaType(String expectedFormat, String[] supportedFormats) {
146 
147     if (!isSupportedFormat(expectedFormat, supportedFormats)) {
148       throw new WebApplicationException(Status.UNSUPPORTED_MEDIA_TYPE);
149     }
150 
151     if (expectedFormat.equals("json") && isSupportedFormat("json", supportedFormats)) {
152       return MediaType.APPLICATION_JSON_TYPE;
153     } else if (expectedFormat.equals("xml") && isSupportedFormat("xml", supportedFormats)) {
154       return MediaType.APPLICATION_XML_TYPE;
155     } else if (expectedFormat.equals("atom") && isSupportedFormat("atom", supportedFormats)) {
156       return MediaType.APPLICATION_ATOM_XML_TYPE;
157     }
158     //TODO What's about RSS format?
159     throw new WebApplicationException(Status.NOT_ACCEPTABLE);
160   }
161 
162   
163   /**
164    * Get viewerId from servlet request data information provided by OpenSocial signed request.
165    *  
166    * @param uriInfo
167    * @return
168    */
169   public static String getViewerId (UriInfo uriInfo) {
170     String viewerId = null;
171 
172     URI uri = uriInfo.getRequestUri();
173     String requestString = uri.getQuery();
174     if (requestString != null) {
175       String[] queryParts = requestString.split("&");
176     
177       for (String queryPart : queryParts) {
178         if (queryPart.startsWith("opensocial_viewer_id")) {
179           viewerId = queryPart.substring(queryPart.indexOf("=") + 1, queryPart.length());
180           break;
181         }
182       }
183     }
184     
185     if (viewerId == null) {
186       ConversationState state = ConversationState.getCurrent();
187       if (state != null) {
188         viewerId = state.getIdentity().getUserId();
189       }
190     }
191 
192     return viewerId;
193   }
194 
195   /**
196    * Gets identity of viewer user (logged-in user). Do not load profile.
197    *
198    * @return identity
199    * @since 1.2.0 GA
200    * @deprecated Use {@link #getViewerIdentity(String, String)} instead.
201    *             Will be removed by 1.3.x
202    */
203   @Deprecated
204   public static Identity getViewerIdentity(String viewerId) {
205     return getUserIdentity(viewerId, false);
206   }
207 
208   /**
209    * Gets identity of viewer user (logged-in user). Do not load profile.
210    *
211    * @return identity
212    * @since 1.2.3
213    */
214   public static Identity getViewerIdentity(String portalContainerName, String viewerId) {
215     return getUserIdentity(portalContainerName, viewerId, false);
216   }
217 
218   /**
219    * Gets identity from the remote id (user name)
220    * 
221    * @param userName
222    * @param loadProfile
223    * @return identity
224    * @since 1.2.0 GA
225    * @deprecated Use {@link #getUserIdentity(String, String, boolean)} instead.
226    *             Will be removed by 1.3.x
227    */
228   @Deprecated
229   public static Identity getUserIdentity(String userName, boolean loadProfile) {
230     return getIdentityManager().getOrCreateIdentity(OrganizationIdentityProvider.NAME, userName, loadProfile);
231   }
232 
233   /**
234    * Gets identity from the remote id (user name)
235    *
236    * @param portalContainerName
237    * @param userName
238    * @param loadProfile
239    * @return identity
240    * @since 1.2.3
241    */
242   public static Identity getUserIdentity(String portalContainerName, String userName, boolean loadProfile) {
243     return getIdentityManager(portalContainerName).
244            getOrCreateIdentity(OrganizationIdentityProvider.NAME, userName, loadProfile);
245   }
246   
247   /**
248    * Gets identityManager with default portal container.
249    *
250    * @return identityManager
251    * @since 1.2.0 GA
252    * @deprecated Use {@link #getIdentityManager(String)} instead.
253    *             Will be removed by 1.3.x
254    */
255   @Deprecated
256   public static final IdentityManager getIdentityManager() {
257     return (IdentityManager) getDefaultPortalContainer().getComponentInstanceOfType(IdentityManager.class);
258   }
259 
260   /**
261    * Gets {@link IdentityManager} with specified portal container name.
262    *
263    * @param portalContainerName the specified portal container name
264    * @return the identity manager
265    * @since  1.2.0-GA
266    */
267   public static final IdentityManager getIdentityManager(String portalContainerName) {
268     return (IdentityManager) getPortalContainerByName(portalContainerName).
269                              getComponentInstanceOfType(IdentityManager.class);
270   }
271 
272 
273   /**
274    * Gets {@link SpaceService} with default portal container.
275    *
276    * @return the space service
277    * @since  1.2.0-GA
278    * @deprecated Use {@link #getSpaceService(String)} instead.
279    *             Will be removed by 1.3.x
280    */
281   @Deprecated
282   public static final SpaceService getSpaceService() {
283     return (SpaceService) getDefaultPortalContainer().getComponentInstanceOfType(SpaceService.class);
284   }
285 
286   /**
287    * Gets {@link SpaceService} with specified portal container name.
288    *
289    * @param portalContainerName the specified portal container name
290    * @return the space service
291    * @since  1.2.0-GA
292    */
293   public static final SpaceService getSpaceService(String portalContainerName) {
294     return (SpaceService) getPortalContainerByName(portalContainerName).getComponentInstanceOfType(SpaceService.class);
295   }
296 
297 
298   /**
299    * Gets {@link ActivityManager} with default portal container.
300    *
301    * @return the activity manager
302    * @since  1.2.0-GA
303    * @deprecated Use {@link #getActivityManager(String)} instead.
304    *             Will be removed by 1.3.x
305    */
306   @Deprecated
307   public static final ActivityManager getActivityManager() {
308     return (ActivityManager) getDefaultPortalContainer().getComponentInstanceOfType(ActivityManager.class);
309   }
310 
311   /**
312    * Gets {@link ActivityManager} with specified portal container name.
313    *
314    * @param portalContainerName the specified portal container
315    * @return the activity manager
316    * @since  1.2.0-GA
317    */
318   public static final ActivityManager getActivityManager(String portalContainerName) {
319     return (ActivityManager) getPortalContainerByName(portalContainerName).
320                              getComponentInstanceOfType(ActivityManager.class);
321   }
322 
323   /**
324    * Gets {@link RelationshipManager} with default portal container.
325    *
326    * @return the relationship manager
327    * @since  1.2.0-GA
328    * @deprecated Use {@link #getRelationshipManager(String)} instead.
329    *             Will be removed by 1.3.x
330    */
331   @Deprecated
332   public static final RelationshipManager getRelationshipManager() {
333     return (RelationshipManager) getDefaultPortalContainer().getComponentInstanceOfType(RelationshipManager.class);
334   }
335 
336 
337   /**
338    * Gets {@link RelationshipManager} with specified portal container name.
339    *
340    * @param portalContainerName the specified portal container name
341    * @return the relationship manager
342    * @since  1.2.0-GA
343    */
344   public static final RelationshipManager getRelationshipManager(String portalContainerName) {
345     return (RelationshipManager) getPortalContainerByName(portalContainerName).
346                                  getComponentInstanceOfType(RelationshipManager.class);
347   }
348 
349   /**
350    * Gets a portal container by its name.
351    *
352    * @param portalContainerName the specified portal container name
353    * @return the portal container name
354    * @since  1.2.3
355    */
356   public static final PortalContainer getPortalContainerByName(String portalContainerName) {
357     return (PortalContainer) ExoContainerContext.getContainerByName(portalContainerName);
358   }
359 
360 
361   /**
362    * Converts a timestamp string to time string by the pattern: EEE MMM d HH:mm:ss Z yyyy.
363    *
364    * @param timestamp the timestamp to convert
365    * @return the time string
366    */
367   public static final String convertTimestampToTimeString(long timestamp) {
368    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss Z yyyy");
369    dateFormat.setTimeZone(TimeZone.getDefault());
370    return dateFormat.format(new Date(timestamp));
371   }
372 
373   /**
374    * Gets a owner identity Id from a provided activity.
375    *
376    * @param activity the activity to gets its owner identity
377    * @return the owner identity
378    * @since  1.2.3
379    * @deprecated Use {@link #getOwnerIdentityIdFromActivity(String, ExoSocialActivity)} instead.
380    *             Will be removed by 1.3.x
381    */
382   @Deprecated
383   public static Identity getOwnerIdentityIdFromActivity(ExoSocialActivity activity) {
384     IdentityManager identityManager = getIdentityManager();
385     ActivityStream activityStream=  activity.getActivityStream();
386     ActivityStream.Type activityType =  activityStream.getType();
387     String name = activity.getStreamOwner();
388     if(activityType.equals(ActivityStream.Type.USER)){
389       return identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, name, false);
390     } else {
391       return identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, name, false);
392     }
393   }
394 
395   /**
396    * Gets a owner identity Id from a provided activity.
397    *
398    * @param portalContainerName the portal container name
399    * @param activity the activity to gets its owner identity
400    * @return the owner identity
401    * @since  1.2.0-GA
402    */
403   public static Identity getOwnerIdentityIdFromActivity(String portalContainerName, ExoSocialActivity activity) {
404     IdentityManager identityManager = getIdentityManager(portalContainerName);
405     ActivityStream activityStream=  activity.getActivityStream();
406     ActivityStream.Type activityType =  activityStream.getType();
407     String name = activity.getStreamOwner();
408     if(activityType.equals(ActivityStream.Type.USER)){
409       return identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, name, false);
410     } else {
411       return identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, name, false);
412     }
413   }
414 
415 
416   /**
417    * Gets base url (host + post) from a context uriInfo.
418    * <br>
419    * For example: http://localhost:8080
420    *
421    * @return the base url (host + port)
422    * @author <a href="http://hoatle">hoatle (hoatlevan at gmail dot com)</a>
423    * @since  1.2.3
424    *
425    */
426   public static final String getBaseUrl() {
427     HttpServletRequest currentServletRequest = getCurrentServletRequest();
428     //always returns the port, even the request has no explicit port => avatarUrl always return with 80 port.
429     //need to improve this: if no port is specified => the return link should have no port specified as
430     // 80 is the default port.
431     return currentServletRequest.getScheme() + "://" + currentServletRequest.getServerName() +
432                                                  ":" + currentServletRequest.getServerPort();
433   }
434 
435 
436   /**
437    * Gets current http servlet request provided by Rest Service Framework.
438    *
439    * @return the current http servlet request
440    */
441   public static HttpServletRequest getCurrentServletRequest() {
442     EnvironmentContext environmentContext = EnvironmentContext.getCurrent();
443     return (HttpServletRequest) environmentContext.get(HttpServletRequest.class);
444   }
445 
446   /**
447    * Checks if an expected format is supported not not.
448    *
449    * @param expectedFormat  the expected format
450    * @param supportedFormats the array of supported format
451    * @return true or false
452    */
453   private static boolean isSupportedFormat(String expectedFormat, String[] supportedFormats) {
454     for (String supportedFormat : supportedFormats) {
455       if (supportedFormat.equals(expectedFormat)) {
456         return true;
457       }
458     }
459     return false;
460   }
461 
462   /**
463    * Gets default portal container name.
464    *
465    * @return the portal container
466    */
467   private static PortalContainer getDefaultPortalContainer() {
468     return PortalContainer.getInstance();
469   }
470   
471   /**
472    * Build absolute AvatarURL from in IndentityRestOut if avatar == null or "" use default avatar base on Identity's type
473    * @param resultIdentity
474    */
475   
476   public static void buildAbsoluteAvatarURL(IdentityRestOut resultIdentity){
477     if(resultIdentity.getProfile() != null && 
478         resultIdentity.getProviderId() != null){
479       ProfileRestOut resultProfile =  resultIdentity.getProfile();
480       if(resultProfile.getAvatarUrl() == null || resultProfile.getAvatarUrl().trim().equals("") ){
481         if(resultIdentity.getProviderId().
482             equals(SpaceIdentityProvider.NAME)){
483           resultProfile.setAvatarUrl(getBaseUrl() + LinkProvider.SPACE_DEFAULT_AVATAR_URL);
484         } else {
485           resultProfile.setAvatarUrl(getBaseUrl() + LinkProvider.PROFILE_DEFAULT_AVATAR_URL);
486         }
487       } else {
488         if(!resultProfile.getAvatarUrl().startsWith("http://") && !resultProfile.getAvatarUrl().startsWith("https://")){
489           resultProfile.setAvatarUrl(getBaseUrl() + resultProfile.getAvatarUrl());
490         }
491       }
492     }
493   }
494   
495   /**
496    * Build absolute AvatarURL from in IndentityRestOut if avatar == null or "" use default avatar base on Identity's type
497    * @param resultIdentity
498    */
499   
500   public static String buildAbsoluteAvatarURL(Identity resultIdentity){
501     if(resultIdentity.getProfile() != null && 
502         resultIdentity.getProviderId() != null){
503       Profile resultProfile =  resultIdentity.getProfile();
504       if(resultProfile.getAvatarUrl() == null || resultProfile.getAvatarUrl().trim().equals("") ){
505         if(resultIdentity.getProviderId().
506             equals(SpaceIdentityProvider.NAME)){
507           return getBaseUrl() + LinkProvider.SPACE_DEFAULT_AVATAR_URL;
508         } else {
509           return getBaseUrl() + LinkProvider.PROFILE_DEFAULT_AVATAR_URL;
510         }
511       } else {
512           return getBaseUrl() + resultProfile.getAvatarUrl();
513       }
514     } else {
515       return null;
516     }
517     
518   }
519   
520   /**
521    * Gets UserIdentity of authenticated user.
522    * @param portalContainerName current portal container name
523    * @return Identity of user, if not authenticated return null
524    */
525   public static Identity getAuthenticatedUserIdentity(String portalContainerName) {
526     if(ConversationState.getCurrent()!=null && ConversationState.getCurrent().getIdentity() != null &&
527               ConversationState.getCurrent().getIdentity().getUserId() != null){
528       IdentityManager identityManager =  Util.getIdentityManager(portalContainerName);
529       String authenticatedUserRemoteID = ConversationState.getCurrent().getIdentity().getUserId(); 
530       return identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, authenticatedUserRemoteID, false);
531     } else {
532       return null;
533     }
534   }
535   
536   /**
537    * Check if identityId contained in liked Identity, if yes return true else return false.
538    * @param identityID
539    * @param activity
540    * @return
541    */
542   public static boolean isLikedByIdentity(String identityID, ExoSocialActivity activity){
543     String[] likedIdentityIds = activity.getLikeIdentityIds();
544     if(activity.getLikeIdentityIds()!=null && likedIdentityIds.length > 0 ){
545       for (int i = 0; i < likedIdentityIds.length; i++) {
546         if (identityID.equals(likedIdentityIds[i])){
547           return true;
548         }
549       }
550     }
551     return false;
552   }
553   
554   /**
555    * Try to guess the mime type of url using the Content-Type from header, the extension of filename or some bytes of content.
556    * This method can be wrong if server don't provide the Content-Type, wrong or unknown file extension. So use it as your risk.
557    * @param urlString
558    * @return
559    * @since 1.2.7
560    */
561   public static String getMimeTypeOfURL(String urlString){
562     URLConnection urlConnection = null;
563     try {
564       String mimeType = null;
565       URL url = new URL(urlString); 
566       urlConnection = url.openConnection();
567       mimeType = urlConnection.getContentType();
568       if(mimeType != null){
569         return mimeType;
570       }
571       mimeType = URLConnection.guessContentTypeFromName(urlString);
572       if(mimeType != null){
573         return mimeType;
574       }
575       mimeType = URLConnection.guessContentTypeFromStream(urlConnection.getInputStream());
576       if(mimeType != null){
577         return mimeType;
578       }
579       return "";
580     } catch (MalformedURLException e) {
581       return "";
582     } catch (IOException e) {
583       return "";
584     } finally {
585       urlConnection = null;
586     }
587   }
588   
589   /**
590    * Decode query parameters of string URL
591    * Example:
592    * - Input: {@code http://google.com?%3Cscript%3E}
593    * - Output: {@code http://google.com?<script>}
594    *
595    * @param url The string URL to decode
596    * @return The URL decoded query parameters
597    * @since 4.1.0
598    */
599   public static String getDecodeQueryURL(String url) {
600     if (isValidURL(url)) {
601       String query;
602       try {
603         query = new URL(url).getQuery();
604         if (query != null) {
605           String newQuery = URLDecoder.decode(query, "UTF-8");
606           return url.replace(query, newQuery);
607         }
608       } catch (Exception e) {
609         return url;
610       }
611     }
612     return url;
613   }
614   
615   /**
616    * Checks if user is mentioned or not.
617    * 
618    * @param existingActivity Activity to check.
619    * @param identityId Identity Id to check mentioned or not.
620    * 
621    * @return true if input user has been mentioned in activity.
622    */
623   public static boolean hasMentioned(ExoSocialActivity existingActivity, String identityId) {
624     for (String mentioner : existingActivity.getMentionedIds()) {
625       if (mentioner.startsWith(identityId)) { // identityId@mentioned_times
626         return true;
627       }
628     }
629     return false;
630   }
631   
632   /** 
633    * Get base url of rest service
634    * 
635    * @param type the type of rest service
636    * @param id the id of object
637    * 
638    * @return base rest url like : http://localhost:8080/rest/v1/social/users/123456
639    */
640   public static String getRestUrl(String type, String id, String restPath) {
641     String version = restPath.split("/")[1]; // path /v1/social/identities
642     String socialResource = restPath.split("/")[2]; // path /v1/social/identities
643     
644     return new StringBuffer(getBaseRestUrl())
645     .append("/").append(version)
646     .append("/").append(socialResource)
647     .append("/").append(type)
648     .append("/").append(id).toString();
649   }
650   
651   /** 
652    * Get base url of rest service
653    * 
654    * @return base rest url like : http://localhost:8080/rest
655    */
656   public static String getBaseRestUrl() {
657     return new StringBuffer(CommonsUtils.getCurrentDomain()).append("/").append(CommonsUtils.getRestContextName()).toString();
658   }
659   
660   /**
661    * Get the rest url to load all members or managers of a space
662    * 
663    * @param id the id of space
664    * @param returnManager return managers or members
665    * @return rest url to load all members or managers of a space
666    */
667   public static String getMembersSpaceRestUrl(String id, boolean returnManager, String restPath) {
668     StringBuffer spaceMembersRestUrl = new StringBuffer(getRestUrl(RestUtils.SPACES_TYPE, id, restPath)).append("/").append(RestUtils.USERS_TYPE);
669     if (returnManager) {
670       return spaceMembersRestUrl.append("?role=manager").toString();
671     }
672     return spaceMembersRestUrl.toString();
673   }
674   
675   /**
676    * Get the rest url in order to load all comments of an activity
677    * 
678    * @param activityId activity's id
679    * @return
680    */
681   public static String getCommentsActivityRestUrl(String activityId, String restPath) {
682     return new StringBuffer(getRestUrl(RestUtils.ACTIVITIES_TYPE, activityId, restPath)).append("/").append("comments").toString();
683   }
684   
685   /**
686    * Check if the current user is authenticated
687    * 
688    * @return true if user not authenticated
689    */
690   public static boolean isAnonymous() {
691     return IdentityConstants.ANONIM.equals(ConversationState.getCurrent().getIdentity().getUserId());
692   }
693 }