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.Indexer;
25 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
26 import com.liferay.portal.kernel.search.SearchEngineUtil;
27 import com.liferay.portal.kernel.search.SearchException;
28 import com.liferay.portal.kernel.util.FileUtil;
29 import com.liferay.portal.kernel.util.GetterUtil;
30 import com.liferay.portal.kernel.util.PropsKeys;
31 import com.liferay.portal.kernel.util.StringBundler;
32 import com.liferay.portal.kernel.util.StringPool;
33 import com.liferay.portal.kernel.util.Validator;
34 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
35 import com.liferay.portal.service.ServiceContext;
36 import com.liferay.portal.util.PropsUtil;
37 import com.liferay.util.SystemProperties;
38
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.IOException;
42 import java.io.InputStream;
43
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collection;
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 Collection<Document> documents = new ArrayList<Document>();
295
296 try {
297 S3Object[] searchObjects = _s3Service.listObjects(
298 _s3Bucket, getKey(companyId, repositoryId), null);
299
300 Set<String> fileNameSet = new HashSet<String>();
301
302 for (int i = 0; i < searchObjects.length; i++) {
303 S3Object currentObject = searchObjects[i];
304
305 String fileName = getFileName(currentObject.getKey());
306
307 fileNameSet.add(fileName);
308 }
309
310 Iterator<String> itr = fileNameSet.iterator();
311
312 while (itr.hasNext()) {
313 String fileName = itr.next();
314
315 try {
316 Indexer indexer = IndexerRegistryUtil.getIndexer(
317 FileModel.class);
318
319 FileModel fileModel = new FileModel();
320
321 fileModel.setCompanyId(companyId);
322 fileModel.setFileName(fileName);
323 fileModel.setGroupId(groupId);
324 fileModel.setPortletId(portletId);
325 fileModel.setRepositoryId(repositoryId);
326
327 Document document = indexer.getDocument(fileModel);
328
329 if (document == null) {
330 continue;
331 }
332
333 documents.add(document);
334 }
335 catch (Exception e) {
336 _log.error("Reindexing " + fileName, e);
337 }
338 }
339 }
340 catch (S3ServiceException s3se) {
341 throw new SearchException(s3se);
342 }
343
344 SearchEngineUtil.updateDocuments(companyId, documents);
345 }
346
347 public void updateFile(
348 long companyId, String portletId, long groupId, long repositoryId,
349 long newRepositoryId, String fileName, long fileEntryId)
350 throws PortalException, SystemException {
351
352 try {
353 S3Object[] s3Objects = _s3Service.listObjects(
354 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
355
356 for (int i = 0; i < s3Objects.length; i++) {
357 S3Object oldS3Object = s3Objects[i];
358
359 String oldKey = oldS3Object.getKey();
360
361 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
362
363 File tempFile = new File(
364 SystemProperties.get(SystemProperties.TMP_DIR) +
365 File.separator + PortalUUIDUtil.generate());
366
367 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
368
369 InputStream is = new FileInputStream(tempFile);
370
371 String newPrefix = getKey(companyId, newRepositoryId);
372
373 int x = oldKey.indexOf(StringPool.SLASH);
374
375 x = oldKey.indexOf(StringPool.SLASH, x + 1);
376
377 String newKey =
378 newPrefix + oldKey.substring(x + 1, oldKey.length());
379
380 S3Object newS3Object = new S3Object(
381 _s3Bucket, newKey);
382
383 newS3Object.setDataInputStream(is);
384
385 _s3Service.putObject(_s3Bucket, newS3Object);
386 _s3Service.deleteObject(_s3Bucket, oldKey);
387
388 FileUtil.delete(tempFile);
389 }
390
391 Indexer indexer = IndexerRegistryUtil.getIndexer(
392 FileModel.class);
393
394 FileModel fileModel = new FileModel();
395
396 fileModel.setCompanyId(companyId);
397 fileModel.setFileName(fileName);
398 fileModel.setPortletId(portletId);
399 fileModel.setRepositoryId(repositoryId);
400
401 indexer.delete(fileModel);
402
403 fileModel.setRepositoryId(newRepositoryId);
404 fileModel.setGroupId(groupId);
405
406 indexer.reindex(fileModel);
407 }
408 catch (IOException ioe) {
409 throw new SystemException(ioe);
410 }
411 catch (S3ServiceException s3se) {
412 throw new SystemException(s3se);
413 }
414 }
415
416 public void updateFile(
417 long companyId, String portletId, long groupId, long repositoryId,
418 String fileName, String newFileName, boolean reindex)
419 throws PortalException, SystemException {
420
421 try {
422 S3Object[] s3Objects = _s3Service.listObjects(
423 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
424
425 for (int i = 0; i < s3Objects.length; i++) {
426 S3Object oldS3Object = s3Objects[i];
427
428 String oldKey = oldS3Object.getKey();
429
430 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
431
432 File tempFile = new File(
433 SystemProperties.get(SystemProperties.TMP_DIR) +
434 File.separator + PortalUUIDUtil.generate());
435
436 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
437
438 InputStream is = new FileInputStream(tempFile);
439
440 String newPrefix = getKey(companyId, repositoryId, newFileName);
441
442 int x = oldKey.indexOf(StringPool.SLASH);
443
444 x = oldKey.indexOf(StringPool.SLASH, x + 1);
445
446 x = oldKey.indexOf(StringPool.SLASH, x + 1);
447
448 String newKey =
449 newPrefix + oldKey.substring(x + 1, oldKey.length());
450
451 S3Object newS3Object = new S3Object(
452 _s3Bucket, newKey);
453
454 newS3Object.setDataInputStream(is);
455
456 _s3Service.putObject(_s3Bucket, newS3Object);
457 _s3Service.deleteObject(_s3Bucket, oldKey);
458
459 FileUtil.delete(tempFile);
460 }
461
462 if (reindex) {
463 Indexer indexer = IndexerRegistryUtil.getIndexer(
464 FileModel.class);
465
466 FileModel fileModel = new FileModel();
467
468 fileModel.setCompanyId(companyId);
469 fileModel.setFileName(fileName);
470 fileModel.setPortletId(portletId);
471 fileModel.setRepositoryId(repositoryId);
472
473 indexer.delete(fileModel);
474
475 fileModel.setFileName(newFileName);
476 fileModel.setGroupId(groupId);
477
478 indexer.reindex(fileModel);
479 }
480 }
481 catch (IOException ioe) {
482 throw new SystemException(ioe);
483 }
484 catch (S3ServiceException s3se) {
485 throw new SystemException(s3se);
486 }
487 }
488
489 public void updateFile(
490 long companyId, String portletId, long groupId, long repositoryId,
491 String fileName, String versionNumber, String sourceFileName,
492 long fileEntryId, String properties, Date modifiedDate,
493 ServiceContext serviceContext, InputStream is)
494 throws PortalException, SystemException {
495
496 try {
497 S3Object s3Object = new S3Object(
498 _s3Bucket,
499 getKey(companyId, repositoryId, fileName, versionNumber));
500
501 s3Object.setDataInputStream(is);
502
503 _s3Service.putObject(_s3Bucket, s3Object);
504
505 Indexer indexer = IndexerRegistryUtil.getIndexer(
506 FileModel.class);
507
508 FileModel fileModel = new FileModel();
509
510 fileModel.setAssetCategoryIds(serviceContext.getAssetCategoryIds());
511 fileModel.setAssetTagNames(serviceContext.getAssetTagNames());
512 fileModel.setCompanyId(companyId);
513 fileModel.setFileEntryId(fileEntryId);
514 fileModel.setFileName(fileName);
515 fileModel.setGroupId(groupId);
516 fileModel.setModifiedDate(modifiedDate);
517 fileModel.setPortletId(portletId);
518 fileModel.setProperties(properties);
519 fileModel.setRepositoryId(repositoryId);
520
521 indexer.reindex(fileModel);
522 }
523 catch (S3ServiceException s3se) {
524 throw new SystemException(s3se);
525 }
526 }
527
528 protected AWSCredentials getAWSCredentials() throws S3ServiceException {
529 if (Validator.isNull(_ACCESS_KEY) || Validator.isNull(_SECRET_KEY)) {
530 throw new S3ServiceException(
531 "S3 access and secret keys are not set");
532 }
533 else {
534 return new AWSCredentials(_ACCESS_KEY, _SECRET_KEY);
535 }
536 }
537
538 protected String getFileName(String key) {
539 int x = key.indexOf(StringPool.SLASH);
540
541 x = key.indexOf(StringPool.SLASH, x + 1);
542
543 int y = key.lastIndexOf(StringPool.SLASH);
544
545 return key.substring(x + 1, y);
546 }
547
548 protected String getHeadVersionNumber(
549 long companyId, long repositoryId, String fileName)
550 throws PortalException, S3ServiceException {
551
552 S3Object[] s3Objects = _s3Service.listObjects(
553 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
554
555 String[] keys = new String[s3Objects.length];
556
557 for (int i = 0; i < s3Objects.length; i++) {
558 S3Object s3Object = s3Objects[i];
559
560 keys[i] = s3Object.getKey();
561 }
562
563 if (keys.length > 0) {
564 Arrays.sort(keys);
565
566 String headKey = keys[keys.length - 1];
567
568 int x = headKey.lastIndexOf(StringPool.SLASH);
569
570 return headKey.substring(x + 1, headKey.length());
571 }
572 else {
573 throw new NoSuchFileException(fileName);
574 }
575 }
576
577 protected String getKey(long companyId, long repositoryId) {
578 StringBundler sb = new StringBundler(4);
579
580 sb.append(companyId);
581 sb.append(StringPool.SLASH);
582 sb.append(repositoryId);
583 sb.append(StringPool.SLASH);
584
585 return sb.toString();
586 }
587
588 protected String getKey(
589 long companyId, long repositoryId, String fileName) {
590
591 StringBundler sb = new StringBundler(6);
592
593 sb.append(companyId);
594 sb.append(StringPool.SLASH);
595 sb.append(repositoryId);
596 sb.append(StringPool.SLASH);
597 sb.append(fileName);
598 sb.append(StringPool.SLASH);
599
600 return sb.toString();
601 }
602
603 protected String getKey(
604 long companyId, long repositoryId, String fileName,
605 String versionNumber) {
606
607 StringBundler sb = new StringBundler(7);
608
609 sb.append(companyId);
610 sb.append(StringPool.SLASH);
611 sb.append(repositoryId);
612 sb.append(StringPool.SLASH);
613 sb.append(fileName);
614 sb.append(StringPool.SLASH);
615 sb.append(versionNumber);
616
617 return sb.toString();
618 }
619
620 protected S3Bucket getS3Bucket() throws S3ServiceException {
621 if (Validator.isNull(_BUCKET_NAME)) {
622 throw new S3ServiceException("S3 bucket name is not set");
623 }
624 else {
625 return getS3Service().createBucket(_BUCKET_NAME);
626 }
627 }
628
629 protected S3Service getS3Service() throws S3ServiceException {
630 AWSCredentials credentials = getAWSCredentials();
631
632 return new RestS3Service(credentials);
633 }
634
635 private static final String _ACCESS_KEY = PropsUtil.get(
636 PropsKeys.DL_HOOK_S3_ACCESS_KEY);
637
638 private static final String _BUCKET_NAME = PropsUtil.get(
639 PropsKeys.DL_HOOK_S3_BUCKET_NAME);
640
641 private static final String _SECRET_KEY = PropsUtil.get(
642 PropsKeys.DL_HOOK_S3_SECRET_KEY);
643
644 private static Log _log = LogFactoryUtil.getLog(S3Hook.class);
645
646 private S3Bucket _s3Bucket;
647 private S3Service _s3Service;
648
649 }