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