JavaDoc


001    /**
002     * Copyright (c) 2003 Daffodil Software Ltd all rights reserved,
003     * Modifications Copyright (c) 2008 Regiscope Digital Imaging Co, LLC, All rights reserved.
004     * This program is free software; you can redistribute it and/or modify
005     * it under the terms of version 2 of the GNU General Public License as
006     * published by the Free Software Foundation.
007     * There are special exceptions to the terms and conditions of the GPL
008     * as it is applied to this software. See the GNU General Public License for more details.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018     */
019    
020    package org.dbreplicator.replication;
021    
022    import java.io.*;
023    import java.net.*;
024    import java.net.UnknownHostException;
025    import java.rmi.*;
026    import java.rmi.server.*;
027    import java.sql.*;
028    import java.util.*;
029    import javax.xml.parsers.*;
030    
031    import org.xml.sax.*;
032    import org.xml.sax.ContentHandler;
033    import org.dbreplicator.replication.DBHandler.*;
034    import org.dbreplicator.replication.xml.*;
035    import org.dbreplicator.replication.zip.*;
036    import java.util.ArrayList;
037    import java.io.FileOutputStream;
038    import org.dbreplicator.replication.synchronize.AbstractSynchronize;
039    import org.apache.log4j.Logger;
040    
041    /**
042     * The Publication class holds all the methods which are required for the physical
043     * creation of the publication(i.e system tables) and which are used at the time
044     * of synchronization at publisher's end. It implements three interfaces,
045     * <p>
046     * _PubImpl : It makes this class to implement all the remote methods which are
047     * called by the subscriber, at the time of subscribing, taking snapshot,
048     * synchronizing and for different tasks related to synchronization.
049     * <p>
050     * _Publication : It makes this class to implement all the methods which are
051     * called by the user, at the time of publishing, and for different tasks
052     * related to publishing.
053     * <p>
054     * _Replicator : It makes this class to implement all the methods which are called
055     * at the time of synchronization to get the publisher's information.
056     *
057     */
058    
059    public class Publication
060        extends UnicastRemoteObject implements _PubImpl, _Publication, _Replicator {
061      /**
062       * name of publication
063       */
064      private String pubName;
065    
066      /**
067       * connection of server side
068       */
069      private ConnectionPool connectionPool;
070    
071      /**
072       * conflict resolver
073       */
074      private String conflictResolver;
075    
076      /**
077       * tables included in publication
078       */
079      private ArrayList pubRepTables;
080    
081      /**
082       * server side database handler
083       */
084      private AbstractDataBaseHandler dbh;
085    
086      /**
087       * number of tables included in publication
088       */
089      public int noOfPubTables;
090    
091      /**
092       * connection of server side
093       */
094    //  public Connection pubConnection;
095    
096      /**
097       * handler for syncronisation
098       */
099      SyncXMLCreator syncXMLCreator;
100      /**
101       * Tables in which updations are required during synchronisation.
102       */
103      ArrayList usedActualTables;
104      // for locking synchronization or snapshot operations
105      // for thread safety
106      private static boolean isLocked = false;
107      private ReplicationServer localServer;
108      private static final boolean LOCK = true;
109      private static final boolean UNLOCK = false;
110      //Kept for multiple subsriber case trying to get lock
111      ArrayList listOfWaitingSubcription = new ArrayList();
112      HashMap syncIdMap;
113      protected static Logger log = Logger.getLogger(Publication.class.getName());
114      private boolean isPublicationCyclic;
115      String localAddress = null;
116    
117      public Publication() throws RemoteException {
118      }
119    
120      public Publication(ConnectionPool connectionPool0, String pubName0,
121                         String serverName0, ReplicationServer localServer0) throws
122          RemoteException, RepException {
123        pubName = pubName0;
124        connectionPool = connectionPool0;
125        // make sure whether you need this connection statement or not
126        dbh = Utility.getDatabaseHandler(connectionPool, pubName);
127        dbh.setLocalServerName(serverName0);
128        //String databaseName = pubConnection.getMetaData().getDatabaseProductName();
129        syncXMLCreator = new SyncXMLCreator(pubName, connectionPool, dbh);
130        localServer = localServer0;
131        try{
132           //localAddress = InetAddress.getLocalHost().getHostAddress();
133               // bjt - fix address
134           localAddress = InetAddress.getLocalHost().getHostName();
135         }
136         catch (UnknownHostException ex) {
137           RepConstants.writeERROR_FILE(ex);
138           RepException rex = new RepException("REP056", new Object[] {pubName,ex.getMessage()});
139           rex.setStackTrace(ex.getStackTrace());
140           throw rex;
141         }
142    
143      }
144    
145      /**
146       * Sets the conflict resolver for publication. This can be one of:
147       *
148       *  <ul>
149       *  <li>publisher_wins</li>
150       *  <li>subscriber_wins</li>
151       *  </ul>
152       *
153       * @param conflictReolver0 conflict resolver
154       * @throws RepException
155       */
156      public void setConflictResolver(String conflictReolver0) throws RepException {
157          if (! (conflictReolver0.equalsIgnoreCase(_Publication.publisher_wins) ||
158                 conflictReolver0.equalsIgnoreCase(_Publication.subscriber_wins))) {
159            throw new RepException("REP016", null);
160          }
161          conflictResolver = conflictReolver0;
162          log.info("conflictResolver " + conflictResolver);
163      }
164    
165      /**
166       * Set the replication tables for the publication
167       * @param repTables0 list of tables
168       */
169      public void setPublicationTables(ArrayList repTables0) {
170        pubRepTables = repTables0;
171        noOfPubTables = repTables0.size();
172      }
173    
174      public void setCyclic(boolean isCyclic){
175        isPublicationCyclic = isCyclic;
176        for (int i = 0; i < pubRepTables.size() ; i++) {
177          ((RepTable)pubRepTables.get(i) ).setCyclicDependency(isPublicationCyclic ? "Y" : "N") ;
178        }
179      }
180    
181      public boolean isPublicationCyclic(){
182       return isPublicationCyclic;
183      }
184    
185      public String getConflictResolver() throws RemoteException {
186          log.info("Returning conflictResolver " + conflictResolver);
187          return conflictResolver;
188      }
189    
190      /**
191       * Set the given filter clause for the given table
192       * <p>A filter clause is simply the end of a where clause in an SQL statement.  For example, to determine if your
193       * filterclause will work, insert it into this statement, where tablename is the table to which the filter is being
194       * applied:</p>
195       * <code>select * from &lt;tablename&gt; where &lt;filterclause&gt;</code>
196       * <p>As you can see, the filterclause can be almost anything, including subselects.</p>
197       *
198       * @param tableName0 for which filter clause is to be added
199       * @param filterClause0 filter clause to be set
200       * @throws RepException if table does not exist or if filter clause is invalid
201       */
202      public void setFilter(String tableName0, String filterClause0) throws RepException {
203        setFilter(tableName0, filterClause0, 0);
204      }
205    
206      public void setFilter(String tableName0, String filterClause0, int paramCount0) throws RepException {
207            Connection pubConnection = null;
208        Statement stmt = null;
209        ResultSet rs = null;
210        try {
211              pubConnection = connectionPool.getConnection(pubName);
212              MetaDataInfo mdi = Utility.getDatabaseMataData(pubConnection);
213          SchemaQualifiedName sname = new SchemaQualifiedName(mdi, tableName0);
214          if (tableName0.indexOf('.') == -1) {
215            mdi.checkTableExistance(sname);
216          }
217          log.debug("Table name : " + tableName0);
218          log.debug("pubRepTables : " + pubRepTables);
219          log.info("Set the filter : " + filterClause0 + " for table " + tableName0);
220          for (int i = 0, size = pubRepTables.size(); i < size; i++) {
221            RepTable repTable = (RepTable) pubRepTables.get(i);
222            String sqname = repTable.getSchemaQualifiedName().toString();
223            if (sqname.equalsIgnoreCase(sname.toString())) {
224              String query = "Select * from " + sqname + " where " + filterClause0;
225             try {
226              PreparedStatement st = pubConnection.prepareStatement(query);
227              if (paramCount0 > 0) {
228                for (int j = 1; j <= paramCount0; j++) {
229                st.setString(j, null);
230                }
231              }
232              rs = st.executeQuery();
233                rs.next();
234              }
235              catch (SQLException ex1) {
236                RepConstants.writeERROR_FILE(ex1);
237                RepException rex = new RepException("REP019",new Object[] {filterClause0});
238                rex.setStackTrace(ex1.getStackTrace());
239                throw rex;
240              }
241              repTable.setFilterClause(filterClause0);
242              log.debug("Filter clause set successfully ");
243              return;
244            }
245          }
246          throw new RepException("REP017", new Object[] {tableName0});
247        }
248        finally {
249          connectionPool.removeSubPubFromMap(pubName);
250          try {
251            if (rs != null) {
252              rs.close();
253              if (stmt != null)
254                stmt.close();
255            }
256          }
257          catch (SQLException ex) {
258            //Ignore the Exception
259          }
260              connectionPool.returnConnection(pubConnection);
261        }
262      }
263    
264    
265      /**
266       * This method come in use if tables in a publications are refering to
267       * each other and It is required to
268       *
269       * @param tableName0 String
270       * @param createShadowTable boolean
271       * @throws RepException
272       */
273      public void setCreateShadowTable(String tableName0, boolean createShadowTable) throws
274          RepException {
275            Connection connection = null;
276            try {
277              connection = connectionPool.getConnection(pubName);
278              MetaDataInfo mdi = Utility.getDatabaseMataData(connection);
279        SchemaQualifiedName sname = new SchemaQualifiedName(mdi, tableName0);
280        if (tableName0.indexOf('.') == -1) {
281          mdi.checkTableExistance(sname);
282        }
283        RepTable repTable = getRepTable(sname.toString());
284        repTable.setCreateShadowTable(createShadowTable ? RepConstants.YES :RepConstants.NO);
285      }
286            finally {
287              connectionPool.returnConnection(connection);
288            }
289      }
290    
291    
292      /**
293       * This method is responsible for creating required system tables in publication database
294       * and shadow tables and triggers on tables to be published.  It is required for replication
295       * and saves data into system tables about the publication.
296       *
297       * @throws RepException
298       */
299      public void publish() throws RepException {
300       Connection connection = null;
301       Statement stmt =null;
302        try {
303          //Creates Publication Table
304          //Creates BookMark Table
305          //Creates Super Log Table
306          //Creates Rep Table
307              connection = connectionPool.getConnection(pubName);
308          stmt = connection.createStatement();
309          dbh.createRemoteSystemTables(pubName);
310          SchemaQualifiedName[] tableNames = getSchemaQualifiedTableNames();
311          MetaDataInfo mdi = Utility.getDatabaseMataData(connection);
312          for (int i = 0; i < tableNames.length; i++) {
313            RepTable repTable = getRepTable(tableNames[i].toString());
314            if (repTable.getCreateShadowTable().equalsIgnoreCase(RepConstants.NO))
315              continue;
316            String schema = tableNames[i].getSchemaName();
317            String table = tableNames[i].getTableName();
318            ArrayList colInfoList = mdi.getColumnDataTypeInfo(dbh, schema, table);
319            //Searches pubRepTables by the tablename and returns the corresponding object of RepTable and calls function
320            String[] primCols = getRepTable(tableNames[i].toString()).getPrimaryColumns();
321            //We will get a sequence of  columns and there datatypes along with primary columns and there datatypes.
322            //as    " col1 number(10),col2 varchar2(24),old_col1 number(10) "
323            String allColSequence = dbh.getShadowTableColumnDataTypeSequence(colInfoList, primCols,repTable);
324            //Creates Shadow Tables For all the participating tables
325            dbh.createShadowTable(pubName, tableNames[i].toString(), allColSequence,primCols);
326            dbh.makeProvisionForLOBDataTypes(colInfoList);
327            dbh.createShadowTableTriggers(pubName, tableNames[i].toString(),colInfoList, primCols);
328          }
329          //Add an entry in Publication table And Rep Table
330          savePublicationData(dbh,connection,stmt);
331        }
332        catch (SQLException ex) {
333          RepConstants.writeERROR_FILE(ex);
334          throw new RepException("REP020", new Object[] {ex.getMessage()});
335        }
336        catch (Throwable ex) {
337          log.error(ex, ex);
338          throw new RepException("REP020", new Object[] {ex.getMessage()});
339        }
340        finally {
341          connectionPool.removeSubPubFromMap(pubName);
342          try {
343            if (stmt != null) {
344              stmt.close();
345            }
346          }
347          catch (SQLException ex1) {
348          }
349              connectionPool.returnConnection(connection);
350        }
351      }
352    
353      /**
354       * Saves the publication name and its tables into server side replication
355       * system tables.
356       * @param dbh database handler for server side
357       * @throws RepException
358       */
359      private void savePublicationData(AbstractDataBaseHandler dbh,Connection connection,Statement stmt) throws
360          RepException {
361        try {
362          log.info("conflictResolver " + conflictResolver);
363          if (conflictResolver == null) {
364            log.info("setting conflictResolver " + publisher_wins + " by default");
365            conflictResolver = RepConstants.publisher_wins;
366            // Insert Into Pulication Table
367          }
368          StringBuffer insertquery = new StringBuffer();
369          insertquery.append("insert into " + dbh.getPublicationTableName() +" values ( '")
370              .append(pubName).append("' ,'").append(conflictResolver)
371              .append("','").append(dbh.getLocalServerName()).append("' )");
372          stmt.execute(insertquery.toString());
373          log.info("Query exceuted:" + insertquery.toString());
374    
375          // Insert Into Rep Table, for all tables in publication
376          for (int i = 0; i < noOfPubTables; i++) {
377            RepTable repTable = (RepTable) pubRepTables.get(i);
378            repTable.setConflictResolver(conflictResolver);
379            dbh.saveRepTableData(connection, pubName, repTable);
380            // NEW REP TABLE VIOLATION SACHIN
381          }
382        }
383        catch (SQLException ex) {
384          RepConstants.writeERROR_FILE(ex);
385          throw new RepException("REP035", new Object[] {pubName});
386        }
387    
388      }
389    
390      private void appendValue(StringBuffer sb, Object value) {
391        if (value == null) {
392          sb.append(value);
393        }
394        else {
395          sb.append("'" + value + "'");
396        }
397      }
398    
399      /**
400       * This method is responsible to assist to subscribe a subscription. This
401       * method creates a XML file to get all the tables involved in the publication
402       * and makes an entry in bookmark table of serverside to save the publication
403       * name with the subscription.
404       * @param clientVendorType0 client database type i.e. oracle or sql server
405       * @param subName Subscription Name
406       * @param address IP Address
407       * @param isSchemaSupported True/False (boolean)
408       * @param fileUpload
409       * @param remoteMachineAddress IP Address
410       * @throws RemoteException
411       * @throws RepException
412       */
413      public void createStructure(int clientVendorType0, String subName,String address, boolean isSchemaSupported,_FileUpload fileUpload,String remoteMachineAddress) throws
414          RemoteException, RepException {
415        FileOutputStream fos = null;
416        OutputStreamWriter os = null;
417        try {
418          if (pubRepTables == null) {
419            return;
420          }
421          //Do entry in the BookMark Table of publication  for each
422          //participatig tables in the publication with subscription detail
423          int srcVendorType = Utility.getVendorType(connectionPool, pubName);
424              Connection connection = null;
425          try {
426            String filePath = PathHandler.getDefaultFilePathForCreateStructure("struct_" + pubName + "_" +subName);
427            fos = new FileOutputStream(filePath);
428            os = new OutputStreamWriter(fos);
429            os.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
430            os.write("<Database>\r\n");
431                    connection = connectionPool.getConnection(pubName);
432            TreeMap primCons = new TreeMap(String.CASE_INSENSITIVE_ORDER);
433            MetaDataInfo mdi = Utility.getDatabaseMataData(connection);
434            AbstractDataBaseHandler dbh = Utility.getDatabaseHandler(connectionPool,pubName);
435            ArrayList foreignKeyQueries = new ArrayList();
436            for (int i = 0; i < noOfPubTables; i++) {
437              RepTable repTable = (RepTable) pubRepTables.get(i);
438              SchemaQualifiedName sname = repTable.getSchemaQualifiedName();
439              StringBuffer createTableQuery = new StringBuffer();
440              String schema = sname.getSchemaName();
441              String table = sname.getTableName();
442              if(isSchemaSupported){
443                createTableQuery.append(" Create Table ").append(schema + "." +table)
444                    .append(" ( ").append(mdi.generateColumnsQueryForClientNode(dbh,srcVendorType, schema, table, clientVendorType0))
445                    .append(mdi.getAppliedConstraints(schema, table, primCons)).append(")");
446              }else{
447                createTableQuery.append(" Create Table ").append(table)
448                    .append(" ( ").append(mdi.generateColumnsQueryForClientNode(dbh,srcVendorType, schema, table, clientVendorType0))
449                    .append(mdi.getAppliedConstraints(schema, table, primCons)).append(")");
450              }
451              if (isSchemaSupported) {
452                  os.write("<SchemaName>");
453                  os.write(schema);
454                  os.write("</SchemaName>");
455               }
456              os.write("<Table>");
457              os.write("<Query>");
458              os.write(createTableQuery.toString());
459              os.write("</Query>\n");
460              os.write("<TableName>");
461              if (isSchemaSupported) {
462                os.write(sname.toString());
463              } else {
464                 os.write(table);
465              }
466              os.write("</TableName>\r\n");
467              os.write("<PrimaryColumns>\r\n");
468              String[] primCols = repTable.getPrimaryColumns();
469              for (int j = 0; j < primCols.length; j++) {
470                os.write("<ColumnName>");
471                os.write(primCols[j]);
472                os.write("</ColumnName>");
473              }
474              os.write("</PrimaryColumns>\r\n");
475              os.write("<ForeignKeyColumns>\r\n");
476              String[] foreignKeyCols = repTable.getForeignKeyCols();
477              if (foreignKeyCols != null) {
478                for (int j = 0, size = foreignKeyCols.length; j < size; j++) {
479                  os.write("<FKColumnName>");
480                  os.write(foreignKeyCols[j]);
481                  os.write("</FKColumnName>");
482                }
483              }
484              os.write("</ForeignKeyColumns>\r\n");
485              String[] columnstoBeIgnored = repTable.getColumnsToBeIgnored();
486              os.write("<IgnoredColumns>\r\n");
487              if (columnstoBeIgnored != null) {
488                for (int j = 0, size = columnstoBeIgnored.length; j < size; j++) {
489                  os.write("<IgnoredColumnName>");
490                  os.write(columnstoBeIgnored[j]);
491                  os.write("</IgnoredColumnName>");
492                }
493              }
494              os.write("</IgnoredColumns>\r\n");
495              os.write("<FilterClause>");
496              if (repTable.getFilterClause() == null) {
497                os.write("NO_DATA");
498              }
499              else {
500                os.write("<![CDATA[");
501                os.write(repTable.getFilterClause());
502                os.write("]]>");
503              }
504              os.write("</FilterClause>");
505    
506              os.write("<CreateShadowTable>");
507              os.write(repTable.getCreateShadowTable());
508              os.write("</CreateShadowTable>");
509              os.write("<CyclicDependency>");
510              os.write(repTable.getCyclicDependency());
511              os.write("</CyclicDependency>");
512              os.write("</Table>\r\n");
513            }
514    
515            for (int i = 0; i < noOfPubTables; i++) {
516              RepTable repTable = (RepTable) pubRepTables.get(i);
517              SchemaQualifiedName sname = repTable.getSchemaQualifiedName();
518              ArrayList alterTabelStatements = mdi.getForeignKeyConstraints(sname.getSchemaName(), sname.getTableName());
519              if (alterTabelStatements != null && alterTabelStatements.size() > 0) {
520                foreignKeyQueries.addAll(alterTabelStatements);
521              }
522            }
523            for (int i = 0, size = foreignKeyQueries.size(); i < size; i++) {
524              os.write("<AlterTableForeignKeyStatement>");
525              os.write( (String) foreignKeyQueries.get(i));
526              os.write("</AlterTableForeignKeyStatement>");
527            }
528    
529            os.write("</Database>\r\n");
530            os.close();
531            String localMachineAddress = InetAddress.getLocalHost().getHostName();
532            if(!localMachineAddress.equalsIgnoreCase(remoteMachineAddress)) {
533              String zipFilePath = PathHandler.getDefaultZIPFilePathForCreateStructure("struct_" + pubName + "_" +subName);
534              ZipHandler.makeStructZip(zipFilePath, filePath,"struct_" + pubName + "_" + subName);
535              WriteOnSocket writeOnSocket = new WriteOnSocket(zipFilePath, filePath,Publication.xmlAndShadow_entries,"struct_" + pubName + "_" + subName, fileUpload, false);
536              writeOnSocket.start();
537              writeOnSocket.join();
538            }
539            log.debug("wrote XMLFile  ClientSocket ");
540          }
541          catch (IOException ex) {
542            RepConstants.writeERROR_FILE(ex);
543            RemoteException rem = new RemoteException(ex.getMessage());
544            rem.setStackTrace(ex.getStackTrace());
545            RepConstants.writeERROR_FILE(rem);
546            throw rem;
547          }
548          catch (InterruptedException ex) {
549          RepConstants.writeERROR_FILE(ex);
550          RemoteException rem = new RemoteException(ex.getMessage());
551          rem.setStackTrace(ex.getStackTrace());
552          RepConstants.writeERROR_FILE(rem);
553          throw rem;
554    
555          }
556             finally {
557               connectionPool.returnConnection(connection);
558             }
559        }
560        finally {
561          try {
562            os.close();
563            fos.close();
564          }
565          catch (IOException ex1) {
566            // Ignore the Exception
567          }
568        }
569      }
570    
571      public Object[] getPublisherAddressAndPort() throws
572          RemoteException, RepException {
573        try {
574        Integer portNumber = null;
575        ServerSocket serverSocket = connectionPool.startServerSocket();
576          portNumber = new Integer(serverSocket.getLocalPort());
577          syncXMLCreator.serverSocket = serverSocket;
578          return new Object[] {localAddress, portNumber};
579        }
580        finally {
581          connectionPool.removeSubPubFromMap(pubName);
582        }
583    
584      }
585    
586    
587      /**
588       * Inserts a row into bookmark table of server side to put a matching pair of
589       * publication name and subscription name.
590       * @param subName sub name
591       * @throws RepException
592       */
593      public void saveSubscriptionData(String subName) throws RemoteException {
594            Connection connection = null;
595        Statement stt = null;
596        try {
597          connection = connectionPool.getConnection(pubName);
598          stt = connection.createStatement();
599          for (int i = 0; i < noOfPubTables; i++) {
600            RepTable repTable = (RepTable) pubRepTables.get(i);
601            StringBuffer sb0 = new StringBuffer();
602            sb0.append(" Insert into ").append(dbh.getBookMarkTableName()).append(
603                " values ( '").append(pubName).append("','").append(subName).append(
604                "','").append(repTable.getSchemaQualifiedName()).append("',0,0,'N')");
605            stt.execute(sb0.toString());
606          }
607        }
608        catch (SQLException ex) {
609          RepConstants.writeERROR_FILE(ex);
610          throw new RemoteException(ex.getMessage());
611        }
612        catch (RepException ex) {
613          RepConstants.writeERROR_FILE(ex);
614          throw new RemoteException(ex.getMessage());
615        }
616        finally {
617          connectionPool.removeSubPubFromMap(pubName);
618          try {
619            if (stt != null)
620              stt.close();
621               try {
622                 connectionPool.returnConnection(connection);
623               }
624               catch (RepException ex) {
625                       // Ignore the exception
626               }
627          }
628          catch (SQLException ex1) {
629            // Ignore the exception
630          }
631        }
632      }
633    
634      /**
635       * creates an XMl file for getting Snapshot on clients side.
636       * Do entry in the server side bookmark table.
637       * Deletes all records from the server side log table.
638       *
639       * @param subName String
640       * @param isSchemaSupported True/False (boolean)
641       * @param fileUpload
642       * @param remoteMachineAddress IP Address
643       * @throws SQLException
644       * @throws RemoteException
645       * @throws RepException
646       */
647      public void createSnapShot(String subName,boolean isSchemaSupported,_FileUpload fileUpload,String remoteMachineAddress) throws SQLException, RemoteException, RepException {
648            Connection pubConnection = null;
649        Statement stmt = null;
650        ResultSet rows = null, shadowResult = null;
651        try {
652          FileOutputStream fos = new FileOutputStream(PathHandler.getDefaultFilePathForClient("snapshot_" + pubName + "_" +subName));
653          OutputStreamWriter os = new OutputStreamWriter(fos);
654          BufferedWriter bw = new BufferedWriter(os);
655              pubConnection = connectionPool.getConnection(pubName);
656          stmt =pubConnection.createStatement();
657              /* Leave for debugging/timing purposes */
658          /*  long startTime=System.currentTimeMillis(); */
659          XMLWriter xmlWriter = new XMLWriter(bw, dbh, pubConnection);
660          bw.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
661          bw.write("<root_snapshot>");
662          String tableName;
663          SchemaQualifiedName sname;
664          String[] primaryKeyColumns;
665          stmt = pubConnection.createStatement();
666          for (int i = 0; i < noOfPubTables; i++) {
667            RepTable repTable = (RepTable) pubRepTables.get(i);
668            primaryKeyColumns =repTable.getPrimaryColumns();
669            if (repTable.getCreateShadowTable().equalsIgnoreCase(RepConstants.NO))
670              continue;
671            sname = (repTable).getSchemaQualifiedName();
672            tableName = isSchemaSupported ? sname.toString() : sname.getTableName();
673            ArrayList encodedCols = PathHandler.getEncodedColumns(tableName);
674            bw.write("<tableName>");
675            bw.write(tableName);
676            String query;
677            String[] parameters = null;
678            if (repTable.getFilterClause() == null || repTable.getFilterClause().equalsIgnoreCase("")) {
679              query = "Select * from " + repTable.getRepTableQualifiedIdentifier();
680            }
681            else {
682              query = "Select * from " + repTable.getRepTableQualifiedIdentifier() + " where " + repTable.getFilterClause();
683            }
684    
685            /** @todo comment the method getResultSet and create the statement
686             *  outside the loop as anywhere as require.*/
687    
688                    log.debug("running " + query);
689            pubConnection.setAutoCommit(false);
690            Statement st = pubConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
691                    st.setFetchSize(1000);
692            rows = st.executeQuery(query); // Query
693                    log.debug("getting metadata");
694            ResultSetMetaData rsmt = rows.getMetaData();
695                    log.debug("getting column count");
696            int noOfColumns = rsmt.getColumnCount();
697                    log.debug("getting PrimaryKeyResultSet");
698            ResultSet primayKeyResultSet =getPrimaryKeyResultSet(stmt,tableName,repTable.getPrimaryColumns());
699                    log.debug("Starting to loop through rows");
700            while (rows.next()) {
701              bw.write("<operation>");
702              bw.write("I");
703              bw.write("<row>");
704              for (int c = 1; c <= noOfColumns; c++) {
705                String columnName = rsmt.getColumnName(c);
706                if (!encodedCols.contains(columnName.toUpperCase())) {
707                  bw.write("<c" + c + ">");
708                }
709                else {
710                  bw.write("<c" + c + "  Encode=\"y\">");
711                }
712                // Special Handelling for Blob Clob Case
713                xmlWriter.write(rows, c, encodedCols, columnName);
714                bw.write("</c" + c + ">\r\n");
715              }
716              bw.write("</row>\r\n");
717              xmlWriter.writePrimaryKeyElement(primaryKeyColumns,primayKeyResultSet,encodedCols);
718              bw.write("</operation>\r\n");
719              primayKeyResultSet.next();
720              bw.flush();
721            }
722            // Close the resultset because new instance of resultset has been created for each table.
723            pubConnection.commit();
724            rows.close();
725            bw.write("</tableName>\r\n");
726            // updating values for bookmark table
727            String selectMaxSyncID= " select " + RepConstants.shadow_sync_id1 + " from " +
728                RepConstants.shadow_Table(tableName) + " order by " + 
729                            RepConstants.shadow_sync_id1 + " desc limit 1";
730            log.debug(selectMaxSyncID);
731            pubConnection.setAutoCommit(true);
732            shadowResult = stmt.executeQuery(selectMaxSyncID);
733                    Object maxvalue = null;
734            if (shadowResult.next()) { 
735                                    maxvalue = shadowResult.getObject(1);
736                            }
737            if (maxvalue == null) {
738            maxvalue = new Long(0);
739            }
740            log.debug("max(" + RepConstants.shadow_sync_id1 + ")=" + maxvalue);
741            StringBuffer updateBookmarkQuery = new StringBuffer("update " +dbh.getBookMarkTableName() + " set ");
742            updateBookmarkQuery.append(RepConstants.bookmark_lastSyncId4 + " = " +maxvalue + ", ");
743            updateBookmarkQuery.append(RepConstants.bookmark_ConisderedId5 + " = " +maxvalue + " ");
744            updateBookmarkQuery.append(" where " + RepConstants.bookmark_LocalName1 +" ='" + pubName + "' ");
745            updateBookmarkQuery.append(" and  " + RepConstants.bookmark_RemoteName2 +" ='" + subName + "' ");
746            updateBookmarkQuery.append(" and  " + RepConstants.bookmark_TableName3 +" ='" + tableName + "'");
747            stmt.executeUpdate(updateBookmarkQuery.toString());
748            log.debug(updateBookmarkQuery.toString());
749          }
750          bw.write("</root_snapshot>\r\n");
751              /* Keep for debugging / timing */
752          /*  System.out.println("TIME TAKEN IN CREATING XML FOR SNAPSHOT:::"+(System.currentTimeMillis()-startTime)); */
753          if(bw!=null)
754          bw.close();
755          fos.close();
756    
757          localAddress = InetAddress.getLocalHost().getHostName();
758          if(!localAddress.equalsIgnoreCase(remoteMachineAddress)) {
759            // making zip file from xml file
760            ZipHandler.makeZip(PathHandler.getDefaultZIPFilePathForClient("snapshot_" +pubName + "_" + subName),
761                               PathHandler.getDefaultFilePathForClient("snapshot_" +pubName + "_" + subName),
762                               "snapshot_" + pubName + "_" + subName /*+ ".xml"*/);
763            // writing zip file on socket
764            WriteOnSocket writeOnSocket = new WriteOnSocket(PathHandler.getDefaultZIPFilePathForClient("snapshot_" + pubName + "_" +subName),
765                PathHandler.getDefaultFilePathForClient("snapshot_" + pubName + "_" + subName),_Publication.xmlAndShadow_entries,
766                   "snapshot_" + pubName + "_" + subName, fileUpload, true);
767            writeOnSocket.start();
768            writeOnSocket.join();
769          }
770           dbh.deleteRecordsFromSuperLogTable(stmt);
771        }
772    
773        catch (FileNotFoundException ex) {
774          RepConstants.writeERROR_FILE(ex);
775          throw new RepException("REP085", null);
776        } //Temporary Snapshot File Can not created.
777        catch (IOException ex) {
778          RepConstants.writeERROR_FILE(ex);
779          RepException rex = new RepException("REP086", new Object[] {ex.getMessage()});
780          rex.setStackTrace(ex.getStackTrace());
781          throw rex;
782        }
783        catch (SQLException ex) {
784          RepConstants.writeERROR_FILE(ex);
785          RepException rex = new RepException("REP055", new Object[] {pubName,ex.getMessage()});
786          rex.setStackTrace(ex.getStackTrace());
787          throw rex;
788        }
789        catch (RepException ex) {
790          RepConstants.writeERROR_FILE(ex);
791          throw ex;
792        }
793        catch (InterruptedException ex) {
794         RepConstants.writeERROR_FILE(ex);
795         RepException rex = new RepException("REP055", new Object[] {pubName,ex.getMessage()});
796         rex.setStackTrace(ex.getStackTrace());
797         throw rex;
798          }
799        finally {
800              // bjt
801          // connectionPool.removeSubPubFromMap(pubName);
802          /** @todo  Close the statement */
803          if (shadowResult != null)
804            shadowResult.close();
805          if (stmt != null)
806            stmt.close();
807            isLocked = UNLOCK;
808            pubConnection.setAutoCommit(true);
809                    connectionPool.returnConnection(pubConnection);
810          }
811    
812      }
813    
814      /**
815       * Creates an XML file for synchronization purpose and send it to subscriber's
816       * socket.
817       * Creates a server socket and send's it's information to the subscriber,
818       * so that subscriber can transfer file over it.
819       *
820       * @param subName String
821       * @param clientServerName String
822       * @param isSchemaSupported boolean
823       * @param fileUpload
824       * @param remoteMachineAddress String
825       * @return Object[]
826       * @throws RemoteException
827       * @throws RepException
828       */
829    
830      public Object[] createXMLForClient(String subName, String clientServerName,boolean isSchemaSupported, _FileUpload fileUpload,String remoteMachineAddress) throws
831          RemoteException, RepException {
832          Object[] usedActualTablesLastSyncId;
833          Object[] LastSyncId = null;
834          String localAddress = null;
835          Integer portNumber = null;
836          try {
837            localAddress = InetAddress.getLocalHost().getHostName();
838            if (noOfPubTables > 0) {
839              usedActualTablesLastSyncId = syncXMLCreator.createXMLFile(PathHandler.
840                  getDefaultFilePathForClient("server_" + pubName + "_" +subName) // xml file path
841                  , PathHandler.getDefaultZIPFilePathForClient("server_" + pubName + "_" +subName) // zip file path
842                  , "server_" + pubName + "_" +subName//+ ".xml" // xml file name
843                  , subName, pubRepTables, clientServerName,
844                  noOfPubTables,_Publication.xmlAndShadow_entries, pubName,isSchemaSupported,fileUpload,localAddress,remoteMachineAddress);
845    
846              usedActualTables = (ArrayList) usedActualTablesLastSyncId[0];
847              LastSyncId = (Object[]) usedActualTablesLastSyncId[1];
848            }
849    
850            ServerSocket serverSocket = connectionPool.startServerSocket();
851            localAddress = null;
852            try {
853              //localAddress = InetAddress.getLocalHost().getHostAddress();
854                      // bjt - fix address
855              localAddress = InetAddress.getLocalHost().getHostName();
856            }
857            catch (UnknownHostException ex) {
858              RepConstants.writeERROR_FILE(ex);
859              RepException rex = new RepException("REP056", new Object[] {pubName,ex.getMessage()});
860              rex.setStackTrace(ex.getStackTrace());
861              throw rex;
862            }
863            portNumber = new Integer(serverSocket.getLocalPort());
864            syncXMLCreator.serverSocket = serverSocket;
865          }
866          catch (RepException ex1) {
867             ex1.printStackTrace();
868            RepConstants.writeERROR_FILE(ex1);
869            throw ex1;
870          }
871          catch (Exception ex1) {
872             ex1.printStackTrace();
873            RepConstants.writeERROR_FILE(ex1);
874            throw new RepException("REP054", new Object[] {subName, ex1.getMessage()});
875          }
876          catch (Throwable ex1) {
877            ex1.printStackTrace();
878            log.error(ex1.getMessage(), ex1);
879            throw new RepException("REP054", new Object[] {subName, ex1.getMessage()});
880          }finally {
881          connectionPool.removeSubPubFromMap(pubName);
882        }
883          return new Object[] {localAddress, portNumber, LastSyncId};
884      }
885    
886    
887    
888    
889      private ResultSet getResultSet(String preparedQuery, String[] parameters) throws
890          SQLException,RepException {
891            Connection pubConnection = null;
892        try
893        {
894          pubConnection = connectionPool.getConnection(pubName);
895          //PreparedStatement pst = pubConnection.prepareStatement(preparedQuery);
896              // bjt - below *seems* to work
897          PreparedStatement pst = pubConnection.prepareStatement(preparedQuery,ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
898          if (parameters != null) {
899            for (int i = 0, size = parameters.length; i < size; i++) {
900              pst.setString(i + 1, parameters[i]);
901            }
902          }
903              // bjt - attempt to tell postgres to not hold the whole resultset in memory
904              pst.setFetchSize(1);
905          return pst.executeQuery();
906        } finally {
907               connectionPool.returnConnection(pubConnection);
908               // bjt 
909           //connectionPool.removeSubPubFromMap(pubName);
910        }
911      }
912    
913      /**
914       * merges the data between the client side and server side.
915       * @param subName
916       * @param remoteServerName
917       * @throws RemoteException
918       * @throws RepException
919       */
920      public synchronized void synchronize(String subName, String remoteServerName,boolean isCreateTransactionLogFile,String remoteMachineAddress) throws
921          RemoteException, RepException {
922        BufferedWriter bw = null;
923            Connection pubConnection = null;
924            Connection subConnection = null;
925        Statement stmt = null;
926        ResultSet rs = null;
927        boolean isCurrentTableCyclic =false;
928        String localMachineAddress=null;
929        try {
930          Utility.createTransactionLogFile = isCreateTransactionLogFile;
931          localMachineAddress =InetAddress.getLocalHost().getHostName();
932    
933          // unzipping zip file from client
934          if(!localMachineAddress.equalsIgnoreCase(remoteMachineAddress)) {
935            ZipHandler.unZip(PathHandler.getDefaultZIPFilePathForClient("client_" +subName + "_" + pubName),PathHandler.getDefaultFilePathForClient("client_" +subName + "_" + pubName));
936          }
937          SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
938          XMLReader reader = saxParser.getXMLReader();
939                    subConnection = connectionPool.getConnection(subName);
940                    pubConnection = connectionPool.getConnection(pubName);
941                    MergeHandler mg = new MergeHandler(true, subConnection, this,
942                                             remoteServerName, dbh, bw,
943                                             "MERGE REPLICATION",
944                                             PathHandler.
945                                             fullOrPartialTransactionLogFile(),Utility.getDatabaseMataData(pubConnection));
946          mg.setLocalName(pubName);
947          mg.setRemoteName(subName);
948          ContentHandler ch = mg;
949          reader.setContentHandler(ch);
950    
951          //initializing hashmap for maxSyncId for updating consideredId of bookMarkTable further
952          syncIdMap = new HashMap();
953          RepTable repTable=null;
954          for (int i = 0; i < pubRepTables.size(); i++) {
955            repTable =(RepTable) pubRepTables.get(i);
956            String tableName = repTable.getSchemaQualifiedName().toString();
957            isCurrentTableCyclic = repTable.getCyclicDependency().equalsIgnoreCase(RepConstants.YES);
958            StringBuffer query = new StringBuffer();
959            stmt = pubConnection.createStatement();
960            query.append(" select ").append(RepConstants.shadow_sync_id1).
961                append(" from ").append(RepConstants.shadow_Table(tableName)).
962                            append(" order by ").append(RepConstants.shadow_sync_id1).
963                            append(" desc limit 1");
964            rs = stmt.executeQuery(query.toString());
965                    long syncIdValue = new Long(0);
966            if(rs.next()) {
967                            syncIdValue = rs.getLong(1);
968                    }
969            syncIdMap.put(tableName, syncIdValue);
970            long maxSynId = syncIdValue;
971            syncIdMap.put(tableName, new Long(maxSynId));
972          }
973          reader.parse(PathHandler.getDefaultFilePathForClient("client_" + subName + "_" +pubName));
974          makePublicationTransactionLogFile(pubName,mg,bw);
975          mg.closeAllStatementAndResultset();
976    
977          /**
978           * Following code has been written to handle the case of cyclic  table and update the value of all the columns that are set to null in first pass.
979           */
980         if(isCurrentTableCyclic){
981    
982         MergeHandler mg1 = new MergeHandler(false, subConnection, this,
983                                            remoteServerName, dbh, bw,
984                                            "MERGE REPLICATION",
985                                            PathHandler.
986                                            fullOrPartialTransactionLogFile(),Utility.getDatabaseMataData(pubConnection));
987         mg1.setLocalName(pubName);
988         mg1.setRemoteName(subName);
989         ContentHandler ch1 = mg1;
990         reader.setContentHandler(ch1);
991         reader.parse(PathHandler.getDefaultFilePathForClient("client_" + subName + "_" +pubName));
992         makePublicationTransactionLogFile(pubName,mg,bw);
993         mg1.closeAllStatementAndResultset();
994       }
995    
996          if (_Publication.xmlAndShadow_entries) {
997            // deleting XML file
998            deleteFile(PathHandler.getDefaultFilePathForClient("client_" + subName + "_" +pubName));
999            // deleting zip file
1000            deleteFile(PathHandler.getDefaultZIPFilePathForClient("client_" +subName + "_" +pubName));
1001          }
1002          deleteRecordsFromSuperLogTable(stmt);
1003          for (int i = 0; i < pubRepTables.size(); i++) {
1004            repTable = (RepTable) pubRepTables.get(i);
1005            if (repTable.getCreateShadowTable().equalsIgnoreCase(RepConstants.NO))
1006              continue;
1007            String tableName = ( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName().toString();
1008            // we have updated last sync id at the time of creating xml file too beacause of any power failure or other reasons
1009            // we are also updating Coincederd Id as well as Last Sync Id so that we do not
1010            // get last record while making xml file previously from shadow table in next cycle of synchronisation
1011            // as client changes can also occur at server whihc are not to be sent back to client.
1012            UpdateConisdered_LastsyncIdForBookMarksTable(pubName, subName,tableName, ((Number) syncIdMap.get(tableName)).toString(),stmt);
1013          }
1014    
1015          syncIdMap.clear();
1016          if (_Publication.xmlAndShadow_entries) {
1017            deleteRecordsFromShadowTable(stmt);
1018          }
1019    
1020        }
1021        catch (Exception ex) {
1022          if(Utility.createTransactionLogFile)  {
1023            AbstractSynchronize.writeUnsuccessfullOperationInTransaction(bw);
1024          }
1025          RepConstants.writeERROR_FILE(ex);
1026          RepException rex = null;
1027          if (ex instanceof SAXException) {
1028            Exception e = ( (SAXException) ex).getException();
1029            if (e instanceof RepException) {
1030              throw (RepException) e;
1031            }
1032            else {
1033              rex = new RepException("REP056", new Object[] {pubName, e.getMessage()});
1034              rex.setStackTrace(e.getStackTrace());
1035              throw rex;
1036            }
1037          }
1038          else {
1039            rex = new RepException("REP056", new Object[] {pubName, ex.getMessage()});
1040            rex.setStackTrace(ex.getStackTrace());
1041          }
1042          throw rex;
1043        }
1044        finally {
1045           connectionPool.removeSubPubFromMap(pubName);
1046          try {
1047            if (rs != null) {
1048              rs.close();
1049            }
1050            if (stmt != null) {
1051              stmt.close();
1052            }
1053          }
1054          catch (SQLException ex1) {
1055          }
1056          try {
1057            if(bw!=null)
1058            bw.close();
1059          }
1060          catch (IOException ex2) {
1061          }
1062             connectionPool.returnConnection(subConnection);
1063             connectionPool.returnConnection(pubConnection);
1064        }
1065      }
1066    
1067      /**
1068       * It handle the push replication operation in publication data source.
1069       * @param subName String
1070       * @param remoteServerName String
1071       * @throws RemoteException
1072       * @throws RepException
1073       */
1074    
1075      public synchronized void push(String subName, String remoteServerName,boolean isCreateTransactionLogFile,String remoteMachineAddress) throws
1076          RemoteException, RepException {
1077        BufferedWriter bw = null;
1078        Statement stmt = null;
1079        ResultSet rs = null;
1080        Connection pubConnection =null;
1081        Connection subConnection =null;
1082         boolean isCurrentTableCyclic =false;
1083         Utility.createTransactionLogFile = isCreateTransactionLogFile;
1084         String localMachineAddress =null;
1085        try {
1086    
1087          // unzipping zip file from client
1088          localMachineAddress = InetAddress.getLocalHost().getHostName();
1089          if(!localMachineAddress.equalsIgnoreCase(remoteMachineAddress)) {
1090            ZipHandler.unZip(PathHandler.getDefaultZIPFilePathForClient("client_" +subName + "_" + pubName),PathHandler.getDefaultFilePathForClient("client_" +subName + "_" + pubName));
1091          }
1092          SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
1093          XMLReader reader = saxParser.getXMLReader();
1094              subConnection = connectionPool.getConnection(subName);
1095              pubConnection = connectionPool.getConnection(pubName);
1096          MergeHandler mg = new MergeHandler(true, subConnection, this,
1097                                             remoteServerName, dbh, bw,
1098                                             "PUSH REPLICATION",PathHandler.fullOrPartialTransactionLogFile(),
1099                                             Utility.getDatabaseMataData(pubConnection));
1100          mg.setLocalName(pubName);
1101          mg.setRemoteName(subName);
1102          ContentHandler ch = mg;
1103          reader.setContentHandler(ch);
1104    //     initializing hashmap for maxSyncId for updating consideredId of bookMarkTable further
1105          syncIdMap = new HashMap();
1106    
1107    
1108          syncIdMap = new HashMap();
1109          for (int i = 0; i < pubRepTables.size(); i++) {
1110            RepTable repTable  =( (RepTable) pubRepTables.get(i));
1111           String tableName = repTable.getSchemaQualifiedName().toString();
1112    
1113             isCurrentTableCyclic = repTable.getCyclicDependency().equalsIgnoreCase(RepConstants.YES);
1114            StringBuffer query = new StringBuffer();
1115    
1116            stmt = pubConnection.createStatement();
1117            query.append(" select ").append(RepConstants.shadow_sync_id1).
1118                        append(" from ").append(RepConstants.shadow_Table(tableName)).
1119                            append(" order by ").append(RepConstants.shadow_sync_id1).
1120                            append(" desc limit 1");
1121            rs = stmt.executeQuery(query.toString());
1122            if (rs.next()) {
1123            syncIdMap.put(tableName,new Long(rs.getLong(1)));
1124            long maxSynId =rs.getLong(1);
1125            syncIdMap.put(tableName,new Long(maxSynId));
1126                    } else {
1127                            syncIdMap.put(tableName, new Long(0));
1128                    }
1129          }
1130          reader.parse(PathHandler.getDefaultFilePathForClient("client_" + subName + "_" +pubName));
1131          mg.closeAllStatementAndResultset();
1132    
1133          makePublicationTransactionLogFile(pubName,mg,bw);
1134           if(isCurrentTableCyclic){
1135              MergeHandler mg1 = new MergeHandler(false, subConnection, this,
1136                                             remoteServerName, dbh, bw,
1137                                             "PUSH REPLICATION",
1138                                             PathHandler.fullOrPartialTransactionLogFile(),
1139                                             Utility.getDatabaseMataData(pubConnection));
1140              mg1.setLocalName(subName);
1141              mg1.setRemoteName(pubName);
1142              ContentHandler ch1 = mg1;
1143              reader.setContentHandler(ch1);
1144              AbstractSynchronize.writeDateInTransactionLogFile(bw);
1145              reader.parse(PathHandler.getDefaultFilePathForClient("client_" +subName));
1146              makePublicationTransactionLogFile(pubName,mg,bw);
1147              mg1.closeAllStatementAndResultset();
1148            }
1149          if (_Publication.xmlAndShadow_entries) {
1150            // deleting XML file
1151            deleteFile(PathHandler.getDefaultFilePathForClient("client_" + subName + "_" +pubName));
1152            // deleting zip file
1153            deleteFile(PathHandler.getDefaultZIPFilePathForClient("client_" +subName + "_" +pubName));
1154          }
1155    
1156          deleteRecordsFromSuperLogTable(stmt);
1157          for (int i = 0; i < pubRepTables.size(); i++) {
1158            String tableName = ( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName().toString();
1159            // we have updated last sync id at the time of creating xml file too beacause of any power failure or other reasons
1160            // we are also updating Coinsiderd Id as well as Last Sync Id so that we do not
1161            // get last record while making xml file previously from shadow table in next cycle of synchronisation
1162            // as client changes can also occur at server whihc are not to be sent back to client.
1163            UpdateConisdered_LastsyncIdForBookMarksTable(pubName, subName,tableName, ((Number) syncIdMap.get(tableName)).toString(),stmt);
1164          }
1165          syncIdMap.clear();
1166          if (_Publication.xmlAndShadow_entries) {
1167            deleteRecordsFromShadowTable(stmt);
1168          }
1169        }
1170        catch (Exception ex) {
1171          if(Utility.createTransactionLogFile)
1172          AbstractSynchronize.writeUnsuccessfullOperationInTransaction(bw);
1173          RepConstants.writeERROR_FILE(ex);
1174          RepException rex = null;
1175          if (ex instanceof SAXException) {
1176            Exception e = ( (SAXException) ex).getException();
1177            if (e instanceof RepException) {
1178              throw (RepException) e;
1179            }
1180            else {
1181              rex = new RepException("REP056", new Object[] {pubName, e.getMessage()});
1182              rex.setStackTrace(e.getStackTrace());
1183              throw rex;
1184            }
1185          }
1186          else {
1187            rex = new RepException("REP056", new Object[] {pubName, ex.getMessage()});
1188            rex.setStackTrace(ex.getStackTrace());
1189          }
1190          throw rex;
1191        }
1192        finally {
1193           connectionPool.removeSubPubFromMap(pubName);
1194          try {
1195            if(bw!=null)
1196            bw.close();
1197            if (rs != null) {
1198              rs.close();
1199            }
1200            if (stmt != null) {
1201              stmt.close();
1202            }
1203          }
1204          catch (SQLException ex1) {
1205          }
1206          catch (IOException ex2) {
1207          }
1208             connectionPool.returnConnection(pubConnection);
1209             connectionPool.returnConnection(subConnection);
1210        }
1211      }
1212    
1213      private ArrayList getUsedActualtable() {
1214        ArrayList includedTables = new ArrayList();
1215        for (int i = 0; i < noOfPubTables; i++) {
1216          SchemaQualifiedName sname = ( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName();
1217           includedTables.add(sname.toString());
1218        }
1219        return includedTables;
1220      }
1221    
1222      /**
1223       * writes the zip file on client socket
1224       * @param address
1225       * @param portNo
1226       * @param xmlFilePath
1227       * @throws IOException
1228       */
1229      private void writeXMLFileOnClientSocket(String address, int portNo,String xmlFilePath) throws IOException {
1230        log.debug("write XMLFile  ClientSocket on address " + address + ",portNo " + portNo + " xmlFilePath " + xmlFilePath);
1231        Socket s = new Socket(address, portNo);
1232            s.setKeepAlive(true); /* bjt */
1233        FileInputStream fis = new FileInputStream(xmlFilePath);
1234        s.setSendBufferSize(Integer.MAX_VALUE);
1235        OutputStream sos = s.getOutputStream();
1236        BufferedOutputStream bos = new BufferedOutputStream(sos);
1237        byte[] buf = new byte[1024];
1238        int len = 0;
1239        while ( (len = fis.read(buf)) > 0) {
1240          bos.write(buf, 0, len);
1241        }
1242        bos.flush();
1243        bos.close();
1244        sos.close();
1245        fis.close();
1246        s.close();
1247      }
1248    
1249      private SchemaQualifiedName[] getSchemaQualifiedTableNames() {
1250        SchemaQualifiedName[] tableNames = new SchemaQualifiedName[noOfPubTables];
1251        for (int i = 0; i < noOfPubTables; i++) {
1252          RepTable repTable = (RepTable) pubRepTables.get(i);
1253          tableNames[i] = repTable.getSchemaQualifiedName();
1254        }
1255        return tableNames;
1256      }
1257    
1258      public String getServerName() throws RemoteException {
1259          return dbh.getLocalServerName();
1260      }
1261    
1262      public String getFilterClause(SchemaQualifiedName tableName) throws RemoteException {
1263          for (int i = 0; i < noOfPubTables; i++) {
1264            RepTable repTable = (RepTable) pubRepTables.get(i);
1265            if (repTable.getSchemaQualifiedName().equals(tableName)) {
1266              return repTable.getFilterClause();
1267            }
1268          }
1269          throw new RemoteException("Invalid table name " + tableName);
1270        }
1271    
1272      public AbstractDataBaseHandler getDBDataTypeHandler() {
1273        return dbh;
1274      }
1275    
1276      public String getPub_SubName() {
1277        return pubName;
1278      }
1279    
1280      public RepTable getRepTable(String tableName) throws RepException {
1281          log.debug("Number of tables " + pubRepTables.size());
1282          SchemaQualifiedName sname;
1283          String tabNames;
1284          for (int i = 0; i < pubRepTables.size(); i++) {
1285          log.debug(" Qualified Names  " +( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName());
1286          sname =( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName();
1287          tabNames = tableName.indexOf(".") !=-1 ? sname.toString() : sname.getTableName();
1288          if (tabNames.equalsIgnoreCase(tableName)) {
1289            return (RepTable) pubRepTables.get(i);
1290          }
1291        }
1292        RepException rep = new RepException("REP033", new Object[] {tableName});
1293        RepConstants.writeERROR_FILE(rep);
1294        throw rep;
1295      }
1296    
1297      private void deleteFile(String fileName) {
1298        File f = new File(fileName);
1299        boolean deleted = f.delete();
1300      }
1301    
1302      private void deleteRecordsFromSuperLogTable(Statement stmt) throws
1303          SQLException {
1304        // insert one record in superLogTable
1305        ResultSet rs=null;
1306        try {
1307          StringBuffer query = new StringBuffer();
1308          query.append("insert into ").append(dbh.getLogTableName()).append(" (").
1309              append(RepConstants.logTable_tableName2)
1310              .append(") values  ('$$$$$$')");
1311          stmt.execute(query.toString());
1312    
1313          query = new StringBuffer();
1314          query.append("Select max(").append(RepConstants.logTable_commonId1).
1315              append(") from ").append(dbh.getLogTableName());
1316          rs= stmt.executeQuery(query.toString());
1317          rs.next();
1318          long maxCID = rs.getLong(1);
1319    
1320          query = new StringBuffer();
1321          query.append("delete from ").append(dbh.getLogTableName()).append(" where ")
1322              .append(RepConstants.logTable_commonId1).append(" !=").append(maxCID);
1323          stmt.executeUpdate(query.toString());
1324          log.debug(query.toString());
1325        }
1326        finally {
1327          if(rs!=null)
1328            rs.close();
1329          }
1330      }
1331    
1332      /**
1333       * deletes the unwanted reocrds from  shadow table.
1334       * @throws SQLException
1335       */
1336      private void deleteRecordsFromShadowTable(Statement stmt) throws SQLException, RepException {
1337         if (usedActualTables == null) {
1338           usedActualTables = getUsedActualtable();
1339         }
1340         int noofTables = usedActualTables.size();
1341         if (noofTables > 0) {
1342           StringBuffer query;
1343           for (int i = 0; i < noofTables; i++) {
1344    //         // selecting min of syncid or concideredId  from bookmarks table for one table
1345             Object minValue= dbh.getMinValOfSyncIdTodeleteRecordsFromShadowTable((String)
1346                 usedActualTables.get(i),stmt);
1347             if (minValue instanceof Number) {
1348               minValue = new Long(((Number)minValue).longValue());
1349             } else {
1350               minValue = new Long(Long.parseLong((String)minValue));
1351             }
1352             // deleting records from shadow table for that table
1353             query = new StringBuffer();
1354             query.append("delete from ").append(RepConstants.shadow_Table( (String)
1355                 usedActualTables.get(i)))
1356                 .append(" where  ").append(RepConstants.shadow_sync_id1).append(
1357                 " < ").append(minValue);
1358             stmt.executeUpdate(query.toString());
1359             log.debug(query.toString());
1360           }
1361         }
1362      }
1363    
1364    
1365      /**
1366       * updates the bookmarks table with the considered Id for all tables.
1367       * @param pubName
1368       * @param subName
1369       * @param tableName
1370       * @throws SQLException
1371       */
1372    
1373      private void UpdateConisdered_LastsyncIdForBookMarksTable(String pubName,
1374          String subName, String tableName, Object syncId,Statement stmt) throws SQLException,
1375          RepException {
1376          StringBuffer query = new StringBuffer();
1377          Connection pubConnection = connectionPool.getConnection(pubName);
1378          stmt = pubConnection.createStatement();
1379    
1380          Object maxSyncId = syncId;
1381    
1382          log.debug("maxSyncId" + maxSyncId);
1383    
1384          // appened updation of LastSyncId in Bookmarks Table
1385          query.append(" UPDATE  ").append(dbh.getBookMarkTableName()).append(
1386              " set  ").append(RepConstants.bookmark_ConisderedId5)
1387              .append(" = ").append(maxSyncId).append("  where ").append(
1388              RepConstants.bookmark_LocalName1).append(
1389              " = '").append(pubName).append("' and ").append(RepConstants.
1390              bookmark_RemoteName2)
1391              .append(" = '").append(subName).append("' and ")
1392              .append(RepConstants.bookmark_TableName3).append(" = '").append(
1393              tableName).append("'");
1394          stmt.executeUpdate(query.toString());
1395          log.debug(query.toString());
1396              stmt.close();
1397              connectionPool.returnConnection(pubConnection);
1398      }
1399    
1400      private void UpdateConisdered_LastsyncIdForBookMarksTable_old(String pubName,
1401          String subName, String tableName) throws SQLException, RepException {
1402            Connection pubConnection = null;
1403        Statement stmt = null;
1404        try {
1405          StringBuffer query = new StringBuffer();
1406          pubConnection = connectionPool.getConnection(pubName);
1407          stmt = pubConnection.createStatement();
1408          query.append(" select ").append(RepConstants.shadow_sync_id1).
1409                  append(" from ").append(RepConstants.shadow_Table(tableName)).
1410                      append(" order by ").append(RepConstants.shadow_sync_id1).
1411                      append(" desc limit 1");
1412          ResultSet rs = stmt.executeQuery(query.toString());
1413          rs.next();
1414          long maxSyncId = rs.getLong(1);
1415    
1416          query = new StringBuffer();
1417          // appened updation of LastSyncId in Bookmarks Table
1418          query.append(" UPDATE  ").append(dbh.getBookMarkTableName()).append(
1419              " set  ").append(RepConstants.bookmark_ConisderedId5)
1420              .append(" = ").append(maxSyncId).append(" , ").append(RepConstants.
1421              bookmark_lastSyncId4).append(" = ").append(maxSyncId)
1422              .append("  where ").append(RepConstants.bookmark_LocalName1).append(
1423              " = '").append(pubName).append("' and ").append(RepConstants.
1424              bookmark_RemoteName2)
1425              .append(" = '").append(subName).append("' and ")
1426              .append(RepConstants.bookmark_TableName3).append(" = '").append(
1427              tableName).append("'");
1428          stmt.executeUpdate(query.toString());
1429        }
1430        finally {
1431          connectionPool.removeSubPubFromMap(pubName);
1432          try {
1433            if (stmt != null)
1434              stmt.close();
1435          }
1436          catch (SQLException ex) {
1437          }
1438             connectionPool.returnConnection(pubConnection);
1439        }
1440      }
1441    
1442      public void unpublish() throws RepException {
1443            Connection con = null;
1444        Statement stmt = null;
1445        try {
1446          con = connectionPool.getConnection(pubName);
1447          stmt = con.createStatement();
1448          checkDependingSubscriptions(stmt);
1449          try {
1450            String query = " delete from " + dbh.getPublicationTableName() +
1451                        " where " + RepConstants.publication_pubName1 + " = '" +pubName + "'";
1452            stmt.execute(query);
1453            log.debug("Unpublish query :"+query);
1454          }
1455          catch (SQLException ex) {
1456            RepConstants.writeERROR_FILE(ex);
1457            throw new RepException("REP036", new Object[] {pubName});
1458          }
1459          deleteNonSharedPublishedSubscribedTables(con, pubName,stmt);
1460          localServer.refershPublication(pubName);
1461        }
1462        catch (SQLException ex) {
1463          log.error(ex.getMessage(), ex);
1464          RepConstants.writeERROR_FILE(ex);
1465        }
1466        finally {
1467          connectionPool.removeSubPubFromMap(pubName);
1468          try {
1469            if (stmt != null)
1470              stmt.close();
1471          }
1472          catch (SQLException ex1) {
1473          }
1474             connectionPool.returnConnection(con);
1475        }
1476      }
1477    
1478      private void deleteNonSharedPublishedSubscribedTables(Connection con, String pubsubName,Statement stmt) throws SQLException, RepException {
1479    
1480        //" Select Table_Name from RepTable Where PubSub_Name = '"+pubName+"' and Table_Name Not In "
1481        //"( Select Distinct Table_Name from RepTable Where PubSub_Name <> '"+pubName+"') ";
1482    
1483        ResultSet rs = null;
1484        ResultSet rsSub=null;
1485        try {
1486          StringBuffer tablesToDelete = new StringBuffer();
1487          tablesToDelete.append(" Select ").append(RepConstants.repTable_tableName2)
1488              .append(" from ").append(dbh.getRepTableName()).append(" where ")
1489              .append(RepConstants.repTable_pubsubName1).append(" = '")
1490              .append(pubsubName).append("' and ").append(RepConstants.
1491              repTable_tableName2)
1492              .append(" not in ( Select Distinct ").append(RepConstants.
1493              repTable_tableName2).append(" from ").append(dbh.getRepTableName())
1494              .append(" Where ").append(RepConstants.repTable_pubsubName1)
1495              .append(" <> '").append(pubsubName).append("') ");
1496          rs = stmt.executeQuery(tablesToDelete.toString());
1497              Connection pubsubConnection = null;
1498              try
1499              {
1500                    pubsubConnection = connectionPool.getConnection(pubsubName);
1501          while (rs.next()) {
1502            MetaDataInfo mdi = Utility.getDatabaseMataData(pubsubConnection);
1503            SchemaQualifiedName sname = new SchemaQualifiedName(mdi,
1504                rs.getString(RepConstants.repTable_tableName2));
1505            deleteAll(con, pubsubName, sname.toString());
1506          }
1507              }
1508              finally {
1509                    connectionPool.returnConnection(pubsubConnection);
1510              }
1511    
1512          String deleteQuery = " delete from " + dbh.getRepTableName() + " where " +RepConstants.repTable_pubsubName1 + " = '" + pubsubName + "'";
1513          stmt.execute(deleteQuery);
1514          log.debug(deleteQuery);
1515          deleteQuery =" delete from " + dbh.getBookMarkTableName() + " where " +RepConstants.bookmark_LocalName1 + " = '" + pubsubName + "'";
1516          stmt.execute(deleteQuery);
1517          log.debug(deleteQuery);
1518          rs = stmt.executeQuery("select * from " + dbh.getPublicationTableName());
1519          boolean ispubTableExist = rs != null ? rs.next() ? true : false : false;
1520          try {
1521            rsSub = stmt.executeQuery("select * from " +dbh.getSubscriptionTableName());
1522            String query = " delete from " + dbh.getRepTableName() + " where " +RepConstants.repTable_pubsubName1 + " = '" + pubsubName + "'";
1523            stmt.execute(query);
1524            log.debug(query);
1525            query = " delete from " + dbh.getBookMarkTableName() + " where " +RepConstants.bookmark_LocalName1 + " = '" + pubsubName + "'";
1526            stmt.execute(query);
1527            log.debug(query);
1528            rs = stmt.executeQuery("select * from " + dbh.getPublicationTableName());
1529            if (!rs.next()) {
1530              dbh.dropPublisherSystemTables(con);
1531            }
1532          }
1533          catch (SQLException ex) {
1534            /**
1535            *  Ignore the exception becuase Sublication table
1536            *  does not exist in Publisher Database. It is the
1537            *  case when table is published and subscribed in
1538            *  same database.
1539            */
1540          }
1541           boolean issubTableExist = rsSub != null ? rsSub.next() ? true : false : false;
1542           if(!ispubTableExist&& !issubTableExist)
1543           dbh.dropPublisherSystemTables(con);
1544        }
1545        finally {
1546          if (rs != null)
1547            rs.close();
1548          if (rsSub != null)
1549            rsSub.close();
1550        }
1551    
1552      }
1553    
1554      private void deleteAll(Connection connection, String pubsubName, String table) throws SQLException, RepException {
1555        dbh.dropTriggersAndShadowTable(connection, table, pubsubName);
1556      }
1557    
1558    
1559    
1560      public void dropSubscription(String subName) throws RemoteException, RepException {
1561            Connection con = null;
1562        Statement stmt = null;
1563        try {
1564          con = connectionPool.getConnection(pubName);
1565          stmt = con.createStatement();
1566          String query = "Delete from " + dbh.getBookMarkTableName() +
1567              " where " + RepConstants.bookmark_RemoteName2 + " = '" + subName +"'";
1568          stmt.execute(query);
1569          log.debug(query);
1570        }
1571        catch (SQLException ex) {
1572          RepConstants.writeERROR_FILE(ex);
1573          throw new RepException("REP034", new Object[] {ex.getMessage()});
1574        }
1575        catch (RepException ex) {
1576          RepConstants.writeERROR_FILE(ex);
1577          throw ex;
1578        }
1579        finally {
1580          connectionPool.removeSubPubFromMap(pubName);
1581          try {
1582            if (stmt != null)
1583              stmt.close();
1584          }
1585          catch (SQLException ex1) {
1586          }
1587             connectionPool.returnConnection(con);
1588        }
1589      }
1590    
1591    
1592      synchronized public void checkForLock(String pubSubName) throws RepException, RemoteException {
1593       if(  listOfWaitingSubcription.size() > 0){
1594        if(listOfWaitingSubcription.contains(pubSubName) ){
1595           if(isLocked) {
1596                 /* bjt - test socket to make sure it's still active */
1597             throw new RepException("REP052", null);
1598           }
1599           log.debug("locking for subscription::"+pubSubName);
1600          listOfWaitingSubcription.remove(pubSubName);
1601          isLocked = LOCK;
1602          return;
1603        }
1604          listOfWaitingSubcription.add(pubSubName);
1605          throw new RepException("REP052", null);
1606       }
1607        if (isLocked) {
1608              /* bjt - test socket to make sure it's still active */
1609          listOfWaitingSubcription.add(pubSubName);
1610          throw new RepException("REP052", null);
1611        }
1612        log.debug("locking for subscription::"+pubSubName);
1613         isLocked = LOCK;
1614      }
1615    
1616      private void checkDependingSubscriptions(Statement stmt) throws RepException {
1617        StringBuffer sb = new StringBuffer();
1618        sb.append(" Select * From ").append(dbh.getBookMarkTableName())
1619            .append(" where ").append(RepConstants.bookmark_LocalName1)
1620            .append(" = '").append(pubName).append("'");
1621        ResultSet rs = null;
1622        try {
1623          rs = stmt.executeQuery(sb.toString());
1624          if (rs.next()) {
1625            do {
1626         log.debug("Subscriber " + rs.getString(2) + " exists");
1627          }  while (rs.next());
1628            throw new RepException("REP047", new Object[] {pubName});
1629          }
1630        }
1631        catch (RepException ex) {
1632          RepConstants.writeERROR_FILE(ex);
1633          throw ex;
1634        }
1635        catch (SQLException ex) {
1636          RepConstants.writeERROR_FILE(ex);
1637          throw new RepException("REP045", new Object[] {pubName, ex.getMessage()});
1638        }
1639        finally {
1640          try {
1641            if(rs!=null)
1642              rs.close();
1643          }
1644          catch (SQLException ex1) {
1645          }
1646        }
1647      }
1648    
1649      public  void releaseLOCK() throws RemoteException {
1650        isLocked = UNLOCK;
1651        log.debug("isLocked :" + isLocked);
1652      }
1653    
1654      public int getPubVendorName() throws RepException {
1655          int pubVendor = Utility.getVendorType(connectionPool, pubName);
1656          return pubVendor;
1657      }
1658    
1659    
1660      public void updateBookMarkLastSyncId(String remote_Pub_Sub_Name, Object[] lastId) throws RemoteException,
1661          SQLException, RepException  {
1662            Connection pubConnection = null;
1663        Statement stmt = null;
1664        try {
1665              pubConnection = connectionPool.getConnection(pubName);
1666          stmt = pubConnection.createStatement();
1667          for (int i = 0; i < pubRepTables.size(); i++) {
1668            String tableName = ( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName().toString();
1669            String updateQuery = "update " + dbh.getBookMarkTableName() + " set " +
1670                RepConstants.bookmark_lastSyncId4 + "=" + lastId[i] + " where  " +
1671                RepConstants.bookmark_LocalName1 + " = '" + pubName + "' and " +
1672                RepConstants.bookmark_RemoteName2 + " = '" + remote_Pub_Sub_Name +"' and " +
1673                RepConstants.bookmark_TableName3 + " = '" + tableName + "' ";
1674            stmt.executeUpdate(updateQuery);
1675          }
1676        }
1677        finally {
1678          connectionPool.removeSubPubFromMap(pubName);
1679          if (stmt != null)
1680            stmt.close();
1681                    connectionPool.returnConnection(pubConnection);
1682        }
1683      }
1684    
1685    
1686      public void addTableToPublication(String[] newTableList,String[] filterClauses) throws
1687          RepException {
1688        Connection pubConnection=null;
1689        Statement stmt=null;
1690         boolean islockedTaken=false;
1691        try {
1692          checkForLock(pubName);
1693          islockedTaken=true;
1694           pubConnection = connectionPool.getConnection(pubName);
1695           stmt=pubConnection.createStatement();
1696          checkTableNameIfNull(newTableList);
1697          //check if user is passing null instead of string array else check filter clause syntax
1698          if (filterClauses == null) {
1699            filterClauses = new String[newTableList.length];
1700            for (int i = 0; i < filterClauses.length; i++)
1701              filterClauses[i] = null;
1702          }
1703          else  {
1704            checkFilter(stmt,newTableList, filterClauses);
1705          }
1706          localServer.addTableToPublication(pubName, newTableList,filterClauses,pubRepTables, this);
1707          SchemaQualifiedName[] tableNames = getSchemaQualifiedTableNames();
1708          MetaDataInfo mdi = Utility.getDatabaseMataData(pubConnection);
1709          for (int i = 0; i < tableNames.length; i++) {
1710           String schema = tableNames[i].getSchemaName();
1711           String table = tableNames[i].getTableName();
1712           ArrayList colInfoList = mdi.getColumnDataTypeInfo(dbh, schema, table);
1713           //Searches pubRepTables by the tablename and returns the corresponding object of RepTable and calls function
1714           RepTable repTable=getRepTable(tableNames[i].toString());
1715           String[] primCols =repTable.getPrimaryColumns();
1716           //We will get a sequence of  columns and there datatypes along with primary columns and there datatypes.
1717           //as    " col1 number(10),col2 varchar2(24),old_col1 number(10) "
1718           String allColSequence = dbh.getShadowTableColumnDataTypeSequence(colInfoList, primCols,repTable);
1719           //Creates Shadow Tables For all the participating tables
1720           dbh.createShadowTable(pubName, tableNames[i].toString(), allColSequence,primCols);
1721           dbh.makeProvisionForLOBDataTypes(colInfoList);
1722           dbh.createShadowTableTriggers(pubName, tableNames[i].toString(),colInfoList, primCols);
1723            }
1724            savePublicationNewTables(pubConnection,stmt,pubRepTables);
1725        }
1726        catch (SQLException ex) {
1727          RepConstants.writeERROR_FILE(ex);
1728          throw new RepException("REP311", new Object[] {pubName, ex.getMessage()});
1729        }
1730        catch (Throwable ex) {
1731          throw new RepException("REP311", new Object[] {pubName, ex.getMessage()});
1732        }
1733        finally {
1734          connectionPool.removeSubPubFromMap(pubName);
1735            if (islockedTaken)
1736             isLocked = UNLOCK;
1737           if(stmt!=null)
1738            try {
1739              stmt.close();
1740            }
1741            catch (SQLException ex1) {
1742            }
1743              connectionPool.returnConnection(pubConnection);
1744        }
1745    
1746      }
1747    
1748      /**
1749       * Saves the publication name and its tables into server side replication
1750       * system tables.
1751       * @param dbh database handler for server side
1752       * @throws RepException
1753       */
1754      private void savePublicationNewTables( Connection connection ,Statement stmt,ArrayList tablesList) throws
1755          RepException {
1756        try {
1757          //Delete all entries from Rep_table
1758          StringBuffer sb = new StringBuffer();
1759          sb.append("delete from ").append(dbh.getRepTableName()).append(" where ")
1760              .append(RepConstants.repTable_pubsubName1).append(" = '")
1761              .append(pubName).append("'");
1762    log.debug(sb.toString());
1763          stmt.execute(sb.toString());
1764          // Insert Into Rep Table, for all tables in publication
1765          for (int i = 0; i < tablesList.size(); i++) {
1766            RepTable repTable = (RepTable) tablesList.get(i);
1767            repTable.setConflictResolver(conflictResolver);
1768            dbh.saveRepTableData(connection, pubName, repTable);
1769          }
1770        }
1771        catch (SQLException ex) {
1772          RepConstants.writeERROR_FILE(ex);
1773          throw new RepException("REP0202", new Object[] {pubName,ex.getMessage()});
1774        }
1775      }
1776    
1777      /**
1778       * Inserts a row into bookmark table of server side to put a matching pair of
1779       * publication name and subscription name.
1780       * @param subName sub name
1781       * @throws RepException
1782       */
1783      public void saveSubscriptionNewData(String subName) throws RemoteException {
1784            Connection connection = null;
1785        Statement stt = null;
1786        ResultSet rs = null;
1787        try {
1788          connection = connectionPool.getConnection(pubName);
1789          MetaDataInfo mdi = Utility.getDatabaseMataData(connection);
1790          ArrayList dropTableFromBookMarkList = new ArrayList();
1791          ArrayList insertTableToBookMarkList = new ArrayList();
1792          ArrayList wrongPubRepTableList = new ArrayList();
1793          ArrayList correctPubRepTableList = new ArrayList();
1794          stt = connection.createStatement();
1795          for (int i = 0; i < noOfPubTables; i++) {
1796            RepTable repTable = (RepTable) pubRepTables.get(i);
1797            StringBuffer sb0 = new StringBuffer();
1798            sb0.append(" Insert into ").append(dbh.getBookMarkTableName()).append(
1799                " values ( '").append(pubName).append("','").append(subName).append(
1800                "','").append(repTable.getSchemaQualifiedName()).append("',0,0,'N')");
1801            try {
1802               log.debug(sb0.toString());
1803              stt.execute(sb0.toString());
1804            }
1805            catch (SQLException ex2) {
1806              //ignore the Exception
1807            }
1808          }
1809          StringBuffer  updatewithN = new StringBuffer();
1810            updatewithN.append("Update ")
1811                .append(dbh.getBookMarkTableName()).append(" set ")
1812                .append(RepConstants.bookmark_IsDeletedTable).append(" ='N' " );
1813            log.debug("upadting IsDeletedTable to 'N' :"+updatewithN.toString());
1814            stt.execute(updatewithN.toString());
1815    
1816          //get correct pubReptable list
1817          for (int i = 0; i < pubRepTables.size(); i++) {
1818            RepTable repTable = (RepTable) pubRepTables.get(i);
1819            correctPubRepTableList.add(repTable.getSchemaQualifiedName());
1820          }
1821          //get wrong pubReptable list
1822          StringBuffer sb = new StringBuffer();
1823          sb.append("select ").append(RepConstants.bookmark_TableName3).append(
1824              " from ").append(dbh.getBookMarkTableName()).append(" where ")
1825              .append(RepConstants.bookmark_LocalName1).append(" = '")
1826              .append(pubName).append("'").append(" and ").append(RepConstants.
1827              bookmark_RemoteName2).append(" = '")
1828              .append(subName).append("'"); ;
1829          rs = stt.executeQuery(sb.toString());
1830    
1831          while (rs.next()) {
1832            SchemaQualifiedName sname = new SchemaQualifiedName(mdi, rs.getString(1));
1833            String schema = sname.getSchemaName();
1834            String table = sname.getTableName();
1835            RepTable repTable = new RepTable(sname, RepConstants.publisher);
1836            //Sets Sorted primary key columns in repTable.
1837            mdi.setPrimaryColumns(repTable, schema, table);
1838            wrongPubRepTableList.add(repTable.getSchemaQualifiedName());
1839          }
1840          //get list of tables whose entry to be dropped from bookmarktable
1841          for (int j = 0; j < correctPubRepTableList.size(); j++) {
1842            if (!wrongPubRepTableList.contains(correctPubRepTableList.get(j))) {
1843              insertTableToBookMarkList.add(correctPubRepTableList.get(j));
1844            }
1845          }
1846          //get list of tables whose entry to be inserted into bookmarktable
1847          for (int j = 0; j < wrongPubRepTableList.size(); j++) {
1848            if (!correctPubRepTableList.contains(wrongPubRepTableList.get(j))) {
1849              dropTableFromBookMarkList.add(wrongPubRepTableList.get(j));
1850            }
1851          }
1852          for (int j = 0; j < dropTableFromBookMarkList.size(); j++) {
1853            StringBuffer deleteQuery = new StringBuffer();
1854            deleteQuery.append(" delete from ").append(dbh.getBookMarkTableName()).
1855                append(" where ").append(RepConstants.bookmark_LocalName1).append(
1856                " = '").append(pubName)
1857                .append("'").append(" and ").append(RepConstants.bookmark_TableName3).append(
1858                " ='").append(dropTableFromBookMarkList.get(j).toString()).append(
1859                " '").append(
1860                " and ").append(RepConstants.bookmark_RemoteName2).append(" ='").
1861                append(subName).append(" '");
1862            log.debug("dropTableFromBookMarkList ::"+deleteQuery.toString());
1863            stt.execute(deleteQuery.toString());
1864          }
1865          for (int j = 0; j < insertTableToBookMarkList.size(); j++) {
1866            StringBuffer insertQuery = new StringBuffer();
1867            insertQuery.append(" Insert into ").append(dbh.getBookMarkTableName()).
1868                append(" values ( '").append(pubName).append("','").append(subName).append(
1869                "','").append(insertTableToBookMarkList.get(j).toString()).append(
1870                "',0,0,'N')");
1871            log.debug("insertTableToBookMarkList ::"+insertQuery.toString());
1872            stt.execute(insertQuery.toString());
1873          }
1874        }
1875        catch (SQLException ex) {
1876        }
1877        catch (RepException ex) {
1878          RepConstants.writeERROR_FILE(ex);
1879          throw new RemoteException(ex.getMessage());
1880        }
1881        finally {
1882          connectionPool.removeSubPubFromMap(pubName);
1883          try {
1884            if(rs!=null)
1885                rs.close();
1886            if (stt != null)
1887              stt.close();
1888                    try {
1889                      connectionPool.returnConnection(connection);
1890                    }
1891                    catch (RepException ex) {
1892                            // Ignore the exception
1893                    }
1894          }
1895          catch (SQLException ex1) {
1896            // Ignore the exception
1897          }
1898        }
1899      }
1900    
1901      public void dropTableFromPublication(String[] dropTableList) throws RepException {
1902            Connection connection = null;
1903        Statement stt = null;
1904         boolean islockedTaken=false;
1905        try {
1906          checkForLock(pubName);
1907          islockedTaken=true;
1908          checkTableNameIfNull(dropTableList);
1909          ArrayList dropRepTableList = new ArrayList();
1910          ArrayList repTableList = localServer.dropTableFromPublication(pubName,dropTableList, this, pubRepTables);
1911          for (int i = 0; i < repTableList.size(); i++) {
1912            RepTable repTable = (RepTable) repTableList.get(i);
1913            dropRepTableList.add(repTable.getSchemaQualifiedName());
1914          }
1915          connection = connectionPool.getConnection(pubName);
1916          stt = connection.createStatement();
1917          //drop triggers,shadow tables,delete from logtable
1918          for (int i = 0; i < dropRepTableList.size(); i++) {
1919    
1920            StringBuffer query = new StringBuffer();
1921            //delete entry from reptable
1922            query.append(" DELETE " +" FROM  " +dbh.getRepTableName()+ " WHERE ");
1923            query.append(RepConstants.repTable_pubsubName1);
1924            query.append(" = '");
1925            query.append(pubName);
1926            query.append("' and ");
1927            query.append(RepConstants.repTable_tableName2);
1928            query.append(" ='");
1929            query.append(dropRepTableList.get(i).toString());
1930            query.append("'");
1931            log.debug(query.toString());
1932            stt.execute(query.toString());
1933            StringBuffer updateQuery = new StringBuffer();
1934                            updateQuery.append(" update ").append(dbh.getBookMarkTableName()).
1935                                append(" set ").append(RepConstants.bookmark_ConisderedId5).
1936                                append(" = 0 ,").append(RepConstants.bookmark_lastSyncId4).
1937                                append(" = 0 ,").append(RepConstants.bookmark_IsDeletedTable).append(" = 'Y' ").
1938                                append(" where ").append(RepConstants.bookmark_LocalName1).append(" = '").
1939                                append(pubName).append("'").append(" and ").append(RepConstants.bookmark_TableName3).
1940                                append(" ='").append(dropRepTableList.get(i).toString()).append("'");
1941            log.debug("updating bookmarktable lstsyncid,consideredId and isDeletedTable : "+updateQuery.toString());
1942            stt.execute(updateQuery.toString());
1943            dbh.dropTriggersAndShadowTable(connection,dropRepTableList.get(i).toString(),pubName);
1944          }
1945          //modifying the pubRepTablesList
1946          for (int i = 0; i < repTableList.size(); i++) {
1947            RepTable repTable = (RepTable) repTableList.get(i);
1948            for (int j = 0; j < pubRepTables.size(); j++) {
1949              RepTable pRepTable = (RepTable) pubRepTables.get(j);
1950              if (pRepTable.getRepTableQualifiedIdentifier().toString().equals(
1951                  repTable.getRepTableQualifiedIdentifier().toString())) {
1952                pubRepTables.remove(pubRepTables.get(j));
1953                noOfPubTables--;
1954              }
1955            }
1956          }
1957        }
1958        catch (Exception ex) {
1959          RepConstants.writeERROR_FILE(ex);
1960          if (ex instanceof RepException) {
1961            throw (RepException) ex;
1962          }
1963          RepException rex = new RepException("REP311", new Object[] {ex.getMessage()});
1964          rex.setStackTrace(ex.getStackTrace());
1965          throw rex;
1966        }
1967        finally {
1968          connectionPool.removeSubPubFromMap(pubName);
1969          if (islockedTaken)
1970             isLocked = UNLOCK;
1971          try {
1972            if (stt != null) {
1973              stt.close();
1974            }
1975          }
1976          catch (SQLException ex1) {
1977          }
1978             connectionPool.returnConnection(connection);
1979        }
1980      }
1981    
1982      public ConnectionPool getConnectionPool() {
1983        return connectionPool;
1984      }
1985    //check filter in case of add tables to publisher.
1986    //  This method does early checking of filter clauses
1987      public void checkFilter(Statement stmt,String[] tableName0, String[] filterClause0) throws
1988            RepException {
1989              Connection pubConnection = null;
1990          ResultSet rs = null;
1991          try {
1992            if(tableName0.length!=filterClause0.length){
1993           throw new RepException("REP319",null);
1994            }
1995                    pubConnection = connectionPool.getConnection(pubName);
1996            MetaDataInfo mdi = Utility.getDatabaseMataData(pubConnection);
1997            for (int i = 0; i < tableName0.length; i++) {
1998              SchemaQualifiedName sname = new SchemaQualifiedName(mdi, tableName0[i]);
1999              if (tableName0[i].indexOf('.') == -1) {
2000                mdi.checkTableExistance(sname);
2001              }
2002             log.debug("Table name : " + tableName0[i]);
2003             log.info("check the filter : " + filterClause0[i] + " for table " +tableName0[i]);
2004              if (filterClause0[i]!=null) {
2005                try {
2006                  String query = "Select * from " + sname + " where " +filterClause0[i];
2007                 log.debug("check filter query  : " + query);
2008                  rs = stmt.executeQuery(query);
2009                  rs.next();
2010                }
2011                catch (SQLException ex1) {
2012                  RepConstants.writeERROR_FILE(ex1);
2013                  RepException rex = new RepException("REP019",new Object[] {filterClause0[i]});
2014                  rex.setStackTrace(ex1.getStackTrace());
2015                  throw rex;
2016                }
2017              }
2018            }
2019          }
2020          finally {
2021            try {
2022              if (rs != null) {
2023                rs.close();
2024              }
2025            }
2026            catch (SQLException ex) {
2027            }
2028               connectionPool.returnConnection(pubConnection);
2029          }
2030        }
2031    
2032    
2033        public void checkTableNameIfNull(String[] tableNames) throws RepException {
2034          if (tableNames == null) {
2035            throw new RepException("REP316", null);
2036          }
2037          for (int i = 0; i < tableNames.length; i++) {
2038            if (tableNames[i] == null) {
2039              throw new RepException("REP320", null);
2040            }
2041          }
2042        }
2043        /**
2044           * creates an XMl file for getting Snapshot on clients side.
2045           * Do entry in the server side bookmark table.
2046           * Deletes all records from the server side log table.
2047           *
2048           * @param address
2049           * @param portNo
2050           * @param subName
2051           * @throws SQLException
2052           * @throws RemoteException
2053           * @throws RepException
2054           */
2055          public void createSnapShotAfterUpdateSub(String address, int portNo, String subName,ArrayList tablesForSnapShot,boolean isSchemaSupported,_FileUpload fileUpload,String remoteMachineAddress) throws
2056              SQLException, RemoteException, RepException {
2057                    Connection pubConnection = null;
2058            Statement stmt = null;
2059            ResultSet rows = null, shadowResult = null;
2060            try {
2061              FileOutputStream fos = new FileOutputStream(PathHandler.getDefaultFilePathForClient("snapshot_" + pubName+ "_" +subName));
2062              OutputStreamWriter os = new OutputStreamWriter(fos);
2063              BufferedWriter bw = new BufferedWriter(os);
2064              pubConnection = connectionPool.getConnection(pubName);
2065              XMLWriter xmlWriter = new XMLWriter(bw, dbh, pubConnection);
2066              bw.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
2067              bw.write("<root_snapshot>");
2068              String tableName;
2069              SchemaQualifiedName sname;
2070              stmt = pubConnection.createStatement();
2071              for (int i = 0; i < noOfPubTables; i++) {
2072                RepTable repTable = (RepTable) pubRepTables.get(i);
2073                sname =(repTable).getSchemaQualifiedName();
2074                tableName = isSchemaSupported ? sname.toString() : sname.getTableName() ;
2075                //compare for new table list
2076                if(tablesForSnapShot.contains(tableName.toLowerCase())){
2077                ArrayList encodedCols = PathHandler.getEncodedColumns(tableName);
2078                bw.write("<tableName>");
2079                bw.write(tableName);
2080                String query;
2081                if (repTable.getFilterClause() == null || repTable.getFilterClause().equalsIgnoreCase("")) {
2082                  query = "Select * from " + repTable.getRepTableQualifiedIdentifier();
2083                }
2084                else {
2085                  query = "Select * from " + repTable.getRepTableQualifiedIdentifier() +" where " + repTable.getFilterClause();
2086                }
2087                rows = stmt.executeQuery(query);
2088                ResultSetMetaData rsmt = rows.getMetaData();
2089                int noOfColumns = rsmt.getColumnCount();
2090                while (rows.next()) {
2091                  bw.write("<row>");
2092                  for (int c = 1; c <= noOfColumns; c++) {
2093                    String columnName = rsmt.getColumnName(c);
2094                    if (!encodedCols.contains(columnName.toUpperCase())) {
2095                      bw.write("<" + columnName + ">");
2096                    }
2097                    else {
2098                      bw.write("<" + columnName + "  Encode=\"y\">");
2099                    }
2100                    // Special Handelling for Blob Clob Case
2101                    xmlWriter.write(rows, c, encodedCols, columnName);
2102                    bw.write("</" + columnName + ">\r\n");
2103                  }
2104                  bw.write("</row>\r\n");
2105                  bw.flush();
2106                }
2107                bw.write("</tableName>\r\n");
2108                // updating values for bookmark table
2109                stmt.execute(" select " + RepConstants.shadow_sync_id1 + 
2110                                " from " +RepConstants.shadow_Table(tableName) + 
2111                                    " order by " + RepConstants.shadow_sync_id1 + 
2112                                    " desc limit 1");
2113                log.debug(" select " + RepConstants.shadow_sync_id1 + 
2114                                " from " +RepConstants.shadow_Table(tableName) + 
2115                                    " order by " + RepConstants.shadow_sync_id1 + 
2116                                    " desc limit 1");
2117                shadowResult = stmt.getResultSet();
2118                boolean value = shadowResult.next();
2119                            Object maxvalue = null;
2120                               if (value) {
2121                                      maxvalue = shadowResult.getObject(1);
2122                               }
2123                               if (maxvalue == null) {
2124                                    maxvalue = new Long(0);
2125                               }
2126    
2127                log.debug("max(" + RepConstants.shadow_sync_id1 + ")=" + maxvalue);
2128                StringBuffer updateBookmarkQuery = new StringBuffer("update " +dbh.getBookMarkTableName() + " set ");
2129                updateBookmarkQuery.append(RepConstants.bookmark_lastSyncId4 + " = " +maxvalue + ", ");
2130                updateBookmarkQuery.append(RepConstants.bookmark_ConisderedId5 + " = " +maxvalue + " ");
2131                updateBookmarkQuery.append(" where " + RepConstants.bookmark_LocalName1 +" ='" + pubName + "' ");
2132                updateBookmarkQuery.append(" and  " + RepConstants.bookmark_RemoteName2 +" ='" + subName + "' ");
2133                updateBookmarkQuery.append(" and  " + RepConstants.bookmark_TableName3 +" ='" + tableName + "'");
2134                stmt.executeUpdate(updateBookmarkQuery.toString());
2135                log.debug(updateBookmarkQuery.toString());
2136               }
2137              }
2138              bw.write("</root_snapshot>\r\n");
2139              if(bw!=null)
2140              bw.close();
2141              fos.close();
2142    
2143              // making zip file from xml file
2144              if(!localAddress.equalsIgnoreCase(remoteMachineAddress)) {
2145                ZipHandler.makeZip(PathHandler.getDefaultZIPFilePathForClient("snapshot_" + pubName + "_" + subName),PathHandler.getDefaultFilePathForClient("snapshot_" + pubName +"_" + subName), "snapshot_" + pubName + "_" + subName + ".xml");
2146                // writing zip file on socket
2147                WriteOnSocket writeOnSocket = new WriteOnSocket(PathHandler.getDefaultZIPFilePathForClient("snapshot_" + pubName),PathHandler.getDefaultFilePathForClient("snapshot_" + pubName),_Publication.xmlAndShadow_entries, "snapshot_" + pubName,fileUpload, true);
2148                writeOnSocket.start();
2149                writeOnSocket.join();
2150              }
2151              deleteRecordsFromSuperLogTable(stmt);
2152            }
2153            catch (FileNotFoundException ex) {
2154              RepConstants.writeERROR_FILE(ex);
2155              throw new RepException("REP085", null);
2156            } //Temporary Snapshot File Can not created.
2157            catch (IOException ex) {
2158              RepConstants.writeERROR_FILE(ex);
2159              RepException rex = new RepException("REP086", new Object[] {ex.getMessage()});
2160              rex.setStackTrace(ex.getStackTrace());
2161              throw rex;
2162            }
2163            catch (SQLException ex) {
2164              RepConstants.writeERROR_FILE(ex);
2165              RepException rex = new RepException("REP055", new Object[] {pubName,ex.getMessage()});
2166              rex.setStackTrace(ex.getStackTrace());
2167              throw rex;
2168            }
2169            catch (InterruptedException ex) {
2170              RepConstants.writeERROR_FILE(ex);
2171              RepException rex = new RepException("REP055", new Object[] {pubName,ex.getMessage()});
2172              rex.setStackTrace(ex.getStackTrace());
2173              throw rex;
2174    
2175              }
2176            catch (RepException ex) {
2177              RepConstants.writeERROR_FILE(ex);
2178              throw ex;
2179            }
2180            finally {
2181              connectionPool.removeSubPubFromMap(pubName);
2182              /** @todo  Close the statement */
2183              if (rows != null)
2184                rows.close();
2185              if (shadowResult != null)
2186                shadowResult.close();
2187              if (stmt != null)
2188                stmt.close();
2189                      connectionPool.returnConnection(pubConnection);
2190            }
2191          }
2192          public ArrayList dropTableListForSub(String subName) throws RepException,
2193          SQLException ,RemoteException{
2194                    Connection con = null;
2195            ResultSet rs=null;
2196            Statement stt=null;
2197            ArrayList dropTableFromSub=new ArrayList();
2198            try{
2199                      con = connectionPool.getConnection(pubName);
2200                      stt = con.createStatement();
2201              StringBuffer sb = new StringBuffer();
2202              sb.append("select ").append(RepConstants.bookmark_TableName3)
2203                  .append(" from ").append(dbh.getBookMarkTableName()).append(" where ")
2204                  .append(RepConstants.bookmark_LocalName1).append(" = '")
2205                  .append(pubName).append("'").append(" and ")
2206                  .append(RepConstants.bookmark_RemoteName2).append(" = '")
2207                  .append(subName).append("'").append(" and ")
2208                  .append(RepConstants.bookmark_IsDeletedTable).append(" ='Y'");
2209              rs = stt.executeQuery(sb.toString());
2210              while(rs.next()){
2211                dropTableFromSub.add(rs.getString(RepConstants.bookmark_TableName3));
2212              }
2213              return dropTableFromSub;
2214            }finally{
2215              connectionPool.removeSubPubFromMap(pubName);
2216              try {
2217                if (rs != null) {
2218                  rs.close();
2219                }
2220                if (stt != null) {
2221                  stt.close();
2222                }
2223              }
2224              catch (SQLException ex) {
2225              }
2226                     connectionPool.returnConnection(con);
2227            }
2228          }
2229    
2230          public void updatePublisherShadowAndBookmarkTableAfterPullOnSubscriber(String remote_Pub_Sub_Name,
2231              Object[] lastId) throws RemoteException, SQLException, RepException {
2232                    Connection pubConnection = null;
2233            Statement stmt = null;
2234            try {
2235              updateBookMarkLastSyncId(remote_Pub_Sub_Name, lastId);
2236              pubConnection = connectionPool.getConnection(pubName);
2237              stmt = pubConnection.createStatement();
2238              for (int i = 0; i < pubRepTables.size(); i++) {
2239                String tableName = ( (RepTable) pubRepTables.get(i)).getSchemaQualifiedName().toString();
2240                UpdateConisdered_LastsyncIdForBookMarksTable(pubName,remote_Pub_Sub_Name,tableName, lastId[i], stmt);
2241              }
2242              deleteRecordsFromShadowTable(stmt);
2243            }
2244            finally {
2245              connectionPool.removeSubPubFromMap(pubName);
2246              try {
2247                if (stmt != null) {
2248                  stmt.close();
2249                }
2250              }
2251              catch (SQLException ex) {
2252              }
2253                     connectionPool.returnConnection(pubConnection);
2254            }
2255          }
2256    
2257        public void setIgnoredColumns(String tableName,
2258                    String[] columnNamesToBeIgnored) throws RepException {
2259              Connection connection = null;
2260              try {
2261                    connection = connectionPool.getConnection(pubName);
2262                    MetaDataInfo mdi = Utility.getDatabaseMataData(connection);
2263          SchemaQualifiedName sname = new SchemaQualifiedName(mdi, tableName);
2264          if (tableName.indexOf('.') == -1) {
2265            mdi.checkTableExistance(sname);
2266          }
2267          getRepTable(tableName).setColumnsToBeIgnored(columnNamesToBeIgnored);
2268        }
2269             finally {
2270               connectionPool.returnConnection(connection);
2271             }
2272            }
2273    
2274        /**
2275         * To get the result of primary columns to write its value in XML
2276         * file during snapshot.
2277         * @param connection Connection
2278         * @param tableName String
2279         * @param primaryColumnNames String[]
2280         * @throws SQLException
2281         * @return ResultSet
2282         */
2283        private ResultSet getPrimaryKeyResultSet(Statement stmt,String tableName, String[] primaryColumnNames) throws SQLException{
2284         StringBuffer sb =new StringBuffer();
2285               sb.append("SELECT  ");
2286               for (int i = 0; i < primaryColumnNames.length; i++) {
2287                 if(i!=0)
2288                 sb.append(",");
2289                 sb.append(primaryColumnNames[i]);
2290               }
2291               sb.append(" FROM ").append(tableName);
2292               stmt.setFetchSize(1);
2293               ResultSet resultSetPrimaryKey = stmt.executeQuery(sb.toString());
2294               resultSetPrimaryKey.next();
2295               return resultSetPrimaryKey;
2296       }
2297    
2298      private void makePublicationTransactionLogFile(String subName,MergeHandler mg ,BufferedWriter bw ) throws Exception {
2299          if(Utility.createTransactionLogFile) {
2300            String transactionLogURL = PathHandler.getDefaultTransactionLogFilePathForPublisher(pubName);
2301            FileOutputStream fos1 = new FileOutputStream(transactionLogURL, true);
2302            OutputStreamWriter os = new OutputStreamWriter(fos1);
2303            bw = new BufferedWriter(os);
2304            AbstractSynchronize.writeDateInTransactionLogFile(bw);
2305            AbstractSynchronize.writeOperationInTransactionLogFile(bw, mg.insert,mg.update, mg.delete, "MERGE");
2306            bw.flush();
2307          }
2308    }
2309    
2310        private boolean isSchemaSupported() {
2311          return  dbh.isSchemaSupported();
2312        }
2313    
2314      /**
2315       * getFileUploader
2316       *
2317       * @return ArrayList
2318       */
2319      public _FileUpload getFileUploader()throws RepException,
2320          SQLException,RemoteException {
2321        return new FileUpload();
2322      }
2323    
2324    }





























































Powered by Drupal - Theme by Danger4k