1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.exoplatform.shareextension.service;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30
31 import org.exoplatform.R;
32 import org.exoplatform.model.SocialPostInfo;
33 import org.exoplatform.shareextension.service.Action.ActionListener;
34 import org.exoplatform.shareextension.service.PostAction.PostActionListener;
35 import org.exoplatform.singleton.DocumentHelper;
36 import org.exoplatform.singleton.SocialServiceHelper;
37 import org.exoplatform.social.client.api.SocialClientLibException;
38 import org.exoplatform.social.client.api.model.RestActivity;
39 import org.exoplatform.social.client.api.model.RestComment;
40 import org.exoplatform.social.client.api.service.ActivityService;
41 import org.exoplatform.utils.ExoConnectionUtils;
42 import org.exoplatform.utils.ExoConstants;
43 import org.exoplatform.utils.ExoDocumentUtils;
44 import org.exoplatform.utils.ExoDocumentUtils.DocumentInfo;
45 import org.exoplatform.utils.Log;
46 import org.exoplatform.utils.TitleExtractor;
47
48 import android.app.IntentService;
49 import android.app.NotificationManager;
50 import android.content.Context;
51 import android.content.Intent;
52 import android.net.Uri;
53 import android.support.v4.app.NotificationCompat;
54
55
56
57
58
59
60
61
62
63
64 public class ShareService extends IntentService {
65
66 public static final String LOG_TAG = "____eXo____ShareService____";
67
68 public static final String POST_INFO = "postInfo";
69
70 private int notifId = 1;
71
72 private SocialPostInfo postInfo;
73
74
75 private List<UploadInfo> uploadedMap = new ArrayList<UploadInfo>();
76
77 private enum ShareResult {
78 SUCCESS, ERROR_INCORRECT_CONTENT_URI, ERROR_INCORRECT_ACCOUNT, ERROR_CREATE_FOLDER, ERROR_UPLOAD_FAILED, ERROR_POST_FAILED, ERROR_COMMENT_FAILED
79 }
80
81 public ShareService() {
82 super("eXo_Share_Service");
83 }
84
85
86
87
88 @Override
89 protected void onHandleIntent(Intent intent) {
90
91 postInfo = (SocialPostInfo) intent.getParcelableExtra(POST_INFO);
92
93
94 notifyBegin();
95
96 if (postInfo.ownerAccount == null) {
97 notifyResult(ShareResult.ERROR_INCORRECT_ACCOUNT);
98 return;
99 }
100
101 if (postInfo.hasAttachment()) {
102
103 UploadInfo initUploadInfo = initUpload();
104 boolean uploadStarted = startUpload(initUploadInfo);
105 if (uploadStarted) {
106 boolean uploadedAll = doUpload(initUploadInfo);
107 if (uploadedAll) {
108
109 doPost();
110 }
111 }
112 ;
113 } else {
114
115
116 String link = null;
117 link = extractLinkFromText();
118 if (link != null) {
119 postInfo.activityType = SocialPostInfo.TYPE_LINK;
120 postInfo.postMessage = postInfo.postMessage.replace(link, String.format(Locale.US, "<a href=\"%s\">%s</a>", link, link));
121 }
122 postInfo.templateParams = linkParams(link);
123 doPost();
124 }
125
126 }
127
128
129
130
131
132 private UploadInfo initUpload() {
133 postInfo.activityType = SocialPostInfo.TYPE_DOC;
134 UploadInfo uploadInfo = new UploadInfo();
135 uploadInfo.init(postInfo);
136
137 return uploadInfo;
138
139 }
140
141
142
143
144
145 private boolean startUpload(UploadInfo uploadInfo) {
146 return CreateFolderAction.execute(postInfo, uploadInfo, new ActionListener() {
147
148 @Override
149 public boolean onSuccess(String message) {
150 return true;
151 }
152
153 @Override
154 public boolean onError(String error) {
155 notifyResult(ShareResult.ERROR_CREATE_FOLDER);
156 return false;
157 }
158 });
159 }
160
161
162
163
164 private boolean doUpload(UploadInfo initUploadInfo) {
165 boolean uploadedAll = false;
166 uploadedMap.clear();
167 UploadInfo uploadInfo = initUploadInfo;
168 final int numberOfFiles = postInfo.postAttachedFiles.size();
169 for (int i = 0; i < numberOfFiles; i++) {
170
171 notifyProgress(i + 1, numberOfFiles);
172
173 if (uploadInfo != null && uploadInfo.fileToUpload != null)
174 uploadInfo.fileToUpload.closeDocStream();
175
176 if (i != 0) {
177 uploadInfo = new UploadInfo(uploadInfo);
178 }
179
180 String fileUri = "file://" + postInfo.postAttachedFiles.get(i);
181 Uri uri = Uri.parse(fileUri);
182 uploadInfo.fileToUpload = ExoDocumentUtils.documentInfoFromUri(uri, getBaseContext());
183
184 if (uploadInfo.fileToUpload == null) {
185 notifyResult(ShareResult.ERROR_INCORRECT_CONTENT_URI);
186 return false;
187 } else {
188 uploadInfo.fileToUpload.documentName = ExoDocumentUtils.cleanupFilename(uploadInfo.fileToUpload.documentName);
189 }
190 uploadedAll = UploadAction.execute(postInfo, uploadInfo, new ActionListener() {
191
192 @Override
193 public boolean onSuccess(String message) {
194 return true;
195 }
196
197 @Override
198 public boolean onError(String error) {
199 notifyResult(ShareResult.ERROR_UPLOAD_FAILED);
200 return false;
201 }
202 });
203 if (uploadInfo != null && uploadInfo.fileToUpload != null)
204 uploadInfo.fileToUpload.closeDocStream();
205 if (!uploadedAll) {
206 if (Log.LOGD)
207 Log.e(LOG_TAG, String.format("Failed to upload file %d/%d : %s (doUpload)", i + 1, numberOfFiles, fileUri));
208 break;
209 }
210 if (uploadedAll) {
211 if (Log.LOGD)
212 Log.d(LOG_TAG, String.format("Uploaded file %d/%d OK %s (doUpload)", i + 1, numberOfFiles, fileUri));
213 if (i == 0)
214 postInfo.buildTemplateParams(uploadInfo);
215 else {
216 uploadedMap.add(uploadInfo);
217 }
218 }
219
220 File f = new File(postInfo.postAttachedFiles.get(i));
221 if (Log.LOGD)
222 Log.d(LOG_TAG, "File " + f.getName() + " deleted: " + (f.delete() ? "YES" : "NO"));
223 }
224 return uploadedAll;
225
226 }
227
228
229
230
231 private boolean doPost() {
232 RestActivity createdAct = PostAction.execute(postInfo, new PostActionListener());
233 boolean ret = createdAct != null;
234 if (ret) {
235 if (Log.LOGD)
236 Log.d(LOG_TAG, "Post activity done");
237 for (UploadInfo commentInfo : uploadedMap) {
238 ret = doComment(createdAct, commentInfo);
239 if (!ret)
240 break;
241 if (Log.LOGD)
242 Log.d(LOG_TAG, "Comment activity done");
243 }
244
245
246 if (ret) {
247 ExoConnectionUtils.loggingOut();
248
249 notifyResult(ShareResult.SUCCESS);
250 } else
251 notifyResult(ShareResult.ERROR_COMMENT_FAILED);
252 } else
253 notifyResult(ShareResult.ERROR_POST_FAILED);
254 return ret;
255 }
256
257
258
259
260
261
262
263
264 private boolean doComment(RestActivity restAct, UploadInfo commentInfo) {
265
266 boolean ret = false;
267 String mimeType = (commentInfo == null ? null
268 : (commentInfo.fileToUpload == null ? null
269 : commentInfo.fileToUpload.documentMimeType));
270 String urlWithoutServer = null;
271 try {
272 URL url = new URL(commentInfo.getUploadedUrl());
273 urlWithoutServer = url.getPath();
274 if (urlWithoutServer != null && !urlWithoutServer.startsWith("/"))
275 urlWithoutServer = "/" + urlWithoutServer;
276 } catch (MalformedURLException e) {
277 if (Log.LOGW)
278 Log.w(LOG_TAG, e.getMessage());
279 return false;
280 }
281 StringBuilder bld = new StringBuilder();
282
283 bld.append("<a href=\"")
284 .append(urlWithoutServer)
285 .append("\">")
286 .append(commentInfo.fileToUpload.documentName)
287 .append("</a>");
288
289 if (mimeType != null && mimeType.startsWith("image/")) {
290 String thumbnailUrl = urlWithoutServer.replace("/jcr/", "/thumbnailImage/large/");
291 bld.append("<br/><a href=\"").append(urlWithoutServer).append("\"><img src=\"").append(thumbnailUrl).append("\" /></a>");
292 }
293
294 ActivityService<RestActivity> activityService = SocialServiceHelper.getInstance().activityService;
295 RestComment restComment = new RestComment();
296 restComment.setText(bld.toString());
297 try {
298 ret = activityService.createComment(restAct, restComment) != null;
299 } catch (SocialClientLibException e) {
300 if (Log.LOGD)
301 Log.e(LOG_TAG, Log.getStackTraceString(e));
302 }
303 return ret;
304 }
305
306 private Map<String, String> linkParams(String link) {
307
308
309 if (link == null)
310 return null;
311 Map<String, String> templateParams = new HashMap<String, String>();
312 templateParams.put("comment", postInfo.postMessage);
313 templateParams.put("link", link);
314 templateParams.put("description", "");
315 templateParams.put("image", "");
316 try {
317 templateParams.put("title", TitleExtractor.getPageTitle(link));
318 } catch (IOException e) {
319 Log.e(LOG_TAG, "Cannot retrieve link title", e);
320 templateParams.put("title", link);
321 }
322 return templateParams;
323 }
324
325 private String extractLinkFromText() {
326 String text = postInfo.postMessage;
327
328
329 int posHttp = text.indexOf("http://");
330 int posHttps = text.indexOf("https://");
331 int startOfLink = -1;
332 if (posHttps > -1)
333 startOfLink = posHttps;
334 else if (posHttp > -1)
335 startOfLink = posHttp;
336 if (startOfLink > -1) {
337 int endOfLink = text.indexOf(' ', startOfLink);
338 if (endOfLink == -1)
339 return text.substring(startOfLink);
340 else
341 return text.substring(startOfLink, endOfLink);
342 } else {
343 return null;
344 }
345 }
346
347
348
349
350 private void notifyBegin() {
351 notifId = (int) System.currentTimeMillis();
352 String title = postInfo.hasAttachment() ? getString(R.string.ShareDocumentTitle) : getString(R.string.ShareMessageTitle);
353 String text = postInfo.hasAttachment() ? getString(R.string.ShareDocumentText) : getString(R.string.ShareMessageText);
354 NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
355 builder.setSmallIcon(R.drawable.icon_share_notif);
356 builder.setContentTitle(title);
357 builder.setContentText(text);
358 builder.setAutoCancel(true);
359 builder.setProgress(0, 0, true);
360 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
361 manager.notify(notifId, builder.build());
362 }
363
364
365
366
367
368
369
370
371 private void notifyProgress(int current, int total) {
372 String text = String.format(Locale.US, "%s (%d/%d)", getString(R.string.ShareDocumentText), current, total);
373 NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
374 builder.setSmallIcon(R.drawable.icon_share_notif);
375 builder.setContentTitle(getString(R.string.ShareDocumentTitle));
376 builder.setContentText(text);
377 builder.setAutoCancel(true);
378 builder.setProgress(0, 0, true);
379 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
380 manager.notify(notifId, builder.build());
381 }
382
383
384
385
386
387
388 private void notifyResult(ShareResult result) {
389 String text = "";
390 switch (result) {
391 case ERROR_CREATE_FOLDER:
392 text = getString(R.string.ShareErrorUploadFolderFailed);
393 break;
394 case ERROR_INCORRECT_ACCOUNT:
395 text = getString(R.string.ShareErrorIncorrectAccount);
396 break;
397 case ERROR_INCORRECT_CONTENT_URI:
398 text = getString(R.string.ShareErrorCannotReadDoc);
399 break;
400 case ERROR_POST_FAILED:
401 text = getString(R.string.ShareErrorPostFailed);
402 break;
403 case ERROR_COMMENT_FAILED:
404 text = getString(R.string.ShareErrorCommentFailed);
405 break;
406 case ERROR_UPLOAD_FAILED:
407 text = getString(R.string.ShareErrorUploadFailed);
408 break;
409 case SUCCESS:
410 text = getString(R.string.ShareOperationSuccess);
411 break;
412 default:
413 break;
414 }
415 String title = postInfo.hasAttachment() ? getString(R.string.ShareDocumentTitle) : getString(R.string.ShareMessageTitle);
416 NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
417 builder.setSmallIcon(R.drawable.icon_share_notif);
418 builder.setContentTitle(title);
419 builder.setContentText(text);
420 builder.setAutoCancel(true);
421 builder.setProgress(0, 0, false);
422 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
423 manager.notify(notifId, builder.build());
424 }
425
426 public static class UploadInfo {
427
428 public String uploadId;
429
430 public DocumentInfo fileToUpload;
431
432 public String repository;
433
434 public String workspace;
435
436 public String drive;
437
438 public String folder;
439
440 public String jcrUrl;
441
442 public UploadInfo() {
443 super();
444 }
445
446 public UploadInfo(UploadInfo another) {
447 uploadId = Long.toHexString(System.currentTimeMillis());
448 this.repository = another.repository;
449 this.workspace = another.workspace;
450 this.drive = another.drive;
451 this.folder = another.folder;
452 this.jcrUrl = another.jcrUrl;
453 }
454
455 public void init(SocialPostInfo postInfo) {
456
457 uploadId = Long.toHexString(System.currentTimeMillis());
458 repository = DocumentHelper.getInstance().repository;
459 workspace = DocumentHelper.getInstance().workspace;
460
461 if (postInfo.isPublic()) {
462
463
464 drive = ExoConstants.DOCUMENT_PERSONAL_DRIVE_NAME;
465 folder = "Public/Mobile";
466 jcrUrl = DocumentHelper.getInstance().getRepositoryHomeUrl();
467 } else {
468
469
470 drive = ".spaces." + postInfo.destinationSpace.getOriginalName();
471 folder = "Mobile";
472 StringBuffer url = new StringBuffer(postInfo.ownerAccount.serverUrl).append(ExoConstants.DOCUMENT_JCR_PATH)
473 .append("/")
474 .append(repository)
475 .append("/")
476 .append(workspace)
477 .append("/Groups/spaces/")
478 .append(postInfo.destinationSpace.getOriginalName())
479 .append("/Documents");
480 jcrUrl = url.toString();
481 }
482 }
483
484 public String getUploadedUrl() {
485 return new StringBuffer(jcrUrl).append("/").append(folder).append("/").append(fileToUpload.documentName).toString();
486 }
487 }
488 }