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