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