    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 クラスにセットすることで、メール１件ごとに receive( MailMessage ) メソッドが
    033 * 呼び出されます。
    034 * メール１件に、添付ファイルが複数登録されている場合の処理を行っています。
    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         * メール受信処理で、１メール受信ごとに呼び出されます。
    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         * 処理は、３種類あります。
    160         * １．エラーメールを、EXCELIN_URL/ERROR_MAIL フォルダに、メッセージID.txt で保存します。
    161         * ２．COMMON_MAIL_SERVER と ERROR_MAIL_TO_USERS が設定されている場合に、
    162         *     そのあて先に、返信メールを送信します。
    163         * ３．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}