    001package org.opengion.plugin.cloud;
    002
    003import java.io.ByteArrayInputStream;
    004import java.io.File;
    005import java.io.FileFilter;
    006import java.io.FileNotFoundException;
    007import java.io.IOException;
    008import java.io.InputStream;
    009import java.util.ArrayList;
    010import java.util.List;
    011
    012import org.opengion.fukurou.model.CloudFileOperation;
    013import org.opengion.fukurou.model.FileOperation;
    014import org.opengion.fukurou.model.FileOperationInfo;
    015import org.opengion.fukurou.util.StringUtil;
    016import org.opengion.hayabusa.common.HybsSystem;
    017import org.opengion.hayabusa.common.HybsSystemException;
    018
    019import com.microsoft.azure.storage.CloudStorageAccount;
    020import com.microsoft.azure.storage.blob.CloudBlob;
    021import com.microsoft.azure.storage.blob.CloudBlobClient;
    022import com.microsoft.azure.storage.blob.CloudBlobContainer;
    023import com.microsoft.azure.storage.blob.CloudBlobDirectory;
    024import com.microsoft.azure.storage.blob.CloudBlockBlob;
    025import com.microsoft.azure.storage.blob.ListBlobItem;
    026
    027/**
    028 * FileOperation_AZURE.javaは、Azureのストレージに対して、
    029 * ファイル操作を行うクラスです。
    030 *
    031 * @og.rev 5.10.8.0 (2019/02/01) 新規作成
    032 *
    033 * @version 5
    034 * @author  oota
    035 * @since   JDK7.0
    036 */
    037public class FileOperation_AZURE extends CloudFileOperation {
    038        /** クラス変数 */
    039        private final CloudBlobContainer azureContainer;
    040        private final String PLUGIN = "azure";
    041
    042        /**
    043         * コンストラクター
    044         *
    045         * 初期化処理です。
    046         * Azureの認証処理を行います。
    047         *
    048         * @param bucket バケット
    049         * @param inPath パス
    050         */
    051        public FileOperation_AZURE(String bucket, String inPath) {
    052                super( StringUtil.nval( bucket, HybsSystem.sys("CLOUD_BUCKET") ), inPath);
    053                setPlugin(PLUGIN);
    054
    055                String storageConnectionString = HybsSystem.sys("CLOUD_STORAGE_AZURE_KEY");
    056
    057                if (StringUtil.isNull(storageConnectionString)) {
    058                        String errMsg = "Azure用認証キー(CLOUD_STORAGE_AZURE_KEY)がシステムリソースに登録されていません。";
    059                        throw new HybsSystemException(errMsg);
    060                }
    061
    062                try {
    063                        CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString);
    064                        CloudBlobClient serviceClient = account.createCloudBlobClient();
    065                        azureContainer = serviceClient.getContainerReference(conBucket);
    066                        // コンテナが存在しない場合は作成する
    067                        azureContainer.createIfNotExists();
    068                } catch (Exception e) {
    069                        StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_MIDDLE);
    070                        errMsg.append("コンテナの作成に失敗しました。container：").append(conBucket);
    071                        errMsg.append(" システムエラー情報：").append(e.getMessage());
    072                        throw new HybsSystemException(errMsg.toString());
    073                }
    074        }
    075
    076        /**
    077         * 書き込み処理
    078         *
    079         * InputStreamのデータを書き込みます。
    080         *
    081         * @param is 書き込みデータのInputStream
    082         * @throws IOException ファイル関連エラー情報
    083         */
    084        @Override
    085        public void write(InputStream is) throws IOException {
    086                try {
    087                        CloudBlockBlob blob = azureContainer.getBlockBlobReference(conPath);
    088                        byte[] bytes = toByteArray(is);
    089                        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    090
    091                        blob.upload(bais, bytes.length);
    092                } catch (Exception e) {
    093                        StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_MIDDLE);
    094                        errMsg.append("Azureストレージに書き込みが失敗しました。path：").append(conPath);
    095                        errMsg.append(" システムエラー情報：").append(e.getMessage());
    096                        throw new IOException(errMsg.toString());
    097                }
    098        }
    099
    100        /**
    101         * 読み込み処理
    102         *
    103         * データを読み込み、InputStreamとして、返します。
    104         *
    105         * @return 読み込みデータのInputStream
    106         * @throws FileNotFoundException ファイル非存在エラー情報
    107         */
    108        @Override
    109        public InputStream read() throws FileNotFoundException {
    110                CloudBlockBlob blob;
    111                InputStream is;
    112                try {
    113                        blob = azureContainer.getBlockBlobReference(conPath);
    114                        is = blob.openInputStream();
    115                } catch (Exception e) {
    116                        StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_MIDDLE);
    117                        errMsg.append("Azureストレージから読み込みが失敗しました。path：").append(conPath);
    118                        errMsg.append(" システムエラー情報：").append(e.getMessage());
    119                        throw new FileNotFoundException(errMsg.toString());
    120                }
    121                return is;
    122        }
    123
    124        /**
    125         * 削除処理
    126         *
    127         * ファイルを削除します。
    128         *
    129         * @return 成否フラグ
    130         */
    131        @Override
    132        public boolean delete() {
    133                boolean flgRtn = false;
    134
    135                try {
    136                        azureContainer.getBlockBlobReference(conPath).delete();
    137                        flgRtn = true;
    138                } catch (Exception e) {
    139                        // エラーはスルーして、falseを返す
    140                }
    141
    142                return flgRtn;
    143        }
    144
    145        /**
    146         * コピー処理
    147         *
    148         * ファイルを指定先に、コピーします。
    149         *
    150         * @param afPath コピー先
    151         * @return 成否フラグ
    152         */
    153        @Override
    154        public boolean copy(String afPath) {
    155                boolean flgRtn = false;
    156
    157                try {
    158                        CloudBlockBlob copyTrg = azureContainer.getBlockBlobReference(conPath);
    159                        CloudBlockBlob copySaki = azureContainer.getBlockBlobReference(afPath);
    160
    161                        copySaki.startCopy(copyTrg);
    162                        flgRtn = true;
    163                } catch (Exception e) {
    164                        // エラーはスルーして、falseを返す
    165                }
    166
    167                return flgRtn;
    168        }
    169
    170        /**
    171         * ファイルサイズ取得
    172         *
    173         * ファイルサイズを返します。
    174         *
    175         * @return ファイルサイズ
    176         */
    177        @Override
    178        public long length() {
    179                long rtn = 0;
    180
    181                try {
    182                        CloudBlob blob = azureContainer.getBlockBlobReference(conPath);
    183                        rtn = blob.getProperties().getLength();
    184                } catch (Exception e) {
    185                        // スルーして、0を返す
    186                }
    187                return rtn;
    188        }
    189
    190        /**
    191         * 最終更新時刻取得
    192         *
    193         * 最終更新時刻を取得します。
    194         *
    195         * @return 最終更新時刻
    196         */
    197        @Override
    198        public long lastModified() {
    199                long rtn = 0;
    200
    201                try {
    202                        CloudBlob blob = azureContainer.getBlockBlobReference(conPath);
    203                        rtn = blob.getProperties().getLastModified().getTime();
    204                } catch (Exception e) {
    205                        // スルーして、0を返す
    206                }
    207
    208                return rtn;
    209        }
    210
    211        /**
    212         * ファイル判定
    213         *
    214         * ファイルの場合は、trueを返します。
    215         *
    216         * @return ファイルフラグ
    217         */
    218        @Override
    219        public boolean isFile() {
    220                boolean blnRtn = false;
    221
    222                try {
    223                        CloudBlockBlob blob = azureContainer.getBlockBlobReference(conPath);
    224
    225                        if (blob.exists()) {
    226                                blnRtn = true;
    227                        }
    228                } catch (Exception e) {
    229                        // ここのエラーはスルーして、falseを返す
    230                }
    231
    232                return blnRtn;
    233        }
    234
    235        /**
    236         * ディレクトリ判定
    237         *
    238         * ディレクトリの場合は、trueを返します。
    239         *
    240         * @return ディレクトリフラグ
    241         */
    242        @Override
    243        public boolean isDirectory() {
    244                boolean blnRtn = false;
    245
    246                // 後尾に「/」をつけないこと
    247                for (ListBlobItem item : azureContainer.listBlobs(rTrim(conPath, '/'))) {
    248                        if (item instanceof CloudBlobDirectory) {
    249                                blnRtn = true;
    250                                break;
    251                        }
    252                }
    253
    254                return blnRtn;
    255        }
    256
    257        /**
    258         * ファイル一覧取得
    259         *
    260         * パスのファイルとディレクトリ一覧を取得します。
    261         *
    262         * @param filter フィルター情報
    263         * @return ファイルとティレクトリ一覧
    264         */
    265        @Override
    266        public File[] listFiles(FileFilter filter) {
    267                if (!exists()) {
    268                        return new FileOperationInfo[0];
    269                }
    270
    271                String search = conPath;
    272                if (isDirectory()) {
    273                        search = setDirTail(conPath);
    274                }
    275
    276                List<File> rtnList = new ArrayList<File>();
    277
    278                for (ListBlobItem item : azureContainer.listBlobs(search)) {
    279                        if (item instanceof CloudBlob) {
    280                                // ファイルの情報を設定
    281                                CloudBlob blob = (CloudBlob) item;
    282                                FileOperationInfo fi = new FileOperationInfo(PLUGIN, conBucket, blob.getName());
    283                                fi.setLastModifiedValue(blob.getProperties().getLastModified().getTime());
    284                                fi.setSize(blob.getProperties().getLength());
    285                                fi.setFile(true);
    286                                rtnList.add(fi);
    287                        } else if (item instanceof CloudBlobDirectory) {
    288                                // ディレクトリの情報を設定
    289                                CloudBlobDirectory directory = (CloudBlobDirectory) item;
    290                                final String key = rTrim(directory.getPrefix(), '/');
    291                                FileOperationInfo fi = new FileOperationInfo(PLUGIN, conBucket, key);
    292                                fi.setDirectory(true);
    293                                rtnList.add(fi);
    294                        }
    295                }
    296
    297                File[] filterList = filter(rtnList, filter);
    298
    299                return filterList;
    300        }
    301
    302        /**
    303         * 親ディレクトリ取得
    304         *
    305         * 親のディレクトリを返します。
    306         *
    307         * @return 親のディレクトリ
    308         */
    309        @Override
    310        public FileOperation getParentFile() {
    311                return new FileOperation_AZURE(conBucket,getParent());
    312        }
    313
    314                /** 以下はローカル環境でのテスト用メソッドです。 */
    315//              /**
    316//               * ローカルでのテスト用コンストラクタ
    317//               *
    318//               * 要：super.bucketの値は固定値に変更してください。
    319//               *
    320//               * @param inPath
    321//               */
    322//              public FileOperation_AZURE(String bucket, String inPath, boolean test) {
    323//                      // super( StringUtil.nval( bucket, HybsSystem.sys("CLOUD_BUCKET") ), inPath);
    324//                      super( StringUtil.nval( bucket, "opengiontestbucket" ), inPath);
    325//                      conBucket = bucket;
    326//
    327//                      // ローカル環境で実行する場合の、proxy設定
    328//                      System.setProperty("https.proxyHost","mtc-px14");
    329//                      System.setProperty("https.proxyPort","8081");
    330//
    331//                      String storageConnectionString = "[接続文字列]";
    332//
    333//                      if (StringUtil.isNull(storageConnectionString)) {
    334//                              String errMsg = "Azure用認証キー(CLOUD_STORAGE_AZURE_KEY)がシステムリソースに登録されていません。";
    335//                              throw new HybsSystemException(errMsg);
    336//                      }
    337//
    338//                      try {
    339//                              CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString);
    340//                              CloudBlobClient serviceClient = account.createCloudBlobClient();
    341//                              azureContainer = serviceClient.getContainerReference(bucket);
    342//                              // コンテナが存在しない場合は作成する
    343//                              azureContainer.createIfNotExists();
    344//                      } catch (Exception e) {
    345//                              StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_MIDDLE);
    346//                              errMsg.append("コンテナの作成に失敗しました。container：").append(bucket);
    347//                              errMsg.append(" システムエラー情報：").append(e.getMessage());
    348//                              throw new HybsSystemException(errMsg.toString());
    349//                      }
    350//              }
    351//
    352//              /** テスト用メソッド */
    353//              public static void main(String[] args) {
    354//      //              writeTest();
    355//      //              listTest();
    356//      //              methodTest();
    357//              }
    358//
    359//              public static void writeTest() {
    360//                      FileOperation file = new FileOperation_AZURE("", "sample/test.txt", true);
    361//
    362//                      try (InputStream is = new ByteArrayInputStream("sample".getBytes())) {
    363//                              file.write(is);
    364//                      } catch (Exception e) {
    365//                              System.out.println(e.getMessage());
    366//                      }
    367//              }
    368//
    369//              public static void listTest() {
    370//                      FileOperation file = new FileOperation_AZURE("", "sample", true);
    371//
    372//                      FileOperation[] list = file.listFiles();
    373//                      System.out.println(list.length);
    374//                      for (FileOperation f : list) {
    375//                              System.out.println(f.getPath());
    376//                      }
    377//              }
    378//
    379//              public static void methodTest() {
    380//                      FileOperation file = new FileOperation_AZURE("", "test", true);
    381//                      boolean rtn = false;
    382//                      rtn = file.isFile();
    383//
    384//                      System.out.println(rtn);
    385//              }
    386}