001package org.opengion.plugin.cloud;
002
003import java.io.InputStream;
004import java.text.SimpleDateFormat;
005import java.util.ArrayList;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009
010import javax.servlet.http.HttpSession;
011
012import org.apache.commons.lang3.StringUtils;
013import org.opengion.fukurou.util.Closer;
014import org.opengion.fukurou.util.FileUtil;
015import org.opengion.hayabusa.common.HybsSystem;
016import org.opengion.hayabusa.common.HybsSystemException;
017import org.opengion.hayabusa.io.StorageAPI;
018
019import com.amazonaws.auth.AWSCredentials;
020import com.amazonaws.auth.AWSStaticCredentialsProvider;
021import com.amazonaws.auth.BasicAWSCredentials;
022import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
023import com.amazonaws.services.s3.AmazonS3;
024import com.amazonaws.services.s3.AmazonS3ClientBuilder;
025import com.amazonaws.services.s3.model.CopyObjectRequest;
026import com.amazonaws.services.s3.model.DeleteObjectRequest;
027import com.amazonaws.services.s3.model.ListObjectsV2Request;
028import com.amazonaws.services.s3.model.ListObjectsV2Result;
029import com.amazonaws.services.s3.model.ObjectMetadata;
030import com.amazonaws.services.s3.model.PutObjectRequest;
031import com.amazonaws.services.s3.model.S3Object;
032import com.amazonaws.services.s3.model.S3ObjectSummary;
033import com.microsoft.azure.storage.blob.BlobOutputStream;
034
035/**
036 * azure用のクラウドストレージ操作実装
037 *
038 * システムリソースのS3_ACCESS_KEY,S3_SECRET_KEY,S3_SERVICE_END_POINT,S3_REGIONに、AWSのキー情報を登録する必要があります。
039 *
040 * @og.group クラウド
041 * @og.rev  (2018/02/15) 新規作成
042 *
043 * @version 5.0
044 * @author T.OTA
045 * @sinse JDK7.0
046 */
047public class StorageAPI_aws implements StorageAPI {
048        // 認証文字列
049        // アクセスキー
050        private String s3AccessKey = "";
051        // シークレットキー
052        private String s3SecretKey = "";
053        // エンドポイント
054        private String s3ServiceEndPoint = "";
055        // レギオン
056        private String s3Region = "";
057        // バケット名(コンテナ名)
058        String s3bucket = "";
059
060        AmazonS3 client = null;
061
062        /**
063         * コンストラクタ
064         *
065         * @param container
066         * @param hsession
067         */
068        public StorageAPI_aws(String container, HttpSession hsession){
069                // リソースパラメータ設定
070                // アクセスキー
071                s3AccessKey = HybsSystem.sys("CLOUD_STORAGE_S3_ACCESS_KEY");
072                // シークレットキー
073                s3SecretKey = HybsSystem.sys("CLOUD_STORAGE_S3_SECRET_KEY");
074                // エンドポイント
075                s3ServiceEndPoint = HybsSystem.sys("CLOUD_STORAGE_S3_SERVICE_END_POINT");
076                // レギオン
077                s3Region = HybsSystem.sys("CLOUD_STORAGE_S3_REGION");
078        // コンテナ名をs3bucketとして保持しておく
079        s3bucket = container;
080
081                // 初期チェック
082                initCheck();
083
084        // AWSの認証情報
085        AWSCredentials credentials = new BasicAWSCredentials(s3AccessKey, s3SecretKey);
086
087        // エンドポイント設定
088        EndpointConfiguration endpointConfiguration = new EndpointConfiguration(s3ServiceEndPoint,  s3Region);
089
090        // S3アクセスクライアントの生成
091        client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials))
092                        .withEndpointConfiguration(endpointConfiguration).build();
093
094        // S3に指定されたバケット(コンテナ)が存在しない場合は、作成する
095        if(!client.doesBucketExist(container)){
096                client.createBucket(container);
097        }
098        }
099
100        /**
101         * 初期チェック
102         */
103        private void initCheck(){
104                // システムリソースに認証情報が登録されていない場合は、エラー
105                StringBuilder errString = new StringBuilder();
106                if(StringUtils.isEmpty(s3AccessKey)){
107                        errString.append("CLOUD_STORAGE_S3_ACCESS_KEY");
108                }
109                if(StringUtils.isEmpty(s3SecretKey)){
110                        errString.append(",CLOUD_STORAGE_S3_SECRET_KEY");
111                }
112                if(StringUtils.isEmpty(s3ServiceEndPoint)){
113                        errString.append(",CLOUD_STORAGE_S3_SERVICE_END_POINT");
114                }
115                if(StringUtils.isEmpty(s3Region)){
116                        errString.append(",CLOUD_STORAGE_S3_REGION");
117                }
118
119                if(errString.length() > 0){
120                        throw new HybsSystemException("AWSのキー情報("+errString.toString()+")がシステムリソースに登録されていません。");
121                }
122
123        }
124
125        /**
126         * アップロード
127         *
128         * @param partInputStream       アップロード対象のストリーム
129         * @param updFolder             アップロードフォルタ名
130         * @param updFileName           アップロードファイル名
131         * @param hsession                      セッション
132         */
133        @Override
134        public void add(InputStream partInputStream, String updFolder, String updFileName, HttpSession hsession) {
135                BlobOutputStream blobOutputStream = null;
136                try {
137                        // アップロード処理
138                        ObjectMetadata om = new ObjectMetadata();
139                        final PutObjectRequest putRequest = new PutObjectRequest(s3bucket, updFolder + updFileName, partInputStream,om);
140                        // アップロード実行
141                        client.putObject(putRequest);
142
143                } catch (Exception e) {
144                        StringBuilder sbErrMsg = new StringBuilder();
145                        sbErrMsg.append("ストレージへのファイルアップロードに失敗しました。updFolder:");
146                        sbErrMsg.append(updFolder);
147                        sbErrMsg.append(" updFileName:");
148                        sbErrMsg.append(updFileName);
149                        sbErrMsg.append(" errInfo:");
150                        sbErrMsg.append(e);
151                        throw new HybsSystemException(sbErrMsg.toString());
152                } finally {
153                        // クローズ処理
154                        Closer.ioClose(blobOutputStream);
155                        Closer.ioClose(partInputStream);
156                }
157        }
158
159        /**
160         * ダウンロード
161         *
162         * @param filePath      ダウンロード対象のファイルパス
163         * @param hsession      セッション
164         * @return ストリーム
165         */
166        @Override
167        public InputStream get(String filePath, HttpSession hsession) {
168                InputStream is = null;
169                // ダウンロード
170                try {
171                        S3Object object = client.getObject(s3bucket, filePath);
172
173                        is = object.getObjectContent();
174                } catch (Exception e) {
175                        StringBuilder sbErrMsg = new StringBuilder();
176                        sbErrMsg.append("ストレージからのファイルダウンロードに失敗しました。filePath:");
177                        sbErrMsg.append(filePath);
178                        sbErrMsg.append(" errInfo:");
179                        sbErrMsg.append(e);
180                        throw new HybsSystemException(sbErrMsg.toString());
181                }
182
183                return is;
184        }
185
186        /**
187         * コピー
188         *
189         * @param oldFilePath   コピー元ファイルパス
190         * @param newFilePath   コピー先ファイルパス
191         * @param hsession              セッション
192         */
193        @Override
194        public void copy(String oldFilePath, String newFilePath, HttpSession hsession) {
195                try {
196                        final CopyObjectRequest copyRequest = new CopyObjectRequest(s3bucket, oldFilePath, s3bucket, newFilePath);
197                        client.copyObject(copyRequest);
198                } catch (Exception e) {
199                        StringBuilder sbErrMsg = new StringBuilder();
200                        sbErrMsg.append("ストレージのファイルコピー処理に失敗しました。oldFilePath:");
201                        sbErrMsg.append(oldFilePath);
202                        sbErrMsg.append(" newFilePath:");
203                        sbErrMsg.append(newFilePath);
204                        sbErrMsg.append(" errInfo:");
205                        sbErrMsg.append(e);
206                        throw new HybsSystemException(sbErrMsg.toString());
207                }
208        }
209
210        /**
211         * 削除
212         *
213         * @param filePath      削除ファイルのパス
214         * @param hsession      セッション
215         */
216        @Override
217        public void delete(String filePath, HttpSession hsession) {
218                // 削除
219                try {
220                        final DeleteObjectRequest deleteRequest = new DeleteObjectRequest(s3bucket, filePath);
221                        client.deleteObject(deleteRequest);
222                        client.deleteObject(s3bucket, filePath);
223                } catch (Exception e) {
224                        StringBuilder sbErrMsg = new StringBuilder();
225                        sbErrMsg.append("ストレージのファイル削除に失敗しました。filePath:");
226                        sbErrMsg.append(filePath);
227                        sbErrMsg.append(" errInfo:");
228                        sbErrMsg.append(e);
229                        throw new HybsSystemException(sbErrMsg.toString());
230                }
231        }
232
233        /**
234         * ファイル名変更
235         *
236         * @param filePath              ファイルパス
237         * @param oldFileName   変更前ファイル名
238         * @param newFileName   変更後ファイル名
239         * @param useBackup     変更後ファイル名が既に存在する場合のバックアップ作成フラグ
240         * @param hsession              セッション
241         */
242        public void rename(String filePath, String oldFileName, String newFileName, final boolean useBackup,
243                        HttpSession hsession) {
244                String newFilePath = filePath + newFileName;
245                String oldFilePath = filePath + oldFileName;
246
247                // 変更先のファイルが存在した場合の処理
248                if (exists(newFilePath, hsession)) {
249                        // バックアップ作成する場合
250                        if (useBackup) {
251                                // バックアップファイル名は、元のファイル名(拡張子含む) + "_" + 現在時刻のlong値 + "." +
252                                // 元のファイルの拡張子
253                                String bkupPath = filePath + "_backup/" + newFileName + "_" + System.currentTimeMillis()
254                                                + FileUtil.EXTENSION_SEPARATOR + FileUtil.getExtension(newFileName);
255                                // バックアップフォルダに移動
256                                copy(newFilePath, bkupPath, hsession);
257                        }
258                }
259
260                // コピー
261                copy(oldFilePath, newFilePath, hsession);
262                // 削除
263                delete(oldFilePath, hsession);
264        }
265
266        /**
267         * ファイル存在チェック
268         *
269         * @param filePath                      ファイルパス
270         * @param hsession              セッション
271         * @return                              true:存在 false:存在しない
272         */
273//      @Override
274        public boolean exists(String filePath, HttpSession hsession) {
275                boolean blnRtn = true;
276                try {
277                        if (!client.doesObjectExist(s3bucket, filePath)) {
278                                // ファイルが取得できなかった場合は、falseを設定
279                                blnRtn = false;
280                        }
281                } catch (Exception e) {
282                        StringBuilder sbErrMsg = new StringBuilder();
283                        sbErrMsg.append("ストレージのファイル取得に失敗しました。filePath:");
284                        sbErrMsg.append(filePath);
285                        sbErrMsg.append(" errInfo:");
286                        sbErrMsg.append(e);
287                        throw new HybsSystemException(sbErrMsg.toString());
288                }
289
290                return blnRtn;
291        }
292
293        /**
294         * ファイル一覧取得
295         *
296         * @param startsWith    パスの前方一致
297         * @param hsession              セッション
298         * @return                              ファイルパス一覧
299         */
300        @Override
301        public String[] list(String startsWith, HttpSession hsession) {
302                // 認証
303                List<String> rtnList = new ArrayList<String>();
304                try{
305                        ListObjectsV2Request request = new ListObjectsV2Request()
306                                        .withBucketName(s3bucket)
307                                        .withPrefix(startsWith);
308                        ListObjectsV2Result list = client.listObjectsV2(request);
309                        List<S3ObjectSummary> objects =  list.getObjectSummaries();
310                        // 一覧の取得
311                        for(S3ObjectSummary obj: objects){
312                                // 名称を格納
313                                rtnList.add(obj.getKey());
314                        }
315                } catch (Exception e){
316                        StringBuilder sbErrMsg = new StringBuilder();
317                        sbErrMsg.append("ファイル一覧の取得に失敗しました。startsWith:");
318                        sbErrMsg.append(startsWith);
319                        sbErrMsg.append(" errInfo:");
320                        sbErrMsg.append("e");
321                        throw new HybsSystemException(sbErrMsg.toString());
322                }
323                return rtnList.toArray(new String[rtnList.size()]);
324        }
325
326        /**
327         * ファイル情報取得
328         *
329         * @param path                  ファイルパス
330         * @param hsession              セッション
331         * @return                              ファイル情報格納Map
332         */
333//      @Override
334        public Map<String, String> getInfo(String path, HttpSession hsession) {
335                Map<String, String> rtnMap = new HashMap<String,String>();
336
337                ObjectMetadata meta = null;
338                try{
339                        // ファイルオブジェクトの取得
340                        meta = client.getObjectMetadata(s3bucket, path);
341                }catch(Exception e){
342                        StringBuilder sbErrMsg = new StringBuilder();
343                        sbErrMsg.append("ファイルの取得に失敗しました。path:");
344                        sbErrMsg.append(path);
345                        sbErrMsg.append(" errInfo:");
346                        sbErrMsg.append(e);
347                        throw new HybsSystemException(sbErrMsg.toString());
348                }
349                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
350
351                // ファイルサイズ
352                rtnMap.put(FILEINFO_SIZE, String.valueOf(meta.getContentLength()));
353                // 最終更新時刻
354                rtnMap.put(FILEINFO_LASTMODIFIED, sdf.format(meta.getLastModified()));
355
356                return rtnMap;
357        }
358}