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