1    package com.instantbank.component.lettersftpmdb.ejb;
2    
3    import java.io.File;
4    
5    import javax.ejb.MessageDrivenBean;
6    import javax.ejb.EJBException;
7    import javax.ejb.MessageDrivenContext;
8    import javax.jms.Message;
9    import javax.jms.MessageListener;
10   import javax.jms.MapMessage;
11   
12   import com.instantbank.common.utilcomponents.Debug;
13   import com.instantbank.common.utilcomponents.CommonUtil;
14   import com.instantbank.common.utilcomponents.JNDINames;
15   import com.instantbank.common.utilcomponents.LetterTemplateGlobals;
16   import com.instantbank.component.lettertemplate.ejb.LetterTemplate;
17   import com.instantbank.component.lettertemplate.ejb.LetterTemplateHome;
18   import com.instantbank.component.lettertemplate.util.CompanyLocation;
19   
20   import com.enterprisedt.net.ftp.FTPClient;
21   import com.enterprisedt.net.ftp.FTPConnectMode;
22   import com.enterprisedt.net.ftp.FTPTransferType;
23   import com.enterprisedt.net.ftp.FTPException;
24   
25   import javax.naming.InitialContext;
26   
27   /**
28    * Message Driven bean that sends letter zip files by ftp.
29    * See {@link #onMessage(Message)} for message description.
30    *
31    * @author InstantBank (Rodrigo Lopez)
32    * @created October 2002
33    */
34   public class LettersJobFtpMdb
35       implements MessageDrivenBean, MessageListener {
36   
37     /**
38      * The ubiquitous debugger object.
39      */
40     private Debug debug;
41   
42     /**
43      * Number of milliseconds to wait for retry when all locations
44      * have been tried and failed.
45      */
46     public static final long WAIT_RETRY = 3 * 60 * 1000;
47   
48   
49     /**
50      * This method has void body for Message Driven Beans.
51      *
52      * @throws EJBException Description of the Exception
53      */
54     public void ejbRemove() throws EJBException { }
55   
56   
57     /**
58      * Nothing interesting here.
59      *
60      * @param mdc The new messageDrivenContext value
61      * @throws EJBException Description of the Exception
62      */
63     public void setMessageDrivenContext(MessageDrivenContext mdc)
64        throws EJBException { }
65   
66   
67     /**
68      * Initializes the Debug facility.
69      */
70     public void ejbCreate() {
71       debug = new Debug();
72       debug.setDebugginOn(true);
73       debug.setPreMessage("** LetterJobFtpMdb: ");
74   
75     }
76   
77   
78     /**
79      * Sends by ftp a  zip file. Messages are expected to be MapMessages
80      * containing:
81      * <ul>
82      *   <li> CompanyId: Company Id (as a String)
83      *   <li> UserId: User Id (as a Long)
84      *   <li> FilePath: Full path of the file to be sent.
85      *   <li> JobLogId: Id of the job execution that generated the file.
86      *   <li> FtpPrimLoc: Primary location to try sending the file.
87      *   <li> FtpAltLoc: Secondary location to try sending the file.
88      * </ul>
89      *
90      * Information is stored in the LETT_JOB_FTP_LOG table recording whether or
91      * not the file was sent, and a comment in case ftp fails.
92      *
93      * @param jobMsg Description of the Parameter
94      */
95     public void onMessage(Message jobMsg) {
96       MapMessage msg = null;
97   
98       LetterTemplateHome lethome;
99       LetterTemplate letejb;
100  
101      String companyId;
102      Long userId;
103      long ftpPrinLoc;
104      long ftpAltLoc;
105      String filePath;
106      long jobLogId;
107  
108      CompanyLocation[] companyLoc = new CompanyLocation[2];
109  
110      debug.println("Second MDB in the chain");
111      try {
112        //Gets the message
113        if(jobMsg instanceof MapMessage) {
114          msg = (MapMessage)jobMsg;
115          companyId = msg.getString("CompanyId");
116          userId = (Long)msg.getObject("UserId");
117          filePath = msg.getString("FilePath");
118          jobLogId = msg.getLong("JobLogId");
119          ftpPrinLoc = msg.getLong("FtpPrimLoc");
120          ftpAltLoc = msg.getLong("FtpAltLoc");
121        }
122        else {
123          throw new Exception("Only MapMessages are processed");
124        }
125  
126        InitialContext ctx = new InitialContext();
127        lethome = (LetterTemplateHome)ctx.lookup(JNDINames.LETTERTEMPLATE_EJBHOME);
128        letejb = lethome.create(companyId, userId);
129  
130        companyLoc[0] = letejb.loadCompanyLocation(ftpPrinLoc);
131  
132        if(ftpPrinLoc == ftpAltLoc) {
133          companyLoc[1] = companyLoc[0];
134        }
135        else {
136          companyLoc[1] = letejb.loadCompanyLocation(ftpAltLoc);
137        }
138  
139        int locationIndx = 0;
140        int attempts = 1;
141        boolean success = false;
142        FTPClient ftp = null;
143        CompanyLocation location = companyLoc[locationIndx];
144  
145        //Generate zip files, send ftp messages and record log information
146        do {
147          try {
148            ftp = ftpTransfer(location, filePath);
149            success = true;
150            if(attempts == 1) {
151              letejb.storeLetterFtpJobLog(
152                jobLogId, filePath, true, 1,
153                location.getIpAddress(), location.getPath(), "File sent");
154            }
155            else {
156              letejb.updateLetterFtpJobLog(
157                jobLogId, filePath, true, attempts,
158                location.getIpAddress(), location.getPath(), "File sent");
159            }
160            ftp.quit();
161          }
162          catch(FTPException fex) {
163  
164            if(attempts == 1) {
165              letejb.storeLetterFtpJobLog(
166                jobLogId, filePath, false, 1,
167                location.getIpAddress(), location.getPath(), fex.getMessage());
168            }
169            else {
170              letejb.updateLetterFtpJobLog(
171                jobLogId, filePath, false, attempts,
172                location.getIpAddress(), location.getPath(), fex.getMessage());
173            }
174          }
175  
176          locationIndx = (locationIndx + 1) % 2;
177          location = companyLoc[locationIndx];
178          attempts++;
179  
180          //Wait a little bit if all locations have been tried without success
181          if(!success && locationIndx == 0
182            && attempts <= LetterTemplateGlobals.MAX_FTP_TRANSFER_ATTEMPTS) {
183            Thread.sleep(WAIT_RETRY);
184          }
185        }while (!success && attempts <= LetterTemplateGlobals.MAX_FTP_TRANSFER_ATTEMPTS);
186      }
187      catch(Exception ex) {
188        debug.println(CommonUtil.stackTraceToString(ex));
189      }
190      catch(Throwable tex) {
191        debug.println(CommonUtil.stackTraceToString(tex));
192      }
193    }
194  
195  
196    /**
197     * Sends a file to a location's ip address.
198     *
199     * @param location Information about the target location.
200     * @param filePath Full path of the file to be sent.
201     * @return The ftp client that succeded sending the file.
202     * @throws FTPException if anything goes wrong.
203     */
204    private FTPClient ftpTransfer(CompanyLocation location, String filePath)
205       throws FTPException {
206      try {
207        File f = new File(filePath);
208        String fileName = f.getName();
209        File localDir = f.getParentFile();
210        FTPClient ftp = new FTPClient(location.getIpAddress());
211  
212        ftp.login(location.getUser(), location.getPassword());
213        ftp.setType(FTPTransferType.BINARY);
214        ftp.setConnectMode(FTPConnectMode.ACTIVE);
215        ftp.chdir(location.getPath());
216        ftp.put(filePath, fileName);
217        return ftp;
218      }
219      catch(FTPException fex) {
220        throw fex;
221      }
222      catch(Exception ex) {
223        throw new FTPException(ex.getMessage());
224      }
225    }
226  
227  }
228