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