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;
019import org.opengion.fukurou.util.StringUtil;
020
021import org.opengion.fukurou.mail.MailReceiveListener ;
022import org.opengion.fukurou.mail.MailTX ;
023import org.opengion.fukurou.mail.MailMessage ;
024import org.opengion.fukurou.mail.MailAttachFiles ;
025
026import java.util.Date;
027
028/**
029 * MailReceiveListener の実装クラスです。
030 * MailRX クラスにセットすることで、メール1件ごとに receive( MailMessage ) メソッドが
031 * 呼び出されます。
032 * メール1件に、添付ファイルが複数登録されている場合の処理を行っています。
033 * 添付ファイルごとに要求番号を採番して、要求番号.xls としてセーブし、帳票要求テーブルに
034 * 書き込みます。
035 *
036 * @og.rev 3.8.0.0 (2005/06/07) 新規追加
037 * @og.group 帳票システム
038 *
039 * @version  4.0
040 * @author   Kazuhiko Hasegawa
041 * @since    JDK5.0,
042 */
043public class ExcelInsertReceiveListener implements MailReceiveListener {
044
045        // EXCEL取込時に使用するテンポラリフォルダ名。ファイル名は、要求番号.xls
046        private final String EXCELIN_URL =
047                HybsSystem.url2dir( StringUtil.nval(
048                                                                HybsSystem.sys( "EXCEL_IN_FILE_URL" ) ,
049                                                                HybsSystem.sys( "FILE_URL"   ) + "EXCELIN/" ) ) ;
050
051        private GE50Access ge50 = null;
052
053        /**
054         * メール受信処理で、1メール受信ごとに呼び出されます。
055         * 処理結果を、boolean で返します。
056         *
057         * @param message MailMessageオブジェクト
058         *
059         * @return      処理結果(正常:true / 異常:false)
060         */
061        public boolean receive( final MailMessage message ) {
062                System.out.println();
063                System.out.println( "Receive " + new Date() );
064
065                String errMsg ;
066                boolean okFlag = false;
067
068                // 毎回 オブジェクトを構築します。登録日付が初期化されます。
069                ge50 = new GE50Access( "CXXXXX","M_RECEIVE","ExcelInsert" );
070
071                try {
072                        String from             = message.getHeader( "From" );
073                        String subject  = message.getSubject();
074                        String content  = message.getContent();
075                        String msgid    = message.getMessageID();
076                        String comments = from + " " + subject + " " + msgid ;
077
078                        String systemId = getContentParam( content,"SYSTEM_ID" );
079                        if( systemId == null ) {
080                                errMsg = "メール本文に SYSTEM_ID=[xx] のキーワードが存在しません。" ;
081                                errorReport( message,errMsg ) ;
082                                return okFlag;
083                        }
084
085                        System.out.println( " From:" + from );
086                        String joken = getContentParam( content,"JOKEN" );
087                        if( joken == null ) { joken = "EXCELIN"; }
088
089                        ge50.setSystemId( systemId );
090                        ge50.setJoken   ( joken );
091                        ge50.setComments( comments );
092
093                        MailAttachFiles attFiles = new MailAttachFiles( message.getMessage() );
094                        String[] files = attFiles.getNames();
095                        if( files == null || files.length == 0 ) {
096                                errMsg = "メールに EXCEL 添付ファイルが存在しません。" ;
097                                errorReport( message,errMsg ) ;
098                                return okFlag;
099                        }
100
101                        // 添付ファイルの数だけ処理します。
102                        for( int i=0; i<files.length; i++ ) {
103                                String ykno    = ge50.makeYkno();               // 新たな要求番号が内部にもセットされる。
104                                String file    = ykno + ".xls" ;
105                                String attFile = files[i];
106
107                                // LISTID を取得します。 EXCELファイル名に(帳票ID)を入れます。
108                                int st = attFile.indexOf( '(' );
109                                int ed = attFile.indexOf( ')',st );
110                                if( st < 0 || ed < 0 ) {
111                                        errMsg = "EXCEL 添付ファイルに(帳票ID)が存在しません。[" + attFile + "]" ;
112                                        errorReport( message,errMsg ) ;
113                                        return okFlag;
114                                }
115
116                                String listId  = attFile.substring( st+1,ed );
117                                if( listId.length() == 0 ) {
118                                        errMsg = "EXCEL 添付ファイルの(帳票ID)を切り出せません。[" + attFile + "]" ;
119                                        errorReport( message,errMsg ) ;
120                                        return okFlag;
121                                }
122
123                                String fileDir = EXCELIN_URL + systemId + "/" + listId + "/" ;
124
125                                attFiles.saveFileName( fileDir,file,i );
126
127                                ge50.setListId( listId );
128                                ge50.setOutDir( fileDir );
129                                ge50.setOutFile( files[i] );
130
131                                ge50.insertGE50( GE50Access.FG_SET );
132
133                                System.out.println( attFile + " -> " + file );
134                        }
135                        System.out.println( " End." );
136                        okFlag = true;
137                }
138                catch( Throwable ex ) {
139                        errMsg = StringUtil.stringStackTrace( ex );
140                        errorReport( message,errMsg ) ;
141                        okFlag = false;
142                }
143                return okFlag;
144        }
145
146        /**
147         * メール処理中にエラーが発生した場合の処理を行います。
148         * 処理は、3種類あります。
149         * 1.エラーメールを、EXCELIN_URL/ERROR_MAIL フォルダに、メッセージID.txt で保存します。
150         * 2.COMMON_MAIL_SERVER と ERROR_MAIL_TO_USERS が設定されている場合に、
151         *     そのあて先に、返信メールを送信します。
152         * 3.GE50(帳票要求テーブル)と、GE51(帳票エラーテーブル)にエラー状況を書き込みます。
153         *
154         * @param message MailMessageオブジェクト
155         * @param errorMessage エラーメッセージ
156         */
157        private void errorReport( final MailMessage message,final String errorMessage ) {
158                // エラーメールを 所定のディレクトリに出力します。
159                message.saveSimpleMessage( EXCELIN_URL + "/ERROR_MAIL/" );
160
161                String subject          = "EXCEL取込メール受信中にエラーが発生しました。";
162                String org_from         = message.getHeader( "From" ) ;
163                String ord_subject      = message.getSubject();
164                String content          = message.getContent();
165                String errMsg = subject + HybsSystem.CR
166                                        + " Subject=" + ord_subject + " From=" + org_from + HybsSystem.CR
167                                        + " MessageID=" + message.getMessageID() + HybsSystem.CR
168                                        + " Save ErrorMail=" + EXCELIN_URL + "/ERROR_MAIL/" + HybsSystem.CR
169                                        + errorMessage + HybsSystem.CR
170                                        + "==========================================================="
171                                        + HybsSystem.CR
172                                        + content ;
173
174                if( ge50 != null ) {
175                        String systemId = ge50.getSystemId() ;
176                        if( systemId == null ) { ge50.setSystemId( "ERR" ); }
177
178                        // エラー時の要求番号は、新たに採番しなおします。
179                        ge50.makeYkno();
180
181                        ge50.insertGE50( GE50Access.FG_ERR2 );
182                        ge50.insertErrorGE56( errMsg );
183                }
184
185                // host と user のメール送信先が記述されている場合は、メールでも転送する。
186                String   host = message.getHost();
187                String   from = message.getUser();
188
189                if( host != null && from != null ) {
190                        String[] to             = new String[] { org_from };
191                        String[] cc = StringUtil.csv2Array( HybsSystem.sys( "ERROR_MAIL_TO_USERS" ) );
192
193                        MailTX tx = new MailTX( host );
194                        tx.setFrom( from );
195                        tx.setTo( to );
196                        if( cc.length > 0 ) { tx.setCc( cc ); }
197                        tx.setSubject( subject );
198                        tx.setMessage( errMsg );
199                        tx.sendmail();
200                }
201        }
202
203        /**
204         * メッセージ本文より、指定のキーに関連付けられている情報を切り出します。
205         * これは、指定の文字列=[設定値] というキーワードから、設定値を取り出します。
206         * 指定の文字列と=のと間に、スペースを入れないでください。
207         * 設定値の切り出しは、"指定の文字列=[" と "]" の間の文字列を切り出します。
208         * 内部にスペースが入っていても、問題ありません。ただし、] が入っている場合は、
209         * 正常に切り出すことは出来ませんし、エスケープ文字も用意していません。
210         *
211         * @param       content コンテンツの文字列
212         * @param       key     情報を切り出す時のキー
213         *
214         * @return      設定値 (設定値が見つからない場合:null
215         */
216        private String getContentParam( final String content,final String key ) {
217                if( content == null || key == null ) { return null; }
218
219                String newKey = key + "=[" ;
220
221                // キーの存在チェックと場所を求める。
222                int keyAd = content.indexOf( newKey );
223                if( keyAd >= 0 ) {
224                        // [設定値] の終了場所を求める。(見つけた位置+文字列数)
225                        int st = keyAd + newKey.length() ;
226                        int ed = content.indexOf( ']' , st );
227                        if( ed >= 0 ) {
228                                return content.substring( st,ed );
229                        }
230                }
231                return null;
232        }
233}