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 goldengate.ftp.exec.database.data;
22  
23  import goldengate.common.command.ReplyCode;
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.exception.InvalidArgumentException;
33  import goldengate.common.logging.GgInternalLogger;
34  import goldengate.common.logging.GgInternalLoggerFactory;
35  import goldengate.common.xml.XmlDecl;
36  import goldengate.common.xml.XmlType;
37  import goldengate.common.xml.XmlUtil;
38  import goldengate.common.xml.XmlValue;
39  import goldengate.ftp.core.command.FtpCommandCode;
40  import goldengate.ftp.exec.config.FileBasedConfiguration;
41  import goldengate.ftp.exec.database.DbConstant;
42  import goldengate.ftp.exec.database.model.DbModelFactory;
43  
44  import java.io.IOException;
45  import java.io.InvalidObjectException;
46  import java.sql.SQLException;
47  import java.sql.Timestamp;
48  import java.sql.Types;
49  import java.util.TreeSet;
50  
51  import org.dom4j.Document;
52  
53  /**
54   * Transfer Log for FtpExec
55   *
56   * @author Frederic Bregier
57   *
58   */
59  public class DbTransferLog extends AbstractDbData {
60      /**
61       * Internal Logger
62       */
63      private static final GgInternalLogger logger = GgInternalLoggerFactory
64              .getLogger(DbTransferLog.class);
65  
66      public static enum Columns {
67          FILENAME,
68          MODETRANS,
69          STARTTRANS,
70          STOPTRANS,
71          TRANSINFO,
72          INFOSTATUS,
73          UPDATEDINFO,
74          USERID,
75          ACCOUNTID,
76          HOSTID,
77          SPECIALID;
78      }
79  
80      public static final int[] dbTypes = {
81              Types.VARCHAR,
82              Types.VARCHAR, 
83              Types.TIMESTAMP, Types.TIMESTAMP, 
84              Types.LONGVARCHAR, Types.INTEGER, Types.INTEGER,
85              Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BIGINT };
86  
87      public static final String table = " TRANSFLOG ";
88  
89      public static final String fieldseq = "TRANSSEQ";
90  
91      public static final Columns [] indexes = {
92          Columns.STARTTRANS, Columns.UPDATEDINFO, Columns.INFOSTATUS
93      };
94  
95      public static final String XMLRUNNERS = "transferlogs";
96      public static final String XMLRUNNER = "log";
97  
98      // Values
99      private String user;
100     
101     private String account; 
102     
103     private long specialId;
104     
105     private boolean isSender;
106 
107     private String filename;
108 
109     private String mode;
110 
111     private Timestamp start;
112 
113     private Timestamp stop;
114     
115     private String infotransf;
116     
117     private String hostid;
118 
119     /**
120      * Info status error code
121      */
122     private ReplyCode infostatus = ReplyCode.REPLY_000_SPECIAL_NOSTATUS;
123 
124     /**
125      * The global status for running
126      */
127     private int updatedInfo = UpdatedInfo.UNKNOWN.ordinal();
128 
129     /**
130      * Special For DbTransferLog
131      */
132     public static final int NBPRKEY = 4;
133     // ALL TABLE SHOULD IMPLEMENT THIS
134 
135     protected static final String selectAllFields = Columns.FILENAME.name() + "," +
136             Columns.MODETRANS.name() + "," +
137             Columns.STARTTRANS.name() + "," + Columns.STOPTRANS.name() + "," +
138             Columns.TRANSINFO.name() + "," +
139             Columns.INFOSTATUS.name() + "," + Columns.UPDATEDINFO.name() + "," +
140             Columns.USERID.name() + "," + Columns.ACCOUNTID.name() + "," +
141             Columns.HOSTID.name() + "," +Columns.SPECIALID.name();
142 
143     protected static final String updateAllFields = 
144             Columns.FILENAME.name() + "=?," + 
145             Columns.MODETRANS.name() + "=?," +
146             Columns.STARTTRANS.name() + "=?," + Columns.STOPTRANS.name() + "=?," + 
147             Columns.TRANSINFO.name() + "=?," +
148             Columns.INFOSTATUS.name() + "=?," + Columns.UPDATEDINFO.name() + "=?";
149 
150     protected static final String insertAllValues = " (?,?,?,?,?,?,?,?,?,?,?) ";
151 
152     private static final TreeSet<Long> clientNoDbSpecialId = new TreeSet<Long>();
153     
154 
155     /**
156      * Insert into database
157      * @param dbSession
158      * @param user
159      * @param account
160      * @param specialId
161      * @param isSender
162      * @param filename
163      * @param mode
164      * @param infostatus
165      * @param info
166      * @param updatedInfo
167      * @throws GoldenGateDatabaseException 
168      */
169     public DbTransferLog(DbSession dbSession, String user, String account, 
170             long specialId,
171             boolean isSender, String filename, String mode,
172             ReplyCode infostatus, String info,
173             UpdatedInfo updatedInfo) throws GoldenGateDatabaseException {
174         super(dbSession);
175         this.user = user;
176         this.account = account;
177         this.specialId = specialId;
178         this.isSender = isSender;
179         this.filename = filename;
180         this.mode = mode;
181         start = new Timestamp(System.currentTimeMillis());
182         this.infostatus = infostatus;
183         this.infotransf = info;
184         this.updatedInfo = updatedInfo.ordinal();
185         this.hostid = FileBasedConfiguration.fileBasedConfiguration.HOST_ID;
186         setToArray();
187         isSaved = false;
188         insert();
189     }
190     /**
191      * Load from database
192      * @param dbSession
193      * @param user
194      * @param account
195      * @param specialId
196      * @throws GoldenGateDatabaseException 
197      */
198     public DbTransferLog(DbSession dbSession, String user, String account, long specialId) 
199     throws GoldenGateDatabaseException {
200         super(dbSession);
201         this.user = user;
202         this.account = account;
203         this.specialId = specialId;
204         this.hostid = FileBasedConfiguration.fileBasedConfiguration.HOST_ID;
205         select();
206     }
207 
208     /* (non-Javadoc)
209      * @see goldengate.common.database.data.AbstractDbData#initObject()
210      */
211     @Override
212     protected void initObject() {
213         primaryKey = new DbValue[]{
214                 new DbValue(user, Columns.USERID.name()),
215                 new DbValue(account, Columns.ACCOUNTID.name()),
216                 new DbValue(hostid, Columns.HOSTID.name()),
217                 new DbValue(specialId, Columns.SPECIALID.name()) };
218         otherFields = new DbValue[]{
219                 // FILENAME, MODETRANS,
220                 // STARTTRANS, STOPTRANS, TRANSINFO
221                 // INFOSTATUS, UPDATEDINFO
222                 new DbValue(filename, Columns.FILENAME.name()),
223                 new DbValue(mode, Columns.MODETRANS.name()),
224                 new DbValue(start, Columns.STARTTRANS.name()),
225                 new DbValue(stop, Columns.STOPTRANS.name()),
226                 new DbValue(infotransf, Columns.TRANSINFO.name()),
227                 new DbValue(ReplyCode.REPLY_000_SPECIAL_NOSTATUS.getCode(), Columns.INFOSTATUS.name()), // infostatus.getCode()
228                 new DbValue(updatedInfo, Columns.UPDATEDINFO.name()) };
229         allFields = new DbValue[]{
230                 otherFields[0], otherFields[1], otherFields[2], otherFields[3],
231                 otherFields[4], otherFields[5], otherFields[6],  
232                 primaryKey[0], primaryKey[1], primaryKey[2], primaryKey[3] };
233     }
234     /* (non-Javadoc)
235      * @see goldengate.common.database.data.AbstractDbData#getSelectAllFields()
236      */
237     @Override
238     protected String getSelectAllFields() {
239         return selectAllFields;
240     }
241 
242     /* (non-Javadoc)
243      * @see goldengate.common.database.data.AbstractDbData#getTable()
244      */
245     @Override
246     protected String getTable() {
247         return table;
248     }
249 
250     /* (non-Javadoc)
251      * @see goldengate.common.database.data.AbstractDbData#getInsertAllValues()
252      */
253     @Override
254     protected String getInsertAllValues() {
255         return insertAllValues;
256     }
257 
258     /* (non-Javadoc)
259      * @see goldengate.common.database.data.AbstractDbData#getUpdateAllFields()
260      */
261     @Override
262     protected String getUpdateAllFields() {
263         return updateAllFields;
264     }
265 
266     @Override
267     protected void setToArray() {
268         // FILENAME, MODETRANS,
269         // STARTTRANS, STOPTRANS, TRANSINFO
270         // INFOSTATUS, UPDATEDINFO
271         // USERID, ACCOUNTID, SPECIALID
272         allFields[Columns.FILENAME.ordinal()].setValue(filename);
273         allFields[Columns.MODETRANS.ordinal()].setValue(mode);
274         allFields[Columns.STARTTRANS.ordinal()].setValue(start);
275         stop = new Timestamp(System.currentTimeMillis());
276         allFields[Columns.STOPTRANS.ordinal()].setValue(stop);
277         allFields[Columns.TRANSINFO.ordinal()].setValue(infotransf);
278         allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
279         allFields[Columns.UPDATEDINFO.ordinal()].setValue(updatedInfo);
280         allFields[Columns.USERID.ordinal()].setValue(user);
281         allFields[Columns.ACCOUNTID.ordinal()].setValue(account);
282         allFields[Columns.HOSTID.ordinal()].setValue(hostid);
283         allFields[Columns.SPECIALID.ordinal()].setValue(specialId);
284     }
285 
286     @Override
287     protected void setFromArray() throws GoldenGateDatabaseSqlException {
288         filename = (String) allFields[Columns.FILENAME.ordinal()].getValue();
289         mode = (String) allFields[Columns.MODETRANS.ordinal()].getValue();
290         start = (Timestamp) allFields[Columns.STARTTRANS.ordinal()].getValue();
291         stop = (Timestamp) allFields[Columns.STOPTRANS.ordinal()].getValue();
292         try {
293             infostatus = ReplyCode.getReplyCode(((Integer) allFields[Columns.INFOSTATUS
294                                                               .ordinal()].getValue()));
295         } catch (InvalidArgumentException e) {
296             throw new GoldenGateDatabaseSqlException("Wrong Argument", e);
297         }
298         infotransf = (String) allFields[Columns.TRANSINFO.ordinal()]
299                                   .getValue();
300         updatedInfo = (Integer) allFields[Columns.UPDATEDINFO.ordinal()]
301                 .getValue();
302         user = (String) allFields[Columns.USERID.ordinal()]
303                 .getValue();
304         account = (String) allFields[Columns.ACCOUNTID.ordinal()]
305                 .getValue();
306         hostid = (String) allFields[Columns.HOSTID.ordinal()]
307                                      .getValue();
308         specialId = (Long) allFields[Columns.SPECIALID.ordinal()].getValue();
309     }
310     /**
311      *
312      * @return The Where condition on Primary Key
313      */
314     protected String getWherePrimaryKey() {
315         return primaryKey[0].column + " = ? AND " +
316             primaryKey[1].column + " = ? AND " +
317             primaryKey[2].column + " = ? AND " +
318             primaryKey[3].column + " = ? ";
319     }
320     /**
321      * Set the primary Key as current value
322      */
323     protected void setPrimaryKey() {
324         primaryKey[0].setValue(user);
325         primaryKey[1].setValue(account);
326         primaryKey[2].setValue(hostid);
327         primaryKey[3].setValue(specialId);
328     }
329     /**
330      *
331      * @return the condition to limit access to the row concerned by the Host
332      */
333     private static String getLimitWhereCondition() {
334         return " "+Columns.HOSTID + " = '"+
335             FileBasedConfiguration.fileBasedConfiguration.HOST_ID+"' ";
336     }
337     /**
338      * Create a Special Id for NoDb client
339      */
340     private void createNoDbSpecialId() {
341         synchronized (clientNoDbSpecialId) {
342             // New SpecialId is not possible with No Database Model
343             specialId = System.currentTimeMillis();
344             Long newOne = specialId;
345             while (clientNoDbSpecialId.contains(newOne)) {
346                 newOne = specialId++;
347             }
348             clientNoDbSpecialId.add(newOne);
349         }
350     }
351     /**
352      * Remove a Special Id for NoDb Client
353      */
354     private void removeNoDbSpecialId() {
355         synchronized (clientNoDbSpecialId) {
356             Long oldOne = specialId;
357             clientNoDbSpecialId.remove(oldOne);
358         }
359     }
360     /*
361      * (non-Javadoc)
362      *
363      * @see openr66.databaseold.data.AbstractDbData#delete()
364      */
365     @Override
366     public void delete() throws GoldenGateDatabaseException {
367         if (dbSession == null) {
368             removeNoDbSpecialId();
369             return;
370         }
371         super.delete();
372     }
373 
374     /*
375      * (non-Javadoc)
376      *
377      * @see openr66.databaseold.data.AbstractDbData#insert()
378      */
379     @Override
380     public void insert() throws GoldenGateDatabaseException {
381         if (isSaved) {
382             return;
383         }
384         if (dbSession == null) {
385             if (specialId == DbConstant.ILLEGALVALUE) {
386                 // New SpecialId is not possible with No Database Model
387                 createNoDbSpecialId();
388             }
389             isSaved = true;
390             return;
391         }
392         // First need to find a new id if id is not ok
393         if (specialId == DbConstant.ILLEGALVALUE) {
394             specialId = DbModelFactory.dbModel.nextSequence(dbSession);
395             logger.debug("Try Insert create a new Id from sequence: " +
396                     specialId);
397             setPrimaryKey();
398         }
399         super.insert();
400     }
401 
402     /**
403      * As insert but with the ability to change the SpecialId
404      *
405      * @throws GoldenGateDatabaseException
406      */
407     public void create() throws GoldenGateDatabaseException {
408         if (isSaved) {
409             return;
410         }
411         if (dbSession == null) {
412             if (specialId == DbConstant.ILLEGALVALUE) {
413                 // New SpecialId is not possible with No Database Model
414                 createNoDbSpecialId();
415             }
416             isSaved = true;
417             return;
418         }
419         // First need to find a new id if id is not ok
420         if (specialId == DbConstant.ILLEGALVALUE) {
421             specialId = DbModelFactory.dbModel.nextSequence(dbSession);
422             logger.debug("Try Insert create a new Id from sequence: " +
423                     specialId);
424             setPrimaryKey();
425         }
426         setToArray();
427         DbPreparedStatement preparedStatement = new DbPreparedStatement(
428                 dbSession);
429         try {
430             preparedStatement.createPrepareStatement("INSERT INTO " + table +
431                     " (" + selectAllFields + ") VALUES " + insertAllValues);
432             setValues(preparedStatement, allFields);
433             try {
434                 int count = preparedStatement.executeUpdate();
435                 if (count <= 0) {
436                     throw new GoldenGateDatabaseNoDataException("No row found");
437                 }
438             } catch (GoldenGateDatabaseSqlException e) {
439                 logger.error("Problem while inserting", e);
440                 DbPreparedStatement find = new DbPreparedStatement(dbSession);
441                 try {
442                     find.createPrepareStatement("SELECT MAX(" +
443                             primaryKey[3].column + ") FROM " + table + " WHERE " +
444                             primaryKey[0].column + " = ? AND " +
445                             primaryKey[1].column + " = ? AND " +
446                             primaryKey[2].column + " = ? AND " +
447                             primaryKey[3].column + " != ? ");
448                     setPrimaryKey();
449                     setValues(find, primaryKey);
450                     find.executeQuery();
451                     if (find.getNext()) {
452                         long result;
453                         try {
454                             result = find.getResultSet().getLong(1);
455                         } catch (SQLException e1) {
456                             throw new GoldenGateDatabaseSqlException(e1);
457                         }
458                         specialId = result + 1;
459                         DbModelFactory.dbModel.resetSequence(dbSession, specialId + 1);
460                         setToArray();
461                         preparedStatement.close();
462                         setValues(preparedStatement, allFields);
463                         int count = preparedStatement.executeUpdate();
464                         if (count <= 0) {
465                             throw new GoldenGateDatabaseNoDataException("No row found");
466                         }
467                     } else {
468                         throw new GoldenGateDatabaseNoDataException("No row found");
469                     }
470                 } finally {
471                     find.realClose();
472                 }
473             }
474             isSaved = true;
475         } finally {
476             preparedStatement.realClose();
477         }
478     }
479 
480     /**
481      * Private constructor
482      *
483      * @param session
484      */
485     private DbTransferLog(DbSession dBsession) {
486         super(dBsession);
487     }
488 
489     /**
490      * For instance when getting updated information
491      *
492      * @param preparedStatement
493      * @return the next updated DbTaskRunner
494      * @throws GoldenGateDatabaseNoConnectionException
495      * @throws GoldenGateDatabaseSqlException
496      */
497     public static DbTransferLog getFromStatement(
498             DbPreparedStatement preparedStatement)
499             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
500         DbTransferLog dbTaskRunner = new DbTransferLog(preparedStatement
501                 .getDbSession());
502         dbTaskRunner.getValues(preparedStatement, dbTaskRunner.allFields);
503         dbTaskRunner.setFromArray();
504         dbTaskRunner.isSaved = true;
505         return dbTaskRunner;
506     }
507 
508     /**
509      * @param session
510      * @param status
511      * @param limit limit the number of rows
512      * @return the DbPreparedStatement for getting TransferLog according to status ordered by start
513      * @throws GoldenGateDatabaseNoConnectionException
514      * @throws GoldenGateDatabaseSqlException
515      */
516     public static DbPreparedStatement getStatusPrepareStament(
517             DbSession session, ReplyCode status, int limit)
518             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
519         String request = "SELECT " + selectAllFields + " FROM " + table;
520         if (status != null) {
521             request += " WHERE " + Columns.INFOSTATUS.name() + " = " +
522                     status.getCode() + " AND "+getLimitWhereCondition();
523         } else {
524             request += " WHERE "+getLimitWhereCondition();
525         }
526         request += " ORDER BY " + Columns.STARTTRANS.name() + " DESC ";
527         if (limit > 0) {
528             request = DbModelFactory.dbModel.limitRequest(selectAllFields, request, limit);
529         }
530         return new DbPreparedStatement(session, request);
531     }
532     /**
533      *
534      * @param session
535      * @param start
536      * @param stop
537      * @return the DbPreparedStatement for getting Selected Object, whatever their status
538      * @throws GoldenGateDatabaseNoConnectionException
539      * @throws GoldenGateDatabaseSqlException
540      */
541     public static DbPreparedStatement getLogPrepareStament(DbSession session,
542             Timestamp start, Timestamp stop)
543             throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
544         DbPreparedStatement preparedStatement = new DbPreparedStatement(session);
545         String request = "SELECT " + selectAllFields + " FROM " + table;
546         if (start != null & stop != null) {
547             request += " WHERE " + Columns.STARTTRANS.name() + " >= ? AND " +
548                     Columns.STARTTRANS.name() + " <= ? AND "+getLimitWhereCondition()+
549                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
550             preparedStatement.createPrepareStatement(request);
551             try {
552                 preparedStatement.getPreparedStatement().setTimestamp(1, start);
553                 preparedStatement.getPreparedStatement().setTimestamp(2, stop);
554             } catch (SQLException e) {
555                 preparedStatement.realClose();
556                 throw new GoldenGateDatabaseSqlException(e);
557             }
558         } else if (start != null) {
559             request += " WHERE " + Columns.STARTTRANS.name() +
560                     " >= ? AND "+getLimitWhereCondition()+
561                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
562             preparedStatement.createPrepareStatement(request);
563             try {
564                 preparedStatement.getPreparedStatement().setTimestamp(1, start);
565             } catch (SQLException e) {
566                 preparedStatement.realClose();
567                 throw new GoldenGateDatabaseSqlException(e);
568             }
569         } else if (stop != null) {
570             request += " WHERE " + Columns.STARTTRANS.name() +
571                     " <= ? AND "+getLimitWhereCondition()+
572                     " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
573             preparedStatement.createPrepareStatement(request);
574             try {
575                 preparedStatement.getPreparedStatement().setTimestamp(1, stop);
576             } catch (SQLException e) {
577                 preparedStatement.realClose();
578                 throw new GoldenGateDatabaseSqlException(e);
579             }
580         } else {
581             request += " WHERE "+getLimitWhereCondition()+
582                 " ORDER BY " + Columns.SPECIALID.name() + " DESC ";
583             preparedStatement.createPrepareStatement(request);
584         }
585         return preparedStatement;
586     }
587     /**
588     *
589     * @param session
590     * @return the DbPreparedStatement for getting Updated Object
591     * @throws GoldenGateDatabaseNoConnectionException
592     * @throws GoldenGateDatabaseSqlException
593     */
594    public static DbPreparedStatement getCountInfoPrepareStatement(DbSession session)
595            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
596        String request = "SELECT COUNT(" + Columns.SPECIALID.name()+
597                ") FROM " + table + " WHERE " + 
598                Columns.STARTTRANS.name() + " >= ? AND " +getLimitWhereCondition() +
599                " AND " + Columns.UPDATEDINFO.name() +" = ? ";
600        DbPreparedStatement pstt = new DbPreparedStatement(session, request);
601        session.addLongTermPreparedStatement(pstt);
602        return pstt;
603    }
604    /**
605     * 
606     * @param pstt
607     * @param info
608     * @param time
609     * @return the number of elements (COUNT) from the statement
610     */
611    public static long getResultCountPrepareStatement(DbPreparedStatement pstt, UpdatedInfo info,
612            long time) {
613        long result = 0;
614        try {
615            finishSelectOrCountPrepareStatement(pstt, time);
616            pstt.getPreparedStatement().setInt(2, info.ordinal());
617            pstt.executeQuery();
618            if (pstt.getNext()) {
619                result = pstt.getResultSet().getLong(1);
620            }
621         } catch (GoldenGateDatabaseNoConnectionException e) {
622         } catch (GoldenGateDatabaseSqlException e) {
623         } catch (SQLException e) {
624         } finally {
625             pstt.close();
626         }
627        return result;
628    }
629    /**
630     * @param session
631     * @return the DbPreparedStatement for getting Runner according to status ordered by start
632     * @throws GoldenGateDatabaseNoConnectionException
633     * @throws GoldenGateDatabaseSqlException
634     */
635    public static DbPreparedStatement getCountStatusPrepareStatement(
636            DbSession session)
637            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
638        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
639        request += " WHERE "+Columns.STARTTRANS.name() + " >= ? ";
640        request += " AND " + Columns.INFOSTATUS.name() + " = ? AND "+getLimitWhereCondition();
641        DbPreparedStatement prep = new DbPreparedStatement(session, request);
642        session.addLongTermPreparedStatement(prep);
643        return prep;
644    }
645    /**
646     * @param session
647     * @return the DbPreparedStatement for getting All according to status ordered by start
648     * @throws GoldenGateDatabaseNoConnectionException
649     * @throws GoldenGateDatabaseSqlException
650     */
651    public static DbPreparedStatement getCountAllPrepareStatement(
652            DbSession session)
653            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
654        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
655        request += " WHERE "+Columns.STARTTRANS.name() + " >= ? ";
656        request += " AND "+getLimitWhereCondition();
657        DbPreparedStatement prep = new DbPreparedStatement(session, request);
658        session.addLongTermPreparedStatement(prep);
659        return prep;
660    }
661    /**
662     * 
663     * @param pstt
664     * @param error
665     * @param time
666     * @return the number of elements (COUNT) from the statement
667     */
668    public static long getResultCountPrepareStatement(DbPreparedStatement pstt, ReplyCode error,
669            long time) {
670        long result = 0;
671        try {
672            finishSelectOrCountPrepareStatement(pstt, time);
673            pstt.getPreparedStatement().setInt(2, error.getCode());
674            pstt.executeQuery();
675            if (pstt.getNext()) {
676                result = pstt.getResultSet().getLong(1);
677            }
678         } catch (GoldenGateDatabaseNoConnectionException e) {
679         } catch (GoldenGateDatabaseSqlException e) {
680         } catch (SQLException e) {
681         } finally {
682             pstt.close();
683         }
684        return result;
685    }
686    /**
687     * 
688     * @param pstt
689     * @return the number of elements (COUNT) from the statement
690     */
691    public static long getResultCountPrepareStatement(DbPreparedStatement pstt) {
692        long result = 0;
693        try {
694             pstt.executeQuery();
695             if (pstt.getNext()) {
696                 result = pstt.getResultSet().getLong(1);
697             }
698         } catch (GoldenGateDatabaseNoConnectionException e) {
699         } catch (GoldenGateDatabaseSqlException e) {
700         } catch (SQLException e) {
701         } finally {
702             pstt.close();
703         }
704        return result;
705    }
706    /**
707     * Set the current time in the given updatedPreparedStatement
708     * @param pstt
709     * @throws GoldenGateDatabaseNoConnectionException
710     * @throws GoldenGateDatabaseSqlException
711     */
712    public static void finishSelectOrCountPrepareStatement(DbPreparedStatement pstt) throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
713        finishSelectOrCountPrepareStatement(pstt, System.currentTimeMillis());
714    }
715    /**
716     * Set the current time in the given updatedPreparedStatement
717     * @param pstt
718     * @throws GoldenGateDatabaseNoConnectionException
719     * @throws GoldenGateDatabaseSqlException
720     */
721    public static void finishSelectOrCountPrepareStatement(DbPreparedStatement pstt, long time) throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
722        Timestamp startlimit = new Timestamp(time);
723        try {
724            pstt.getPreparedStatement().setTimestamp(1, startlimit);
725        } catch (SQLException e) {
726            logger.error("Database SQL Error: Cannot set timestamp", e);
727            throw new GoldenGateDatabaseSqlException("Cannot set timestamp",e);
728        }
729    }
730    /**
731     * Running or not transfers are concerned
732     * @param session
733     * @param in True for Incoming, False for Outgoing
734     * @return the DbPreparedStatement for getting Runner according to in or out going way and Error
735     * @throws GoldenGateDatabaseNoConnectionException
736     * @throws GoldenGateDatabaseSqlException
737     */
738    public static DbPreparedStatement getCountInOutErrorPrepareStatement(
739            DbSession session, boolean in)
740            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
741        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
742        String inCond = null;
743        if (in) {
744            inCond = " ("+Columns.MODETRANS.name()+" = '"+FtpCommandCode.APPE.name()+"' OR "+
745            Columns.MODETRANS.name()+" = '"+FtpCommandCode.STOR.name()+"' OR "+
746            Columns.MODETRANS.name()+" = '"+FtpCommandCode.STOU.name()+"') ";
747        } else {
748            inCond = " ("+Columns.MODETRANS.name()+" = '"+FtpCommandCode.RETR.name()+"') "; 
749        }
750        request += " WHERE "+inCond;
751        request += " AND "+getLimitWhereCondition()+" ";
752        request += " AND "+Columns.STARTTRANS.name() + " >= ? ";
753        request += " AND " + Columns.UPDATEDINFO.name() +" = "+UpdatedInfo.INERROR.ordinal();
754        DbPreparedStatement prep = new DbPreparedStatement(session, request);
755        session.addLongTermPreparedStatement(prep);
756        return prep;
757    }
758 
759    /**
760     * Running or not transfers are concerned
761     * @param session
762     * @param in True for Incoming, False for Outgoing
763     * @param running True for Running only, False for all
764     * @return the DbPreparedStatement for getting Runner according to in or out going way
765     * @throws GoldenGateDatabaseNoConnectionException
766     * @throws GoldenGateDatabaseSqlException
767     */
768    public static DbPreparedStatement getCountInOutRunningPrepareStatement(
769            DbSession session, boolean in, boolean running)
770            throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
771        String request = "SELECT COUNT(" + Columns.SPECIALID.name() + ") FROM " + table;
772        String inCond = null;
773        if (in) {
774            inCond = " ("+Columns.MODETRANS.name()+" = '"+FtpCommandCode.APPE.name()+"' OR "+
775            Columns.MODETRANS.name()+" = '"+FtpCommandCode.STOR.name()+"' OR "+
776            Columns.MODETRANS.name()+" = '"+FtpCommandCode.STOU.name()+"') ";
777        } else {
778            inCond = " ("+Columns.MODETRANS.name()+" = '"+FtpCommandCode.RETR.name()+"') "; 
779        }
780        request += " WHERE "+inCond;
781        request += " AND "+getLimitWhereCondition()+" ";
782        request += " AND "+Columns.STARTTRANS.name() + " >= ? ";
783        if (running) {
784            request += " AND "+Columns.UPDATEDINFO.name() + " = " + UpdatedInfo.RUNNING.ordinal();
785        }
786        DbPreparedStatement prep = new DbPreparedStatement(session, request);
787        session.addLongTermPreparedStatement(prep);
788        return prep;
789    }
790 
791     /*
792      * (non-Javadoc)
793      *
794      * @see openr66.databaseold.data.AbstractDbData#changeUpdatedInfo(UpdatedInfo)
795      */
796     @Override
797     public void changeUpdatedInfo(UpdatedInfo info) {
798         updatedInfo = info.ordinal();
799         allFields[Columns.UPDATEDINFO.ordinal()].setValue(updatedInfo);
800         isSaved = false;
801     }
802     /**
803      * Set the ReplyCode for the UpdatedInfo
804      * @param code
805      */
806     public void setReplyCodeExecutionStatus(ReplyCode code) {
807         if (infostatus != code) {
808             infostatus = code;
809             allFields[Columns.INFOSTATUS.ordinal()].setValue(infostatus.getCode());
810             isSaved = false;
811         }
812     }
813     /**
814      *
815      * @return The current UpdatedInfo value
816      */
817     public UpdatedInfo getUpdatedInfo() {
818         return UpdatedInfo.values()[updatedInfo];
819     }
820     /**
821      *
822      * @return the ReplyCode code associated with the Updated Info
823      */
824     public ReplyCode getErrorInfo() {
825         return infostatus;
826     }
827     /**
828      * @param filename
829      *            the filename to set
830      */
831     public void setFilename(String filename) {
832         if (!this.filename.equals(filename)) {
833             this.filename = filename;
834             allFields[Columns.FILENAME.ordinal()].setValue(this.filename);
835             isSaved = false;
836         }
837     }
838     /**
839      * @return the isSender
840      */
841     public boolean isSender() {
842         return isSender;
843     }
844     /**
845      * @return the filename
846      */
847     public String getFilename() {
848         return filename;
849     }
850     /**
851      * @return the specialId
852      */
853     public long getSpecialId() {
854         return specialId;
855     }
856     
857     /**
858      * @return the infotransf
859      */
860     public String getInfotransf() {
861         return infotransf;
862     }
863     /**
864      * @param infotransf the infotransf to set
865      */
866     public void setInfotransf(String infotransf) {
867         this.infotransf = infotransf;
868     }
869     /**
870      * @return the user
871      */
872     public String getUser() {
873         return user;
874     }
875     /**
876      * @return the account
877      */
878     public String getAccount() {
879         return account;
880     }
881     /**
882      * @param stop the stop to set
883      */
884     public void setStop(Timestamp stop) {
885         this.stop = stop;
886     }
887     /**
888      * @return the mode
889      */
890     public String getMode() {
891         return mode;
892     }
893     /**
894      * This method is to be called each time an operation is happening on Runner
895      *
896      * @throws GoldenGateDatabaseException
897      */
898     public void saveStatus() throws GoldenGateDatabaseException {
899         update();
900     }
901 
902     /**
903      * Clear the runner
904      */
905     public void clear() {
906 
907     }
908     @Override
909     public String toString() {
910         return "Transfer: on " +
911                 filename + " SpecialId: " +
912                 specialId+" Mode: "+mode + " isSender: " + isSender +
913                 " User: "+user+" Account: "+account+
914                 " Start: " + start + " Stop: " + stop +
915                 " Internal: " + UpdatedInfo.values()[updatedInfo].name()+
916                 ":"+infostatus.getMesg()+
917                 " TransferInfo: "+infotransf;
918     }
919     /**
920      * @return the start
921      */
922     public Timestamp getStart() {
923         return start;
924     }
925 
926     /**
927      * @return the stop
928      */
929     public Timestamp getStop() {
930         return stop;
931     }
932     /*
933         XXXIDXXX XXXUSERXXX XXXACCTXXX XXXFILEXXX XXXMODEXXX XXXSTATUSXXX XXXINFOXXX 
934         XXXUPINFXXX XXXSTARTXXX XXXSTOPXXX
935      */
936     private static final String XML_IDX = "IDX";
937     private static final String XML_USER = "USER";
938     private static final String XML_ACCT = "ACCT";
939     private static final String XML_FILE = "FILE";
940     private static final String XML_MODE = "MODE";
941     private static final String XML_STATUS = "STATUS";
942     private static final String XML_INFO = "INFO";
943     private static final String XML_UPDINFO = "UPDINFO";
944     private static final String XML_START = "START";
945     private static final String XML_STOP = "STOP";
946     private static final String XML_ROOT = "LOGS";
947     private static final String XML_ENTRY = "LOG";
948     /**
949      * Structure of the Configuration file
950      *
951      */
952     private static final XmlDecl [] logDecls = {
953         // identity
954         new XmlDecl(XmlType.STRING, XML_IDX), 
955         new XmlDecl(XmlType.STRING, XML_USER),
956         new XmlDecl(XmlType.STRING, XML_ACCT),
957         new XmlDecl(XmlType.STRING, XML_FILE),
958         new XmlDecl(XmlType.STRING, XML_MODE),
959         new XmlDecl(XmlType.STRING, XML_STATUS),
960         new XmlDecl(XmlType.STRING, XML_INFO),
961         new XmlDecl(XmlType.STRING, XML_UPDINFO),
962         new XmlDecl(XmlType.STRING, XML_START),
963         new XmlDecl(XmlType.STRING, XML_STOP),
964     };
965     /**
966      * Global Structure for Server Configuration
967      */
968     private static final XmlDecl[] logsElements = {
969         new XmlDecl(XML_ENTRY, XmlType.XVAL, XML_ROOT+"/"+XML_ENTRY, 
970                 logDecls, true)
971     };
972     /**
973      * 
974      * @return the associated XmlValue
975      */
976     private XmlValue[] saveIntoXmlValue() {
977         XmlValue []values = new XmlValue[logDecls.length];
978         for (int i = 0; i < logDecls.length; i++) {
979             values[i] = new XmlValue(logDecls[i]);
980         }
981         values[0].setFromString(Long.toString(specialId));
982         values[1].setFromString(user);
983         values[2].setFromString(account);
984         values[3].setFromString(filename);
985         values[4].setFromString(mode);
986         values[5].setFromString(getErrorInfo().getMesg());
987         values[6].setFromString(infotransf);
988         values[7].setFromString(getUpdatedInfo().name());
989         values[8].setFromString(start.toString());
990         values[9].setFromString(stop.toString());
991         return values;
992     }
993     /**
994      * Save the current DbTransferLog to a file
995      * @param filename
996      * @return The message for the HTTPS interface
997      */
998     public String saveDbTransferLog(String filename) {
999         Document document = XmlUtil.createEmptyDocument();
1000         XmlValue [] roots = new XmlValue[1];
1001         XmlValue root = new XmlValue(logsElements[0]);
1002         roots[0] = root;
1003         String message = null;
1004         XmlValue []values = saveIntoXmlValue();
1005         try {
1006             root.addValue(values);
1007         } catch (InvalidObjectException e) {
1008             logger.error("Error during Write DbTransferLog file", e);
1009             return "Error during purge";
1010         }
1011         try {
1012             delete();
1013         } catch (GoldenGateDatabaseException e) {
1014             message = "Error during purge";
1015         }
1016         message = "Purge Correct Logs successful";
1017         XmlUtil.write(document, roots);
1018         try {
1019             XmlUtil.saveDocument(filename, document);
1020         } catch (IOException e1) {
1021             logger.error("Cannot write to file: "+filename+" since {}", e1.getMessage());
1022             return message+" but cannot save file as export";
1023         }
1024         return message;
1025     }
1026     /**
1027      * Export DbTransferLogs to a file and purge the corresponding DbTransferLogs
1028      * @param preparedStatement the DbTransferLog as SELECT command to export (and purge)
1029      * @param filename the filename where the DbLogs will be exported
1030      * @return The message for the HTTPS interface
1031      */
1032     public static String saveDbTransferLogFile(DbPreparedStatement preparedStatement, String filename) {
1033         Document document = XmlUtil.createEmptyDocument();
1034         XmlValue [] roots = new XmlValue[1];
1035         XmlValue root = new XmlValue(logsElements[0]);
1036         roots[0] = root;
1037         String message = null;
1038         try {
1039             try {
1040                 preparedStatement.executeQuery();
1041                 while (preparedStatement.getNext()) {
1042                     DbTransferLog log = DbTransferLog.getFromStatement(preparedStatement);
1043                     XmlValue []values = log.saveIntoXmlValue();
1044                     try {
1045                         root.addValue(values);
1046                     } catch (InvalidObjectException e) {
1047                         logger.error("Error during Write DbTransferLog file", e);
1048                         return "Error during purge";
1049                     }
1050                     log.delete();
1051                 }
1052                 message = "Purge Correct Logs successful";
1053             } catch (GoldenGateDatabaseNoConnectionException e) {
1054                 message = "Error during purge";
1055             } catch (GoldenGateDatabaseSqlException e) {
1056                 message = "Error during purge";
1057             } catch (GoldenGateDatabaseException e) {
1058                 message = "Error during purge";
1059             }
1060         } finally {
1061             preparedStatement.realClose();
1062         }
1063         XmlUtil.write(document, roots);
1064         try {
1065             XmlUtil.saveDocument(filename, document);
1066         } catch (IOException e1) {
1067             logger.error("Cannot write to file: "+filename+" since {}", e1.getMessage());
1068             return message+" but cannot save file as export";
1069         }
1070         return message;
1071     }
1072 }