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}