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