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