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.impl.rest.httpclient.RestS3Service;
044 import org.jets3t.service.model.S3Bucket;
045 import org.jets3t.service.model.S3Object;
046 import org.jets3t.service.security.AWSCredentials;
047
048
053 public class S3Store extends BaseStore {
054
055 public S3Store() {
056 try {
057 _s3Service = getS3Service();
058 _s3Bucket = getS3Bucket();
059 }
060 catch (S3ServiceException s3se) {
061 _log.error(s3se.getMessage());
062 }
063 }
064
065 @Override
066 public void addDirectory(
067 long companyId, long repositoryId, String dirName) {
068 }
069
070 @Override
071 public void addFile(
072 long companyId, long repositoryId, String fileName, InputStream is)
073 throws SystemException {
074
075 try {
076 S3Object s3Object = new S3Object(
077 _s3Bucket,
078 getKey(companyId, repositoryId, fileName, VERSION_DEFAULT));
079
080 s3Object.setDataInputStream(is);
081
082 _s3Service.putObject(_s3Bucket, s3Object);
083 }
084 catch (S3ServiceException s3se) {
085 throw new SystemException(s3se);
086 }
087 }
088
089 @Override
090 public void checkRoot(long companyId) {
091 }
092
093 @Override
094 public void deleteDirectory(
095 long companyId, long repositoryId, String dirName)
096 throws SystemException {
097
098 try {
099 S3Object[] s3Objects = _s3Service.listObjects(
100 _s3Bucket, getKey(companyId, repositoryId, dirName), null);
101
102 for (int i = 0; i < s3Objects.length; i++) {
103 S3Object s3Object = s3Objects[i];
104
105 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
106 }
107 }
108 catch (S3ServiceException s3se) {
109 throw new SystemException(s3se);
110 }
111 }
112
113 @Override
114 public void deleteFile(
115 long companyId, long repositoryId, String fileName)
116 throws SystemException {
117
118 try {
119 S3Object[] s3Objects = _s3Service.listObjects(
120 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
121
122 for (int i = 0; i < s3Objects.length; i++) {
123 S3Object s3Object = s3Objects[i];
124
125 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
126 }
127 }
128 catch (S3ServiceException s3se) {
129 throw new SystemException(s3se);
130 }
131 }
132
133 @Override
134 public void deleteFile(
135 long companyId, long repositoryId, String fileName,
136 String versionLabel)
137 throws SystemException {
138
139 try {
140 _s3Service.deleteObject(
141 _s3Bucket,
142 getKey(companyId, repositoryId, fileName, versionLabel));
143 }
144 catch (S3ServiceException s3se) {
145 throw new SystemException(s3se);
146 }
147 }
148
149 @Override
150 public InputStream getFileAsStream(
151 long companyId, long repositoryId, String fileName,
152 String versionLabel)
153 throws PortalException, SystemException {
154
155 try {
156 if (Validator.isNull(versionLabel)) {
157 versionLabel = getHeadVersionLabel(
158 companyId, repositoryId, fileName);
159 }
160
161 S3Object s3Object = _s3Service.getObject(
162 _s3Bucket,
163 getKey(companyId, repositoryId, fileName, versionLabel));
164
165 return s3Object.getDataInputStream();
166 }
167 catch (S3ServiceException s3se) {
168 throw new SystemException(s3se);
169 }
170 }
171
172 public String[] getFileNames(long companyId, long repositoryId)
173 throws SystemException {
174
175 List<String> fileNames = new ArrayList<String>();
176
177 try {
178 S3Object[] searchObjects = _s3Service.listObjects(
179 _s3Bucket, getKey(companyId, repositoryId), null);
180
181 for (int i = 0; i < searchObjects.length; i++) {
182 S3Object currentObject = searchObjects[i];
183
184 String fileName = getFileName(currentObject.getKey());
185
186 fileNames.add(fileName);
187 }
188 }
189 catch (S3ServiceException s3se) {
190 throw new SystemException(s3se);
191 }
192
193 return fileNames.toArray(new String[0]);
194 }
195
196 @Override
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
211
212
213 String key = s3Object.getKey();
214
215 int x = key.indexOf(CharPool.SLASH);
216
217 x = key.indexOf(CharPool.SLASH, x + 1);
218
219 int y = key.lastIndexOf(CharPool.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 @Override
232 public long getFileSize(
233 long companyId, long repositoryId, String fileName)
234 throws PortalException, SystemException {
235
236 try {
237 String versionLabel = getHeadVersionLabel(
238 companyId, repositoryId, fileName);
239
240 S3Object objectDetails = _s3Service.getObjectDetails(
241 _s3Bucket,
242 getKey(companyId, repositoryId, fileName, versionLabel));
243
244 return objectDetails.getContentLength();
245 }
246 catch (S3ServiceException s3se) {
247 throw new SystemException(s3se);
248 }
249 }
250
251 @Override
252 public boolean hasDirectory(
253 long companyId, long repositoryId, String dirName) {
254
255 return true;
256 }
257
258 @Override
259 public boolean hasFile(
260 long companyId, long repositoryId, String fileName,
261 String versionLabel)
262 throws SystemException {
263
264 try {
265 S3Object[] s3Objects = _s3Service.listObjects(
266 _s3Bucket,
267 getKey(companyId, repositoryId, fileName, versionLabel), null);
268
269 if (s3Objects.length == 0) {
270 return false;
271 }
272 else {
273 return true;
274 }
275 }
276 catch (S3ServiceException s3se) {
277 throw new SystemException(s3se);
278 }
279 }
280
281 @Override
282 public void move(String srcDir, String destDir) {
283 }
284
285 @Override
286 public void updateFile(
287 long companyId, long repositoryId, long newRepositoryId,
288 String fileName)
289 throws SystemException {
290
291 try {
292 S3Object[] s3Objects = _s3Service.listObjects(
293 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
294
295 for (int i = 0; i < s3Objects.length; i++) {
296 S3Object oldS3Object = s3Objects[i];
297
298 String oldKey = oldS3Object.getKey();
299
300 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
301
302 File tempFile = new File(
303 SystemProperties.get(SystemProperties.TMP_DIR) +
304 File.separator + PortalUUIDUtil.generate());
305
306 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
307
308 InputStream is = new FileInputStream(tempFile);
309
310 String newPrefix = getKey(companyId, newRepositoryId);
311
312 int x = oldKey.indexOf(CharPool.SLASH);
313
314 x = oldKey.indexOf(CharPool.SLASH, x + 1);
315
316 String newKey =
317 newPrefix + oldKey.substring(x + 1, oldKey.length());
318
319 S3Object newS3Object = new S3Object(
320 _s3Bucket, newKey);
321
322 newS3Object.setDataInputStream(is);
323
324 _s3Service.putObject(_s3Bucket, newS3Object);
325 _s3Service.deleteObject(_s3Bucket, oldKey);
326
327 FileUtil.delete(tempFile);
328 }
329 }
330 catch (IOException ioe) {
331 throw new SystemException(ioe);
332 }
333 catch (S3ServiceException s3se) {
334 throw new SystemException(s3se);
335 }
336 }
337
338 public void updateFile(
339 long companyId, long repositoryId, String fileName,
340 String newFileName)
341 throws SystemException {
342
343 try {
344 S3Object[] s3Objects = _s3Service.listObjects(
345 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
346
347 for (int i = 0; i < s3Objects.length; i++) {
348 S3Object oldS3Object = s3Objects[i];
349
350 String oldKey = oldS3Object.getKey();
351
352 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
353
354 File tempFile = new File(
355 SystemProperties.get(SystemProperties.TMP_DIR) +
356 File.separator + PortalUUIDUtil.generate());
357
358 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
359
360 InputStream is = new FileInputStream(tempFile);
361
362 String newPrefix = getKey(companyId, repositoryId, newFileName);
363
364 int x = oldKey.indexOf(StringPool.SLASH);
365
366 x = oldKey.indexOf(CharPool.SLASH, x + 1);
367
368 x = oldKey.indexOf(CharPool.SLASH, x + 1);
369
370 String newKey =
371 newPrefix + oldKey.substring(x + 1, oldKey.length());
372
373 S3Object newS3Object = new S3Object(
374 _s3Bucket, newKey);
375
376 newS3Object.setDataInputStream(is);
377
378 _s3Service.putObject(_s3Bucket, newS3Object);
379 _s3Service.deleteObject(_s3Bucket, oldKey);
380
381 FileUtil.delete(tempFile);
382 }
383 }
384 catch (IOException ioe) {
385 throw new SystemException(ioe);
386 }
387 catch (S3ServiceException s3se) {
388 throw new SystemException(s3se);
389 }
390 }
391
392 @Override
393 public void updateFile(
394 long companyId, long repositoryId, String fileName,
395 String versionLabel, InputStream is)
396 throws SystemException {
397
398 try {
399 S3Object s3Object = new S3Object(
400 _s3Bucket,
401 getKey(companyId, repositoryId, fileName, versionLabel));
402
403 s3Object.setDataInputStream(is);
404
405 _s3Service.putObject(_s3Bucket, s3Object);
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(CharPool.SLASH);
424
425 x = key.indexOf(CharPool.SLASH, x + 1);
426
427 int y = key.lastIndexOf(CharPool.SLASH);
428
429 return key.substring(x + 1, y);
430 }
431
432 protected String getHeadVersionLabel(
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(CharPool.SLASH);
453
454 return headKey.substring(x + 1, headKey.length());
455 }
456 else {
457 throw new NoSuchFileException(fileName);
458 }
459 }
460
461 protected String getKey(long companyId, long repositoryId) {
462 StringBundler sb = new StringBundler(4);
463
464 sb.append(companyId);
465 sb.append(StringPool.SLASH);
466 sb.append(repositoryId);
467 sb.append(StringPool.SLASH);
468
469 return sb.toString();
470 }
471
472 protected String getKey(
473 long companyId, long repositoryId, String fileName) {
474
475 StringBundler sb = new StringBundler(6);
476
477 sb.append(companyId);
478 sb.append(StringPool.SLASH);
479 sb.append(repositoryId);
480 sb.append(StringPool.SLASH);
481 sb.append(fileName);
482 sb.append(StringPool.SLASH);
483
484 return sb.toString();
485 }
486
487 protected String getKey(
488 long companyId, long repositoryId, String fileName,
489 String versionLabel) {
490
491 StringBundler sb = new StringBundler(7);
492
493 sb.append(companyId);
494 sb.append(StringPool.SLASH);
495 sb.append(repositoryId);
496 sb.append(StringPool.SLASH);
497 sb.append(fileName);
498 sb.append(StringPool.SLASH);
499 sb.append(versionLabel);
500
501 return sb.toString();
502 }
503
504 protected S3Bucket getS3Bucket() throws S3ServiceException {
505 if (Validator.isNull(_BUCKET_NAME)) {
506 throw new S3ServiceException("S3 bucket name is not set");
507 }
508 else {
509 return getS3Service().createBucket(_BUCKET_NAME);
510 }
511 }
512
513 protected S3Service getS3Service() throws S3ServiceException {
514 AWSCredentials credentials = getAWSCredentials();
515
516 return new RestS3Service(credentials);
517 }
518
519 private static final String _ACCESS_KEY = PropsUtil.get(
520 PropsKeys.DL_STORE_S3_ACCESS_KEY);
521
522 private static final String _BUCKET_NAME = PropsUtil.get(
523 PropsKeys.DL_STORE_S3_BUCKET_NAME);
524
525 private static final String _SECRET_KEY = PropsUtil.get(
526 PropsKeys.DL_STORE_S3_SECRET_KEY);
527
528 private static Log _log = LogFactoryUtil.getLog(S3Store.class);
529
530 private S3Bucket _s3Bucket;
531 private S3Service _s3Service;
532
533 }