View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.database.data;
22  
23  import goldengate.common.command.exception.CommandAbstractException;
24  import goldengate.common.database.DbPreparedStatement;
25  import goldengate.common.database.DbSession;
26  import goldengate.common.database.data.AbstractDbData;
27  import goldengate.common.database.data.DbValue;
28  import goldengate.common.database.exception.GoldenGateDatabaseException;
29  import goldengate.common.database.exception.GoldenGateDatabaseNoConnectionException;
30  import goldengate.common.database.exception.GoldenGateDatabaseNoDataException;
31  import goldengate.common.database.exception.GoldenGateDatabaseSqlException;
32  import goldengate.common.logging.GgInternalLogger;
33  import goldengate.common.logging.GgInternalLoggerFactory;
34  import goldengate.common.utility.GgStringUtils;
35  
36  import java.io.File;
37  import java.io.FileNotFoundException;
38  import java.io.FileOutputStream;
39  import java.io.IOException;
40  import java.io.OutputStream;
41  import java.io.UnsupportedEncodingException;
42  import java.sql.SQLException;
43  import java.sql.Timestamp;
44  import java.sql.Types;
45  import java.util.concurrent.atomic.AtomicLong;
46  
47  import openr66.commander.CommanderNoDb;
48  import openr66.context.ErrorCode;
49  import openr66.context.R66FiniteDualStates;
50  import openr66.context.R66Result;
51  import openr66.context.R66Session;
52  import openr66.context.filesystem.R66Dir;
53  import openr66.context.filesystem.R66File;
54  import openr66.context.task.AbstractTask;
55  import openr66.context.task.TaskType;
56  import openr66.context.task.exception.OpenR66RunnerEndTasksException;
57  import openr66.context.task.exception.OpenR66RunnerErrorException;
58  import openr66.database.DbConstant;
59  import openr66.database.model.DbModelFactory;
60  import openr66.protocol.configuration.Configuration;
61  import openr66.protocol.exception.OpenR66ProtocolBusinessException;
62  import openr66.protocol.exception.OpenR66ProtocolNoSslException;
63  import openr66.protocol.exception.OpenR66ProtocolPacketException;
64  import openr66.protocol.exception.OpenR66ProtocolSystemException;
65  import openr66.protocol.http.HttpFormattedHandler;
66  import openr66.protocol.localhandler.LocalChannelReference;
67  import openr66.protocol.localhandler.packet.ErrorPacket;
68  import openr66.protocol.localhandler.packet.RequestPacket;
69  import openr66.protocol.localhandler.packet.RequestPacket.TRANSFERMODE;
70  import openr66.protocol.utils.ChannelUtils;
71  import openr66.protocol.utils.NbAndSpecialId;
72  import openr66.protocol.utils.R66Future;
73  
74  import org.dom4j.Document;
75  import org.dom4j.DocumentException;
76  import org.dom4j.Element;
77  import org.dom4j.io.OutputFormat;
78  import org.dom4j.io.SAXReader;
79  import org.dom4j.io.XMLWriter;
80  import org.dom4j.tree.DefaultElement;
81  import org.xml.sax.SAXException;
82  
83  /**
84   * Task Runner from pre operation to transfer to post operation, except in case
85   * of error
86   *
87   * @author Frederic Bregier
88   *
89   */
90  public class DbTaskRunner extends AbstractDbData {
91      /**
92       * Internal Logger
93       */
94      private static final GgInternalLogger logger = GgInternalLoggerFactory
95              .getLogger(DbTaskRunner.class);
96  
97      public static enum Columns {
98          GLOBALSTEP,
99          GLOBALLASTSTEP,
100         STEP,
101         RANK,
102         STEPSTATUS,
103         RETRIEVEMODE,
104         FILENAME,
105         ISMOVED,
106         IDRULE,
107         BLOCKSZ,
108         ORIGINALNAME,
109         FILEINFO,
110         MODETRANS,
111         STARTTRANS,
112         STOPTRANS,
113         INFOSTATUS,
114         UPDATEDINFO,
115         OWNERREQ,
116         REQUESTER,
117         REQUESTED,
118         SPECIALID;
119     }
120 
121     public static final int[] dbTypes = {
122             Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER,
123             Types.CHAR, Types.BIT, Types.VARCHAR, Types.BIT, Types.VARCHAR,
124             Types.INTEGER, Types.VARCHAR, Types.LONGVARCHAR, Types.INTEGER,
125             Types.TIMESTAMP, Types.TIMESTAMP, Types.CHAR, Types.INTEGER,
126             Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BIGINT };
127 
128     public static final String table = " RUNNER ";
129 
130     public static final String fieldseq = "RUNSEQ";
131 
132     public static final Columns [] indexes = {
133         Columns.STARTTRANS, Columns.OWNERREQ, Columns.STEPSTATUS, Columns.UPDATEDINFO,
134         Columns.GLOBALSTEP, Columns.INFOSTATUS, Columns.SPECIALID
135     };
136 
137     public static final String XMLRUNNERS = "taskrunners";
138     public static final String XMLRUNNER = "runner";
139     public static final String XMLEXTENSION = "_singlerunner.xml";
140     /**
141      * GlobalStep Value
142      */
143     public static enum TASKSTEP {
144         NOTASK, PRETASK, TRANSFERTASK, POSTTASK, ALLDONETASK, ERRORTASK;
145     }
146 
147     // Values
148     private DbRule rule;
149 
150     private R66Session session;
151 
152     /**
153      * Last step
154      */
155     private int globalstep = TASKSTEP.NOTASK.ordinal();
156     /**
157      * Last global step (only changes in case of success)
158      */
159     private int globallaststep = TASKSTEP.NOTASK.ordinal();
160     /**
161      * Step in the current globalstep
162      */
163     private int step = -1;
164 
165     private int rank = 0;
166 
167     /**
168      * Last step action status error code
169      */
170     private ErrorCode status = ErrorCode.Unknown;
171 
172     private long specialId;
173 
174     private boolean isSender;
175 
176     private String filename;
177 
178     private boolean isFileMoved = false;
179 
180     private String ruleId;
181 
182     private int blocksize;
183 
184     private String originalFilename;
185 
186     private String fileInformation;
187 
188     private int mode;
189 
190     private String ownerRequest;
191 
192     private String requesterHostId;
193 
194     private String requestedHostId;
195 
196     private Timestamp start;
197 
198     private Timestamp stop;
199 
200     /**
201      * Info status error code
202      */
203     private ErrorCode infostatus = ErrorCode.Unknown;
204 
205     /**
206      * The global status for running
207      */
208     private int updatedInfo = UpdatedInfo.UNKNOWN.ordinal();
209 
210     private volatile boolean continueTransfer = true;
211 
212     private volatile boolean rescheduledTransfer = false;
213     
214     private LocalChannelReference localChannelReference = null;
215     
216     private boolean isRecvThrough = false;
217     private boolean isSendThrough = false;
218     
219     /**
220      * Special For DbTaskRunner
221      */
222     public static final int NBPRKEY = 4;
223     // ALL TABLE SHOULD IMPLEMENT THIS
224 
225     protected static final String selectAllFields = Columns.GLOBALSTEP.name() +
226             "," + Columns.GLOBALLASTSTEP.name() + "," + Columns.STEP.name() +
227             "," + Columns.RANK.name() + "," + Columns.STEPSTATUS.name() + "," +
228             Columns.RETRIEVEMODE.name() + "," + Columns.FILENAME.name() + "," +
229             Columns.ISMOVED.name() + "," + Columns.IDRULE.name() + "," +
230             Columns.BLOCKSZ.name() + "," + Columns.ORIGINALNAME.name() + "," +
231             Columns.FILEINFO.name() + "," + Columns.MODETRANS.name() + "," +
232             Columns.STARTTRANS.name() + "," + Columns.STOPTRANS.name() + "," +
233             Columns.INFOSTATUS.name() + "," + Columns.UPDATEDINFO.name() + "," +
234             Columns.OWNERREQ.name() + "," + Columns.REQUESTER.name() + "," +
235             Columns.REQUESTED.name() + "," + Columns.SPECIALID.name();
236 
237     protected static final String updateAllFields = Columns.GLOBALSTEP.name() +
238             "=?," + Columns.GLOBALLASTSTEP.name() + "=?," +
239             Columns.STEP.name() + "=?," + Columns.RANK.name() + "=?," +
240             Columns.STEPSTATUS.name() + "=?," + Columns.RETRIEVEMODE.name() +
241             "=?," + Columns.FILENAME.name() + "=?," + Columns.ISMOVED.name() +
242             "=?," + Columns.IDRULE.name() + "=?," + Columns.BLOCKSZ.name() +
243             "=?," + Columns.ORIGINALNAME.name() + "=?," +
244             Columns.FILEINFO.name() + "=?," + Columns.MODETRANS.name() + "=?," +
245             Columns.STARTTRANS.name() + "=?," + Columns.STOPTRANS.name() +
246             "=?," + Columns.INFOSTATUS.name() + "=?," + Columns.UPDATEDINFO.name() + "=?";
247 
248     protected static final String insertAllValues = " (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ";
249 
250     private static final AtomicLong clientNoDbSpecialIdLast =
251         new AtomicLong(System.currentTimeMillis());
252 
253     /* (non-Javadoc)
254      * @see goldengate.common.database.data.AbstractDbData#initObject()
255      */
256     @Override
257     protected void initObject() {
258         primaryKey = new DbValue[]{
259                 new DbValue(ownerRequest, Columns.OWNERREQ.name()),
260                 new DbValue(requesterHostId, Columns.REQUESTER.name()),
261                 new DbValue(requestedHostId, Columns.REQUESTED.name()),
262                 new DbValue(specialId, Columns.SPECIALID.name()) };
263         otherFields = new DbValue[]{
264                 // GLOBALSTEP, GLOBALLASTSTEP, STEP, RANK, STEPSTATUS, RETRIEVEMODE,
265                 // FILENAME, ISMOVED, IDRULE,
266                 // BLOCKSZ, ORIGINALNAME, FILEINFO, MODETRANS,
267                 // STARTTRANS, STOPTRANS
268                 // INFOSTATUS, UPDATEDINFO
269                 new DbValue(globalstep, Columns.GLOBALSTEP.name()),
270                 new DbValue(globallaststep, Columns.GLOBALLASTSTEP.name()),
271                 new DbValue(step, Columns.STEP.name()),
272                 new DbValue(rank, Columns.RANK.name()),
273                 new DbValue(ErrorCode.Unknown.getCode(), Columns.STEPSTATUS.name()), // status.getCode()
274                 new DbValue(isSender, Columns.RETRIEVEMODE.name()),
275                 new DbValue(filename, Columns.FILENAME.name()),
276                 new DbValue(isFileMoved, Columns.ISMOVED.name()),
277                 new DbValue(ruleId, Columns.IDRULE.name()),
278                 new DbValue(blocksize, Columns.BLOCKSZ.name()),
279                 new DbValue(originalFilename, Columns.ORIGINALNAME.name()),
280                 new DbValue(fileInformation, Columns.FILEINFO.name(), true),
281                 new DbValue(mode, Columns.MODETRANS.name()),
282                 new DbValue(start, Columns.STARTTRANS.name()),
283                 new DbValue(stop, Columns.STOPTRANS.name()),
284                 new DbValue(ErrorCode.Unknown.getCode(), Columns.INFOSTATUS.name()),// infostatus.getCode()
285                 new DbValue(updatedInfo, Columns.UPDATEDINFO.name()) };
286         allFields = new DbValue[]{
287                 otherFields[0], otherFields[1], otherFields[2], otherFields[3],
288                 otherFields[4], otherFields[5], otherFields[6], otherFields[7],
289                 otherFields[8], otherFields[9], otherFields[10], otherFields[11],
290                 otherFields[12], otherFields[13], otherFields[14], otherFields[15],
291                 otherFields[16],
292                 primaryKey[0], primaryKey[1], primaryKey[2], primaryKey[3]  };
293     }
294 
295     /* (non-Javadoc)
296      * @see goldengate.common.database.data.AbstractDbData#getSelectAllFields()
297      */
298     @Override
299     protected String getSelectAllFields() {
300         return selectAllFields;
301     }
302 
303     /* (non-Javadoc)
304      * @see goldengate.common.database.data.AbstractDbData#getTable()
305      */
306     @Override
307     protected String getTable() {
308         return table;
309     }
310 
311     /* (non-Javadoc)
312      * @see goldengate.common.database.data.AbstractDbData#getInsertAllValues()
313      */
314     @Override
315     protected String getInsertAllValues() {
316         return insertAllValues;
317     }
318 
319     /* (non-Javadoc)
320      * @see goldengate.common.database.data.AbstractDbData#getUpdateAllFields()
321      */
322     @Override
323     protected String getUpdateAllFields() {
324         return updateAllFields;
325     }
326 
327     @Override
328     protected void setToArray() {
329         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
330         allFields[Columns.GLOBALLASTSTEP.ordinal()].setValue(globallaststep);
331         allFields[Columns.STEP.ordinal()].setValue(step);
332         allFields[Columns.RANK.ordinal()].setValue(rank);
333         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
334         allFields[Columns.RETRIEVEMODE.ordinal()].setValue(isSender);
335         allFields[Columns.FILENAME.ordinal()].setValue(filename);
336         allFields[Columns.ISMOVED.ordinal()].setValue(isFileMoved);
337         allFields[Columns.IDRULE.ordinal()].setValue(ruleId);
338         allFields[Columns.BLOCKSZ.ordinal()].setValue(blocksize);
339         allFields[Columns.ORIGINALNAME.ordinal()].setValue(originalFilename);
340         allFields[Columns.FILEINFO.ordinal()].setValue(fileInformation);
341         allFields[Columns.MODETRANS.ordinal()].setValue(mode);
342         allFields[Columns.STARTTRANS.ordinal()].setValue(start);
343         stop = new Timestamp(System.currentTimeMillis());
344         allFields[Columns.STOPTRANS.ordinal()].setValue(stop);
345         allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
346         allFields[Columns.UPDATEDINFO.ordinal()].setValue(updatedInfo);
347         allFields[Columns.OWNERREQ.ordinal()].setValue(ownerRequest);
348         allFields[Columns.REQUESTER.ordinal()].setValue(requesterHostId);
349         allFields[Columns.REQUESTED.ordinal()].setValue(requestedHostId);
350         allFields[Columns.SPECIALID.ordinal()].setValue(specialId);
351     }
352 
353     @Override
354     protected void setFromArray() throws GoldenGateDatabaseSqlException {
355         globalstep = (Integer) allFields[Columns.GLOBALSTEP.ordinal()]
356                 .getValue();
357         globallaststep = (Integer) allFields[Columns.GLOBALLASTSTEP.ordinal()]
358                 .getValue();
359         step = (Integer) allFields[Columns.STEP.ordinal()].getValue();
360         rank = (Integer) allFields[Columns.RANK.ordinal()].getValue();
361         status = ErrorCode.getFromCode((String) allFields[Columns.STEPSTATUS
362                 .ordinal()].getValue());
363         isSender = (Boolean) allFields[Columns.RETRIEVEMODE.ordinal()]
364                 .getValue();
365         filename = (String) allFields[Columns.FILENAME.ordinal()].getValue();
366         isFileMoved = (Boolean) allFields[Columns.ISMOVED.ordinal()].getValue();
367         ruleId = (String) allFields[Columns.IDRULE.ordinal()].getValue();
368         blocksize = (Integer) allFields[Columns.BLOCKSZ.ordinal()].getValue();
369         originalFilename = (String) allFields[Columns.ORIGINALNAME.ordinal()]
370                 .getValue();
371         fileInformation = (String) allFields[Columns.FILEINFO.ordinal()]
372                 .getValue();
373         mode = (Integer) allFields[Columns.MODETRANS.ordinal()].getValue();
374         start = (Timestamp) allFields[Columns.STARTTRANS.ordinal()].getValue();
375         stop = (Timestamp) allFields[Columns.STOPTRANS.ordinal()].getValue();
376         infostatus = ErrorCode.getFromCode((String) allFields[Columns.INFOSTATUS
377                                                           .ordinal()].getValue());
378         updatedInfo = (Integer) allFields[Columns.UPDATEDINFO.ordinal()]
379                 .getValue();
380         ownerRequest = (String) allFields[Columns.OWNERREQ.ordinal()]
381                                              .getValue();
382         requesterHostId = (String) allFields[Columns.REQUESTER.ordinal()]
383                 .getValue();
384         requestedHostId = (String) allFields[Columns.REQUESTED.ordinal()]
385                 .getValue();
386         specialId = (Long) allFields[Columns.SPECIALID.ordinal()].getValue();
387     }
388     /**
389      *
390      * @return The Where condition on Primary Key
391      */
392     protected String getWherePrimaryKey() {
393         return primaryKey[0].column + " = ? AND " +
394             primaryKey[1].column + " = ? AND " +
395             primaryKey[2].column + " = ? AND " +
396             primaryKey[3].column + " = ? ";
397     }
398     /**
399      * Set the primary Key as current value
400      */
401     protected void setPrimaryKey() {
402         primaryKey[0].setValue(ownerRequest);
403         primaryKey[1].setValue(requesterHostId);
404         primaryKey[2].setValue(requestedHostId);
405         primaryKey[3].setValue(specialId);
406     }
407 
408     /**
409      *
410      * @param session
411      * @param requestPacket
412      * @return The associated requested Host Id
413      */
414     public static String getRequested(R66Session session,
415             RequestPacket requestPacket) {
416         if (requestPacket.isToValidate()) {
417             // the request is initiated and sent by the requester
418             try {
419                 return Configuration.configuration.getHostId(session.getAuth()
420                         .isSsl());
421             } catch (OpenR66ProtocolNoSslException e) {
422                 return Configuration.configuration.HOST_ID;
423             }
424         } else {
425             // the request is sent after acknowledge by the requested
426             return session.getAuth().getUser();
427         }
428     }
429 
430     /**
431      *
432      * @param session
433      * @param requestPacket
434      * @return The associated requester Host Id
435      */
436     public static String getRequester(R66Session session,
437             RequestPacket requestPacket) {
438         if (requestPacket.isToValidate()) {
439             return session.getAuth().getUser();
440         } else {
441             try {
442                 return Configuration.configuration.getHostId(session.getAuth()
443                         .isSsl());
444             } catch (OpenR66ProtocolNoSslException e) {
445                 return Configuration.configuration.HOST_ID;
446             }
447         }
448     }
449 
450     public void checkThroughMode() {
451         isRecvThrough = RequestPacket.isRecvThroughMode(this.mode, isSelfRequested());
452         isSendThrough = RequestPacket.isSendThroughMode(this.mode, isSelfRequested());
453         if (localChannelReference != null) {
454             if (localChannelReference.isRecvThroughMode()) {
455                 isRecvThrough = true;
456             }
457             if (localChannelReference.isSendThroughMode()) {
458                 isSendThrough = true;
459             }
460             if (isRecvThrough && !localChannelReference.isRecvThroughMode()) {
461                 // Cannot be a RecvThrough
462                 isRecvThrough = false;
463             }
464             if (isSendThrough && !localChannelReference.isSendThroughMode()) {
465                 isSendThrough = false;
466             }
467         }
468         logger.debug("DbTask "+mode+" isRecvThrough: "+isRecvThrough+" isSendThrough: "+isSendThrough);
469     }
470     /**
471      * Constructor for submission (no transfer session), from database. It is
472      * created, so with a new specialId if necessary
473      *
474      * @param dbSession
475      * @param rule
476      * @param isSender
477      * @param requestPacket
478      * @param requested
479      * @param startTime
480      * @throws GoldenGateDatabaseException
481      */
482     public DbTaskRunner(DbSession dbSession, DbRule rule, boolean isSender,
483             RequestPacket requestPacket, String requested, Timestamp startTime)
484             throws GoldenGateDatabaseException {
485         super(dbSession);
486         this.session = null;
487         this.rule = rule;
488         ruleId = this.rule.idRule;
489         rank = requestPacket.getRank();
490         status = ErrorCode.Unknown;
491         infostatus = ErrorCode.Unknown;
492         this.isSender = isSender;
493         filename = requestPacket.getFilename();
494         blocksize = requestPacket.getBlocksize();
495         originalFilename = requestPacket.getFilename();
496         fileInformation = requestPacket.getFileInformation();
497         mode = requestPacket.getMode();
498         // itself but according to SSL
499         requesterHostId = Configuration.configuration.getHostId(dbSession,
500                 requested);
501         // given one
502         requestedHostId = requested;
503         // always itself
504         ownerRequest = Configuration.configuration.HOST_ID;
505 
506         if (startTime != null) {
507             start = startTime;
508         } else {
509             start = new Timestamp(System.currentTimeMillis());
510         }
511         setToArray();
512         isSaved = false;
513         specialId = requestPacket.getSpecialId();
514         if (this.rule == null) {
515             this.rule = new DbRule(this.dbSession, ruleId);
516         }
517         if (mode != rule.mode) {
518             if (RequestPacket.isMD5Mode(mode)) {
519                 mode = RequestPacket.getModeMD5(rule.mode);
520             } else {
521                 mode = rule.mode;
522             }
523         }
524         checkThroughMode();
525         create();
526     }
527 
528     /**
529      * Constructor from a request with a valid Special Id to be inserted into database
530      *
531      * @param dbSession
532      * @param session
533      * @param rule
534      * @param isSender
535      * @param requestPacket
536      * @throws GoldenGateDatabaseException
537      */
538     public DbTaskRunner(DbSession dbSession, R66Session session, DbRule rule,
539             boolean isSender, RequestPacket requestPacket)
540             throws GoldenGateDatabaseException {
541         super(dbSession);
542         this.session = session;
543         this.localChannelReference = session.getLocalChannelReference();
544         this.rule = rule;
545         ruleId = this.rule.idRule;
546         rank = requestPacket.getRank();
547         status = ErrorCode.Unknown;
548         infostatus = ErrorCode.Unknown;
549         this.isSender = isSender;
550         filename = requestPacket.getFilename();
551         blocksize = requestPacket.getBlocksize();
552         originalFilename = requestPacket.getFilename();
553         fileInformation = requestPacket.getFileInformation();
554         mode = requestPacket.getMode();
555         requesterHostId = getRequester(session, requestPacket);
556         requestedHostId = getRequested(session, requestPacket);
557         // always itself
558         ownerRequest = Configuration.configuration.HOST_ID;
559 
560         start = new Timestamp(System.currentTimeMillis());
561         setToArray();
562         isSaved = false;
563         specialId = requestPacket.getSpecialId();
564         if (this.rule == null) {
565             this.rule = new DbRule(this.dbSession, ruleId);
566         }
567         if (mode != rule.mode) {
568             if (RequestPacket.isMD5Mode(mode)) {
569                 mode = RequestPacket.getModeMD5(rule.mode);
570             } else {
571                 mode = rule.mode;
572             }
573         }
574         checkThroughMode();
575         insert();
576     }
577 
578     /**
579      * Constructor from a request with a valid Special Id so loaded from database
580      *
581      * @param dbSession
582      * @param session
583      * @param rule
584      * @param id
585      * @param requester
586      * @param requested
587      * @throws GoldenGateDatabaseException
588      */
589     public DbTaskRunner(DbSession dbSession, R66Session session, DbRule rule,
590             long id, String requester, String requested)
591             throws GoldenGateDatabaseException {
592         super(dbSession);
593         this.session = session;
594         if (this.session != null) {
595             this.localChannelReference = session.getLocalChannelReference();
596         }
597         this.rule = rule;
598 
599         specialId = id;
600         // retrieving a task should be made from the requester, but the caller
601         // is responsible of this
602         requestedHostId = requested;
603         requesterHostId = requester;
604         // always itself
605         ownerRequest = Configuration.configuration.HOST_ID;
606 
607         select();
608         if (rule != null) {
609             if (!ruleId.equals(rule.idRule)) {
610                 throw new GoldenGateDatabaseNoDataException(
611                         "Rule does not correspond");
612             }
613         }
614     }
615     /**
616      * Constructor to initiate a request with a valid previous Special Id so loaded from database.
617      * 
618      * This object cannot be used except to retrieve information.
619      *
620      * @param dbSession
621      * @param id
622      * @param requested
623      * @throws GoldenGateDatabaseException
624      */
625     public DbTaskRunner(DbSession dbSession, long id, String requested)
626             throws GoldenGateDatabaseException {
627         super(dbSession);
628 
629         specialId = id;
630         // retrieving a task should be made from the requester, but the caller
631         // is responsible of this
632         requestedHostId = requested;
633         requesterHostId = Configuration.configuration.getHostId(dbSession,
634                 requested);
635         // always itself
636         ownerRequest = Configuration.configuration.HOST_ID;
637 
638         select();
639     }
640     /**
641      *
642      * @return the condition to limit access to the row concerned by the Host
643      */
644     private static String getLimitWhereCondition() {
645         return " "+Columns.OWNERREQ + " = '"+Configuration.configuration.HOST_ID+"' ";
646     }
647     /**
648      * Create a Special Id for NoDb client
649      */
650     private void createNoDbSpecialId() {
651         synchronized (clientNoDbSpecialIdLast) {
652             // New SpecialId is not possible with No Database Model
653             specialId = System.currentTimeMillis();
654             if (clientNoDbSpecialIdLast.get() >= specialId) {
655                 specialId = clientNoDbSpecialIdLast.incrementAndGet();
656             } else {
657                 clientNoDbSpecialIdLast.set(specialId);
658             }
659             return;
660         }
661     }
662     /**
663      * Remove a Spcieal Id for NoDb Client
664      */
665     private void removeNoDbSpecialId() {
666     }
667     /*
668      * (non-Javadoc)
669      *
670      * @see openr66.databaseold.data.AbstractDbData#delete()
671      */
672     @Override
673     public void delete() throws GoldenGateDatabaseException {
674         if (dbSession == null) {
675             removeNoDbSpecialId();
676             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
677                 deleteXmlWorkNoDb();
678             }
679             return;
680         }
681         super.delete();
682     }
683     
684     private void addNoDb() {
685         DbTaskRunner runner = new DbTaskRunner(null);
686         this.setToArray();
687         DbValue []temp = runner.allFields;
688         runner.allFields = this.allFields;
689         try {
690             runner.setFromArray();
691         } catch (GoldenGateDatabaseSqlException e) {
692         }
693         runner.allFields = temp;
694         runner.setToArray();
695         runner.isRecvThrough = this.isRecvThrough;
696         runner.isSendThrough = this.isSendThrough;
697         runner.rule = this.rule;
698         runner.isSaved = true;
699         CommanderNoDb.todoList.add(runner);
700     }
701 
702     /*
703      * (non-Javadoc)
704      *
705      * @see openr66.databaseold.data.AbstractDbData#insert()
706      */
707     @Override
708     public void insert() throws GoldenGateDatabaseException {
709         if (isSaved) {
710             return;
711         }
712         if (dbSession == null) {
713             if (specialId == DbConstant.ILLEGALVALUE) {
714                 // New SpecialId is not possible with No Database Model
715                 createNoDbSpecialId();
716             }
717             isSaved = true;
718             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
719                 try {
720                     setToArray();
721                     this.writeXmlWorkNoDb();
722                 } catch (OpenR66ProtocolBusinessException e) {
723                     // Ignore
724                 }
725             }
726             if (this.updatedInfo == UpdatedInfo.TOSUBMIT.ordinal()) {
727                 addNoDb();
728             }
729             return;
730         }
731         // First need to find a new id if id is not ok
732         if (specialId == DbConstant.ILLEGALVALUE) {
733             specialId = DbModelFactory.dbModel.nextSequence(dbSession);
734             logger.debug("Try Insert create a new Id from sequence: " +
735                     specialId);
736             setPrimaryKey();
737         }
738         super.insert();
739     }
740 
741     /**
742      * As insert but with the ability to change the SpecialId
743      *
744      * @throws GoldenGateDatabaseException
745      */
746     public void create() throws GoldenGateDatabaseException {
747         if (isSaved) {
748             return;
749         }
750         if (dbSession == null) {
751             if (specialId == DbConstant.ILLEGALVALUE) {
752                 // New SpecialId is not possible with No Database Model
753                 createNoDbSpecialId();
754             }
755             isSaved = true;
756             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
757                 try {
758                     setToArray();
759                     this.writeXmlWorkNoDb();
760                 } catch (OpenR66ProtocolBusinessException e) {
761                     // Ignore
762                 }
763             }
764             if (this.updatedInfo == UpdatedInfo.TOSUBMIT.ordinal()) {
765                 addNoDb();
766             }
767             return;
768         }
769         // First need to find a new id if id is not ok
770         if (specialId == DbConstant.ILLEGALVALUE) {
771             specialId = DbModelFactory.dbModel.nextSequence(dbSession);
772             logger.info("Try Insert create a new Id from sequence: " +
773                     specialId);
774             setPrimaryKey();
775         }
776         setToArray();
777         DbPreparedStatement preparedStatement = new DbPreparedStatement(
778                 dbSession);
779         try {
780             preparedStatement.createPrepareStatement("INSERT INTO " + table +
781                     " (" + selectAllFields + ") VALUES " + insertAllValues);
782             setValues(preparedStatement, allFields);
783             try {
784                 int count = preparedStatement.executeUpdate();
785                 if (count <= 0) {
786                     throw new GoldenGateDatabaseNoDataException("No row found");
787                 }
788             } catch (GoldenGateDatabaseSqlException e) {
789                 logger.error("Problem while inserting", e);
790                 DbPreparedStatement find = new DbPreparedStatement(dbSession);
791                 try {
792                     find.createPrepareStatement("SELECT MAX(" +
793                             primaryKey[3].column + ") FROM " + table + " WHERE " +
794                             primaryKey[0].column + " = ? AND " +
795                             primaryKey[1].column + " = ? AND " +
796                             primaryKey[2].column + " = ? AND " +
797                             primaryKey[3].column + " != ? ");
798                     setPrimaryKey();
799                     setValues(find, primaryKey);
800                     find.executeQuery();
801                     if (find.getNext()) {
802                         long result;
803                         try {
804                             result = find.getResultSet().getLong(1);
805                         } catch (SQLException e1) {
806                             throw new GoldenGateDatabaseSqlException(e1);
807                         }
808                         specialId = result + 1;
809                         DbModelFactory.dbModel.resetSequence(dbSession, specialId + 1);
810                         setToArray();
811                         preparedStatement.close();
812                         setValues(preparedStatement, allFields);
813                         int count = preparedStatement.executeUpdate();
814                         if (count <= 0) {
815                             throw new GoldenGateDatabaseNoDataException("No row found");
816                         }
817                     } else {
818                         throw new GoldenGateDatabaseNoDataException("No row found");
819                     }
820                 } finally {
821                     find.realClose();
822                 }
823             }
824             isSaved = true;
825         } finally {
826             preparedStatement.realClose();
827         }
828     }
829 
830     /*
831      * (non-Javadoc)
832      *
833      * @see openr66.databaseold.data.AbstractDbData#exist()
834      */
835     @Override
836     public boolean exist() throws GoldenGateDatabaseException {
837         if (dbSession == null) {
838             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
839                 return existXmlWorkNoDb();
840             }
841             return false;
842         }
843         return super.exist();
844     }
845 
846     /*
847      * (non-Javadoc)
848      *
849      * @see openr66.databaseold.data.AbstractDbData#select()
850      */
851     @Override
852     public void select() throws GoldenGateDatabaseException {
853         if (dbSession == null) {
854             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
855                 try {
856                     this.loadXmlWorkNoDb();
857                     setFromArray();
858                 } catch (OpenR66ProtocolBusinessException e) {
859                     throw new GoldenGateDatabaseNoDataException("No file found");
860                 }
861                 if (rule == null) {
862                     rule = new DbRule(this.dbSession, ruleId);
863                 }
864                 isSaved = true;
865                 checkThroughMode();
866                 return;
867             }
868             throw new GoldenGateDatabaseNoDataException("No row found");
869         }
870         super.select();
871         if (rule == null) {
872             rule = new DbRule(this.dbSession, ruleId);
873         }
874         checkThroughMode();
875     }
876 
877     /*
878      * (non-Javadoc)
879      *
880      * @see openr66.databaseold.data.AbstractDbData#update()
881      */
882     @Override
883     public void update() throws GoldenGateDatabaseException {
884         if (isSaved) {
885             return;
886         }
887         if (dbSession == null) {
888             isSaved = true;
889             if (Configuration.configuration.saveTaskRunnerWithNoDb) {
890                 try {
891                     setToArray();
892                     this.writeXmlWorkNoDb();
893                 } catch (OpenR66ProtocolBusinessException e) {
894                     // Ignore
895                 }
896             }
897             if (this.updatedInfo == UpdatedInfo.TOSUBMIT.ordinal()) {
898                 addNoDb();
899             }
900             return;
901         }
902         // SNMP notification
903         if (updatedInfo == UpdatedInfo.INERROR.ordinal() ||
904                 updatedInfo == UpdatedInfo.INTERRUPTED.ordinal()) {
905             if (Configuration.configuration.r66Mib != null) {
906                 Configuration.configuration.r66Mib.notifyInfoTask(
907                         "Task is "+UpdatedInfo.values()[updatedInfo].name(), this);
908             }
909         }
910         super.update();
911     }
912     /**
913      * Partial set from another runner (infostatus, rank, status, step, stop,
914      * filename, globallastep, globalstep, isFileMoved)
915      * @param runner
916      */
917     public void setFrom(DbTaskRunner runner) {
918         if (runner != null) {
919             this.infostatus = runner.infostatus;
920             this.rank = runner.rank;
921             this.status = runner.status;
922             this.step = runner.step;
923             this.stop = runner.stop;
924             this.filename = runner.filename;
925             this.globallaststep = runner.globallaststep;
926             this.globalstep = runner.globalstep;
927             this.isFileMoved = runner.isFileMoved;
928         }
929     }
930     
931     public boolean isRecvThrough() {
932         return isRecvThrough;
933     }
934     public boolean isSendThrough() {
935         return isSendThrough;
936     }
937 
938     /**
939      * Private constructor for Commander only
940      *
941      * @param session
942      */
943     private DbTaskRunner(DbSession dBsession) {
944         super(dBsession);
945         session = null;
946         rule = null;
947     }
948     /**
949      * Set a localChannelReference
950      * @param localChannelReference
951      */
952     public void setLocalChannelReference(LocalChannelReference localChannelReference) {
953         this.localChannelReference = localChannelReference;
954     }
955     
956     /**
957      * @return the localChannelReference
958      */
959     public LocalChannelReference getLocalChannelReference() {
960         return localChannelReference;
961     }
962 
963     /**
964      * For instance from Commander when getting updated information
965      *
966      * @param preparedStatement
967      * @return the next updated DbTaskRunner
968      * @throws GoldenGateDatabaseNoConnectionException
969      * @throws GoldenGateDatabaseSqlException
970      */
971     public static DbTaskRunner getFromStatement(
972             DbPreparedStatement preparedStatement)
973             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
974         DbTaskRunner dbTaskRunner = new DbTaskRunner(preparedStatement
975                 .getDbSession());
976         dbTaskRunner.getValues(preparedStatement, dbTaskRunner.allFields);
977         dbTaskRunner.setFromArray();
978         if (dbTaskRunner.rule == null) {
979             try {
980                 dbTaskRunner.rule = new DbRule(dbTaskRunner.dbSession, dbTaskRunner.ruleId);
981             } catch (GoldenGateDatabaseException e) {
982                 throw new GoldenGateDatabaseSqlException(e);
983             }
984         }
985         dbTaskRunner.checkThroughMode();
986         dbTaskRunner.isSaved = true;
987         return dbTaskRunner;
988     }
989 
990     /**
991      * @param session
992      * @param status
993      * @param limit limit the number of rows
994      * @return the DbPreparedStatement for getting Runner according to status ordered by start
995      * @throws GoldenGateDatabaseNoConnectionException
996      * @throws GoldenGateDatabaseSqlException
997      */
998     public static DbPreparedStatement getStatusPrepareStatement(
999             DbSession session, ErrorCode status, int limit)
1000             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1001         String request = "SELECT " + selectAllFields + " FROM " + table;
1002         if (status != null) {
1003             request += " WHERE " + Columns.STEPSTATUS.name() + " = '" +
1004                     status.getCode() + "' AND "+getLimitWhereCondition();
1005         } else {
1006             request += " WHERE "+getLimitWhereCondition();
1007         }
1008         request += " ORDER BY " + Columns.STARTTRANS.name() + " DESC ";
1009         request = DbModelFactory.dbModel.limitRequest(selectAllFields, request, limit);
1010         return new DbPreparedStatement(session, request);
1011     }
1012 
1013     /**
1014      * @param session
1015      * @param globalstep
1016      * @param limit limit the number of rows
1017      * @return the DbPreparedStatement for getting Runner according to
1018      *         globalstep ordered by start
1019      * @throws GoldenGateDatabaseNoConnectionException
1020      * @throws GoldenGateDatabaseSqlException
1021      */
1022     public static DbPreparedStatement getStepPrepareStatement(DbSession session,
1023             TASKSTEP globalstep, int limit) throws GoldenGateDatabaseNoConnectionException,
1024             GoldenGateDatabaseSqlException {
1025         String request = "SELECT " + selectAllFields + " FROM " + table;
1026         if (globalstep != null) {
1027             request += " WHERE (" + Columns.GLOBALSTEP.name() + " = " +
1028                     globalstep.ordinal();
1029             if (globalstep == TASKSTEP.ERRORTASK) {
1030                 request += " OR "+Columns.UPDATEDINFO.name() + " = "+
1031                     UpdatedInfo.INERROR.ordinal()+") AND ";
1032             } else {
1033                 request += ") AND ";
1034             }
1035             request += getLimitWhereCondition();
1036         } else {
1037             request += " WHERE "+getLimitWhereCondition();
1038         }
1039         request += " ORDER BY " + Columns.STARTTRANS.name() + " DESC ";
1040         request = DbModelFactory.dbModel.limitRequest(selectAllFields, request, limit);
1041         return new DbPreparedStatement(session, request);
1042     }
1043 
1044     /**
1045      *
1046      * @param preparedStatement
1047      * @param srcrequest
1048      * @param limit
1049      * @param orderby
1050      * @param startid
1051      * @param stopid
1052      * @param start
1053      * @param stop
1054      * @param rule
1055      * @param req
1056      * @param pending
1057      * @param transfer
1058      * @param error
1059      * @param done
1060      * @param all
1061      * @return The DbPreparedStatement already prepared according to select or
1062      *         delete command
1063      * @throws GoldenGateDatabaseNoConnectionException
1064      * @throws GoldenGateDatabaseSqlException
1065      */
1066     private static DbPreparedStatement getFilterCondition(
1067             DbPreparedStatement preparedStatement, String srcrequest, int limit,
1068             String orderby, String startid, String stopid, Timestamp start, Timestamp stop, String rule,
1069             String req, boolean pending, boolean transfer, boolean error,
1070             boolean done, boolean all) throws GoldenGateDatabaseNoConnectionException,
1071             GoldenGateDatabaseSqlException {
1072         String request = srcrequest;
1073         if (startid == null && stopid == null &&
1074                 start == null && stop == null && rule == null && req == null && all) {
1075             // finish
1076             if (limit > 0) {
1077                 request = DbModelFactory.dbModel.limitRequest(selectAllFields,
1078                         request+orderby, limit);
1079             } else {
1080                 request = request+orderby;
1081             }
1082             preparedStatement.createPrepareStatement(request);
1083             return preparedStatement;
1084         }
1085         request += " WHERE ";
1086         StringBuilder scondition = new StringBuilder();
1087         boolean hasCondition = false;
1088         if (start != null & stop != null) {
1089             scondition.append(Columns.STARTTRANS.name());
1090             scondition.append(" >= ? AND ");
1091             scondition.append(Columns.STARTTRANS.name());
1092             scondition.append(" <= ? ");
1093             hasCondition = true;
1094         } else if (start != null) {
1095             scondition.append(Columns.STARTTRANS.name());
1096             scondition.append(" >= ? ");
1097             hasCondition = true;
1098         } else if (stop != null) {
1099             scondition.append(Columns.STARTTRANS.name());
1100             scondition.append(" <= ? ");
1101             hasCondition = true;
1102         }
1103         if (startid != null) {
1104             if (hasCondition) {
1105                 scondition.append(" AND ");
1106             }
1107             hasCondition = true;
1108             scondition.append(Columns.SPECIALID.name());
1109             scondition.append(" >= ? ");
1110         }
1111         if (stopid != null) {
1112             if (hasCondition) {
1113                 scondition.append(" AND ");
1114             }
1115             hasCondition = true;
1116             scondition.append(Columns.SPECIALID.name());
1117             scondition.append(" <= ? ");
1118         }
1119         if (rule != null) {
1120             if (hasCondition) {
1121                 scondition.append(" AND ");
1122             }
1123             hasCondition = true;
1124             scondition.append(Columns.IDRULE.name());
1125             scondition.append(" LIKE '%");
1126             scondition.append(rule);
1127             scondition.append("%' ");
1128         }
1129         if (req != null) {
1130             if (hasCondition) {
1131                 scondition.append(" AND ");
1132             }
1133             hasCondition = true;
1134             scondition.append("( ");
1135             scondition.append(Columns.REQUESTED.name());
1136             scondition.append(" LIKE '%");
1137             scondition.append(req);
1138             scondition.append("%' OR ");
1139             scondition.append(Columns.REQUESTER.name());
1140             scondition.append(" LIKE '%");
1141             scondition.append(req);
1142             scondition.append("%' )");
1143         }
1144         if (!all) {
1145             if (hasCondition) {
1146                 scondition.append(" AND ");
1147             }
1148             hasCondition = true;
1149             scondition.append("( ");
1150             boolean hasone = false;
1151             if (pending) {
1152                 scondition.append(Columns.UPDATEDINFO.name());
1153                 scondition.append(" = ");
1154                 scondition.append(UpdatedInfo.TOSUBMIT.ordinal());
1155                 hasone = true;
1156             }
1157             if (transfer) {
1158                 if (hasone) {
1159                     scondition.append(" OR ");
1160                 }
1161                 scondition.append("( ");
1162                 scondition.append(Columns.UPDATEDINFO.name());
1163                 scondition.append(" = ");
1164                 scondition.append(UpdatedInfo.RUNNING.ordinal());
1165                 scondition.append(" )");
1166                 hasone = true;
1167             }
1168             if (error) {
1169                 if (hasone) {
1170                     scondition.append(" OR ");
1171                 }
1172                 scondition.append(Columns.GLOBALSTEP.name());
1173                 scondition.append(" = ");
1174                 scondition.append(TASKSTEP.ERRORTASK.ordinal());
1175                 scondition.append(" OR ");
1176                 scondition.append(Columns.UPDATEDINFO.name());
1177                 scondition.append(" = ");
1178                 scondition.append(UpdatedInfo.INERROR.ordinal());
1179                 scondition.append(" OR ");
1180                 scondition.append(Columns.UPDATEDINFO.name());
1181                 scondition.append(" = ");
1182                 scondition.append(UpdatedInfo.INTERRUPTED.ordinal());
1183                 hasone = true;
1184             }
1185             if (done) {
1186                 if (hasone) {
1187                     scondition.append(" OR ");
1188                 }
1189                 scondition.append(Columns.GLOBALSTEP.name());
1190                 scondition.append(" = ");
1191                 scondition.append(TASKSTEP.ALLDONETASK.ordinal());
1192                 scondition.append(" OR ");
1193                 scondition.append(Columns.UPDATEDINFO.name());
1194                 scondition.append(" = ");
1195                 scondition.append(UpdatedInfo.DONE.ordinal());
1196             }
1197             if (scondition.length() <= 3) {
1198                 scondition.append(Columns.UPDATEDINFO.name());
1199                 scondition.append(" IS NOT NULL ");
1200             }
1201             scondition.append(" )");
1202         }
1203         if (limit > 0) {
1204             scondition.insert(0, request);
1205             scondition.append(orderby);
1206             request = scondition.toString();
1207             request = DbModelFactory.dbModel.limitRequest(selectAllFields,
1208                 request, limit);
1209         } else {
1210             scondition.insert(0, request);
1211             scondition.append(orderby);
1212             request = scondition.toString();
1213         }
1214         preparedStatement.createPrepareStatement(request);
1215         int rank = 1;
1216         try {
1217             if (start != null & stop != null) {
1218                 preparedStatement.getPreparedStatement().setTimestamp(rank,
1219                         start);
1220                 rank ++;
1221                 preparedStatement.getPreparedStatement().setTimestamp(rank,
1222                         stop);
1223                 rank ++;
1224             } else if (start != null) {
1225                 preparedStatement.getPreparedStatement().setTimestamp(rank,
1226                         start);
1227                 rank ++;
1228             } else if (stop != null) {
1229                 preparedStatement.getPreparedStatement().setTimestamp(rank,
1230                         stop);
1231                 rank ++;
1232             }
1233             if (startid != null) {
1234                 long value = Long.parseLong(startid);
1235                 preparedStatement.getPreparedStatement().setLong(rank,
1236                         value);
1237                 rank ++;
1238             }
1239             if (stopid != null) {
1240                 long value = Long.parseLong(stopid);
1241                 preparedStatement.getPreparedStatement().setLong(rank,
1242                         value);
1243                 rank ++;
1244             }
1245         } catch (SQLException e) {
1246             preparedStatement.realClose();
1247             throw new GoldenGateDatabaseSqlException(e);
1248         }
1249         return preparedStatement;
1250     }
1251 
1252     /**
1253      *
1254      * @param session
1255      * @param limit
1256      * @param orderBySpecialId
1257      * @param startid
1258      * @param stopid
1259      * @param start
1260      * @param stop
1261      * @param rule
1262      * @param req
1263      * @param pending
1264      * @param transfer
1265      * @param error
1266      * @param done
1267      * @param all
1268      * @return the DbPreparedStatement according to the filter
1269      * @throws GoldenGateDatabaseNoConnectionException
1270      * @throws GoldenGateDatabaseSqlException
1271      */
1272     public static DbPreparedStatement getFilterPrepareStatement(
1273             DbSession session, int limit, boolean orderBySpecialId, String startid, String stopid,
1274             Timestamp start, Timestamp stop, String rule,
1275             String req, boolean pending, boolean transfer, boolean error,
1276             boolean done, boolean all) throws GoldenGateDatabaseNoConnectionException,
1277             GoldenGateDatabaseSqlException {
1278         DbPreparedStatement preparedStatement = new DbPreparedStatement(session);
1279         String request = "SELECT " + selectAllFields + " FROM " + table;
1280         String orderby;
1281         if (startid == null && stopid == null &&
1282                 start == null && stop == null && rule == null && req == null && all) {
1283             orderby = " WHERE "+getLimitWhereCondition();
1284         } else {
1285             orderby = " AND " + getLimitWhereCondition();
1286         }
1287         if (orderBySpecialId) {
1288             orderby += " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
1289         } else {
1290             orderby += " ORDER BY " + Columns.STARTTRANS.name() + " DESC ";
1291         }
1292         return getFilterCondition(preparedStatement, request, limit, orderby,
1293                 startid, stopid, start, stop, rule,
1294                 req, pending, transfer, error, done, all);
1295     }
1296 
1297     /**
1298      *
1299      * @param session
1300      * @param info
1301      * @param orderByStart If true, sort on Start ; If false, does not set the limit on start
1302      * @param limit
1303      * @return the DbPreparedStatement for getting Updated Object
1304      * @throws GoldenGateDatabaseNoConnectionException
1305      * @throws GoldenGateDatabaseSqlException
1306      */
1307     public static DbPreparedStatement getSelectFromInfoPrepareStatement(DbSession session,
1308             UpdatedInfo info, boolean orderByStart, int limit)
1309             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1310         String request = "SELECT " + selectAllFields+
1311                 " FROM " + table + " WHERE " + Columns.UPDATEDINFO.name() +
1312                 " = " + info.ordinal()+ 
1313                 " AND "+Columns.STARTTRANS.name() + " <= ? AND " +getLimitWhereCondition();
1314         if (orderByStart) {
1315             request += " ORDER BY " + Columns.STARTTRANS.name() + " DESC ";
1316         }
1317         request =
1318             DbModelFactory.dbModel.limitRequest(selectAllFields, request, limit);
1319         DbPreparedStatement pstt = new DbPreparedStatement(session, request);
1320         return pstt;
1321     }
1322     /**
1323     *
1324     * @param session
1325     * @return the DbPreparedStatement for getting Updated Object
1326     * @throws GoldenGateDatabaseNoConnectionException
1327     * @throws GoldenGateDatabaseSqlException
1328     */
1329    public static DbPreparedStatement getCountInfoPrepareStatement(DbSession session)
1330            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1331        String request = "SELECT COUNT(" + Columns.SPECIALID.name()+
1332                ") FROM " + table + " WHERE " + 
1333                Columns.STARTTRANS.name() + " >= ? AND " +getLimitWhereCondition() +
1334                " AND " + Columns.UPDATEDINFO.name() +" = ? ";
1335        DbPreparedStatement pstt = new DbPreparedStatement(session, request);
1336        session.addLongTermPreparedStatement(pstt);
1337        return pstt;
1338    }
1339 
1340    /**
1341     * 
1342     * @param pstt
1343     * @param info
1344     * @param time
1345     * @return the number of elements (COUNT) from the statement
1346     */
1347    public static long getResultCountPrepareStatement(DbPreparedStatement pstt, UpdatedInfo info,
1348            long time) {
1349        long result = 0;
1350        try {
1351            finishSelectOrCountPrepareStatement(pstt, time);
1352            pstt.getPreparedStatement().setInt(2, info.ordinal());
1353            pstt.executeQuery();
1354            if (pstt.getNext()) {
1355                result = pstt.getResultSet().getLong(1);
1356            }
1357         } catch (GoldenGateDatabaseNoConnectionException e) {
1358         } catch (GoldenGateDatabaseSqlException e) {
1359         } catch (SQLException e) {
1360         } finally {
1361             pstt.close();
1362         }
1363        return result;
1364    }
1365 
1366    /**
1367     * @param session
1368     * @param globalstep
1369     * @return the DbPreparedStatement for getting Runner according to
1370     *         globalstep ordered by start
1371     * @throws GoldenGateDatabaseNoConnectionException
1372     * @throws GoldenGateDatabaseSqlException
1373     */
1374    public static DbPreparedStatement getCountStepPrepareStatement(DbSession session,
1375            TASKSTEP globalstep) throws GoldenGateDatabaseNoConnectionException,
1376            GoldenGateDatabaseSqlException {
1377        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
1378        if (globalstep != null) {
1379            request += " WHERE " + Columns.GLOBALSTEP.name() + " = " +
1380                    globalstep.ordinal()+" AND ";
1381            request += Columns.STARTTRANS.name() + " >= ? AND " + getLimitWhereCondition();
1382        } else {
1383            request += " WHERE "+Columns.STARTTRANS.name() + " >= ? AND " + getLimitWhereCondition();
1384        }
1385        DbPreparedStatement prep = new DbPreparedStatement(session, request);
1386        session.addLongTermPreparedStatement(prep);
1387        return prep;
1388    }
1389    /**
1390     * @param session
1391     * @return the DbPreparedStatement for getting Runner according to status ordered by start
1392     * @throws GoldenGateDatabaseNoConnectionException
1393     * @throws GoldenGateDatabaseSqlException
1394     */
1395    public static DbPreparedStatement getCountStatusPrepareStatement(
1396            DbSession session)
1397            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1398        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
1399        request += " WHERE "+Columns.STARTTRANS.name() + " >= ? ";
1400        request += " AND " + Columns.INFOSTATUS.name() + " = ? AND "+getLimitWhereCondition();
1401        DbPreparedStatement prep = new DbPreparedStatement(session, request);
1402        session.addLongTermPreparedStatement(prep);
1403        return prep;
1404    }
1405    /**
1406     * 
1407     * @param pstt
1408     * @param error
1409     * @param time
1410     * @return the number of elements (COUNT) from the statement
1411     */
1412    public static long getResultCountPrepareStatement(DbPreparedStatement pstt, ErrorCode error,
1413            long time) {
1414        long result = 0;
1415        try {
1416            finishSelectOrCountPrepareStatement(pstt, time);
1417            pstt.getPreparedStatement().setString(2, error.getCode());
1418            pstt.executeQuery();
1419            if (pstt.getNext()) {
1420                result = pstt.getResultSet().getLong(1);
1421            }
1422         } catch (GoldenGateDatabaseNoConnectionException e) {
1423         } catch (GoldenGateDatabaseSqlException e) {
1424         } catch (SQLException e) {
1425         } finally {
1426             pstt.close();
1427         }
1428        return result;
1429    }
1430    /**
1431     * Only running transfers
1432     * @param session
1433     * @param status
1434     * @return the DbPreparedStatement for getting Runner according to status ordered by start
1435     * @throws GoldenGateDatabaseNoConnectionException
1436     * @throws GoldenGateDatabaseSqlException
1437     */
1438    public static DbPreparedStatement getCountStatusRunningPrepareStatement(
1439            DbSession session, ErrorCode status)
1440            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1441        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
1442        if (status != null) {
1443            request += " WHERE " + Columns.STEPSTATUS.name() + " = '" +
1444                    status.getCode() + "' AND "+getLimitWhereCondition();
1445        } else {
1446            request += " WHERE "+getLimitWhereCondition();
1447        }
1448        request += " AND "+Columns.STARTTRANS.name() + " >= ? ";
1449        request += " AND "+Columns.UPDATEDINFO.name() + " = " + UpdatedInfo.RUNNING.ordinal();
1450        DbPreparedStatement prep = new DbPreparedStatement(session, request);
1451        session.addLongTermPreparedStatement(prep);
1452        return prep;
1453    }
1454    /**
1455     * Running or not transfers are concerned
1456     * @param session
1457     * @param in True for Incoming, False for Outgoing
1458     * @return the DbPreparedStatement for getting Runner according to in or out going way and Error
1459     * @throws GoldenGateDatabaseNoConnectionException
1460     * @throws GoldenGateDatabaseSqlException
1461     */
1462    public static DbPreparedStatement getCountInOutErrorPrepareStatement(
1463            DbSession session, boolean in)
1464            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1465        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
1466        String requesterd;
1467        String from = Configuration.configuration.HOST_ID;
1468        String sfrom = Configuration.configuration.HOST_SSLID;
1469        if (in) {
1470            requesterd = Columns.REQUESTED.name();
1471        } else {
1472            requesterd = Columns.REQUESTER.name();
1473        }
1474        if (from != null & sfrom != null) {
1475            request += " WHERE ((" + requesterd + " = '" +
1476                from + "' OR " + requesterd + " = '" +sfrom+ "') ";
1477        } else if (from != null) {
1478            request += " WHERE (" + requesterd + " = '" + from + "' ";
1479        } else {
1480            request += " WHERE (" + requesterd + " = '" + sfrom+ "' ";
1481        }
1482        request += " AND "+getLimitWhereCondition()+") ";
1483        request += " AND "+Columns.STARTTRANS.name() + " >= ? ";
1484        request += " AND " + Columns.UPDATEDINFO.name() +" = "+UpdatedInfo.INERROR.ordinal();
1485        DbPreparedStatement prep = new DbPreparedStatement(session, request);
1486        session.addLongTermPreparedStatement(prep);
1487        return prep;
1488    }
1489 
1490    /**
1491     * Running or not transfers are concerned
1492     * @param session
1493     * @param in True for Incoming, False for Outgoing
1494     * @param running True for Running only, False for all
1495     * @return the DbPreparedStatement for getting Runner according to in or out going way
1496     * @throws GoldenGateDatabaseNoConnectionException
1497     * @throws GoldenGateDatabaseSqlException
1498     */
1499    public static DbPreparedStatement getCountInOutRunningPrepareStatement(
1500            DbSession session, boolean in, boolean running)
1501            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1502        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
1503        String requesterd;
1504        String from = Configuration.configuration.HOST_ID;
1505        String sfrom = Configuration.configuration.HOST_SSLID;
1506        if (in) {
1507            requesterd = Columns.REQUESTED.name();
1508        } else {
1509            requesterd = Columns.REQUESTER.name();
1510        }
1511        if (from != null & sfrom != null) {
1512            request += " WHERE ((" + requesterd + " = '" +
1513                from + "' OR " + requesterd + " = '" +sfrom+ "') ";
1514        } else if (from != null) {
1515            request += " WHERE (" + requesterd + " = '" + from + "' ";
1516        } else {
1517            request += " WHERE (" + requesterd + " = '" + sfrom+ "' ";
1518        }
1519        request += " AND "+getLimitWhereCondition()+") ";
1520        request += " AND "+Columns.STARTTRANS.name() + " >= ? ";
1521        if (running) {
1522            request += " AND "+Columns.UPDATEDINFO.name() + " = " + UpdatedInfo.RUNNING.ordinal();
1523        }
1524        DbPreparedStatement prep = new DbPreparedStatement(session, request);
1525        session.addLongTermPreparedStatement(prep);
1526        return prep;
1527    }
1528    /**
1529     * 
1530     * @param pstt
1531     * @return the number of elements (COUNT) from the statement
1532     */
1533    public static long getResultCountPrepareStatement(DbPreparedStatement pstt) {
1534        long result = 0;
1535        try {
1536             pstt.executeQuery();
1537             if (pstt.getNext()) {
1538                 result = pstt.getResultSet().getLong(1);
1539             }
1540         } catch (GoldenGateDatabaseNoConnectionException e) {
1541         } catch (GoldenGateDatabaseSqlException e) {
1542         } catch (SQLException e) {
1543         } finally {
1544             pstt.close();
1545         }
1546        return result;
1547    }
1548     /**
1549      * Set the current time in the given updatedPreparedStatement
1550      * @param pstt
1551      * @throws GoldenGateDatabaseNoConnectionException
1552      * @throws GoldenGateDatabaseSqlException
1553      */
1554     public static void finishSelectOrCountPrepareStatement(DbPreparedStatement pstt) throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1555         finishSelectOrCountPrepareStatement(pstt, System.currentTimeMillis());
1556     }
1557     /**
1558      * Set the current time in the given updatedPreparedStatement
1559      * @param pstt
1560      * @throws GoldenGateDatabaseNoConnectionException
1561      * @throws GoldenGateDatabaseSqlException
1562      */
1563     public static void finishSelectOrCountPrepareStatement(DbPreparedStatement pstt, long time) throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1564         Timestamp startlimit = new Timestamp(time);
1565         try {
1566             pstt.getPreparedStatement().setTimestamp(1, startlimit);
1567         } catch (SQLException e) {
1568             logger.error("Database SQL Error: Cannot set timestamp", e);
1569             throw new GoldenGateDatabaseSqlException("Cannot set timestamp",e);
1570         }
1571     }
1572 
1573     /**
1574      *
1575      * @param session
1576      * @param start
1577      * @param stop
1578      * @return the DbPreparedStatement for getting Selected Object, whatever their status
1579      * @throws GoldenGateDatabaseNoConnectionException
1580      * @throws GoldenGateDatabaseSqlException
1581      */
1582     public static DbPreparedStatement getLogPrepareStatement(DbSession session,
1583             Timestamp start, Timestamp stop)
1584             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1585         DbPreparedStatement preparedStatement = new DbPreparedStatement(session);
1586         String request = "SELECT " + selectAllFields + " FROM " + table;
1587         if (start != null & stop != null) {
1588             request += " WHERE " + Columns.STARTTRANS.name() + " >= ? AND " +
1589                     Columns.STARTTRANS.name() + " <= ? AND "+getLimitWhereCondition()+
1590                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
1591             preparedStatement.createPrepareStatement(request);
1592             try {
1593                 preparedStatement.getPreparedStatement().setTimestamp(1, start);
1594                 preparedStatement.getPreparedStatement().setTimestamp(2, stop);
1595             } catch (SQLException e) {
1596                 preparedStatement.realClose();
1597                 throw new GoldenGateDatabaseSqlException(e);
1598             }
1599         } else if (start != null) {
1600             request += " WHERE " + Columns.STARTTRANS.name() +
1601                     " >= ? AND "+getLimitWhereCondition()+
1602                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
1603             preparedStatement.createPrepareStatement(request);
1604             try {
1605                 preparedStatement.getPreparedStatement().setTimestamp(1, start);
1606             } catch (SQLException e) {
1607                 preparedStatement.realClose();
1608                 throw new GoldenGateDatabaseSqlException(e);
1609             }
1610         } else if (stop != null) {
1611             request += " WHERE " + Columns.STARTTRANS.name() +
1612                     " <= ? AND "+getLimitWhereCondition()+
1613                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
1614             preparedStatement.createPrepareStatement(request);
1615             try {
1616                 preparedStatement.getPreparedStatement().setTimestamp(1, stop);
1617             } catch (SQLException e) {
1618                 preparedStatement.realClose();
1619                 throw new GoldenGateDatabaseSqlException(e);
1620             }
1621         } else {
1622             request += " WHERE "+getLimitWhereCondition()+
1623                 " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
1624             preparedStatement.createPrepareStatement(request);
1625         }
1626         return preparedStatement;
1627     }
1628 
1629     /**
1630      * purge in same interval all runners with globallaststep as ALLDONETASK or
1631      * UpdatedInfo as Done
1632      *
1633      * @param session
1634      * @param start
1635      * @param stop
1636      * @return the number of log purged
1637      * @throws GoldenGateDatabaseNoConnectionException
1638      * @throws GoldenGateDatabaseSqlException
1639      */
1640     public static int purgeLogPrepareStatement(DbSession session,
1641             Timestamp start, Timestamp stop)
1642             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
1643         DbPreparedStatement preparedStatement = new DbPreparedStatement(session);
1644         String request = "DELETE FROM " + table + " WHERE (" +
1645                 Columns.GLOBALLASTSTEP + " = " +TASKSTEP.ALLDONETASK.ordinal() + " OR " +
1646                 Columns.UPDATEDINFO + " = " +UpdatedInfo.DONE.ordinal() +
1647                 ") AND "+getLimitWhereCondition();
1648         try {
1649             if (start != null & stop != null) {
1650                 request += " AND " + Columns.STARTTRANS.name() + " >= ? AND " +
1651                         Columns.STOPTRANS.name() + " <= ? ";
1652                 preparedStatement.createPrepareStatement(request);
1653                 try {
1654                     preparedStatement.getPreparedStatement().setTimestamp(1, start);
1655                     preparedStatement.getPreparedStatement().setTimestamp(2, stop);
1656                 } catch (SQLException e) {
1657                     preparedStatement.realClose();
1658                     throw new GoldenGateDatabaseSqlException(e);
1659                 }
1660             } else if (start != null) {
1661                 request += " AND " + Columns.STARTTRANS.name() + " >= ? ";
1662                 preparedStatement.createPrepareStatement(request);
1663                 try {
1664                     preparedStatement.getPreparedStatement().setTimestamp(1, start);
1665                 } catch (SQLException e) {
1666                     preparedStatement.realClose();
1667                     throw new GoldenGateDatabaseSqlException(e);
1668                 }
1669             } else if (stop != null) {
1670                 request += " AND " + Columns.STOPTRANS.name() + " <= ? ";
1671                 preparedStatement.createPrepareStatement(request);
1672                 try {
1673                     preparedStatement.getPreparedStatement().setTimestamp(1, stop);
1674                 } catch (SQLException e) {
1675                     preparedStatement.realClose();
1676                     throw new GoldenGateDatabaseSqlException(e);
1677                 }
1678             } else {
1679                 preparedStatement.createPrepareStatement(request);
1680             }
1681             int nb = preparedStatement.executeUpdate();
1682             logger.info("Purge " + nb + " from " + request);
1683             return nb;
1684         } finally {
1685             preparedStatement.realClose();
1686         }
1687     }
1688 
1689     /**
1690      *
1691      * @param session
1692      * @param startid
1693      * @param stopid
1694      * @param start
1695      * @param stop
1696      * @param rule
1697      * @param req
1698      * @param pending
1699      * @param transfer
1700      * @param error
1701      * @param done
1702      * @param all
1703      * @return the DbPreparedStatement according to the filter and
1704      * ALLDONE, ERROR globallaststep
1705      * @throws GoldenGateDatabaseNoConnectionException
1706      * @throws GoldenGateDatabaseSqlException
1707      */
1708     public static int purgeLogPrepareStatement(
1709             DbSession session, String startid, String stopid,
1710             Timestamp start, Timestamp stop, String rule,
1711             String req, boolean pending, boolean transfer, boolean error,
1712             boolean done, boolean all) throws GoldenGateDatabaseNoConnectionException,
1713             GoldenGateDatabaseSqlException {
1714         DbPreparedStatement preparedStatement = new DbPreparedStatement(session);
1715         String request = "DELETE FROM " + table;
1716         String orderby;
1717         if (startid == null && stopid == null && start == null && stop == null &&
1718                 rule == null && req == null && all) {
1719             orderby = " WHERE (" +
1720                 Columns.GLOBALLASTSTEP + " = " +TASKSTEP.ALLDONETASK.ordinal() + " OR " +
1721                 Columns.UPDATEDINFO + " = " +UpdatedInfo.DONE.ordinal() +
1722                 ") AND "+getLimitWhereCondition();
1723         } else {
1724             if (all) {
1725                 orderby = " AND (" +
1726                     Columns.GLOBALLASTSTEP + " = " +TASKSTEP.ALLDONETASK.ordinal() + " OR " +
1727                     Columns.UPDATEDINFO + " = " +UpdatedInfo.DONE.ordinal() + " OR " +
1728                     Columns.UPDATEDINFO + " = " +UpdatedInfo.INERROR.ordinal() +
1729                     ") AND "+getLimitWhereCondition();
1730             } else {
1731                 orderby = " AND "+
1732                     Columns.UPDATEDINFO + " <> " +UpdatedInfo.RUNNING.ordinal()+
1733                     " AND "+getLimitWhereCondition();// limit by field
1734             }
1735         }
1736         int nb = 0;
1737         try {
1738             preparedStatement = getFilterCondition(preparedStatement, request, 0,
1739                     orderby, startid, stopid, start, stop, rule,
1740                     req, pending, transfer, error, done, all);
1741             nb = preparedStatement.executeUpdate();
1742             logger.info("Purge " + nb + " from " + request);
1743         } finally {
1744             if (preparedStatement != null) {
1745                 preparedStatement.realClose();
1746             }
1747         }
1748         return nb;
1749     }
1750 
1751     /**
1752      * Change RUNNING, INTERRUPTED to TOSUBMIT TaskRunner from database.
1753      * This method is to be used when the commander is starting the very first time,
1754      * in order to be ready to rerun tasks that are pending.
1755      *
1756      * @param session
1757      * @throws GoldenGateDatabaseNoConnectionException
1758      */
1759     public static void resetToSubmit(DbSession session)
1760             throws GoldenGateDatabaseNoConnectionException {
1761         // Change RUNNING and INTERRUPTED to TOSUBMIT since they should be ready
1762         String request = "UPDATE " + table + " SET " +
1763                 Columns.UPDATEDINFO.name() + "=" +
1764                 AbstractDbData.UpdatedInfo.TOSUBMIT.ordinal()+
1765                 " WHERE (" + Columns.UPDATEDINFO.name() + " = " +
1766                 AbstractDbData.UpdatedInfo.RUNNING.ordinal() +
1767                 " OR "+ Columns.UPDATEDINFO.name() + " = " +
1768                 AbstractDbData.UpdatedInfo.INTERRUPTED.ordinal()+") AND "+
1769                 getLimitWhereCondition();
1770         DbPreparedStatement initial = new DbPreparedStatement(session);
1771         try {
1772             initial.createPrepareStatement(request);
1773             initial.executeUpdate();
1774         } catch (GoldenGateDatabaseNoConnectionException e) {
1775             logger.error("Database No Connection Error: Cannot execute Commander", e);
1776             return;
1777         } catch (GoldenGateDatabaseSqlException e) {
1778             logger.error("Database SQL Error: Cannot execute Commander", e);
1779             return;
1780         } finally {
1781             initial.close();
1782         }
1783     }
1784 
1785     /**
1786      * Change CompleteOk+ALLDONETASK to Updated = DONE TaskRunner from database.
1787      * This method is a clean function to be used for instance before log export or
1788      * at the very beginning of the commander.
1789      *
1790      * @param session
1791      * @throws GoldenGateDatabaseNoConnectionException
1792      */
1793     public static void changeFinishedToDone(DbSession session)
1794             throws GoldenGateDatabaseNoConnectionException {
1795         // Update all UpdatedInfo to DONE where GlobalLastStep = ALLDONETASK and
1796         // status = CompleteOk
1797         String request = "UPDATE " + table + " SET " +
1798                 Columns.UPDATEDINFO.name() + "=" +
1799                 AbstractDbData.UpdatedInfo.DONE.ordinal()+
1800                 " WHERE " + Columns.UPDATEDINFO.name() + " <> " +
1801                 AbstractDbData.UpdatedInfo.DONE.ordinal() + " AND " +
1802                 Columns.UPDATEDINFO.name() + " > 0 AND " +
1803                 Columns.GLOBALLASTSTEP.name() + " = " +
1804                 TASKSTEP.ALLDONETASK.ordinal() + " AND " +
1805                 Columns.STEPSTATUS.name() + " = '" +
1806                 ErrorCode.CompleteOk.getCode() + "' AND "+
1807                 getLimitWhereCondition();
1808         DbPreparedStatement initial = new DbPreparedStatement(session);
1809         try {
1810             initial.createPrepareStatement(request);
1811             initial.executeUpdate();
1812         } catch (GoldenGateDatabaseNoConnectionException e) {
1813             logger.error("Database No Connection Error: Cannot execute Commander", e);
1814             return;
1815         } catch (GoldenGateDatabaseSqlException e) {
1816             logger.error("Database SQL Error: Cannot execute Commander", e);
1817             return;
1818         } finally {
1819             initial.realClose();
1820         }
1821     }
1822 
1823     /**
1824      * Reset the runner (ready to be run again)
1825      *
1826      * @return True if OK, False if already finished
1827      */
1828     public boolean reset() {
1829         // Reset the status if already stopped and not finished
1830         if (this.getStatus() != ErrorCode.CompleteOk) {
1831             // restart
1832             switch (TASKSTEP.values()[this.getGloballaststep()]) {
1833                 case PRETASK:
1834                     // restart
1835                     this.setPreTask();
1836                     this.setExecutionStatus(ErrorCode.InitOk);
1837                     break;
1838                 case TRANSFERTASK:
1839                     // continue
1840                     int newrank = this.getRank();
1841                     this.setTransferTask(newrank);
1842                     this.setExecutionStatus(ErrorCode.PreProcessingOk);
1843                     break;
1844                 case POSTTASK:
1845                     // restart
1846                     this.setPostTask();
1847                     this.setExecutionStatus(ErrorCode.TransferOk);
1848                     break;
1849             }
1850             this.changeUpdatedInfo(UpdatedInfo.UNKNOWN);
1851             this.setErrorExecutionStatus(this.status);
1852             return true;
1853         } else {
1854             // Already finished
1855             return false;
1856         }
1857     }
1858     /**
1859      * Decrease if necessary the rank
1860      */
1861     public void restartRank() {
1862         if (! this.isSender) {
1863             int newrank = this.getRank();
1864             if (newrank > 0) {
1865                 logger.debug("Decrease Rank Restart of -"+Configuration.RANKRESTART+
1866                         " from "+newrank);
1867                 newrank -= Configuration.RANKRESTART;
1868                 if (newrank <= 0) {
1869                     newrank = 1;
1870                 }
1871                 if (this.getRank() != newrank) {
1872                     logger.warn("Decreased Rank Restart at rank: "+newrank+" for {}", this);
1873                 }
1874             }
1875             this.setTransferTask(newrank);
1876         }
1877     }
1878     /**
1879      * Make this Runner ready for restart
1880      * @param submit True to resubmit this task, else False to keep it as running (only reset)
1881      * @return True if OK or False if Already finished or if submitted and the request is
1882      *          a selfRequested and is not ready to restart locally
1883      * @throws OpenR66RunnerErrorException
1884      */
1885     public boolean restart(boolean submit) throws OpenR66RunnerErrorException {
1886         // Restart if not Requested
1887         if (submit) {
1888             if (isSelfRequested() && (this.globallaststep < TASKSTEP.POSTTASK.ordinal())) {
1889                 return false;
1890             }
1891         }
1892         // Restart if already stopped and not finished
1893         if (reset()) {
1894             // if not submit and transfertask and receiver AND not requester
1895             // If requester and receiver => rank is already decreased when request is sent
1896             if ((!submit) && (this.globalstep == TASKSTEP.TRANSFERTASK.ordinal()) &&
1897                     (! this.isSender) && (this.isSelfRequested())) {
1898                 logger.debug("Will try to restart transfer {}",this);
1899                 this.restartRank();
1900                 logger.debug("New restart for transfer is {}",this);
1901             }
1902             if (submit) {
1903                 this.changeUpdatedInfo(UpdatedInfo.TOSUBMIT);
1904             } else {
1905                 this.changeUpdatedInfo(UpdatedInfo.RUNNING);
1906             }
1907             this.saveStatus();
1908             return true;
1909         } else {
1910             // Already finished so DONE
1911             this.setAllDone();
1912             this.setErrorExecutionStatus(ErrorCode.QueryAlreadyFinished);
1913             try {
1914                 this.saveStatus();
1915             } catch (OpenR66RunnerErrorException e) {
1916             }
1917             return false;
1918         }
1919     }
1920 
1921     /**
1922      * Stop or Cancel a Runner from database point of view
1923      * @param code
1924      * @return True if correctly stopped or canceled
1925      */
1926     public boolean stopOrCancelRunner(ErrorCode code) {
1927         try {
1928             if (! isFinished()) {
1929                 reset();
1930                 switch (code) {
1931                     case CanceledTransfer:
1932                     case StoppedTransfer:
1933                     case RemoteShutdown:
1934                         this.changeUpdatedInfo(UpdatedInfo.INERROR);
1935                         break;
1936                     default:
1937                         this.changeUpdatedInfo(UpdatedInfo.INTERRUPTED);
1938                 }
1939                 update();
1940                 logger.warn("StopOrCancel: {}\n    {}",code.mesg,this.toShortString());
1941                 return true;
1942             } else {
1943                 // is finished so do nothing
1944             }
1945         } catch (GoldenGateDatabaseException e) {
1946         }
1947         return false;
1948     }
1949     /*
1950      * (non-Javadoc)
1951      *
1952      * @see openr66.databaseold.data.AbstractDbData#changeUpdatedInfo(UpdatedInfo)
1953      */
1954     @Override
1955     public void changeUpdatedInfo(UpdatedInfo info) {
1956         updatedInfo = info.ordinal();
1957         allFields[Columns.UPDATEDINFO.ordinal()].setValue(updatedInfo);
1958         isSaved = false;
1959     }
1960     /**
1961      * Set the ErrorCode for the UpdatedInfo
1962      * @param code
1963      */
1964     public void setErrorExecutionStatus(ErrorCode code) {
1965         if (infostatus != code) {
1966             infostatus = code;
1967             allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
1968             isSaved = false;
1969         }
1970     }
1971     /**
1972      *
1973      * @return The current UpdatedInfo value
1974      */
1975     public UpdatedInfo getUpdatedInfo() {
1976         return UpdatedInfo.values()[updatedInfo];
1977     }
1978     /**
1979      *
1980      * @return the error code associated with the Updated Info
1981      */
1982     public ErrorCode getErrorInfo() {
1983         return infostatus;
1984     }
1985     
1986     /**
1987      * @return the step
1988      */
1989     public int getStep() {
1990         return step;
1991     }
1992 
1993     /**
1994      * @return the rescheduledTransfer
1995      */
1996     public boolean isRescheduledTransfer() {
1997         return rescheduledTransfer;
1998     }
1999 
2000     /**
2001      * Set this DbTaskRunner as rescheduled (valid only while still in memory) 
2002      */
2003     public void setRescheduledTransfer() {
2004         this.rescheduledTransfer = true;
2005     }
2006 
2007     /**
2008      * To set the rank at startup of the request if the request specify a
2009      * specific rank
2010      *
2011      * @param rank
2012      *            the rank to set
2013      */
2014     public void setRankAtStartup(int rank) {
2015         if (this.rank > rank) {
2016             this.rank = rank;
2017             allFields[Columns.RANK.ordinal()].setValue(this.rank);
2018             isSaved = false;
2019         }
2020     }
2021 
2022     /**
2023      * @param filename
2024      *            the filename to set
2025      */
2026     public void setFilename(String filename) {
2027         if (!this.filename.equals(filename)) {
2028             this.filename = filename;
2029             allFields[Columns.FILENAME.ordinal()].setValue(this.filename);
2030             isSaved = false;
2031         }
2032     }
2033 
2034     /**
2035      * @param newFilename
2036      *            the new Filename to set
2037      * @param isFileMoved
2038      *            the isFileMoved to set
2039      */
2040     public void setFileMoved(String newFilename, boolean isFileMoved) {
2041         if (this.isFileMoved != isFileMoved) {
2042             this.isFileMoved = isFileMoved;
2043             allFields[Columns.ISMOVED.ordinal()].setValue(this.isFileMoved);
2044             isSaved = false;
2045         }
2046         this.setFilename(newFilename);
2047     }
2048 
2049     /**
2050      * @param originalFilename
2051      *            the originalFilename to set
2052      */
2053     public void setOriginalFilename(String originalFilename) {
2054         if (!this.originalFilename.equals(originalFilename)) {
2055             this.originalFilename = originalFilename;
2056             allFields[Columns.ORIGINALNAME.ordinal()]
2057                     .setValue(this.originalFilename);
2058             isSaved = false;
2059         }
2060     }
2061 
2062     /**
2063      * @return the rank
2064      */
2065     public int getRank() {
2066         return rank;
2067     }
2068 
2069     /**
2070      * Change the status from Task Execution
2071      *
2072      * @param status
2073      */
2074     public void setExecutionStatus(ErrorCode status) {
2075         this.status = status;
2076         allFields[Columns.STEPSTATUS.ordinal()].setValue(this.status.getCode());
2077         isSaved = false;
2078     }
2079 
2080     /**
2081      * @return the status
2082      */
2083     public ErrorCode getStatus() {
2084         return status;
2085     }
2086 
2087     /**
2088      * @return the isSender
2089      */
2090     public boolean isSender() {
2091         return isSender;
2092     }
2093 
2094     /**
2095      * @return the isFileMoved
2096      */
2097     public boolean isFileMoved() {
2098         return isFileMoved;
2099     }
2100 
2101     /**
2102      * @return the blocksize
2103      */
2104     public int getBlocksize() {
2105         return blocksize;
2106     }
2107 
2108     /**
2109      * @return the filename
2110      */
2111     public String getFilename() {
2112         return filename;
2113     }
2114 
2115     /**
2116      * @return the originalFilename
2117      */
2118     public String getOriginalFilename() {
2119         return originalFilename;
2120     }
2121 
2122     /**
2123      * @return the fileInformation
2124      */
2125     public String getFileInformation() {
2126         return fileInformation;
2127     }
2128 
2129     /**
2130      * @return the specialId
2131      */
2132     public long getSpecialId() {
2133         return specialId;
2134     }
2135 
2136     /**
2137      * @return the rule
2138      */
2139     public DbRule getRule() {
2140         if (rule == null) {
2141             if (ruleId != null) {
2142                 try {
2143                     rule = new DbRule(dbSession, ruleId);
2144                 } catch (GoldenGateDatabaseException e) {
2145                 }
2146             }
2147         }
2148         return rule;
2149     }
2150 
2151     /**
2152      * @return the ruleId
2153      */
2154     public String getRuleId() {
2155         return ruleId;
2156     }
2157 
2158     /**
2159      * @return the mode
2160      */
2161     public int getMode() {
2162         return mode;
2163     }
2164 
2165     /**
2166      * @return the globallaststep
2167      */
2168     public int getGloballaststep() {
2169         return globallaststep;
2170     }
2171 
2172     /**
2173      *
2174      * @return True if this runner is ready for transfer or post operation
2175      */
2176     public boolean ready() {
2177         return globalstep > TASKSTEP.PRETASK.ordinal();
2178     }
2179 
2180     /**
2181     *
2182     * @return True if the runner is currently in transfer
2183     */
2184    public boolean isInTransfer() {
2185        return globalstep == TASKSTEP.TRANSFERTASK.ordinal();
2186    }
2187 
2188     /**
2189      *
2190      * @return True if this runner is finished, either in success or in error
2191      */
2192     public boolean isFinished() {
2193         return isAllDone() || isInError();
2194     }
2195 
2196     /**
2197      *
2198      * @return True if this runner is in error and no more running
2199      */
2200     public boolean isInError() {
2201         return (globalstep == TASKSTEP.ERRORTASK.ordinal() && status != ErrorCode.Running);
2202     }
2203 
2204     /**
2205      *
2206      * @return True if the runner is finished in success
2207      */
2208     public boolean isAllDone() {
2209         return globalstep == TASKSTEP.ALLDONETASK.ordinal();
2210     }
2211 
2212     /**
2213      * To be called before executing Pre execution
2214      * @return True if the task is going to run PRE task from the first action
2215      */
2216     public boolean isPreTaskStarting() {
2217         if (globallaststep == TASKSTEP.PRETASK.ordinal() ||
2218                 globallaststep == TASKSTEP.NOTASK.ordinal()) {
2219             return (step-1 <= 0);
2220         }
2221         return false;
2222     }
2223     /**
2224      * Set Pre Task step
2225      *
2226      */
2227     public void setPreTask() {
2228         globalstep = TASKSTEP.PRETASK.ordinal();
2229         globallaststep = TASKSTEP.PRETASK.ordinal();
2230         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
2231         allFields[Columns.GLOBALLASTSTEP.ordinal()].setValue(globallaststep);
2232         if (step <= 0) {
2233             this.step = 0;
2234         } else {
2235             this.step--;
2236         }
2237         allFields[Columns.STEP.ordinal()].setValue(this.step);
2238         status = ErrorCode.Running;
2239         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
2240         this.changeUpdatedInfo(UpdatedInfo.RUNNING);
2241         this.setErrorExecutionStatus(ErrorCode.InitOk);
2242         isSaved = false;
2243     }
2244 
2245     /**
2246      * Set Transfer rank
2247      *
2248      * @param rank
2249      */
2250     public void setTransferTask(int rank) {
2251         globalstep = TASKSTEP.TRANSFERTASK.ordinal();
2252         globallaststep = TASKSTEP.TRANSFERTASK.ordinal();
2253         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
2254         allFields[Columns.GLOBALLASTSTEP.ordinal()].setValue(globallaststep);
2255         if (this.rank > rank) {
2256             this.rank = rank;
2257         }
2258         allFields[Columns.RANK.ordinal()].setValue(this.rank);
2259         status = ErrorCode.Running;
2260         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
2261         this.setErrorExecutionStatus(ErrorCode.PreProcessingOk);
2262         isSaved = false;
2263     }
2264 
2265     /**
2266      * Set the status of the transfer
2267      *
2268      * @param code
2269      *            TransferOk if success
2270      * @return the current rank of transfer
2271      */
2272     public int finishTransferTask(ErrorCode code) {
2273         if (code == ErrorCode.TransferOk) {
2274             this.status = code;
2275             this.setErrorExecutionStatus(code);
2276         } else {
2277             continueTransfer = false;
2278             if (this.infostatus == ErrorCode.InitOk ||
2279                     this.infostatus == ErrorCode.PostProcessingOk ||
2280                     this.infostatus == ErrorCode.PreProcessingOk ||
2281                     this.infostatus == ErrorCode.Running ||
2282                     this.infostatus == ErrorCode.TransferOk) {
2283                 this.setErrorExecutionStatus(code);
2284             }
2285             if (this.updatedInfo != UpdatedInfo.INTERRUPTED.ordinal()) {
2286                 this.changeUpdatedInfo(UpdatedInfo.INERROR);
2287             }
2288         }
2289         allFields[Columns.STEPSTATUS.ordinal()].setValue(this.status.getCode());
2290         isSaved = false;
2291         return rank;
2292     }
2293     /**
2294      *
2295      * @return True if the transfer is valid to continue
2296      */
2297     public boolean continueTransfer() {
2298         return continueTransfer;
2299     }
2300     /**
2301      * Set the Post Task step
2302      *
2303      */
2304     public void setPostTask() {
2305         globalstep = TASKSTEP.POSTTASK.ordinal();
2306         globallaststep = TASKSTEP.POSTTASK.ordinal();
2307         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
2308         allFields[Columns.GLOBALLASTSTEP.ordinal()].setValue(globallaststep);
2309         if (step <= 0) {
2310             this.step = 0;
2311         } else {
2312             this.step--;
2313         }
2314         allFields[Columns.STEP.ordinal()].setValue(this.step);
2315         status = ErrorCode.Running;
2316         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
2317         this.setErrorExecutionStatus(ErrorCode.TransferOk);
2318         isSaved = false;
2319     }
2320 
2321     /**
2322      * Set the Error Task step
2323      * @param localChannelReference (to get session)
2324      */
2325     public void setErrorTask(LocalChannelReference localChannelReference) {
2326         if (this.session == null && localChannelReference != null) {
2327             this.session = localChannelReference.getSession();
2328         }
2329         if (this.session != null) {
2330             if (this.session.getRunner() == null)
2331                 this.session.setNoSessionRunner(this, localChannelReference);
2332         }
2333         globalstep = TASKSTEP.ERRORTASK.ordinal();
2334         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
2335         this.step = 0;
2336         allFields[Columns.STEP.ordinal()].setValue(this.step);
2337         status = ErrorCode.Running;
2338         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
2339         isSaved = false;
2340     }
2341 
2342     /**
2343      * Set the global step as finished (after post task in success)
2344      */
2345     public void setAllDone() {
2346         globalstep = TASKSTEP.ALLDONETASK.ordinal();
2347         globallaststep = TASKSTEP.ALLDONETASK.ordinal();
2348         allFields[Columns.GLOBALSTEP.ordinal()].setValue(globalstep);
2349         allFields[Columns.GLOBALLASTSTEP.ordinal()].setValue(globallaststep);
2350         step = 0;
2351         allFields[Columns.STEP.ordinal()].setValue(step);
2352         status = ErrorCode.CompleteOk;
2353         allFields[Columns.STEPSTATUS.ordinal()].setValue(status.getCode());
2354         infostatus = ErrorCode.CompleteOk;
2355         allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
2356         changeUpdatedInfo(UpdatedInfo.DONE);
2357         isSaved = false;
2358     }
2359 
2360     /**
2361      * Run the task from the given task information (from rule)
2362      *
2363      * @param tasks
2364      * @return The future of the operation (in success or not)
2365      * @throws OpenR66RunnerEndTasksException
2366      * @throws OpenR66RunnerErrorException
2367      */
2368     private R66Future runNextTask(String[][] tasks)
2369             throws OpenR66RunnerEndTasksException, OpenR66RunnerErrorException {
2370         logger.debug((session==null)+":"+(session==null?"norunner":(this.session.getRunner() == null))+":"+this.toLogRunStep()+":"+step+":"+(tasks==null?"null":tasks.length)+"\nSender: "+this.isSender+" "+this.rule.printTasks(isSender, 
2371                 TASKSTEP.values()[globalstep]));
2372         if (tasks == null) {
2373             throw new OpenR66RunnerEndTasksException("No tasks!");
2374         }
2375         R66Session tempSession = this.session;
2376         if (tempSession == null) {
2377             tempSession = new R66Session();
2378             if (tempSession.getRunner() == null) {
2379                 tempSession.setNoSessionRunner(this, localChannelReference);
2380             }
2381         } else {
2382             if (tempSession.getRunner() == null) {
2383                 tempSession.setNoSessionRunner(this, tempSession.getLocalChannelReference());
2384             }
2385         }
2386         this.session = tempSession;
2387         if (this.session.getLocalChannelReference().getCurrentCode() == ErrorCode.Unknown) {
2388             this.session.getLocalChannelReference().setErrorMessage(this.infostatus.mesg, this.infostatus);
2389         }
2390         if (tasks.length <= step) {
2391             throw new OpenR66RunnerEndTasksException();
2392         }
2393         String name = tasks[step][0];
2394         String arg = tasks[step][1];
2395         int delay = Integer.parseInt(tasks[step][2]);
2396         AbstractTask task = TaskType.getTaskFromId(name, arg, delay, tempSession);
2397         logger.debug(this.toLogRunStep()+" Task: "+task.getClass().getName());
2398         task.run();
2399         try {
2400             task.getFutureCompletion().await();
2401         } catch (InterruptedException e) {
2402         }
2403         return task.getFutureCompletion();
2404     }
2405 
2406     /**
2407      *
2408      * @return the future of the task run
2409      * @throws OpenR66RunnerEndTasksException
2410      * @throws OpenR66RunnerErrorException
2411      * @throws OpenR66RunnerEndTasksException
2412      */
2413     private R66Future runNext() throws OpenR66RunnerErrorException,
2414             OpenR66RunnerEndTasksException {
2415         logger.debug(this.toLogRunStep()+"\nSender: "+this.isSender+" "+this.rule.printTasks(isSender, 
2416                 TASKSTEP.values()[globalstep]));
2417         if (rule == null) {
2418             if (ruleId != null) {
2419                 try {
2420                     rule = new DbRule(dbSession, ruleId);
2421                 } catch (GoldenGateDatabaseException e) {
2422                     rule = null;
2423                 }
2424             }
2425             if (rule == null) {
2426                 throw new OpenR66RunnerErrorException("Rule Object not initialized");
2427             }
2428         }
2429         switch (TASKSTEP.values()[globalstep]) {
2430             case PRETASK:
2431                 try {
2432                     if (this.isSender) {
2433                         return runNextTask(rule.spreTasksArray);
2434                     } else {
2435                         return runNextTask(rule.rpreTasksArray);
2436                     }
2437                 } catch (OpenR66RunnerEndTasksException e) {
2438                     if (status == ErrorCode.Running) {
2439                         infostatus = status = ErrorCode.PreProcessingOk;
2440                     }
2441                     throw e;
2442                 }
2443             case POSTTASK:
2444                 try {
2445                     if (this.isSender) {
2446                         return runNextTask(rule.spostTasksArray);
2447                     } else {
2448                         return runNextTask(rule.rpostTasksArray);
2449                     }
2450                 } catch (OpenR66RunnerEndTasksException e) {
2451                     if (status == ErrorCode.Running) {
2452                         infostatus = status = ErrorCode.PostProcessingOk;
2453                     }
2454                     throw e;
2455                 }
2456             case ERRORTASK:
2457                 try {
2458                     if (this.isSender) {
2459                         return runNextTask(rule.serrorTasksArray);
2460                     } else {
2461                         return runNextTask(rule.rerrorTasksArray);
2462                     }
2463                 } catch (OpenR66RunnerEndTasksException e) {
2464                     throw e;
2465                 }
2466             default:
2467                 throw new OpenR66RunnerErrorException("Global Step unknown");
2468         }
2469     }
2470 
2471     /**
2472      * Run all task from current status (globalstep and step)
2473      *
2474      * @throws OpenR66RunnerErrorException
2475      */
2476     public void run() throws OpenR66RunnerErrorException {
2477         R66Future future;
2478         logger.debug(this.toLogRunStep()+" Status: "+status+"\nSender: "+this.isSender+" "+this.rule.printTasks(isSender, 
2479                 TASKSTEP.values()[globalstep]));
2480         if (status != ErrorCode.Running) {
2481             throw new OpenR66RunnerErrorException(
2482                     "Current global STEP not ready to run: "+ this.toString());
2483         }
2484         while (true) {
2485             logger.debug(this.toLogRunStep());
2486             try {
2487                 future = runNext();
2488             } catch (OpenR66RunnerEndTasksException e) {
2489                 step = 0;
2490                 allFields[Columns.STEP.ordinal()].setValue(step);
2491                 allFields[Columns.STEPSTATUS.ordinal()].setValue(status
2492                         .getCode());
2493                 allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
2494                 isSaved = false;
2495                 this.saveStatus();
2496                 return;
2497             } catch (OpenR66RunnerErrorException e) {
2498                 infostatus = ErrorCode.ExternalOp;
2499                 allFields[Columns.STEP.ordinal()].setValue(step);
2500                 allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
2501                 isSaved = false;
2502                 this.setErrorExecutionStatus(infostatus);
2503                 this.saveStatus();
2504                 throw new OpenR66RunnerErrorException("Runner is in error: " +
2505                         e.getMessage(), e);
2506             }
2507             if ((!future.isDone()) || future.isFailed()) {
2508                 R66Result result = future.getResult();
2509                 if (result != null) {
2510                     infostatus = future.getResult().code;
2511                 } else {
2512                     infostatus = ErrorCode.ExternalOp;
2513                 }
2514                 this.setErrorExecutionStatus(infostatus);
2515                 allFields[Columns.STEP.ordinal()].setValue(step);
2516                 allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
2517                 isSaved = false;
2518                 this.saveStatus();
2519                 logger.info("Future is failed: "+infostatus.mesg);
2520                 if (future.getCause() != null) {
2521                     throw new OpenR66RunnerErrorException("Runner is failed: " +
2522                         future.getCause().getMessage(), future.getCause());
2523                 } else {
2524                     throw new OpenR66RunnerErrorException("Runner is failed: " +
2525                             infostatus.mesg);
2526                 }
2527             }
2528             step ++;
2529         }
2530     }
2531 
2532     /**
2533      * Once the transfer is over, finalize the Runner by running
2534      * the error or post operation according to the status.
2535      * @param localChannelReference
2536      * @param file
2537      * @param finalValue
2538      * @param status
2539      * @throws OpenR66RunnerErrorException
2540      * @throws OpenR66ProtocolSystemException
2541      */
2542     public void finalizeTransfer(LocalChannelReference localChannelReference, R66File file,
2543             R66Result finalValue, boolean status)
2544     throws OpenR66RunnerErrorException, OpenR66ProtocolSystemException {
2545         logger.debug("status"+status+":"+finalValue);
2546 
2547         if (session == null) {
2548             this.session = localChannelReference.getSession();
2549         }
2550         if (status) {
2551             // First move the file
2552             if (this.isSender()) {
2553                 // Nothing to do since it is the original file
2554                 this.setPostTask();
2555             } else {
2556                 int poststep = this.step;
2557                 this.setPostTask();
2558                 this.saveStatus();
2559                 if (!isRecvThrough()) {
2560                     if (this.globalstep == TASKSTEP.TRANSFERTASK.ordinal() ||
2561                             (this.globalstep == TASKSTEP.POSTTASK.ordinal() &&
2562                                     poststep == 0)) {
2563                         // Result file moves
2564                         String finalpath = R66Dir.getFinalUniqueFilename(file);
2565                         logger.debug("Will move file {}", finalpath);
2566                         try {
2567                             file.renameTo(this.getRule().setRecvPath(finalpath));
2568                         } catch (OpenR66ProtocolSystemException e) {
2569                             R66Result result = new R66Result(e, session, false,
2570                                     ErrorCode.FinalOp, this);
2571                             result.file = file;
2572                             result.runner = this;
2573                             if (localChannelReference != null) {
2574                                 localChannelReference.invalidateRequest(result);
2575                             }
2576                             throw e;
2577                         } catch (CommandAbstractException e) {
2578                             R66Result result = new R66Result(
2579                                     new OpenR66RunnerErrorException(e), session,
2580                                     false, ErrorCode.FinalOp, this);
2581                             result.file = file;
2582                             result.runner = this;
2583                             if (localChannelReference != null) {
2584                                 localChannelReference.invalidateRequest(result);
2585                             }
2586                             throw (OpenR66RunnerErrorException) result.exception;
2587                         }
2588                         logger.debug("File finally moved: {}", file);
2589                         try {
2590                             this.setFilename(file.getFile());
2591                         } catch (CommandAbstractException e) {
2592                         }
2593                     }
2594                 }
2595             }
2596             this.saveStatus();
2597             if (isRecvThrough() || isSendThrough()) {
2598                 // File could not exist
2599             } else if (this.step == 0) {
2600                 // File must exist
2601                 try {
2602                     if (! file.exists()) {
2603                         // error
2604                         R66Result error =
2605                             new R66Result(this.session, finalValue.isAnswered,
2606                                     ErrorCode.FileNotFound, this);
2607                         this.setErrorExecutionStatus(ErrorCode.FileNotFound);
2608                         errorTransfer(error, file, localChannelReference);
2609                         return;
2610                     }
2611                 } catch (CommandAbstractException e) {
2612                     // error
2613                     R66Result error =
2614                         new R66Result(this.session, finalValue.isAnswered,
2615                                 ErrorCode.FileNotFound, this);
2616                     this.setErrorExecutionStatus(ErrorCode.FileNotFound);
2617                     errorTransfer(error, file, localChannelReference);
2618                     return;
2619                 }
2620             }
2621             try {
2622                 this.run();
2623             } catch (OpenR66RunnerErrorException e1) {
2624                 R66Result result = new R66Result(e1, this.session, false,
2625                         ErrorCode.ExternalOp, this);
2626                 result.file = file;
2627                 result.runner = this;
2628                 this.changeUpdatedInfo(UpdatedInfo.INERROR);
2629                 this.saveStatus();
2630                 errorTransfer(result, file, localChannelReference);
2631                 if (localChannelReference != null) {
2632                     localChannelReference.invalidateRequest(result);
2633                 }
2634                 throw e1;
2635             }
2636             this.saveStatus();
2637             /*Done later on after EndRequest
2638              * this.setAllDone();
2639             this.saveStatus();*/
2640             logger.info("Transfer done on {} at RANK {}",file != null ? file : "no file", rank);
2641             if (localChannelReference != null) {
2642                 localChannelReference.validateEndTransfer(finalValue);
2643             }
2644         } else {
2645             logger.debug("ContinueTransfer: "+continueTransfer+" status:"+status+":"+finalValue);
2646             /*if (!continueTransfer) {
2647                 // already setup
2648                 return;
2649             }*/
2650             errorTransfer(finalValue, file, localChannelReference);
2651         }
2652     }
2653     /**
2654      * Finalize a transfer in error
2655      * @param finalValue
2656      * @param file
2657      * @param localChannelReference
2658      * @throws OpenR66RunnerErrorException
2659      */
2660     private void errorTransfer(R66Result finalValue, R66File file,
2661             LocalChannelReference localChannelReference) throws OpenR66RunnerErrorException {
2662         // error or not ?
2663         ErrorCode runnerStatus = this.getErrorInfo();
2664         if (finalValue.exception != null) {
2665             logger.error("Transfer KO on " + file+ " due to "+ finalValue.exception.getMessage());
2666         } else {
2667             logger.error("Transfer KO on " + file+" due to "+finalValue.toString());
2668         }
2669         if (runnerStatus == ErrorCode.CanceledTransfer) {
2670             // delete file, reset runner
2671             this.setRankAtStartup(0);
2672             this.deleteTempFile();
2673             this.changeUpdatedInfo(UpdatedInfo.INERROR);
2674             this.saveStatus();
2675             finalValue.isAnswered = true;
2676         } else if (runnerStatus == ErrorCode.StoppedTransfer) {
2677             // just save runner and stop
2678             this.changeUpdatedInfo(UpdatedInfo.INERROR);
2679             this.saveStatus();
2680             finalValue.isAnswered = true;
2681         } else if (runnerStatus == ErrorCode.Shutdown) {
2682             // just save runner and stop
2683             this.changeUpdatedInfo(UpdatedInfo.INERROR);
2684             this.saveStatus();
2685             finalValue.isAnswered = true;
2686         }
2687         logger.debug("status: "+status+" wasNotError:"+(this.globalstep != TASKSTEP.ERRORTASK.ordinal())+
2688                 ":"+finalValue);
2689         if (this.globalstep != TASKSTEP.ERRORTASK.ordinal()) {
2690             // errorstep was not already executed
2691             // real error
2692             localChannelReference.setErrorMessage(finalValue.getMessage(),finalValue.code);
2693             // First send error mesg
2694             if (!finalValue.isAnswered) {
2695                 localChannelReference.sessionNewState(R66FiniteDualStates.ERROR);
2696                 ErrorPacket errorPacket = new ErrorPacket(finalValue
2697                         .getMessage(),
2698                         finalValue.code.getCode(), ErrorPacket.FORWARDCLOSECODE);
2699                 try {
2700                     ChannelUtils.writeAbstractLocalPacket(localChannelReference,
2701                             errorPacket, true);
2702                     finalValue.isAnswered = true;
2703                 } catch (OpenR66ProtocolPacketException e1) {
2704                     // should not be
2705                 }
2706             }
2707             // now run error task
2708             this.setErrorTask(localChannelReference);
2709             this.saveStatus();
2710             try {
2711                 this.run();
2712             } catch (OpenR66RunnerErrorException e1) {
2713                 this.changeUpdatedInfo(UpdatedInfo.INERROR);
2714                 this.setErrorExecutionStatus(runnerStatus);
2715                 this.saveStatus();
2716                 if (localChannelReference != null) {
2717                     localChannelReference.invalidateRequest(finalValue);
2718                 }
2719                 throw e1;
2720             }
2721         }
2722         this.changeUpdatedInfo(UpdatedInfo.INERROR);
2723         if (RequestPacket.isThroughMode(this.getMode())) {
2724             this.setErrorExecutionStatus(runnerStatus);
2725             this.saveStatus();
2726             if (localChannelReference != null) {
2727                 localChannelReference.invalidateRequest(finalValue);
2728             }
2729             return;
2730         }
2731         // re set the original status
2732         this.setErrorExecutionStatus(runnerStatus);
2733         this.saveStatus();
2734         if (localChannelReference != null) {
2735             localChannelReference.invalidateRequest(finalValue);
2736         }
2737     }
2738     /**
2739      * Increment the rank of the transfer
2740      * @throws OpenR66ProtocolPacketException
2741      */
2742     public void incrementRank() throws OpenR66ProtocolPacketException {
2743         rank ++;
2744         allFields[Columns.RANK.ordinal()].setValue(rank);
2745         isSaved = false;
2746         if (rank % 10 == 0) {
2747             // Save each 10 blocks
2748             try {
2749                 update();
2750             } catch (GoldenGateDatabaseException e) {
2751                 logger.warn("Cannot update Runner: {}", e.getMessage());
2752             }
2753         }
2754     }
2755 
2756     /**
2757      * This method is to be called each time an operation is happening on Runner
2758      *
2759      * @throws OpenR66RunnerErrorException
2760      */
2761     public void saveStatus() throws OpenR66RunnerErrorException {
2762         try {
2763             update();
2764         } catch (GoldenGateDatabaseException e) {
2765             throw new OpenR66RunnerErrorException(e);
2766         }
2767     }
2768 
2769     /**
2770      * Clear the runner
2771      */
2772     public void clear() {
2773 
2774     }
2775 
2776     /**
2777      * Delete the temporary empty file (retrieved file at rank 0)
2778      */
2779     public void deleteTempFile() {
2780         if ((!isSender()) && getRank() == 0) {
2781             try {
2782                 if (session != null) {
2783                     R66File file = session.getFile();
2784                     if (file != null) {
2785                         file.delete();
2786                     }
2787                 }
2788             } catch (CommandAbstractException e1) {
2789                 logger.warn("Cannot delete temporary empty file", e1);
2790             }
2791         }
2792     }
2793 
2794     @Override
2795     public String toString() {
2796         return "Run: " + (rule != null? rule.toString() : ruleId) + " on " +
2797                 filename + " STEP: " + TASKSTEP.values()[globalstep] + "(" +
2798                 TASKSTEP.values()[globallaststep] + "):" + step + ":" +
2799                 status.mesg + " Transfer Rank: " + rank + " Blocksize: "+blocksize+
2800                 " SpecialId: " +
2801                 specialId + " isSender: " + isSender + " isMoved: " +
2802                 isFileMoved + " Mode: " + TRANSFERMODE.values()[mode] +
2803                 " Requester: " + requesterHostId + " Requested: " +
2804                 requestedHostId + " Start: " + start + " Stop: " + stop +
2805                 " Internal: " + UpdatedInfo.values()[updatedInfo].name()+
2806                 ":"+infostatus.mesg+
2807                 " Fileinfo: "+fileInformation;
2808     }
2809 
2810     public String toLogRunStep() {
2811         return "Run: " + ruleId + " on " +
2812         filename + " STEP: " + TASKSTEP.values()[globalstep] + "(" +
2813         TASKSTEP.values()[globallaststep] + "):" + step + ":" +
2814         status.mesg;
2815     }
2816     public String toShortNoHtmlString(String newline) {
2817         return "Run: " + ruleId + " on " +
2818                 filename + newline+" STEP: " + TASKSTEP.values()[globalstep] + "(" +
2819                 TASKSTEP.values()[globallaststep] + "):" + step + ":" +
2820                 status.mesg + newline+" Transfer Rank: " + rank + " Blocksize: "+blocksize+
2821                 " SpecialId: " +
2822                 specialId + " isSender: " + isSender + " isMoved: " +
2823                 isFileMoved + " Mode: " + TRANSFERMODE.values()[mode] +
2824                 newline+" Requester: " + requesterHostId + " Requested: " +
2825                 requestedHostId + " Start: " + start + " Stop: " + stop +
2826                 newline+" Internal: " + UpdatedInfo.values()[updatedInfo].name()+
2827                 ":"+infostatus.mesg+
2828                 newline+" Fileinfo: "+fileInformation;
2829     }
2830 
2831     public String toShortString() {
2832         return "<RULE>" + ruleId + "</RULE><ID>" + specialId + "</ID><FILE>" +
2833                 filename + "</FILE>\n    <STEP>" + TASKSTEP.values()[globalstep] +
2834                 "(" + TASKSTEP.values()[globallaststep] + "):" + step + ":" +
2835                 status.mesg + "</STEP><RANK>" + rank + "</RANK><BLOCKSIZE>"+ blocksize+
2836                 "</BLOCKSIZE>\n    <SENDER>" +
2837                 isSender + "</SENDER><MOVED>" + isFileMoved + "</MOVED><MODE>" +
2838                 TRANSFERMODE.values()[mode] + "</MODE>\n    <REQR>" +
2839                 requesterHostId + "</REQR><REQD>" + requestedHostId +
2840                 "</REQD>\n    <START>" + start + "</START><STOP>" + stop +
2841                 "</STOP>\n    <INTERNAL>" + UpdatedInfo.values()[updatedInfo].name()
2842                 +" : "+infostatus.mesg+ "</INTERNAL>\n    <FILEINFO>"+
2843                 fileInformation+"</FILEINFO>";
2844     }
2845 
2846     /**
2847      *
2848      * @return the header for a table of runners in Html format
2849      */
2850     public static String headerHtml() {
2851         return "<td>SpecialId</td><td>Rule</td><td>Filename</td><td>Info"
2852                 + "</td><td>Step (LastStep)</td><td>Action</td><td>Status"
2853                 + "</td><td>Internal</t><td>Transfer Rank</td><td>BlockSize</td><td>isMoved"
2854                 + "</td><td>Requester</td><td>Requested"
2855                 + "</td><td>Start</td><td>Stop</td><td>Bandwidth (Mbits)</td><td>Free Space(MB)</td>";
2856     }
2857 
2858     /**
2859      * @param session
2860      * @return The associated freespace of the current directory
2861      */
2862     public long freespace(R66Session session) {
2863         long freespace = -1;
2864         DbRule rule = null;
2865         try {
2866             rule = (this.rule != null)? this.rule : new DbRule(this.dbSession,
2867                     this.ruleId);
2868         } catch (GoldenGateDatabaseException e) {
2869         }
2870         if (this.rule == null) {
2871             this.rule = rule;
2872         }
2873         if (rule != null) {
2874             if (!this.isSender) {
2875                 try {
2876                     String sdir;
2877                     if (this.globallaststep == TASKSTEP.ALLDONETASK.ordinal()) {
2878                         // all finished
2879                         sdir = rule.recvPath;
2880                     } else if (this.globallaststep == TASKSTEP.POSTTASK
2881                             .ordinal()) {
2882                         // Post task
2883                         sdir = rule.recvPath;
2884                     } else {
2885                         // are we in sending or receive
2886                         sdir = rule.workPath;
2887                     }
2888                     R66Dir dir;
2889                     if (HttpFormattedHandler.usedDir.containsKey(sdir)) {
2890                         dir = HttpFormattedHandler.usedDir.get(sdir);
2891                     } else {
2892                         dir = new R66Dir(session);
2893                         dir.changeDirectory(sdir);
2894                         HttpFormattedHandler.usedDir.put(sdir, dir);
2895                     }
2896                     freespace = dir.getFreeSpace() / 0x100000L;
2897                 } catch (CommandAbstractException e) {
2898                     logger.warn("Error while freespace compute {}", e.getMessage());
2899                 }
2900             }
2901         }
2902         return freespace;
2903     }
2904 
2905     private String bandwidth() {
2906         double drank = (rank<=0 ? 1 : rank);
2907         double dblocksize = blocksize*8;
2908         double size = drank*dblocksize;
2909         double time = (stop.getTime() + 1 - start.getTime());
2910         double result = size/time / ((double) 0x100000L) * ((double) 1000);
2911         return String.format("%,.2f", result);
2912     }
2913 
2914     private String getHtmlColor() {
2915         String color;
2916         switch (TASKSTEP.values()[globalstep]) {
2917             case NOTASK:
2918                 color = "Orange";
2919                 break;
2920             case PRETASK:
2921                 color = "Yellow";
2922                 break;
2923             case TRANSFERTASK:
2924                 color = "LightGreen";
2925                 break;
2926             case POSTTASK:
2927                 color = "Turquoise";
2928                 break;
2929             case ERRORTASK:
2930                 color = "Red";
2931                 break;
2932             case ALLDONETASK:
2933                 color = "Cyan";
2934                 break;
2935             default:
2936                 color = "";
2937         }
2938         return color;
2939     }
2940 
2941     private String getInfoHtmlColor() {
2942         String color;
2943         switch (UpdatedInfo.values()[updatedInfo]) {
2944             case DONE:
2945                 color = "Cyan";
2946                 break;
2947             case INERROR:
2948                 color = "Red";
2949                 break;
2950             case INTERRUPTED:
2951                 color = "Orange";
2952                 break;
2953             case NOTUPDATED:
2954                 color = "Yellow";
2955                 break;
2956             case RUNNING:
2957                 color = "LightGreen";
2958                 break;
2959             case TOSUBMIT:
2960                 color = "Turquoise";
2961                 break;
2962             case UNKNOWN:
2963                 color = "Turquoise";
2964                 break;
2965             default:
2966                 color = "";
2967         }
2968         return color;
2969     }
2970 
2971     /**
2972      * @param session
2973      * @param running special info
2974      * @return the runner in Html format compatible with the header from
2975      *         headerHtml method
2976      */
2977     public String toHtml(R66Session session, String running) {
2978         long freespace = freespace(session);
2979         String color = getHtmlColor();
2980         String updcolor = getInfoHtmlColor();
2981         return "<td>" +
2982                 specialId +
2983                 "</td><td>" +
2984                 (rule != null? rule.toShortString() : ruleId) +
2985                 "</td><td>" +
2986                 filename +
2987                 "</td><td>" +fileInformation+
2988                 "</td><td bgcolor=\"" +
2989                 color +
2990                 "\">" +
2991                 TASKSTEP.values()[globalstep] +
2992                 " (" +
2993                 TASKSTEP.values()[globallaststep] +
2994                 ")</td><td>" +
2995                 step +
2996                 "</td><td>" +
2997                 status.mesg+" <b>"+running+
2998                 "</b></td><td bgcolor=\"" +
2999                 updcolor+"\">" +
3000                 UpdatedInfo.values()[updatedInfo].name()+" : "+infostatus.mesg +
3001                 "</td><td>" +
3002                 rank +
3003                 "</td><td>" +
3004                 blocksize +
3005                 "</td><td>" +
3006                 isFileMoved +
3007                 "</td><td>" +
3008                 requesterHostId +
3009                 "</td><td>" +
3010                 requestedHostId +
3011                 "</td><td>" +
3012                 start +
3013                 "</td><td>" +
3014                 stop +
3015                 "</td><td>" +
3016                 bandwidth() + "</td>" + "<td>" +
3017                 freespace + "</td>";
3018     }
3019 
3020     /**
3021      * @param session
3022      * @param body
3023      * @param running special info
3024      * @return the runner in Html format specified by body by replacing all
3025      *         instance of fields
3026      */
3027     public String toSpecializedHtml(R66Session session, String body, String running) {
3028         long freespace = freespace(session);
3029         StringBuilder builder = new StringBuilder(body);
3030         GgStringUtils.replaceAll(builder, "XXXSpecIdXXX", Long.toString(specialId));
3031         GgStringUtils.replace(builder, "XXXRulXXX", (rule != null? rule.toShortString()
3032                 : ruleId));
3033         GgStringUtils.replace(builder, "XXXFileXXX", filename);
3034         GgStringUtils.replace(builder, "XXXInfoXXX", fileInformation);
3035         GgStringUtils.replace(builder, "XXXStepXXX", TASKSTEP.values()[globalstep] + " (" +
3036                 TASKSTEP.values()[globallaststep] + ")");
3037         GgStringUtils.replace(builder, "XXXCOLXXX", getHtmlColor());
3038         GgStringUtils.replace(builder, "XXXActXXX", Integer.toString(step));
3039         GgStringUtils.replace(builder, "XXXStatXXX", status.mesg);
3040         GgStringUtils.replace(builder, "XXXRunningXXX", running);
3041         GgStringUtils.replace(builder, "XXXInternXXX", UpdatedInfo.values()[updatedInfo].name()+
3042                 " : "+infostatus.mesg);
3043         GgStringUtils.replace(builder, "XXXUPDCOLXXX", getInfoHtmlColor());
3044         GgStringUtils.replace(builder, "XXXBloXXX", Integer.toString(rank));
3045         GgStringUtils.replace(builder, "XXXisSendXXX", Boolean.toString(isSender));
3046         GgStringUtils.replace(builder, "XXXisMovXXX", Boolean.toString(isFileMoved));
3047         GgStringUtils.replace(builder, "XXXModXXX", TRANSFERMODE.values()[mode].toString());
3048         GgStringUtils.replaceAll(builder, "XXXReqrXXX", requesterHostId);
3049         GgStringUtils.replaceAll(builder, "XXXReqdXXX", requestedHostId);
3050         GgStringUtils.replace(builder, "XXXStarXXX", start.toString());
3051         GgStringUtils.replace(builder, "XXXStopXXX", stop.toString());
3052         GgStringUtils.replace(builder, "XXXBandXXX", bandwidth());
3053         GgStringUtils.replace(builder, "XXXFreeXXX", Long.toString(freespace));
3054         return builder.toString();
3055     }
3056 
3057     /**
3058      *
3059      * @return True if the current host is the requested host (to prevent
3060      *         request to itself)
3061      */
3062     public boolean isSelfRequested() {
3063         return (this.requestedHostId
3064                 .equals(Configuration.configuration.HOST_ID) || this.requestedHostId
3065                 .equals(Configuration.configuration.HOST_SSLID));
3066     }
3067 
3068     /**
3069      *
3070      * @return the requested HostId
3071      */
3072     public String getRequested() {
3073         return this.requestedHostId;
3074     }
3075 
3076     /**
3077      *
3078      * @return the requester HostId
3079      */
3080     public String getRequester() {
3081         return this.requesterHostId;
3082     }
3083 
3084     /**
3085      * @return the start
3086      */
3087     public Timestamp getStart() {
3088         return start;
3089     }
3090     /**
3091      * @param start new Start time to apply when reschedule 
3092      * @throws OpenR66RunnerErrorException (in fact a GoldenGateDatabaseException)
3093      */
3094     public void setStart(Timestamp start) throws OpenR66RunnerErrorException {
3095         this.start = start;
3096         this.restart(true);
3097     }
3098 
3099     /**
3100      * @return the stop
3101      */
3102     public Timestamp getStop() {
3103         return stop;
3104     }
3105 
3106     /**
3107      *
3108      * @return the associated request
3109      */
3110     public RequestPacket getRequest() {
3111         return new RequestPacket(ruleId, mode, originalFilename, blocksize,
3112                 rank, specialId, fileInformation);
3113     }
3114 
3115     /**
3116      * Used internally
3117      *
3118      * @return a Key representing the primary key as a unique string
3119      */
3120     public String getKey() {
3121         return requestedHostId + " " + requesterHostId + " " + specialId;
3122     }
3123 
3124     /**
3125      * Construct a new Element with value
3126      *
3127      * @param name
3128      * @param value
3129      * @return the new Element
3130      */
3131     private static Element newElement(String name, String value) {
3132         Element node = new DefaultElement(name);
3133         if (value != null) {
3134             node.addText(value);
3135         }
3136         return node;
3137     }
3138 
3139     /**
3140      * Need to call 'setToArray' before
3141      * @param runner
3142      * @return The Element representing the given Runner
3143      * @throws GoldenGateDatabaseSqlException
3144      */
3145     private static Element getElementFromRunner(DbTaskRunner runner)
3146             throws GoldenGateDatabaseSqlException {
3147         Element root = new DefaultElement(XMLRUNNER);
3148         for (DbValue value: runner.allFields) {
3149             if (value.column.equals(Columns.UPDATEDINFO.name())) {
3150                 continue;
3151             }
3152             root.add(newElement(value.column.toLowerCase(), value
3153                     .getValueAsString()));
3154         }
3155         return root;
3156     }
3157     /**
3158      * Set the given runner from the root element of the runner itself (XMLRUNNER but not XMLRUNNERS).
3159      * Need to call 'setFromArray' after.
3160      * @param runner
3161      * @param root
3162      * @throws GoldenGateDatabaseSqlException
3163      */
3164     private static void setRunnerFromElement(DbTaskRunner runner, Element root) 
3165         throws GoldenGateDatabaseSqlException {
3166         for (DbValue value: runner.allFields) {
3167             if (value.column.equals(Columns.UPDATEDINFO.name())) {
3168                 continue;
3169             }
3170             Element elt = (Element) root.selectSingleNode(value.column.toLowerCase());
3171             if (elt != null) {
3172                 String newValue = elt.getText();
3173                 value.setValueFromString(newValue);
3174             }
3175         }
3176     }
3177     /**
3178      * Write the selected TaskRunners from PrepareStatement to a XMLWriter
3179      *
3180      * @param preparedStatement
3181      *            ready to be executed
3182      * @param xmlWriter
3183      * @return the NbAndSpecialId for the number of transfer and higher rank found
3184      * @throws GoldenGateDatabaseNoConnectionException
3185      * @throws GoldenGateDatabaseSqlException
3186      * @throws OpenR66ProtocolBusinessException
3187      */
3188     public static NbAndSpecialId writeXML(DbPreparedStatement preparedStatement, XMLWriter xmlWriter)
3189             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException, OpenR66ProtocolBusinessException {
3190         Element root = new DefaultElement(XMLRUNNERS);
3191         NbAndSpecialId nbAndSpecialId = new NbAndSpecialId();
3192         try {
3193             xmlWriter.writeOpen(root);
3194             Element node;
3195             while (preparedStatement.getNext()) {
3196                 DbTaskRunner runner = DbTaskRunner
3197                         .getFromStatement(preparedStatement);
3198                 if (nbAndSpecialId.higherSpecialId < runner.specialId) {
3199                     nbAndSpecialId.higherSpecialId = runner.specialId;
3200                 }
3201                 node = DbTaskRunner.getElementFromRunner(runner);
3202                 xmlWriter.write(node);
3203                 xmlWriter.flush();
3204                 nbAndSpecialId.nb ++;
3205             }
3206             xmlWriter.writeClose(root);
3207         } catch (IOException e) {
3208             logger.error("Cannot write XML file", e);
3209             throw new OpenR66ProtocolBusinessException("Cannot write file: "+e.getMessage());
3210         }
3211         return nbAndSpecialId;
3212     }
3213     /**
3214      * Write selected TaskRunners to an XML file using an XMLWriter
3215      *
3216      * @param preparedStatement
3217      * @param filename
3218      * @return the NbAndSpecialId for the number of transfer and higher rank found
3219      * @throws GoldenGateDatabaseNoConnectionException
3220      * @throws GoldenGateDatabaseSqlException
3221      * @throws OpenR66ProtocolBusinessException
3222      */
3223     public static NbAndSpecialId writeXMLWriter(DbPreparedStatement preparedStatement, String filename)
3224             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException,
3225             OpenR66ProtocolBusinessException {
3226         NbAndSpecialId nbAndSpecialId = null;
3227         OutputStream outputStream = null;
3228         XMLWriter xmlWriter = null;
3229         try {
3230             outputStream = new FileOutputStream(filename);
3231             OutputFormat format = OutputFormat.createPrettyPrint();
3232             format.setEncoding("ISO-8859-1");
3233             xmlWriter = new XMLWriter(outputStream, format);
3234             preparedStatement.executeQuery();
3235             nbAndSpecialId = writeXML(preparedStatement, xmlWriter);
3236         } catch (FileNotFoundException e) {
3237             logger.error("Cannot write XML file", e);
3238             throw new OpenR66ProtocolBusinessException("File not found");
3239         } catch (UnsupportedEncodingException e) {
3240             logger.error("Cannot write XML file", e);
3241             throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3242         } finally {
3243             if (xmlWriter != null) {
3244                 try {
3245                     xmlWriter.endDocument();
3246                     xmlWriter.flush();
3247                     xmlWriter.close();
3248                 } catch (SAXException e) {
3249                     try {
3250                         outputStream.close();
3251                     } catch (IOException e2) {
3252                     }
3253                     File file = new File(filename);
3254                     file.delete();
3255                     logger.error("Cannot write XML file", e);
3256                     throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3257                 } catch (IOException e) {
3258                     try {
3259                         outputStream.close();
3260                     } catch (IOException e2) {
3261                     }
3262                     File file = new File(filename);
3263                     file.delete();
3264                     logger.error("Cannot write XML file", e);
3265                     throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3266                 }
3267             } else if (outputStream != null){
3268                 try {
3269                     outputStream.close();
3270                 } catch (IOException e) {
3271                 }
3272                 File file = new File(filename);
3273                 file.delete();
3274             }
3275         }
3276         return nbAndSpecialId;
3277     }
3278 
3279     /**
3280      * Write all TaskRunners to an XML file using an XMLWriter
3281      *
3282      * @param filename
3283      * @throws GoldenGateDatabaseNoConnectionException
3284      * @throws GoldenGateDatabaseSqlException
3285      * @throws OpenR66ProtocolBusinessException
3286      */
3287     public static void writeXMLWriter(String filename)
3288             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException,
3289             OpenR66ProtocolBusinessException {
3290         String request = "SELECT " + DbTaskRunner.selectAllFields + " FROM " +
3291                 DbTaskRunner.table+" WHERE "+getLimitWhereCondition();
3292         DbPreparedStatement preparedStatement = null;
3293         try {
3294             preparedStatement = new DbPreparedStatement(
3295                     DbConstant.admin.session);
3296             preparedStatement.createPrepareStatement(request);
3297             writeXMLWriter(preparedStatement, filename);
3298         } finally {
3299             if (preparedStatement != null) {
3300                 preparedStatement.realClose();
3301             }
3302         }
3303     }
3304     /**
3305      * 
3306      * @return the backend XML filename for the current TaskRunner in NoDb Client mode
3307      */
3308     public String backendXmlFilename() {
3309         return Configuration.configuration.baseDirectory+
3310             Configuration.configuration.archivePath+R66Dir.SEPARATOR+
3311             this.requesterHostId+"_"+this.requestedHostId+"_"+this.ruleId+"_"+this.specialId
3312             +XMLEXTENSION;
3313     }
3314     /**
3315      * Method to write the current DbTaskRunner for NoDb client instead of updating DB.
3316      * 'setToArray' must be called priorly to be able to store the values.
3317      * @throws OpenR66ProtocolBusinessException
3318      */
3319     public void writeXmlWorkNoDb() throws OpenR66ProtocolBusinessException {
3320         String filename = backendXmlFilename();
3321         OutputStream outputStream = null;
3322         XMLWriter xmlWriter = null;
3323         try {
3324             outputStream = new FileOutputStream(filename);
3325             OutputFormat format = OutputFormat.createPrettyPrint();
3326             format.setEncoding("ISO-8859-1");
3327             xmlWriter = new XMLWriter(outputStream, format);
3328             Element root = new DefaultElement(XMLRUNNERS);
3329             try {
3330                 xmlWriter.writeOpen(root);
3331                 Element node;
3332                 node = DbTaskRunner.getElementFromRunner(this);
3333                 xmlWriter.write(node);
3334                 xmlWriter.flush();
3335                 xmlWriter.writeClose(root);
3336             } catch (IOException e) {
3337                 logger.error("Cannot write XML file", e);
3338                 throw new OpenR66ProtocolBusinessException("Cannot write file: "+e.getMessage());
3339             } catch (GoldenGateDatabaseSqlException e) {
3340                 logger.error("Cannot write Data", e);
3341                 throw new OpenR66ProtocolBusinessException("Cannot write Data: "+e.getMessage());
3342             }
3343         } catch (FileNotFoundException e) {
3344             logger.error("Cannot write XML file", e);
3345             throw new OpenR66ProtocolBusinessException("File not found");
3346         } catch (UnsupportedEncodingException e) {
3347             logger.error("Cannot write XML file", e);
3348             throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3349         } finally {
3350             if (xmlWriter != null) {
3351                 try {
3352                     xmlWriter.endDocument();
3353                     xmlWriter.flush();
3354                     xmlWriter.close();
3355                 } catch (SAXException e) {
3356                     try {
3357                         outputStream.close();
3358                     } catch (IOException e2) {
3359                     }
3360                     File file = new File(filename);
3361                     file.delete();
3362                     logger.error("Cannot write XML file", e);
3363                     throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3364                 } catch (IOException e) {
3365                     try {
3366                         outputStream.close();
3367                     } catch (IOException e2) {
3368                     }
3369                     File file = new File(filename);
3370                     file.delete();
3371                     logger.error("Cannot write XML file", e);
3372                     throw new OpenR66ProtocolBusinessException("Unsupported Encoding");
3373                 }
3374             } else if (outputStream != null){
3375                 try {
3376                     outputStream.close();
3377                 } catch (IOException e) {
3378                 }
3379                 File file = new File(filename);
3380                 file.delete();
3381             }
3382         }
3383     }
3384     /**
3385      * Method to load a previous existing DbTaskRunner for NoDb client from File instead of from DB.
3386      * 'setFromArray' must be called after.
3387      * @throws OpenR66ProtocolBusinessException
3388      */
3389     public void loadXmlWorkNoDb() throws OpenR66ProtocolBusinessException {
3390         String filename = backendXmlFilename();
3391         File file = new File(filename);
3392         if (! file.canRead()) {
3393             throw new OpenR66ProtocolBusinessException("Backend XML file cannot be read");
3394         }
3395         SAXReader reader = new SAXReader();
3396         Document document;
3397         try {
3398             document = reader.read(file);
3399         } catch (DocumentException e) {
3400             throw new OpenR66ProtocolBusinessException("Backend XML file cannot be read as an XML file");
3401         }
3402         Element root = (Element) document.selectSingleNode("/"+XMLRUNNERS+"/"+XMLRUNNER);
3403         try {
3404             setRunnerFromElement(this, root);
3405         } catch (GoldenGateDatabaseSqlException e) {
3406             throw new OpenR66ProtocolBusinessException("Backend XML file is not conform to the model");
3407         }
3408     }
3409     /**
3410      * 
3411      * @return True if the backend XML for NoDb client is available for this TaskRunner
3412      */
3413     public boolean existXmlWorkNoDb() {
3414         String filename = backendXmlFilename();
3415         File file = new File(filename);
3416         return file.canRead();
3417     }
3418     /**
3419      * Delete the backend XML file for the current TaskRunner for NoDb Client
3420      */
3421     public void deleteXmlWorkNoDb() {
3422         File file = new File(backendXmlFilename());
3423         file.delete();
3424     }
3425 }