1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.social.opensocial.service;
18
19 import java.net.URLEncoder;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.ResourceBundle;
29 import java.util.Set;
30 import java.util.concurrent.CompletableFuture;
31 import java.util.concurrent.Future;
32
33 import javax.servlet.http.HttpServletResponse;
34
35 import org.apache.shindig.auth.AnonymousSecurityToken;
36 import org.apache.shindig.auth.SecurityToken;
37 import org.apache.shindig.protocol.DataCollection;
38 import org.apache.shindig.protocol.ProtocolException;
39 import org.apache.shindig.protocol.RestfulCollection;
40 import org.apache.shindig.protocol.model.SortOrder;
41 import org.apache.shindig.social.core.model.ListFieldImpl;
42 import org.apache.shindig.social.core.model.NameImpl;
43 import org.apache.shindig.social.core.model.UrlImpl;
44 import org.apache.shindig.social.opensocial.model.ListField;
45 import org.apache.shindig.social.opensocial.model.Person;
46 import org.apache.shindig.social.opensocial.model.Url;
47 import org.apache.shindig.social.opensocial.spi.AppDataService;
48 import org.apache.shindig.social.opensocial.spi.CollectionOptions;
49 import org.apache.shindig.social.opensocial.spi.GroupId;
50 import org.apache.shindig.social.opensocial.spi.PersonService;
51 import org.apache.shindig.social.opensocial.spi.UserId;
52 import org.exoplatform.commons.utils.ListAccess;
53 import org.exoplatform.container.PortalContainer;
54 import org.exoplatform.container.component.RequestLifeCycle;
55 import org.exoplatform.portal.config.UserPortalConfig;
56 import org.exoplatform.portal.config.UserPortalConfigService;
57 import org.exoplatform.portal.mop.SiteKey;
58 import org.exoplatform.portal.mop.navigation.Scope;
59 import org.exoplatform.portal.mop.user.UserNavigation;
60 import org.exoplatform.portal.mop.user.UserNode;
61 import org.exoplatform.portal.mop.user.UserPortal;
62 import org.exoplatform.portal.mop.user.UserPortalContext;
63 import org.exoplatform.services.log.ExoLogger;
64 import org.exoplatform.services.log.Log;
65 import org.exoplatform.social.core.identity.model.Identity;
66 import org.exoplatform.social.core.identity.model.Profile;
67 import org.exoplatform.social.core.service.LinkProvider;
68 import org.exoplatform.social.core.space.SpaceException;
69 import org.exoplatform.social.core.space.model.Space;
70 import org.exoplatform.social.core.space.spi.SpaceService;
71 import org.exoplatform.social.opensocial.auth.ExoBlobCrypterSecurityToken;
72 import org.exoplatform.social.opensocial.model.ExoPersonImpl;
73 import org.exoplatform.social.opensocial.model.SpaceImpl;
74
75 import com.google.common.collect.Lists;
76 import com.google.inject.Inject;
77 import com.google.inject.Injector;
78
79
80
81
82 public class ExoPeopleService extends ExoService implements PersonService, AppDataService {
83
84
85
86
87 private Injector injector;
88
89
90
91
92 private static final Log LOG = ExoLogger.getLogger(ExoPeopleService.class);
93
94
95
96
97
98
99 @Inject
100 public ExoPeopleService(Injector injector) {
101 this.injector = injector;
102 }
103
104
105
106
107 private static final Comparator<Person> NAME_COMPARATOR = new Comparator<Person>() {
108 public int compare(Person person, Person person1) {
109 String name = person.getName().getFormatted();
110 String name1 = person1.getName().getFormatted();
111 return name.compareTo(name1);
112 }
113 };
114
115
116
117
118
119 public Future<RestfulCollection<Person>> getPeople(Set<UserId> userIds, GroupId groupId,
120 CollectionOptions collectionOptions, Set<String> fields,
121 SecurityToken token) throws ProtocolException {
122 List<Person> result = Lists.newArrayList();
123 try {
124 Set<Identity> idSet = getIdSet(userIds, groupId, token);
125
126 Iterator<Identity> it = idSet.iterator();
127
128 while (it.hasNext()) {
129 Identity id = it.next();
130 if (id != null) {
131 result.add(convertToPerson(id, fields, token));
132 }
133 }
134
135
136 if (collectionOptions.getSortBy().equals(Person.Field.NAME.toString())) {
137 Collections.sort(result, NAME_COMPARATOR);
138 }
139
140 if (collectionOptions.getSortOrder().equals(SortOrder.descending)) {
141 Collections.reverse(result);
142 }
143
144
145
146
147 int totalSize = result.size();
148 int fromIndex = collectionOptions.getFirst();
149 int toIndex = fromIndex + collectionOptions.getMax();
150 fromIndex = fromIndex < 0 ? 0 : fromIndex;
151 toIndex = totalSize < toIndex ? totalSize : toIndex;
152 toIndex = toIndex < fromIndex ? fromIndex : toIndex;
153 result = result.subList(fromIndex, toIndex);
154
155 return CompletableFuture.completedFuture(new RestfulCollection<Person>(
156 result, collectionOptions.getFirst(), totalSize));
157 } catch (Exception je) {
158 throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, je.getMessage(), je);
159 }
160 }
161
162
163
164
165 public Future<Person> getPerson(UserId id, Set<String> fields, SecurityToken token) throws ProtocolException {
166 try {
167
168 if (token instanceof AnonymousSecurityToken) {
169 throw new Exception(Integer.toString(HttpServletResponse.SC_FORBIDDEN));
170 }
171
172 Identity identity = getIdentity(id.getUserId(token), true, token);
173
174 return CompletableFuture.completedFuture(convertToPerson(identity, fields, token));
175 } catch (Exception e) {
176 throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e);
177 }
178 }
179
180 @Override
181 public Future<Person> updatePerson(UserId userId, Person person, SecurityToken securityToken) throws ProtocolException {
182 throw new UnsupportedOperationException();
183 }
184
185
186
187
188
189
190
191
192
193 private Person convertToPerson(Identity identity, Set<String> fields, SecurityToken st) throws Exception {
194 Person p = new ExoPersonImpl();
195 Profile pro = identity.getProfile();
196 PortalContainer container = getPortalContainer(st);
197 String host = getHost(st);
198 for (String field : fields) {
199 if (Person.Field.DISPLAY_NAME.toString().equals(field)) {
200 p.setDisplayName(pro.getFullName());
201 } else if (Person.Field.EMAILS.toString().equals(field)) {
202 p.setEmails(convertToListFields((List<Map>) pro.getProperty("emails")));
203 } else if (Person.Field.URLS.toString().equals(field)) {
204 p.setUrls(convertToURLListFields((List<Map>) pro.getProperty("urls")));
205 } else if (Person.Field.IMS.toString().equals(field)) {
206 p.setIms(convertToListFields((List<Map>) pro.getProperty("ims")));
207 } else if (Person.Field.ID.toString().equals(field)) {
208 p.setId(identity.getId());
209 } else if (Person.Field.NAME.toString().equals(field)) {
210 NameImpl name = new NameImpl();
211 name.setFamilyName((String) pro.getProperty(Profile.LAST_NAME));
212 name.setGivenName((String) pro.getProperty(Profile.FIRST_NAME));
213 name.setFormatted(name.getGivenName() + " " + name.getFamilyName());
214 p.setName(name);
215 } else if (Person.Field.PROFILE_URL.toString().equals(field)) {
216 String portalOwner = getPortalOwner(st);
217 String portalName = getPortalContainer(st).getName();
218 p.setProfileUrl(LinkProvider.getAbsoluteProfileUrl(identity.getRemoteId(), portalName, portalOwner, host));
219 } else if (Person.Field.GENDER.toString().equals(field)) {
220 String gender = (String) pro.getProperty("gender");
221 if (gender != null && gender.equals("female")) {
222 p.setGender(Person.Gender.female);
223 } else {
224 p.setGender(Person.Gender.male);
225 }
226 } else if (ExoPersonImpl.Field.SPACES.toString().equals(field)) {
227 List<org.exoplatform.social.opensocial.model.Space> spaces =
228 new ArrayList<org.exoplatform.social.opensocial.model.Space>();
229
230 SpaceService spaceService = (SpaceService) (container.getComponentInstanceOfType(SpaceService.class));
231 try {
232 ListAccess<Space> memberSpaceListAccess = spaceService.getMemberSpaces(identity.getRemoteId());
233
234 Space[] spaceArray = memberSpaceListAccess.load(0, 100);
235 SpaceImpl space = new SpaceImpl();
236 for(Space spaceObj : spaceArray) {
237 space.setId(spaceObj.getId());
238 space.setDisplayName(spaceObj.getDisplayName());
239 spaces.add(space);
240 }
241 ((ExoPersonImpl) p).setSpaces(spaces);
242 } catch (SpaceException e) {
243 LOG.warn("Failed to convert spaces!");
244 }
245 } else if (Person.Field.THUMBNAIL_URL.toString().equals(field)) {
246 String avatarUrl = pro.getAvatarUrl();
247 if (avatarUrl != null) {
248 p.setThumbnailUrl(host + avatarUrl);
249 } else {
250 p.setThumbnailUrl(host + LinkProvider.PROFILE_DEFAULT_AVATAR_URL);
251 }
252 } else if (ExoPersonImpl.Field.PORTAL_CONTAINER.toString().equals(field)) {
253 ((ExoPersonImpl) p).setPortalName(container.getName());
254 } else if (ExoPersonImpl.Field.REST_CONTEXT.toString().equals(field)) {
255 ((ExoPersonImpl) p).setRestContextName(container.getRestContextName());
256 } else if (ExoPersonImpl.Field.HOST.toString().equals(field)) {
257 ((ExoPersonImpl) p).setHostName(getHost(st));
258 } else if (ExoPersonImpl.Field.PEOPLE_URI.toString().equals(field)) {
259 ((ExoPersonImpl) p).setPeopleUri(getURIForPeople(container, identity.getRemoteId()));
260 }
261 }
262 return p;
263 }
264
265
266
267
268
269
270
271 private List<ListField> convertToListFields(List<Map> fields) {
272 List<ListField> l = new ArrayList<ListField>();
273 if (fields == null) {
274 return null;
275 }
276 for (Map field : fields) {
277 l.add(new ListFieldImpl((String) field.get("key"), (String) field.get("value")));
278 }
279 return l;
280 }
281
282
283
284
285
286
287
288 private List<Url> convertToURLListFields(List<Map> fields) {
289 List<Url> l = new ArrayList<Url>();
290 if (fields == null) {
291 return null;
292 }
293 for (Map field : fields) {
294 l.add(new UrlImpl((String) field.get("value"), (String) field.get("key"), (String) field.get("key")));
295 }
296 return l;
297 }
298
299
300
301
302 public Future<DataCollection> getPersonData(Set<UserId> userIds, GroupId groupId, String appId,
303 Set<String> fields, SecurityToken token) throws ProtocolException {
304 try {
305 Set<Identity> idSet = getIdSet(userIds, groupId, token);
306 Map<String, Map<String, Object>> idToData = new HashMap<>();
307 Iterator<Identity> it = idSet.iterator();
308
309 String gadgetId = clean(appId);
310 String instanceId = "" + token.getModuleId();
311 while (it.hasNext()) {
312 Identity id = it.next();
313 idToData.put(id.getId(), getPreferences(id.getRemoteId(), gadgetId, instanceId, fields));
314 }
315 return CompletableFuture.completedFuture(new DataCollection(idToData));
316 } catch (Exception e) {
317 throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e);
318 }
319 }
320
321
322
323
324
325
326
327 private String clean(String url) {
328 url = URLEncoder.encode(url);
329 url = url.replaceAll(":", "");
330 return url;
331 }
332
333
334
335
336
337
338
339
340
341
342
343 private Map<String, Object> getPreferences(String userID, String gadgetId, String instanceID,
344 Set<String> fields) throws Exception {
345
346
347
348
349 Map<String, Object> values = null;
350 return values;
351 }
352
353
354
355
356
357
358
359
360
361
362 private void savePreferences(String userID, String gadgetId, String instanceID,
363 Map<String, Object> values) throws Exception {
364
365
366
367
368 }
369
370
371
372
373
374
375
376
377
378
379 private void deletePreferences(String userID, String gadgetId, String instanceID, Set<String> keys) throws Exception {
380
381
382
383
384 }
385
386
387
388
389 public Future<Void> deletePersonData(UserId user, GroupId groupId, String appId,
390 Set<String> fields, SecurityToken token) throws ProtocolException {
391 try {
392 if (token instanceof AnonymousSecurityToken) {
393 throw new Exception(Integer.toString(HttpServletResponse.SC_FORBIDDEN));
394 }
395 String userId = user.getUserId(token);
396
397 String portalName = PortalContainer.getCurrentPortalContainerName();
398 if (token instanceof ExoBlobCrypterSecurityToken) {
399 portalName = ((ExoBlobCrypterSecurityToken) token).getPortalContainer();
400 }
401
402 Identity id = getIdentity(userId, true, token);
403 String gadgetId = clean(appId);
404 String instanceId = "" + token.getModuleId();
405
406 deletePreferences(id.getRemoteId(), gadgetId, instanceId, fields);
407 } catch (Exception e) {
408 throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e);
409 }
410 return CompletableFuture.completedFuture(null);
411 }
412
413
414
415
416 public Future<Void> updatePersonData(UserId user, GroupId groupId, String appId, Set<String> fields,
417 Map<String, Object> values, SecurityToken token) throws ProtocolException {
418
419 try {
420 if (token instanceof AnonymousSecurityToken) {
421 throw new Exception(Integer.toString(HttpServletResponse.SC_FORBIDDEN));
422 }
423 String userId = user.getUserId(token);
424
425 Identity id = getIdentity(userId, true, token);
426 String gadgetId = clean(appId);
427 String instanceId = "" + token.getModuleId();
428
429 savePreferences(id.getRemoteId(), gadgetId, instanceId, values);
430 } catch (Exception e) {
431 throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e);
432 }
433 return CompletableFuture.completedFuture(null);
434 }
435
436
437
438
439
440
441
442
443
444 private String getURIForPeople(PortalContainer portalContainer, String remoteId) throws Exception {
445 UserPortalConfigService userPortalConfigSer = (UserPortalConfigService)
446 portalContainer.getComponentInstanceOfType(UserPortalConfigService.class);
447
448 UserPortalContext NULL_CONTEXT = new UserPortalContext() {
449 public ResourceBundle getBundle(UserNavigation navigation) {
450 return null;
451 }
452
453 public Locale getUserLocale() {
454 return Locale.ENGLISH;
455 }
456 };
457 StringBuffer stringBuffer = new StringBuffer();
458 RequestLifeCycle.begin(portalContainer);
459 try {
460 UserPortalConfig userPortalCfg = userPortalConfigSer.
461 getUserPortalConfig(userPortalConfigSer.getDefaultPortal(), remoteId, NULL_CONTEXT);
462 UserPortal userPortal = userPortalCfg.getUserPortal();
463
464 SiteKey siteKey = SiteKey.portal(userPortalConfigSer.getDefaultPortal());
465 UserNavigation userNav = userPortal.getNavigation(siteKey);
466 UserNode rootNode = userPortal.getNode(userNav, Scope.ALL, null, null);
467 UserNode peopleNode = rootNode.getChild("people");
468 UserNode iteratorNode = peopleNode;
469
470 if(iteratorNode != null){
471 while(iteratorNode !=null && iteratorNode.getParent()!=null){
472 stringBuffer.insert(0, iteratorNode.getName());
473 stringBuffer.insert(0, "/");
474 iteratorNode = iteratorNode.getParent();
475 }
476 stringBuffer.insert(0, userPortalConfigSer.getDefaultPortal());
477 stringBuffer.insert(0, "/");
478 stringBuffer.insert(0, portalContainer.getName());
479 stringBuffer.insert(0, "/");
480 }
481 } catch (Exception e){
482 LOG.debug("Could not get the people page node.");
483 }
484 finally{
485 RequestLifeCycle.end();
486 }
487 return stringBuffer.toString();
488 }
489 }