1
14
15 package com.liferay.documentlibrary.util;
16
17 import com.liferay.documentlibrary.NoSuchFileException;
18 import com.liferay.documentlibrary.model.FileModel;
19 import com.liferay.portal.kernel.exception.PortalException;
20 import com.liferay.portal.kernel.exception.SystemException;
21 import com.liferay.portal.kernel.log.Log;
22 import com.liferay.portal.kernel.log.LogFactoryUtil;
23 import com.liferay.portal.kernel.search.Document;
24 import com.liferay.portal.kernel.search.Field;
25 import com.liferay.portal.kernel.search.Indexer;
26 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
27 import com.liferay.portal.kernel.search.SearchEngineUtil;
28 import com.liferay.portal.kernel.search.SearchException;
29 import com.liferay.portal.kernel.util.FileUtil;
30 import com.liferay.portal.kernel.util.GetterUtil;
31 import com.liferay.portal.kernel.util.PropsKeys;
32 import com.liferay.portal.kernel.util.StringBundler;
33 import com.liferay.portal.kernel.util.StringPool;
34 import com.liferay.portal.kernel.util.Validator;
35 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
36 import com.liferay.portal.service.ServiceContext;
37 import com.liferay.portal.util.PropsUtil;
38 import com.liferay.util.SystemProperties;
39
40 import java.io.File;
41 import java.io.FileInputStream;
42 import java.io.IOException;
43 import java.io.InputStream;
44
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Date;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Set;
52
53 import org.jets3t.service.S3Service;
54 import org.jets3t.service.S3ServiceException;
55 import org.jets3t.service.impl.rest.httpclient.RestS3Service;
56 import org.jets3t.service.model.S3Bucket;
57 import org.jets3t.service.model.S3Object;
58 import org.jets3t.service.security.AWSCredentials;
59
60
66 public class S3Hook extends BaseHook {
67
68 public S3Hook() {
69 try {
70 _s3Service = getS3Service();
71 _s3Bucket = getS3Bucket();
72 }
73 catch (S3ServiceException s3se) {
74 _log.error(s3se.getMessage());
75 }
76 }
77
78 public void addDirectory(
79 long companyId, long repositoryId, String dirName) {
80 }
81
82 public void addFile(
83 long companyId, String portletId, long groupId, long repositoryId,
84 String fileName, long fileEntryId, String properties,
85 Date modifiedDate, ServiceContext serviceContext, InputStream is)
86 throws PortalException, SystemException {
87
88 try {
89 S3Object s3Object = new S3Object(
90 _s3Bucket,
91 getKey(companyId, repositoryId, fileName, DEFAULT_VERSION));
92
93 s3Object.setDataInputStream(is);
94
95 _s3Service.putObject(_s3Bucket, s3Object);
96
97 Indexer indexer = IndexerRegistryUtil.getIndexer(
98 FileModel.class);
99
100 FileModel fileModel = new FileModel();
101
102 fileModel.setAssetCategoryIds(serviceContext.getAssetCategoryIds());
103 fileModel.setAssetTagNames(serviceContext.getAssetTagNames());
104 fileModel.setCompanyId(companyId);
105 fileModel.setFileEntryId(fileEntryId);
106 fileModel.setFileName(fileName);
107 fileModel.setGroupId(groupId);
108 fileModel.setModifiedDate(modifiedDate);
109 fileModel.setPortletId(portletId);
110 fileModel.setProperties(properties);
111 fileModel.setRepositoryId(repositoryId);
112
113 indexer.reindex(fileModel);
114 }
115 catch (S3ServiceException s3se) {
116 throw new SystemException(s3se);
117 }
118 }
119
120 public void checkRoot(long companyId) {
121 }
122
123 public void deleteDirectory(
124 long companyId, String portletId, long repositoryId, String dirName)
125 throws SystemException {
126
127 try {
128 S3Object[] s3Objects = _s3Service.listObjects(
129 _s3Bucket, getKey(companyId, repositoryId, dirName), null);
130
131 for (int i = 0; i < s3Objects.length; i++) {
132 S3Object s3Object = s3Objects[i];
133
134 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
135 }
136 }
137 catch (S3ServiceException s3se) {
138 throw new SystemException(s3se);
139 }
140 }
141
142 public void deleteFile(
143 long companyId, String portletId, long repositoryId,
144 String fileName)
145 throws PortalException, SystemException {
146
147 try {
148 S3Object[] s3Objects = _s3Service.listObjects(
149 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
150
151 for (int i = 0; i < s3Objects.length; i++) {
152 S3Object s3Object = s3Objects[i];
153
154 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
155 }
156
157 FileModel fileModel = new FileModel();
158
159 fileModel.setCompanyId(companyId);
160 fileModel.setFileName(fileName);
161 fileModel.setPortletId(portletId);
162 fileModel.setRepositoryId(repositoryId);
163
164 Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
165
166 indexer.delete(fileModel);
167 }
168 catch (S3ServiceException s3se) {
169 throw new SystemException(s3se);
170 }
171 }
172
173 public void deleteFile(
174 long companyId, String portletId, long repositoryId,
175 String fileName, String versionNumber)
176 throws SystemException {
177
178 try {
179 _s3Service.deleteObject(
180 _s3Bucket,
181 getKey(companyId, repositoryId, fileName, versionNumber));
182 }
183 catch (S3ServiceException s3se) {
184 throw new SystemException(s3se);
185 }
186 }
187
188 public InputStream getFileAsStream(
189 long companyId, long repositoryId, String fileName,
190 String versionNumber)
191 throws PortalException, SystemException {
192
193 try {
194 if (Validator.isNull(versionNumber)) {
195 versionNumber = getHeadVersionNumber(
196 companyId, repositoryId, fileName);
197 }
198
199 S3Object s3Object = _s3Service.getObject(
200 _s3Bucket,
201 getKey(companyId, repositoryId, fileName, versionNumber));
202
203 return s3Object.getDataInputStream();
204 }
205 catch (S3ServiceException s3se) {
206 throw new SystemException(s3se);
207 }
208 }
209
210 public String[] getFileNames(
211 long companyId, long repositoryId, String dirName)
212 throws SystemException {
213
214 try {
215 List<String> list = new ArrayList<String>();
216
217 S3Object[] s3Objects = _s3Service.listObjects(
218 _s3Bucket, getKey(companyId, repositoryId, dirName), null);
219
220 for (int i = 0; i < s3Objects.length; i++) {
221 S3Object s3Object = s3Objects[i];
222
223
226 String key = s3Object.getKey();
227
228 int x = key.indexOf(StringPool.SLASH);
229
230 x = key.indexOf(StringPool.SLASH, x + 1);
231
232 int y = key.lastIndexOf(StringPool.SLASH);
233
234 list.add(key.substring(x, y));
235 }
236
237 return list.toArray(new String[list.size()]);
238 }
239 catch (S3ServiceException s3se) {
240 throw new SystemException(s3se);
241 }
242 }
243
244 public long getFileSize(
245 long companyId, long repositoryId, String fileName)
246 throws PortalException, SystemException {
247
248 try {
249 String versionNumber = getHeadVersionNumber(
250 companyId, repositoryId, fileName);
251
252 S3Object objectDetails = _s3Service.getObjectDetails(
253 _s3Bucket,
254 getKey(companyId, repositoryId, fileName, versionNumber));
255
256 return objectDetails.getContentLength();
257 }
258 catch (S3ServiceException s3se) {
259 throw new SystemException(s3se);
260 }
261 }
262
263 public boolean hasFile(
264 long companyId, long repositoryId, String fileName,
265 String versionNumber)
266 throws SystemException {
267
268 try {
269 S3Object[] s3Objects = _s3Service.listObjects(
270 _s3Bucket,
271 getKey(companyId, repositoryId, fileName, versionNumber), null);
272
273 if (s3Objects.length == 0) {
274 return false;
275 }
276 else {
277 return true;
278 }
279 }
280 catch (S3ServiceException s3se) {
281 throw new SystemException(s3se);
282 }
283 }
284
285 public void move(String srcDir, String destDir) {
286 }
287
288 public void reindex(String[] ids) throws SearchException {
289 long companyId = GetterUtil.getLong(ids[0]);
290 String portletId = ids[1];
291 long groupId = GetterUtil.getLong(ids[2]);
292 long repositoryId = GetterUtil.getLong(ids[3]);
293
294 try {
295 S3Object[] searchObjects = _s3Service.listObjects(
296 _s3Bucket, getKey(companyId, repositoryId), null);
297
298 Set<String> fileNameSet = new HashSet<String>();
299
300 for (int i = 0; i < searchObjects.length; i++) {
301 S3Object currentObject = searchObjects[i];
302
303 String fileName = getFileName(currentObject.getKey());
304
305 fileNameSet.add(fileName);
306 }
307
308 Iterator<String> itr = fileNameSet.iterator();
309
310 while (itr.hasNext()) {
311 String fileName = itr.next();
312
313 try {
314 Indexer indexer = IndexerRegistryUtil.getIndexer(
315 FileModel.class);
316
317 FileModel fileModel = new FileModel();
318
319 fileModel.setCompanyId(companyId);
320 fileModel.setFileName(fileName);
321 fileModel.setGroupId(groupId);
322 fileModel.setPortletId(portletId);
323 fileModel.setRepositoryId(repositoryId);
324
325 Document document = indexer.getDocument(fileModel);
326
327 SearchEngineUtil.updateDocument(
328 companyId, document.get(Field.UID), document);
329 }
330 catch (Exception e) {
331 _log.error("Reindexing " + fileName, e);
332 }
333 }
334 }
335 catch (S3ServiceException s3se) {
336 throw new SearchException(s3se);
337 }
338 }
339
340 public void updateFile(
341 long companyId, String portletId, long groupId, long repositoryId,
342 long newRepositoryId, String fileName, long fileEntryId)
343 throws PortalException, SystemException {
344
345 try {
346 S3Object[] s3Objects = _s3Service.listObjects(
347 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
348
349 for (int i = 0; i < s3Objects.length; i++) {
350 S3Object oldS3Object = s3Objects[i];
351
352 String oldKey = oldS3Object.getKey();
353
354 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
355
356 File tempFile = new File(
357 SystemProperties.get(SystemProperties.TMP_DIR) +
358 File.separator + PortalUUIDUtil.generate());
359
360 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
361
362 InputStream is = new FileInputStream(tempFile);
363
364 String newPrefix = getKey(companyId, newRepositoryId);
365
366 int x = oldKey.indexOf(StringPool.SLASH);
367
368 x = oldKey.indexOf(StringPool.SLASH, x + 1);
369
370 String newKey =
371 newPrefix + oldKey.substring(x + 1, oldKey.length());
372
373 S3Object newS3Object = new S3Object(
374 _s3Bucket, newKey);
375
376 newS3Object.setDataInputStream(is);
377
378 _s3Service.putObject(_s3Bucket, newS3Object);
379 _s3Service.deleteObject(_s3Bucket, oldKey);
380
381 FileUtil.delete(tempFile);
382 }
383
384 Indexer indexer = IndexerRegistryUtil.getIndexer(
385 FileModel.class);
386
387 FileModel fileModel = new FileModel();
388
389 fileModel.setCompanyId(companyId);
390 fileModel.setFileName(fileName);
391 fileModel.setPortletId(portletId);
392 fileModel.setRepositoryId(repositoryId);
393
394 indexer.delete(fileModel);
395
396 fileModel.setRepositoryId(newRepositoryId);
397 fileModel.setGroupId(groupId);
398
399 indexer.reindex(fileModel);
400 }
401 catch (IOException ioe) {
402 throw new SystemException(ioe);
403 }
404 catch (S3ServiceException s3se) {
405 throw new SystemException(s3se);
406 }
407 }
408
409 public void updateFile(
410 long companyId, String portletId, long groupId, long repositoryId,
411 String fileName, String versionNumber, String sourceFileName,
412 long fileEntryId, String properties, Date modifiedDate,
413 ServiceContext serviceContext, InputStream is)
414 throws PortalException, SystemException {
415
416 try {
417 S3Object s3Object = new S3Object(
418 _s3Bucket,
419 getKey(companyId, repositoryId, fileName, versionNumber));
420
421 s3Object.setDataInputStream(is);
422
423 _s3Service.putObject(_s3Bucket, s3Object);
424
425 Indexer indexer = IndexerRegistryUtil.getIndexer(
426 FileModel.class);
427
428 FileModel fileModel = new FileModel();
429
430 fileModel.setAssetCategoryIds(serviceContext.getAssetCategoryIds());
431 fileModel.setAssetTagNames(serviceContext.getAssetTagNames());
432 fileModel.setCompanyId(companyId);
433 fileModel.setFileEntryId(fileEntryId);
434 fileModel.setFileName(fileName);
435 fileModel.setGroupId(groupId);
436 fileModel.setModifiedDate(modifiedDate);
437 fileModel.setPortletId(portletId);
438 fileModel.setProperties(properties);
439 fileModel.setRepositoryId(repositoryId);
440
441 indexer.reindex(fileModel);
442 }
443 catch (S3ServiceException s3se) {
444 throw new SystemException(s3se);
445 }
446 }
447
448 public void updateFile(
449 long companyId, String portletId, long groupId, long repositoryId,
450 String fileName, String newFileName, boolean reindex)
451 throws PortalException, SystemException {
452
453 try {
454 S3Object[] s3Objects = _s3Service.listObjects(
455 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
456
457 for (int i = 0; i < s3Objects.length; i++) {
458 S3Object oldS3Object = s3Objects[i];
459
460 String oldKey = oldS3Object.getKey();
461
462 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
463
464 File tempFile = new File(
465 SystemProperties.get(SystemProperties.TMP_DIR) +
466 File.separator + PortalUUIDUtil.generate());
467
468 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
469
470 InputStream is = new FileInputStream(tempFile);
471
472 String newPrefix = getKey(companyId, repositoryId, newFileName);
473
474 int x = oldKey.indexOf(StringPool.SLASH);
475
476 x = oldKey.indexOf(StringPool.SLASH, x + 1);
477
478 x = oldKey.indexOf(StringPool.SLASH, x + 1);
479
480 String newKey =
481 newPrefix + oldKey.substring(x + 1, oldKey.length());
482
483 S3Object newS3Object = new S3Object(
484 _s3Bucket, newKey);
485
486 newS3Object.setDataInputStream(is);
487
488 _s3Service.putObject(_s3Bucket, newS3Object);
489 _s3Service.deleteObject(_s3Bucket, oldKey);
490
491 FileUtil.delete(tempFile);
492 }
493
494 if (reindex) {
495 Indexer indexer = IndexerRegistryUtil.getIndexer(
496 FileModel.class);
497
498 FileModel fileModel = new FileModel();
499
500 fileModel.setCompanyId(companyId);
501 fileModel.setFileName(fileName);
502 fileModel.setPortletId(portletId);
503 fileModel.setRepositoryId(repositoryId);
504
505 indexer.delete(fileModel);
506
507 fileModel.setFileName(newFileName);
508 fileModel.setGroupId(groupId);
509
510 indexer.reindex(fileModel);
511 }
512 }
513 catch (IOException ioe) {
514 throw new SystemException(ioe);
515 }
516 catch (S3ServiceException s3se) {
517 throw new SystemException(s3se);
518 }
519 }
520
521 protected AWSCredentials getAWSCredentials() throws S3ServiceException {
522 if (Validator.isNull(_ACCESS_KEY) || Validator.isNull(_SECRET_KEY)) {
523 throw new S3ServiceException(
524 "S3 access and secret keys are not set");
525 }
526 else {
527 return new AWSCredentials(_ACCESS_KEY, _SECRET_KEY);
528 }
529 }
530
531 protected String getFileName(String key) {
532 int x = key.indexOf(StringPool.SLASH);
533
534 x = key.indexOf(StringPool.SLASH, x + 1);
535
536 int y = key.lastIndexOf(StringPool.SLASH);
537
538 return key.substring(x + 1, y);
539 }
540
541 protected String getHeadVersionNumber(
542 long companyId, long repositoryId, String fileName)
543 throws PortalException, S3ServiceException {
544
545 S3Object[] s3Objects = _s3Service.listObjects(
546 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
547
548 String[] keys = new String[s3Objects.length];
549
550 for (int i = 0; i < s3Objects.length; i++) {
551 S3Object s3Object = s3Objects[i];
552
553 keys[i] = s3Object.getKey();
554 }
555
556 if (keys.length > 0) {
557 Arrays.sort(keys);
558
559 String headKey = keys[keys.length - 1];
560
561 int x = headKey.lastIndexOf(StringPool.SLASH);
562
563 return headKey.substring(x + 1, headKey.length());
564 }
565 else {
566 throw new NoSuchFileException(fileName);
567 }
568 }
569
570 protected String getKey(long companyId, long repositoryId) {
571 StringBundler sb = new StringBundler(4);
572
573 sb.append(companyId);
574 sb.append(StringPool.SLASH);
575 sb.append(repositoryId);
576 sb.append(StringPool.SLASH);
577
578 return sb.toString();
579 }
580
581 protected String getKey(
582 long companyId, long repositoryId, String fileName) {
583
584 StringBundler sb = new StringBundler(6);
585
586 sb.append(companyId);
587 sb.append(StringPool.SLASH);
588 sb.append(repositoryId);
589 sb.append(StringPool.SLASH);
590 sb.append(fileName);
591 sb.append(StringPool.SLASH);
592
593 return sb.toString();
594 }
595
596 protected String getKey(
597 long companyId, long repositoryId, String fileName,
598 String versionNumber) {
599
600 StringBundler sb = new StringBundler(7);
601
602 sb.append(companyId);
603 sb.append(StringPool.SLASH);
604 sb.append(repositoryId);
605 sb.append(StringPool.SLASH);
606 sb.append(fileName);
607 sb.append(StringPool.SLASH);
608 sb.append(versionNumber);
609
610 return sb.toString();
611 }
612
613 protected S3Bucket getS3Bucket() throws S3ServiceException {
614 if (Validator.isNull(_BUCKET_NAME)) {
615 throw new S3ServiceException("S3 bucket name is not set");
616 }
617 else {
618 return getS3Service().createBucket(_BUCKET_NAME);
619 }
620 }
621
622 protected S3Service getS3Service() throws S3ServiceException {
623 AWSCredentials credentials = getAWSCredentials();
624
625 return new RestS3Service(credentials);
626 }
627
628 private static final String _ACCESS_KEY = PropsUtil.get(
629 PropsKeys.DL_HOOK_S3_ACCESS_KEY);
630
631 private static final String _BUCKET_NAME = PropsUtil.get(
632 PropsKeys.DL_HOOK_S3_BUCKET_NAME);
633
634 private static final String _SECRET_KEY = PropsUtil.get(
635 PropsKeys.DL_HOOK_S3_SECRET_KEY);
636
637 private static Log _log = LogFactoryUtil.getLog(S3Hook.class);
638
639 private S3Bucket _s3Bucket;
640 private S3Service _s3Service;
641
642 }