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