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