001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.report;
017
018import org.opengion.hayabusa.common.HybsSystem;
019
020import static org.opengion.fukurou.system.HybsConst.CR ;                        // 6.1.0.0 (2014/12/26)
021import org.opengion.fukurou.util.StringUtil;
022import org.opengion.fukurou.system.ThrowUtil ;                                  // 6.4.2.0 (2016/01/29)
023import org.opengion.fukurou.mail.MailReceiveListener ;
024import org.opengion.fukurou.mail.MailTX ;
025import org.opengion.fukurou.mail.MailMessage ;
026import org.opengion.fukurou.mail.MailAttachFiles ;
027
028import java.util.Date;
029
030/**
031 * MailReceiveListener の実装クラスです。
032 * MailRX クラスにセットすることで、メール1件ごとに receive( MailMessage ) メソッドが
033 * 呼び出されます。
034 * メール1件に、添付ファイルが複数登録されている場合の処理を行っています。
035 * 添付ファイルごとに要求番号を採番して、要求番号.xls としてセーブし、帳票要求テーブルに
036 * 書き込みます。
037 *
038 * @og.rev 3.8.0.0 (2005/06/07) 新規追加
039 * @og.group 帳票システム
040 *
041 * @version  4.0
042 * @author   Kazuhiko Hasegawa
043 * @since    JDK5.0,
044 */
045public class ExcelInsertReceiveListener implements MailReceiveListener {
046
047        // EXCEL取込時に使用するテンポラリフォルダ名。ファイル名は、要求番号.xls
048        private final String EXCELIN_URL =
049                HybsSystem.url2dir( StringUtil.nval(
050                                                                HybsSystem.sys( "EXCEL_IN_FILE_URL" ) ,
051                                                                HybsSystem.sys( "FILE_URL"   ) + "EXCELIN/" ) ) ;
052
053        private GE50Access ge50 ;
054
055        /**
056         * デフォルトコンストラクター
057         *
058         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
059         */
060        public ExcelInsertReceiveListener() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
061
062        /**
063         * メール受信処理で、1メール受信ごとに呼び出されます。
064         * 処理結果を、boolean で返します。
065         *
066         * @og.rev 6.4.2.0 (2016/01/29) StringUtil#stringStackTrace(Throwable) を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
067         *
068         * @param message MailMessageオブジェクト
069         *
070         * @return      処理結果(正常:true / 異常:false)
071         */
072        public boolean receive( final MailMessage message ) {
073                System.out.println();
074                System.out.println( "Receive " + new Date() );
075
076                String errMsg ;
077                boolean okFlag = false;
078
079                // 毎回 オブジェクトを構築します。登録日付が初期化されます。
080                ge50 = new GE50Access( "CXXXXX","M_RECEIVE","ExcelInsert" );
081
082                try {
083                        final String content    = message.getContent();
084
085                        final String systemId = getContentParam( content,"SYSTEM_ID" );
086                        if( systemId == null ) {
087                                errMsg = "メール本文に SYSTEM_ID=[xx] のキーワードが存在しません。" ;
088                                errorReport( message,errMsg ) ;
089                                return okFlag;
090                        }
091
092                        final String from               = message.getHeader( "From" );                  // 6.4.1.1 (2016/01/16) PMD refactoring.
093                        System.out.println( " From:" + from );
094                        String joken = getContentParam( content,"JOKEN" );
095                        if( joken == null ) { joken = "EXCELIN"; }
096
097                        ge50.setSystemId( systemId );
098                        ge50.setJoken   ( joken );
099                        final String subject    = message.getSubject();                                 // 6.4.1.1 (2016/01/16) PMD refactoring.
100                        final String msgid              = message.getMessageID();                               // 6.4.1.1 (2016/01/16) PMD refactoring.
101                        ge50.setComments( from + " " + subject + " " + msgid );                 // 6.1.0.0 (2014/12/26) refactoring
102
103                        final MailAttachFiles attFiles = new MailAttachFiles( message.getMessage() );
104                        final String[] files = attFiles.getNames();
105                        if( files == null || files.length == 0 ) {
106                                errMsg = "メールに EXCEL 添付ファイルが存在しません。" ;
107                                errorReport( message,errMsg ) ;
108                                return okFlag;
109                        }
110
111                        // 添付ファイルの数だけ処理します。
112                        for( int i=0; i<files.length; i++ ) {
113                                final String attFile = files[i];
114
115                                // LISTID を取得します。 EXCELファイル名に(帳票ID)を入れます。
116                                final int st = attFile.indexOf( '(' );
117                                final int ed = attFile.indexOf( ')',st );
118                                if( st < 0 || ed < 0 ) {
119                                        errMsg = "EXCEL 添付ファイルに(帳票ID)が存在しません。[" + attFile + "]" ;
120                                        errorReport( message,errMsg ) ;
121                                        return okFlag;
122                                }
123
124                                final String listId  = attFile.substring( st+1,ed );
125                                if( listId.isEmpty() ) {
126                                        errMsg = "EXCEL 添付ファイルの(帳票ID)を切り出せません。[" + attFile + "]" ;
127                                        errorReport( message,errMsg ) ;
128                                        return okFlag;
129                                }
130
131                                final String fileDir = EXCELIN_URL + systemId + "/" + listId + "/" ;
132                                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point.
133                                final String ykno    = ge50.makeYkno();         // 新たな要求番号が内部にもセットされる。
134                                final String file    = ykno + ".xls" ;
135
136                                attFiles.saveFileName( fileDir,file,i );
137
138                                ge50.setListId( listId );
139                                ge50.setOutDir( fileDir );
140                                ge50.setOutFile( files[i] );
141
142                                ge50.insertGE50( GE50Access.FG_SET );
143
144                                System.out.println( attFile + " -> " + file );
145                        }
146                        System.out.println( " End." );
147                        okFlag = true;
148                }
149                catch( final Throwable ex ) {
150                        errMsg = ThrowUtil.ogStackTrace( ex );                          // 6.4.2.0 (2016/01/29)
151                        errorReport( message,errMsg ) ;
152                        okFlag = false;
153                }
154                return okFlag;
155        }
156
157        /**
158         * メール処理中にエラーが発生した場合の処理を行います。
159         * 処理は、3種類あります。
160         * 1.エラーメールを、EXCELIN_URL/ERROR_MAIL フォルダに、メッセージID.txt で保存します。
161         * 2.COMMON_MAIL_SERVER と ERROR_MAIL_TO_USERS が設定されている場合に、
162         *     そのあて先に、返信メールを送信します。
163         * 3.GE50(帳票要求テーブル)と、GE51(帳票エラーテーブル)にエラー状況を書き込みます。
164         *
165         * @param message MailMessageオブジェクト
166         * @param errorMessage エラーメッセージ
167         */
168        private void errorReport( final MailMessage message,final String errorMessage ) {
169                // エラーメールを 所定のディレクトリに出力します。
170                message.saveSimpleMessage( EXCELIN_URL + "/ERROR_MAIL/" );
171
172                final String subject            = "EXCEL取込メール受信中にエラーが発生しました。";
173                final String org_from           = message.getHeader( "From" ) ;
174                final String ord_subject        = message.getSubject();
175                final String content            = message.getContent();
176                final String errMsg = subject + CR
177                                        + " Subject=" + ord_subject + " From=" + org_from + CR
178                                        + " MessageID=" + message.getMessageID() + CR
179                                        + " Save ErrorMail=" + EXCELIN_URL + "/ERROR_MAIL/" + CR
180                                        + errorMessage + CR
181                                        + "==========================================================="
182                                        + CR
183                                        + content ;
184
185                if( ge50 != null ) {
186                        final String systemId = ge50.getSystemId() ;
187                        if( systemId == null ) { ge50.setSystemId( "ERR" ); }
188
189                        // エラー時の要求番号は、新たに採番しなおします。
190                        ge50.makeYkno();
191
192                        ge50.insertGE50( GE50Access.FG_ERR2 );
193                        ge50.insertErrorGE56( errMsg );
194                }
195
196                // host と user のメール送信先が記述されている場合は、メールでも転送する。
197                final String   host = message.getHost();
198                final String   from = message.getUser();
199
200                if( host != null && from != null ) {
201                        final String[] to               = new String[] { org_from };
202                        final String[] cc = StringUtil.csv2Array( HybsSystem.sys( "ERROR_MAIL_TO_USERS" ) );
203
204                        final MailTX tx = new MailTX( host );
205                        tx.setFrom( from );
206                        tx.setTo( to );
207                        if( cc.length > 0 ) { tx.setCc( cc ); }
208                        tx.setSubject( subject );
209                        tx.setMessage( errMsg );
210                        tx.sendmail();
211                }
212        }
213
214        /**
215         * メッセージ本文より、指定のキーに関連付けられている情報を切り出します。
216         * これは、指定の文字列=[設定値] というキーワードから、設定値を取り出します。
217         * 指定の文字列と=のと間に、スペースを入れないでください。
218         * 設定値の切り出しは、"指定の文字列=[" と "]" の間の文字列を切り出します。
219         * 内部にスペースが入っていても、問題ありません。ただし、] が入っている場合は、
220         * 正常に切り出すことは出来ませんし、エスケープ文字も用意していません。
221         *
222         * @param       content コンテンツの文字列
223         * @param       key     情報を切り出す時のキー
224         *
225         * @return      設定値 (設定値が見つからない場合:null
226         */
227        private String getContentParam( final String content,final String key ) {
228                if( content == null || key == null ) { return null; }
229
230                final String newKey = key + "=[" ;
231
232                // キーの存在チェックと場所を求める。
233                final int keyAd = content.indexOf( newKey );
234                if( keyAd >= 0 ) {
235                        // [設定値] の終了場所を求める。(見つけた位置+文字列数)
236                        final int st = keyAd + newKey.length() ;
237                        final int ed = content.indexOf( ']' , st );
238                        if( ed >= 0 ) {
239                                return content.substring( st,ed );
240                        }
241                }
242                return null;
243        }
244}