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(long companyId, long repositoryId, String fileName)
115 throws SystemException {
116
117 try {
118 S3Object[] s3Objects = _s3Service.listObjects(
119 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
120
121 for (int i = 0; i < s3Objects.length; i++) {
122 S3Object s3Object = s3Objects[i];
123
124 _s3Service.deleteObject(_s3Bucket, s3Object.getKey());
125 }
126 }
127 catch (S3ServiceException s3se) {
128 throw new SystemException(s3se);
129 }
130 }
131
132 @Override
133 public void deleteFile(
134 long companyId, long repositoryId, String fileName,
135 String versionLabel)
136 throws SystemException {
137
138 try {
139 _s3Service.deleteObject(
140 _s3Bucket,
141 getKey(companyId, repositoryId, fileName, versionLabel));
142 }
143 catch (S3ServiceException s3se) {
144 throw new SystemException(s3se);
145 }
146 }
147
148 @Override
149 public InputStream getFileAsStream(
150 long companyId, long repositoryId, String fileName,
151 String versionLabel)
152 throws PortalException, SystemException {
153
154 try {
155 if (Validator.isNull(versionLabel)) {
156 versionLabel = getHeadVersionLabel(
157 companyId, repositoryId, fileName);
158 }
159
160 S3Object s3Object = _s3Service.getObject(
161 _s3Bucket,
162 getKey(companyId, repositoryId, fileName, versionLabel));
163
164 return s3Object.getDataInputStream();
165 }
166 catch (S3ServiceException s3se) {
167 throw new SystemException(s3se);
168 }
169 }
170
171 public String[] getFileNames(long companyId, long repositoryId)
172 throws SystemException {
173
174 List<String> fileNames = new ArrayList<String>();
175
176 try {
177 S3Object[] searchObjects = _s3Service.listObjects(
178 _s3Bucket, getKey(companyId, repositoryId), null);
179
180 for (int i = 0; i < searchObjects.length; i++) {
181 S3Object currentObject = searchObjects[i];
182
183 String fileName = getFileName(currentObject.getKey());
184
185 fileNames.add(fileName);
186 }
187 }
188 catch (S3ServiceException s3se) {
189 throw new SystemException(s3se);
190 }
191
192 return fileNames.toArray(new String[0]);
193 }
194
195 @Override
196 public String[] getFileNames(
197 long companyId, long repositoryId, String dirName)
198 throws SystemException {
199
200 try {
201 List<String> list = new ArrayList<String>();
202
203 S3Object[] s3Objects = _s3Service.listObjects(
204 _s3Bucket, getKey(companyId, repositoryId, dirName), null);
205
206 for (int i = 0; i < s3Objects.length; i++) {
207 S3Object s3Object = s3Objects[i];
208
209
210
211
212 String key = s3Object.getKey();
213
214 int x = key.indexOf(CharPool.SLASH);
215
216 x = key.indexOf(CharPool.SLASH, x + 1);
217
218 int y = key.lastIndexOf(CharPool.SLASH);
219
220 list.add(key.substring(x, y));
221 }
222
223 return list.toArray(new String[list.size()]);
224 }
225 catch (S3ServiceException s3se) {
226 throw new SystemException(s3se);
227 }
228 }
229
230 @Override
231 public long getFileSize(long companyId, long repositoryId, String fileName)
232 throws PortalException, SystemException {
233
234 try {
235 String versionLabel = getHeadVersionLabel(
236 companyId, repositoryId, fileName);
237
238 S3Object objectDetails = _s3Service.getObjectDetails(
239 _s3Bucket,
240 getKey(companyId, repositoryId, fileName, versionLabel));
241
242 return objectDetails.getContentLength();
243 }
244 catch (S3ServiceException s3se) {
245 throw new SystemException(s3se);
246 }
247 }
248
249 @Override
250 public boolean hasDirectory(
251 long companyId, long repositoryId, String dirName) {
252
253 return true;
254 }
255
256 @Override
257 public boolean hasFile(
258 long companyId, long repositoryId, String fileName,
259 String versionLabel)
260 throws SystemException {
261
262 try {
263 S3Object[] s3Objects = _s3Service.listObjects(
264 _s3Bucket,
265 getKey(companyId, repositoryId, fileName, versionLabel), null);
266
267 if (s3Objects.length == 0) {
268 return false;
269 }
270 else {
271 return true;
272 }
273 }
274 catch (S3ServiceException s3se) {
275 throw new SystemException(s3se);
276 }
277 }
278
279 @Override
280 public void move(String srcDir, String destDir) {
281 }
282
283 @Override
284 public void updateFile(
285 long companyId, long repositoryId, long newRepositoryId,
286 String fileName)
287 throws SystemException {
288
289 try {
290 S3Object[] s3Objects = _s3Service.listObjects(
291 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
292
293 for (int i = 0; i < s3Objects.length; i++) {
294 S3Object oldS3Object = s3Objects[i];
295
296 String oldKey = oldS3Object.getKey();
297
298 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
299
300 File tempFile = new File(
301 SystemProperties.get(SystemProperties.TMP_DIR) +
302 File.separator + PortalUUIDUtil.generate());
303
304 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
305
306 InputStream is = new FileInputStream(tempFile);
307
308 String newPrefix = getKey(companyId, newRepositoryId);
309
310 int x = oldKey.indexOf(CharPool.SLASH);
311
312 x = oldKey.indexOf(CharPool.SLASH, x + 1);
313
314 String newKey =
315 newPrefix + oldKey.substring(x + 1, oldKey.length());
316
317 S3Object newS3Object = new S3Object(_s3Bucket, newKey);
318
319 newS3Object.setDataInputStream(is);
320
321 _s3Service.putObject(_s3Bucket, newS3Object);
322 _s3Service.deleteObject(_s3Bucket, oldKey);
323
324 FileUtil.delete(tempFile);
325 }
326 }
327 catch (IOException ioe) {
328 throw new SystemException(ioe);
329 }
330 catch (S3ServiceException s3se) {
331 throw new SystemException(s3se);
332 }
333 }
334
335 public void updateFile(
336 long companyId, long repositoryId, String fileName,
337 String newFileName)
338 throws SystemException {
339
340 try {
341 S3Object[] s3Objects = _s3Service.listObjects(
342 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
343
344 for (int i = 0; i < s3Objects.length; i++) {
345 S3Object oldS3Object = s3Objects[i];
346
347 String oldKey = oldS3Object.getKey();
348
349 oldS3Object = _s3Service.getObject(_s3Bucket, oldKey);
350
351 File tempFile = new File(
352 SystemProperties.get(SystemProperties.TMP_DIR) +
353 File.separator + PortalUUIDUtil.generate());
354
355 FileUtil.write(tempFile, oldS3Object.getDataInputStream());
356
357 InputStream is = new FileInputStream(tempFile);
358
359 String newPrefix = getKey(companyId, repositoryId, newFileName);
360
361 int x = oldKey.indexOf(StringPool.SLASH);
362
363 x = oldKey.indexOf(CharPool.SLASH, x + 1);
364
365 x = oldKey.indexOf(CharPool.SLASH, x + 1);
366
367 String newKey =
368 newPrefix + oldKey.substring(x + 1, oldKey.length());
369
370 S3Object newS3Object = new S3Object(_s3Bucket, newKey);
371
372 newS3Object.setDataInputStream(is);
373
374 _s3Service.putObject(_s3Bucket, newS3Object);
375 _s3Service.deleteObject(_s3Bucket, oldKey);
376
377 FileUtil.delete(tempFile);
378 }
379 }
380 catch (IOException ioe) {
381 throw new SystemException(ioe);
382 }
383 catch (S3ServiceException s3se) {
384 throw new SystemException(s3se);
385 }
386 }
387
388 @Override
389 public void updateFile(
390 long companyId, long repositoryId, String fileName,
391 String versionLabel, InputStream is)
392 throws SystemException {
393
394 try {
395 S3Object s3Object = new S3Object(
396 _s3Bucket,
397 getKey(companyId, repositoryId, fileName, versionLabel));
398
399 s3Object.setDataInputStream(is);
400
401 _s3Service.putObject(_s3Bucket, s3Object);
402 }
403 catch (S3ServiceException s3se) {
404 throw new SystemException(s3se);
405 }
406 }
407
408 protected AWSCredentials getAWSCredentials() throws S3ServiceException {
409 if (Validator.isNull(_ACCESS_KEY) || Validator.isNull(_SECRET_KEY)) {
410 throw new S3ServiceException(
411 "S3 access and secret keys are not set");
412 }
413 else {
414 return new AWSCredentials(_ACCESS_KEY, _SECRET_KEY);
415 }
416 }
417
418 protected String getFileName(String key) {
419 int x = key.indexOf(CharPool.SLASH);
420
421 x = key.indexOf(CharPool.SLASH, x + 1);
422
423 int y = key.lastIndexOf(CharPool.SLASH);
424
425 return key.substring(x + 1, y);
426 }
427
428 protected String getHeadVersionLabel(
429 long companyId, long repositoryId, String fileName)
430 throws PortalException, S3ServiceException {
431
432 S3Object[] s3Objects = _s3Service.listObjects(
433 _s3Bucket, getKey(companyId, repositoryId, fileName), null);
434
435 String[] keys = new String[s3Objects.length];
436
437 for (int i = 0; i < s3Objects.length; i++) {
438 S3Object s3Object = s3Objects[i];
439
440 keys[i] = s3Object.getKey();
441 }
442
443 if (keys.length > 0) {
444 Arrays.sort(keys);
445
446 String headKey = keys[keys.length - 1];
447
448 int x = headKey.lastIndexOf(CharPool.SLASH);
449
450 return headKey.substring(x + 1, headKey.length());
451 }
452 else {
453 throw new NoSuchFileException(fileName);
454 }
455 }
456
457 protected String getKey(long companyId, long repositoryId) {
458 StringBundler sb = new StringBundler(4);
459
460 sb.append(companyId);
461 sb.append(StringPool.SLASH);
462 sb.append(repositoryId);
463 sb.append(StringPool.SLASH);
464
465 return sb.toString();
466 }
467
468 protected String getKey(
469 long companyId, long repositoryId, String fileName) {
470
471 StringBundler sb = new StringBundler(6);
472
473 sb.append(companyId);
474 sb.append(StringPool.SLASH);
475 sb.append(repositoryId);
476 sb.append(StringPool.SLASH);
477 sb.append(fileName);
478 sb.append(StringPool.SLASH);
479
480 return sb.toString();
481 }
482
483 protected String getKey(
484 long companyId, long repositoryId, String fileName,
485 String versionLabel) {
486
487 StringBundler sb = new StringBundler(7);
488
489 sb.append(companyId);
490 sb.append(StringPool.SLASH);
491 sb.append(repositoryId);
492 sb.append(StringPool.SLASH);
493 sb.append(fileName);
494 sb.append(StringPool.SLASH);
495 sb.append(versionLabel);
496
497 return sb.toString();
498 }
499
500 protected S3Bucket getS3Bucket() throws S3ServiceException {
501 if (Validator.isNull(_BUCKET_NAME)) {
502 throw new S3ServiceException("S3 bucket name is not set");
503 }
504 else {
505 return getS3Service().createBucket(_BUCKET_NAME);
506 }
507 }
508
509 protected S3Service getS3Service() throws S3ServiceException {
510 AWSCredentials credentials = getAWSCredentials();
511
512 return new RestS3Service(credentials);
513 }
514
515 private static final String _ACCESS_KEY = PropsUtil.get(
516 PropsKeys.DL_STORE_S3_ACCESS_KEY);
517
518 private static final String _BUCKET_NAME = PropsUtil.get(
519 PropsKeys.DL_STORE_S3_BUCKET_NAME);
520
521 private static final String _SECRET_KEY = PropsUtil.get(
522 PropsKeys.DL_STORE_S3_SECRET_KEY);
523
524 private static Log _log = LogFactoryUtil.getLog(S3Store.class);
525
526 private S3Bucket _s3Bucket;
527 private S3Service _s3Service;
528
529 }