001
014
015 package com.liferay.portlet.documentlibrary.store;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.util.CharPool;
022 import com.liferay.portal.kernel.util.FileUtil;
023 import com.liferay.portal.kernel.util.PropsKeys;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.SystemProperties;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
029 import com.liferay.portal.util.PropsUtil;
030 import com.liferay.portlet.documentlibrary.NoSuchFileException;
031
032 import java.io.File;
033 import java.io.FileInputStream;
034 import java.io.IOException;
035 import java.io.InputStream;
036
037 import java.util.ArrayList;
038 import java.util.Arrays;
039 import java.util.List;
040
041 import org.jets3t.service.S3Service;
042 import org.jets3t.service.S3ServiceException;
043 import org.jets3t.service.ServiceException;
044 import org.jets3t.service.impl.rest.httpclient.RestS3Service;
045 import org.jets3t.service.model.S3Bucket;
046 import org.jets3t.service.model.S3Object;
047 import org.jets3t.service.model.StorageObject;
048 import org.jets3t.service.security.AWSCredentials;
049
050
055 public class S3Store extends BaseStore {
056
057 public S3Store() {
058 try {
059 _s3Service = getS3Service();
060 _s3Bucket = getS3Bucket();
061 }
062 catch (S3ServiceException s3se) {
063 _log.error(s3se.getMessage());
064 }
065 }
066
067 @Override
068 public void addDirectory(
069 long companyId, long repositoryId, String dirName) {
070 }
071
072 @Override
073 public void addFile(
074 long companyId, long repositoryId, String fileName, InputStream is)
075 throws SystemException {
076
077 try {
078 S3Object s3Object = new S3Object(
079 _s3Bucket,
080 getKey(companyId, repositoryId, fileName, VERSION_DEFAULT));
081
082 s3Object.setDataInputStream(is);
083
084 _s3Service.putObject(_s3Bucket, s3Object);
085
086 is.close();
087 }
088 catch (IOException ioe) {
089 throw new SystemException(ioe);
090 }
091 catch (S3ServiceException s3se) {
092 throw new SystemException(s3se);
093 }
094 }
095
096 @Override
097 public void checkRoot(long companyId) {
098 }
099
100 @Override
101 public void deleteDirectory(
102 long companyId, long repositoryId, String dirName)
103 throws SystemException {
104
105 try {
106 S3Object[] s3Objects = _s3Service.listObjects(
107 _s3Bucket.getName(), getKey(companyId, repositoryId, dirName),
108 null);
109
110 for (int i = 0; i < s3Objects.length; i++) {
111 S3Object s3Object = s3Objects[i];
112
113 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
114 }
115 }
116 catch (S3ServiceException s3se) {
117 throw new SystemException(s3se);
118 }
119 }
120
121 @Override
122 public void deleteFile(long companyId, long repositoryId, String fileName)
123 throws SystemException {
124
125 try {
126 S3Object[] s3Objects = _s3Service.listObjects(
127 _s3Bucket.getName(), getKey(companyId, repositoryId, fileName),
128 null);
129
130 for (int i = 0; i < s3Objects.length; i++) {
131 S3Object s3Object = s3Objects[i];
132
133 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
134 }
135 }
136 catch (S3ServiceException s3se) {
137 throw new SystemException(s3se);
138 }
139 }
140
141 @Override
142 public void deleteFile(
143 long companyId, long repositoryId, String fileName,
144 String versionLabel)
145 throws SystemException {
146
147 try {
148 _s3Service.deleteObject(
149 _s3Bucket,
150 getKey(companyId, repositoryId, fileName, versionLabel));
151 }
152 catch (S3ServiceException s3se) {
153 throw new SystemException(s3se);
154 }
155 }
156
157 @Override
158 public InputStream getFileAsStream(
159 long companyId, long repositoryId, String fileName,
160 String versionLabel)
161 throws PortalException, SystemException {
162
163 try {
164 if (Validator.isNull(versionLabel)) {
165 versionLabel = getHeadVersionLabel(
166 companyId, repositoryId, fileName);
167 }
168
169 S3Object s3Object = _s3Service.getObject(
170 _s3Bucket.getName(),
171 getKey(companyId, repositoryId, fileName, versionLabel));
172
173 return s3Object.getDataInputStream();
174 }
175 catch (ServiceException se) {
176 throw new SystemException(se);
177 }
178 }
179
180 public String[] getFileNames(long companyId, long repositoryId)
181 throws SystemException {
182
183 List<String> fileNames = new ArrayList<String>();
184
185 try {
186 S3Object[] searchObjects = _s3Service.listObjects(
187 _s3Bucket.getName(), getKey(companyId, repositoryId), null);
188
189 for (int i = 0; i < searchObjects.length; i++) {
190 S3Object currentObject = searchObjects[i];
191
192 String fileName = getFileName(currentObject.getKey());
193
194 fileNames.add(fileName);
195 }
196 }
197 catch (S3ServiceException s3se) {
198 throw new SystemException(s3se);
199 }
200
201 return fileNames.toArray(new String[fileNames.size()]);
202 }
203
204 @Override
205 public String[] getFileNames(
206 long companyId, long repositoryId, String dirName)
207 throws SystemException {
208
209 try {
210 List<String> list = new ArrayList<String>();
211
212 S3Object[] s3Objects = _s3Service.listObjects(
213 _s3Bucket.getName(), getKey(companyId, repositoryId, dirName),
214 null);
215
216 for (int i = 0; i < s3Objects.length; i++) {
217 S3Object s3Object = s3Objects[i];
218
219
220
221
222 String key = s3Object.getKey();
223
224 int x = key.indexOf(CharPool.SLASH);
225
226 x = key.indexOf(CharPool.SLASH, x + 1);
227
228 int y = key.lastIndexOf(CharPool.SLASH);
229
230 list.add(key.substring(x, y));
231 }
232
233 return list.toArray(new String[list.size()]);
234 }
235 catch (S3ServiceException s3se) {
236 throw new SystemException(s3se);
237 }
238 }
239
240 @Override
241 public long getFileSize(long companyId, long repositoryId, String fileName)
242 throws PortalException, SystemException {
243
244 try {
245 String versionLabel = getHeadVersionLabel(
246 companyId, repositoryId, fileName);
247
248 StorageObject storageObject = _s3Service.getObjectDetails(
249 _s3Bucket.getName(),
250 getKey(companyId, repositoryId, fileName, versionLabel));
251
252 return storageObject.getContentLength();
253 }
254 catch (ServiceException se) {
255 throw new SystemException(se);
256 }
257 }
258
259 @Override
260 public boolean hasDirectory(
261 long companyId, long repositoryId, String dirName) {
262
263 return true;
264 }
265
266 @Override
267 public boolean hasFile(
268 long companyId, long repositoryId, String fileName,
269 String versionLabel)
270 throws SystemException {
271
272 try {
273 S3Object[] s3Objects = _s3Service.listObjects(
274 _s3Bucket.getName(),
275 getKey(companyId, repositoryId, fileName, versionLabel), null);
276
277 if (s3Objects.length == 0) {
278 return false;
279 }
280 else {
281 return true;
282 }
283 }
284 catch (S3ServiceException s3se) {
285 throw new SystemException(s3se);
286 }
287 }
288
289 @Override
290 public void move(String srcDir, String destDir) {
291 }
292
293 @Override
294 public void updateFile(
295 long companyId, long repositoryId, long newRepositoryId,
296 String fileName)
297 throws SystemException {
298
299 try {
300 S3Object[] s3Objects = _s3Service.listObjects(
301 _s3Bucket.getName(), getKey(companyId, repositoryId, fileName),
302 null);
303
304 for (int i = 0; i < s3Objects.length; i++) {
305 S3Object oldS3Object = s3Objects[i];
306
307 String oldKey = oldS3Object.getKey();
308
309 oldS3Object = _s3Service.getObject(_s3Bucket.getName(), oldKey);
310
311 File tempFile = new File(
312 SystemProperties.get(SystemProperties.TMP_DIR) +
313 File.separator + PortalUUIDUtil.generate());
314
315 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
316
317 InputStream is = new FileInputStream(tempFile);
318
319 String newPrefix = getKey(companyId, newRepositoryId);
320
321 int x = oldKey.indexOf(CharPool.SLASH);
322
323 x = oldKey.indexOf(CharPool.SLASH, x + 1);
324
325 String newKey = newPrefix + oldKey.substring(x + 1);
326
327 S3Object newS3Object = new S3Object(_s3Bucket, newKey);
328
329 newS3Object.setDataInputStream(is);
330
331 _s3Service.putObject(_s3Bucket, newS3Object);
332 _s3Service.deleteObject(_s3Bucket, oldKey);
333
334 is.close();
335
336 FileUtil.delete(tempFile);
337 }
338 }
339 catch (IOException ioe) {
340 throw new SystemException(ioe);
341 }
342 catch (ServiceException se) {
343 throw new SystemException(se);
344 }
345 }
346
347 public void updateFile(
348 long companyId, long repositoryId, String fileName,
349 String newFileName)
350 throws SystemException {
351
352 try {
353 S3Object[] s3Objects = _s3Service.listObjects(
354 _s3Bucket.getName(), getKey(companyId, repositoryId, fileName),
355 null);
356
357 for (int i = 0; i < s3Objects.length; i++) {
358 S3Object oldS3Object = s3Objects[i];
359
360 String oldKey = oldS3Object.getKey();
361
362 oldS3Object = _s3Service.getObject(_s3Bucket.getName(), oldKey);
363
364 File tempFile = new File(
365 SystemProperties.get(SystemProperties.TMP_DIR) +
366 File.separator + PortalUUIDUtil.generate());
367
368 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
369
370 oldS3Object.closeDataInputStream();
371
372 InputStream is = new FileInputStream(tempFile);
373
374 String newPrefix = getKey(companyId, repositoryId, newFileName);
375
376 int x = oldKey.indexOf(StringPool.SLASH);
377
378 x = oldKey.indexOf(CharPool.SLASH, x + 1);
379 x = oldKey.indexOf(CharPool.SLASH, x + 1);
380
381 String newKey = newPrefix + oldKey.substring(x + 1);
382
383 S3Object newS3Object = new S3Object(_s3Bucket, newKey);
384
385 newS3Object.setDataInputStream(is);
386
387 _s3Service.putObject(_s3Bucket, newS3Object);
388 _s3Service.deleteObject(_s3Bucket, oldKey);
389
390 newS3Object.closeDataInputStream();
391
392 is.close();
393
394 FileUtil.delete(tempFile);
395 }
396 }
397 catch (IOException ioe) {
398 throw new SystemException(ioe);
399 }
400 catch (ServiceException se) {
401 throw new SystemException(se);
402 }
403 }
404
405 @Override
406 public void updateFile(
407 long companyId, long repositoryId, String fileName,
408 String versionLabel, InputStream is)
409 throws SystemException {
410
411 try {
412 S3Object s3Object = new S3Object(
413 _s3Bucket,
414 getKey(companyId, repositoryId, fileName, versionLabel));
415
416 s3Object.setDataInputStream(is);
417
418 _s3Service.putObject(_s3Bucket, s3Object);
419
420 is.close();
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(CharPool.SLASH);
442
443 x = key.indexOf(CharPool.SLASH, x + 1);
444
445 int y = key.lastIndexOf(CharPool.SLASH);
446
447 return key.substring(x + 1, y);
448 }
449
450 protected String getHeadVersionLabel(
451 long companyId, long repositoryId, String fileName)
452 throws PortalException, S3ServiceException {
453
454 S3Object[] s3Objects = _s3Service.listObjects(
455 _s3Bucket.getName(), getKey(companyId, repositoryId, fileName),
456 null);
457
458 String[] keys = new String[s3Objects.length];
459
460 for (int i = 0; i < s3Objects.length; i++) {
461 S3Object s3Object = s3Objects[i];
462
463 keys[i] = s3Object.getKey();
464 }
465
466 if (keys.length > 0) {
467 Arrays.sort(keys);
468
469 String headKey = keys[keys.length - 1];
470
471 int x = headKey.lastIndexOf(CharPool.SLASH);
472
473 return headKey.substring(x + 1);
474 }
475 else {
476 throw new NoSuchFileException(fileName);
477 }
478 }
479
480 protected String getKey(long companyId, long repositoryId) {
481 StringBundler sb = new StringBundler(4);
482
483 sb.append(companyId);
484 sb.append(StringPool.SLASH);
485 sb.append(repositoryId);
486 sb.append(StringPool.SLASH);
487
488 return sb.toString();
489 }
490
491 protected String getKey(
492 long companyId, long repositoryId, String fileName) {
493
494 StringBundler sb = new StringBundler(6);
495
496 sb.append(companyId);
497 sb.append(StringPool.SLASH);
498 sb.append(repositoryId);
499 sb.append(StringPool.SLASH);
500 sb.append(fileName);
501 sb.append(StringPool.SLASH);
502
503 return sb.toString();
504 }
505
506 protected String getKey(
507 long companyId, long repositoryId, String fileName,
508 String versionLabel) {
509
510 StringBundler sb = new StringBundler(7);
511
512 sb.append(companyId);
513 sb.append(StringPool.SLASH);
514 sb.append(repositoryId);
515 sb.append(StringPool.SLASH);
516 sb.append(fileName);
517 sb.append(StringPool.SLASH);
518 sb.append(versionLabel);
519
520 return sb.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().getBucket(_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 PropsKeys.DL_STORE_S3_ACCESS_KEY);
540
541 private static final String _BUCKET_NAME = PropsUtil.get(
542 PropsKeys.DL_STORE_S3_BUCKET_NAME);
543
544 private static final String _SECRET_KEY = PropsUtil.get(
545 PropsKeys.DL_STORE_S3_SECRET_KEY);
546
547 private static Log _log = LogFactoryUtil.getLog(S3Store.class);
548
549 private S3Bucket _s3Bucket;
550 private S3Service _s3Service;
551
552 }