1 package com.instantbank.component.lettersjobmdb.ejb;
2
3 import java.io.FileOutputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.File;
6
7 import java.util.Locale;
8 import java.util.Date;
9 import java.util.ArrayList;
10 import java.util.zip.ZipOutputStream;
11 import java.util.zip.ZipEntry;
12 import java.util.Set;
13 import java.text.SimpleDateFormat;
14 import java.text.NumberFormat;
15 import java.text.DecimalFormat;
16
17 import javax.ejb.MessageDrivenBean;
18 import javax.ejb.EJBException;
19 import javax.ejb.MessageDrivenContext;
20 import javax.jms.Message;
21 import javax.jms.MessageListener;
22 import javax.jms.MapMessage;
23 import javax.jms.JMSException;
24
25 import com.instantbank.common.utilcomponents.Debug;
26 import com.instantbank.common.utilcomponents.CommonUtil;
27 import com.instantbank.common.utilcomponents.JNDINames;
28 import com.instantbank.common.utilcomponents.LetterTemplateGlobals;
29 import com.instantbank.common.utilcomponents.UtilOnJdk;
30
31 import com.instantbank.component.lettertemplate.ejb.LetterTemplate;
32 import com.instantbank.component.lettertemplate.ejb.LetterTemplateHome;
33 import com.instantbank.component.lettertemplate.util.Template;
34 import com.instantbank.component.lettertemplate.util.LettersJobLogBean;
35
36 import com.instantbank.component.job.ejb.JobHome;
37 import com.instantbank.component.job.ejb.Job;
38 import com.instantbank.component.job.model.JobModel;
39
40 import com.instantbank.component.lettersjobmdb.util.MessageSender;
41
42 import com.instantbank.lettertemplate.editor.web.TemplateTransformer;
43
44 import com.instantbank.common.utilcomponents.DAOUtil;
45 import com.instantbank.common.utilcomponents.SqlUtils;
46
47 import javax.naming.InitialContext;
48 import javax.naming.NamingException;
49
50
51 import java.sql.Connection;
52 import javax.sql.DataSource;
53
54
61 public class LettersJobMessageEJB
62 implements MessageDrivenBean, MessageListener {
63
64
67 private long templateCode;
68
69
72 private String jobName;
73
74
77 private Debug debug;
78
79
80
85 public void ejbRemove() throws EJBException { }
86
87
88
94 public void setMessageDrivenContext(MessageDrivenContext mdc)
95 throws EJBException { }
96
97
98
101 public void ejbCreate() {
102 debug = new Debug();
103 debug.setDebugginOn(true);
104 debug.setPreMessage("** LetterJobMessageEJB: ");
105
106 }
107
108
109
126
127 public void onMessage(Message jobMsg) {
128 MapMessage msg = null;
129
130 LetterTemplateHome lethome;
131 LetterTemplate letejb;
132
133 String companyId;
134 Long userId;
135 Long jobKey;
136 long jobId;
137 long locationId1;
138 long locationId2;
139
140 Template template;
141
142 long zipSizeLimit;
143 String workDir;
144
145 String sql;
146 String ctxProviderUrl;
147 String initContextFactory;
148
149 try {
150
151
152 if(jobMsg instanceof MapMessage) {
153 msg = (MapMessage)jobMsg;
154 companyId = msg.getString("CompanyId");
155 userId = (Long)msg.getObject("UserId");
156 workDir = msg.getString("WorkDir");
157
158 jobKey = (Long)msg.getObject("JobKey");
159 debug.println("jobKey=" + jobKey);
160 ctxProviderUrl = msg.getString("ContextProviderUrl");
161 initContextFactory = msg.getString("InitContextFactory");
162 try {
163 long limitInKbytes = Long.parseLong(msg.getString("MaxZipSize"));
164 zipSizeLimit = limitInKbytes * 1024;
165 }
166 catch(NumberFormatException ex) {
167 zipSizeLimit = LetterTemplateGlobals.ZIP_LETTERS_FILE_MAX_SIZE;
168 }
169
170 debug.println("CompanyId = " + companyId);
171 debug.println("UserId = " + userId);
172 debug.println("workDir = " + workDir);
173
174 debug.println("ContextProviderUrl = " + ctxProviderUrl);
175 debug.println("MaxZipSize =" + zipSizeLimit);
176 }
177 else {
178 throw new Exception("Only MapMessages are processed");
179 }
180
181
182 InitialContext ctx = new InitialContext();
183 JobHome jobHome = (JobHome)ctx.lookup(JNDINames.JOB_EJBHOME);
184
185 Job job = jobHome.findByPrimaryKey(jobKey);
186 JobModel jobModel = job.getState();
187 jobId = jobModel.getJobId().longValue();
188 locationId1 = jobModel.getFtpPrimaryId();
189 locationId2 = jobModel.getFtpAlternateId();
190
191
192 boolean sendFtp = true;
193 if(locationId1 == LetterTemplateGlobals.UNDEF &&
194 locationId2 == LetterTemplateGlobals.UNDEF) {
195 sendFtp = false;
196 }
197 else if(locationId1 != LetterTemplateGlobals.UNDEF &&
198 locationId2 == LetterTemplateGlobals.UNDEF) {
199 locationId2 = locationId1;
200 }
201 else if(locationId1 == LetterTemplateGlobals.UNDEF &&
202 locationId2 != LetterTemplateGlobals.UNDEF) {
203 locationId1 = locationId2;
204 }
205
206 String jobName = UtilOnJdk.squeeze(jobModel.getName(), '_');
207 templateCode = jobModel.getTemplateCode();
208
209
210
211 lethome = (LetterTemplateHome)ctx.lookup(JNDINames.LETTERTEMPLATE_EJBHOME);
212 letejb = lethome.create(companyId, userId);
213
214 template = letejb.loadTemplate(templateCode);
215
216 java.sql.Date sysDate = letejb.loadSysDate();
217 Date templDate = letejb.loadTemplateDate(templateCode);
218
219
220 if(jobModel.getVersion().before(templDate)) {
221 letejb.storeLetterJobLog(jobId, sysDate,
222 LetterTemplateGlobals.LETTER_JOB_OUTDATED, 0, "", "");
223 debug.println("Job outdated");
224 return;
225 }
226
227 String foTemplate = template.toFoTemplate();
228 if(foTemplate == null) {
229 throw new Exception("fo-template null");
230 }
231
232
233 ArrayList[] variables = template.setOfVariables();
234 ArrayList[] images = template.getAllImages();
235
236 String foFileName = jobName + sysDate.getTime();
237
238 TemplateTransformer transf =
239 new TemplateTransformer(workDir, foTemplate, images,
240 variables, foFileName, letejb);
241
242 Set inconsistentVars = transf.offsetConsistency();
243 if(!inconsistentVars.isEmpty()) {
244 letejb.storeLetterJobLog(jobId, sysDate,
245 LetterTemplateGlobals.LETTER_JOB_OFFSET_INCONSISTENCY, 0, "", "");
246 debug.println("Job with date offset inconsistencies");
247 return;
248 }
249
250 debug.println("Transformer initiated");
251 String ext;
252 if(template.getPrintType() == Template.TYPEWRITTER) {
253 transf.setRenderMode(TemplateTransformer.RENDER_TXT);
254 ext = ".txt";
255 }
256 else {
257 ext = ".pdf";
258 }
259
260
261 sql = jobModel.getSqlText();
262
263 ArrayList[] sqlExec =
264 letejb.executeSQL
265 (sql, TemplateTransformer.varCodesFromSet(variables),
266 jobModel.getJobORDERtable());
267
268
269 String loggeableResult = serializeSqlExec(sqlExec);
270
271
272 LettersJobLogBean jobLog =
273 letejb.storeLetterJobLog(
274 jobId, sysDate,
275 LetterTemplateGlobals.LETTER_JOB_OK,
276 sqlExec[0].size(), loggeableResult, foTemplate);
277
278 letejb.updateJobExecDate(jobId, sysDate);
279
280 ArrayList varList = sqlExec[1];
281 debug.println("varlist extracted");
282
283 if(varList.size() == 0) {
284 debug.println("There were no letters to be generated");
285
286
287 letejb.storeLetterFtpJobLog(
288 jobLog.getLogId(), LetterTemplateGlobals.STR_NO_INFO, true, 0,
289 LetterTemplateGlobals.STR_NO_INFO,
290 LetterTemplateGlobals.STR_NO_INFO,
291 "No Zip file to be ftp'ed");
292
293 return;
294 }
295
296 String companyPath = letejb.loadCompanyWorkDir();
297 File companyDir =
298 new File(companyPath, LetterTemplateGlobals.LETTER_JOBS_DIR);
299
300 ZipOutputStream zout = null;
301 ByteArrayOutputStream zipbytes = null;
302 String zipname = null;
303 ByteArrayOutputStream letter = null;
304
305 long zipOutputSize = 0;
306 int numLetter = 0;
307 boolean generateLetter = true;
308 SequencedFileName sequencer = new SequencedFileName(jobName, sysDate, 1);
309
310
311
312 String generatedZip = null;
313
314 MessageSender ftpSender =
315 new MessageSender(
316 ctxProviderUrl,
317 initContextFactory, LetterTemplateGlobals.LETTERS_FTP_JMS_QUEUE);
318
319 long jobLogId = jobLog.getLogId();
320
321
322
323
324
325 String sAgrmCode = "";
326
327 DataSource datasource = DAOUtil.getDataSource(JNDINames.INSTANTBANKDB);
328
329 Connection dbConnection = DAOUtil.getDBConnection(datasource);
330
331 long lAgrmCodeIdx = SqlUtils.getAgreementCodeFieldIndex(dbConnection);
332 Long lVarValue;
333 Long lAgrmCode;
334 Long lAgrmID;
335 long lActionCode = 0;
336 long lResultCode = 0;
337 long lTemplateCode = 0;
338 Long lCompanyID;
339 boolean bAgrmCodeExists = false;
340
341 for(int i = 0; i < variables.length; i++) {
342 lVarValue = (Long)variables[i].get(0);
343 if(lVarValue.longValue() == lAgrmCodeIdx) {
344 bAgrmCodeExists = true;
345 break;
346 }
347 }
348
349
350
351 do {
352
353 if(zipOutputSize == 0) {
354 zipbytes = new ByteArrayOutputStream();
355 zipname = sequencer.nextName();
356 zout = new ZipOutputStream(zipbytes);
357 }
358
359 if(generateLetter) {
360 letter = transf.transform((String[])varList.get(numLetter));
361
362
363 if(bAgrmCodeExists) {
364
365 String[] sAgrmCodes = (String[])varList.get(numLetter);
366 lAgrmCode = Long.valueOf(sAgrmCodes[0]);
367 lCompanyID = Long.valueOf(jobModel.getCompanyId());
368
369 lAgrmID = SqlUtils.getAgreementId(dbConnection, lCompanyID.longValue(), lAgrmCode.longValue());
370
371 java.sql.Date procDate = (java.sql.Date)com.instantbank.collections.util.DateUtils.processDate(lCompanyID.longValue());
372
373 lActionCode = SqlUtils.getActionCodeFieldIndex(dbConnection, "SY", lCompanyID.longValue());
374 lResultCode = SqlUtils.getResultCodeFieldIndex(dbConnection, "SL", lCompanyID.longValue());
375 lTemplateCode = SqlUtils.getLetterTemplateIndex(dbConnection, String.valueOf(templateCode), lCompanyID.longValue());
376
377 letejb.insertLetterARHistory(dbConnection, lCompanyID.longValue(), lAgrmID.longValue(), procDate, lTemplateCode, templateCode, lActionCode, lResultCode);
378 }
379
380 if(letter == null) {
381 debug.println("null letter");
382 throw new Exception("Null letter");
383 }
384 }
385
386 if(zipOutputSize + letter.size() > zipSizeLimit) {
387
388 if(zipOutputSize == 0) {
389 addLetter(zout, letter, numLetter++, ext);
390 generatedZip = writeZipFile(zout, companyDir, zipname, zipbytes);
391 generateLetter = true;
392 }
393 else {
394 generatedZip = writeZipFile(zout, companyDir, zipname, zipbytes);
395 zipOutputSize = 0;
396 generateLetter = false;
397 }
398 }
399 else {
400 addLetter(zout, letter, numLetter++, ext);
401 if(numLetter == varList.size()) {
402 generatedZip = writeZipFile(zout, companyDir, zipname, zipbytes);
403 }
404 zipOutputSize = zipbytes.size();
405 generateLetter = true;
406 }
407
408
409
410 if(generatedZip != null) {
411
412 if(sendFtp) {
413 Message ftpMsg =
414 ftpSender.buildFtpMessage(companyId, userId,
415 generatedZip, jobLogId, locationId1, locationId2);
416
417 ftpSender.send(ftpMsg);
418 debug.println("Message sent to ftp queue");
419 }
420 else {
421 debug.println("Message NOT sent to ftp queue");
422 letejb.storeLetterFtpJobLog
423 (jobLogId, generatedZip, true, 0, null, null, null);
424 }
425
426 generatedZip = null;
427 }
428
429 }while (numLetter < varList.size());
430
431
432 ftpSender.release();
433 transf.cleanfiles();
434
435 }
436 catch(NamingException nex) {
437 debug.println("Naming exception");
438 debug.println(CommonUtil.stackTraceToString(nex));
439 }
440 catch(JMSException jex) {
441 debug.println("JMS exception");
442 debug.println(CommonUtil.stackTraceToString(jex));
443 }
444 catch(Exception ex) {
445 debug.println("Unexpected exception");
446 debug.println(CommonUtil.stackTraceToString(ex));
447 }
448 catch(Throwable tex) {
449 debug.println(CommonUtil.stackTraceToString(tex));
450 }
451 }
452
453
454
463 private void addLetter(ZipOutputStream zout, ByteArrayOutputStream letter,
464 int i, String ext)
465 throws Exception {
466 zout.putNextEntry(new ZipEntry("Letter-" + i + ext));
467 letter.writeTo(zout);
468 zout.closeEntry();
469 }
470
471
472
482 private String writeZipFile(ZipOutputStream zout, File workDir, String zipname,
483 ByteArrayOutputStream zipbytes)
484 throws Exception {
485 zout.close();
486 File f = new File(workDir, zipname);
487 String fullPath = f.getAbsolutePath();
488
489 FileOutputStream fout = new FileOutputStream(f);
490 zipbytes.writeTo(fout);
491 fout.close();
492
493 return fullPath;
494 }
495
496
497
506 private String serializeSqlExec(ArrayList[] execSet) {
507 if(execSet[0].size() == 0) {
508 return "";
509 }
510
511 ArrayList loans = execSet[0];
512 ArrayList vars = execSet[1];
513
514 StringBuffer sb = new StringBuffer();
515
516 for(int i = 0; i < loans.size(); i++) {
517 sb.append((String)loans.get(i));
518 String[] row = (String[])vars.get(i);
519 if(row.length > 0) {
520 sb.append(UtilOnJdk.VALUE_SEPARATOR);
521 }
522 for(int k = 0; k < row.length; k++) {
523 sb.append(row[k]);
524 if(k + 1 < row.length) {
525 sb.append(UtilOnJdk.VALUE_SEPARATOR);
526 }
527 }
528
529 if(i + 1 < loans.size()) {
530 sb.append(UtilOnJdk.ROW_SEPARATOR);
531 }
532 }
533
534 return sb.toString();
535 }
536
537
538
544 class SequencedFileName {
545
548 private int seqnum = 0;
549
550
553 private char[] buffer;
554
555
558 private int seqIndex;
559
560
563 private DecimalFormat df;
564
565
566
573 public SequencedFileName(String jobName, Date date, int seqNum) {
574 StringBuffer sb = new StringBuffer();
575 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
576 seqnum = seqNum - 1;
577
578 sb.append(jobName);
579 sb.append('-');
580 sb.append(date.getTime() % 100000000);
581 sb.append('-');
582 seqIndex = sb.length();
583 sb.append(" -");
584 sb.append(sdf.format(date));
585 sb.append(".zip");
586 buffer = new char[sb.length()];
587 sb.getChars(0, sb.length(), buffer, 0);
588 df = (DecimalFormat)NumberFormat.getInstance(Locale.US);
589 df.applyPattern("00");
590 }
591
592
593
599 public String nextName() {
600 seqnum++;
601 String seq = df.format(seqnum);
602 buffer[seqIndex + 1] = seq.charAt(seq.length() - 1);
603 buffer[seqIndex] = seq.charAt(seq.length() - 2);
604 return new String(buffer);
605 }
606 }
607 }
608
609