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