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