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}