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.xml; 021 022 import java.sql.*; 023 import java.util.*; 024 025 import org.xml.sax.*; 026 import org.xml.sax.helpers.*; 027 import org.dbreplicator.replication.*; 028 import org.dbreplicator.replication.DBHandler.*; 029 import org.dbreplicator.replication.synchronize.*; 030 import java.io.BufferedWriter; 031 import org.apache.log4j.Logger; 032 033 /** 034 * This class is the implementation class for ContentHandler for parsing the 035 * synchronization XML file. This class implements differnt event methods which automatically 036 * are called by the parser. It implements these methods to get and use the different 037 * values stored on the XML file. 038 */ 039 040 public class MergeHandler 041 extends DefaultHandler { 042 XMLElement currentElement; 043 Connection connection; 044 Statement statement; 045 _Replicator replicator; 046 TreeMap treeMap; 047 String conflictResolver, localName, remoteName; 048 PreparedStatement updateConisderedForBookMarksTable; 049 AbstractDataBaseHandler dbHandler; 050 MetaDataInfo mdi; 051 OperationDelete operationDelete; 052 OperationInsert operationInsert; 053 OperationUpdate operationUpdate; 054 String remoteServerName, replicationType, transactionLogType; 055 BufferedWriter bw; 056 public int insert, update, delete; 057 private XMLElement tableElement; 058 boolean isFirstPass; 059 private boolean isCurrentTableCyclic; 060 protected static Logger log = Logger.getLogger(MergeHandler.class.getName()); 061 062 /** 063 * Default Handler for parsing and reading the contents from XML file 064 * @param connection0 065 * @param replicator0 066 * @param remoteServerName0 067 * @throws RepException 068 */ 069 public MergeHandler(boolean isFirstPass0, Connection connection0, 070 _Replicator replicator0, 071 String remoteServerName0, 072 AbstractDataBaseHandler dbHandler0, BufferedWriter bw0, 073 String replicationType0, String transactionLogType0, 074 MetaDataInfo mdi0) throws RepException { 075 try { 076 currentElement = new XMLElement("root"); 077 connection = connection0; 078 statement = connection.createStatement(); 079 /* bjt - start transaction */ 080 replicator = replicator0; 081 dbHandler = dbHandler0; 082 083 mdi = mdi0; 084 transactionLogType = transactionLogType0; 085 remoteServerName = remoteServerName0; 086 bw = bw0; 087 replicationType = replicationType0; 088 isFirstPass = isFirstPass0; 089 /* bjt - looks like transaction should start here */ 090 } 091 catch (Exception ex) { 092 log.error(ex.getMessage(), ex); 093 throw new RepException("REP057", new Object[] {ex.getMessage()}); 094 } 095 } 096 097 /** 098 * Initializing an XML element and adding its children. 099 * @param namespace 100 * @param localname 101 * @param qname 102 * @param atts 103 * @throws SAXException 104 */ 105 public void startElement(String namespace, String localname, String qname, Attributes atts) throws SAXException { 106 XMLElement childElement = null; 107 if ( (currentElement == null || 108 !currentElement.elementName.equals("operation")) && 109 qname.equals("tableName")) { 110 childElement = new XMLElement(qname); 111 tableElement = childElement; 112 } 113 else { 114 if (tableElement != null) { 115 initializeOperations(tableElement.elementValue); 116 } 117 childElement = new XMLElement(qname); 118 tableElement = null; 119 } 120 currentElement.addChild(childElement); 121 childElement.setParentElement(currentElement); 122 childElement.addAtt(atts.getValue("name")); 123 124 // encoded cols 125 childElement.addEncodeAtt(atts.getValue("Encode")); 126 currentElement = childElement; 127 } 128 129 /** 130 * Called after end of an element is reached for calling update/insert/delete on the respective table. 131 * @param namespace 132 * @param localname 133 * @param qname 134 * @throws SAXException 135 */ 136 public void endElement(String namespace, String localname, String qname) throws SAXException { 137 try { 138 currentElement.checkEncoding(); 139 XMLElement parentElement = currentElement.getParentElement(); 140 if ( (parentElement == null || 141 parentElement.elementName.equals("tableName")) && 142 qname.equals("operation")) { 143 //if (currentElement.elementValue.equals(RepConstants.insert_operation)) { 144 if (currentElement.elementValue.equals(RepConstants.insert_operation) && isFirstPass) { 145 createInsertQuery(); 146 } 147 //else if (currentElement.elementValue.equals(RepConstants.update_operation)) { 148 else if (currentElement.elementValue.equals(RepConstants.update_operation) && isFirstPass) { 149 createUpdateQuery(); 150 } 151 //else if (currentElement.elementValue.equals(RepConstants.delete_operation)) { 152 else if (currentElement.elementValue.equals(RepConstants.delete_operation) && !isFirstPass) { 153 createDeleteQuery(); 154 } 155 // bjt - try to free up some memory 156 currentElement.elementList.clear(); 157 } 158 if ( (parentElement == null || 159 !parentElement.elementName.equals("operation")) && 160 qname.equals("tableName")) { 161 try { 162 currentElement.elementList.clear(); 163 } 164 catch (Exception ex) { 165 RepConstants.writeERROR_FILE(ex); 166 } 167 if (operationInsert != null && isFirstPass) { 168 insert += operationInsert.insertCount; 169 operationInsert.closeAllStatments(); 170 } 171 if (operationUpdate != null && isFirstPass) { 172 update += operationUpdate.updateCount; 173 operationUpdate.closeAllStatments(); 174 } 175 if (operationDelete != null && !isFirstPass) { 176 delete += operationDelete.deleteCount; 177 operationDelete.closeAllStatments(); 178 } 179 } 180 currentElement = parentElement; 181 } 182 catch (RepException ex1) { 183 throw new SAXException(ex1.getMessage(), ex1); 184 } 185 } 186 187 /** 188 * getting the value for XML element. 189 * @param ch 190 * @param start 191 * @param len 192 * @throws SAXException 193 */ 194 public void characters(char[] ch, int start, int len) throws SAXException { 195 String elementValue = new String(ch, start, len); 196 if (elementValue.equalsIgnoreCase("") || elementValue.equalsIgnoreCase("\n")) { 197 return; 198 } 199 currentElement.setElementValue(elementValue); 200 } 201 202 private void initializeOperations(String elementValue) throws SAXException { 203 Statement st = null; 204 ResultSet conisderedIdRS = null; 205 try { 206 // Utility.insertCount=0; 207 RepTable repTable = replicator.getRepTable(elementValue); 208 isCurrentTableCyclic = repTable.getCyclicDependency().equalsIgnoreCase(RepConstants.YES); 209 treeMap = repTable.getColumnTreeMap(connection,replicator.getDBDataTypeHandler()); 210 conflictResolver = repTable.getConflictResolver(); 211 st = connection.createStatement(); 212 StringBuffer query = new StringBuffer(); 213 query.append("SELECT ").append(RepConstants.bookmark_ConisderedId5). 214 append(", ").append(RepConstants.bookmark_lastSyncId4). /* bjt - add last sync id to query */ 215 append(" FROM ").append(dbHandler.getBookMarkTableName()). 216 append(" where ").append(RepConstants.bookmark_TableName3).append( 217 " ='").append(repTable.getSchemaQualifiedName().toString()) 218 .append("' and ").append(RepConstants.bookmark_LocalName1).append( 219 "='").append(localName).append("' and ") 220 .append(RepConstants.bookmark_RemoteName2).append(" = '").append( 221 remoteName).append("'"); 222 conisderedIdRS = st.executeQuery(query.toString()); 223 boolean f1 = conisderedIdRS.next(); 224 Object conisderedId = conisderedIdRS.getObject(1); 225 Object lastSyncId = conisderedIdRS.getObject(2); /* bjt - grab the last sync id */ 226 log.debug("bjt - create new OperationDelete object"); 227 operationDelete = new OperationDelete(repTable, connection, treeMap, 228 conisderedId, remoteServerName, 229 dbHandler, bw, replicationType, 230 transactionLogType, mdi, 231 isFirstPass, isCurrentTableCyclic); 232 log.debug("bjt - create new OperationUpdate object"); 233 operationUpdate = new OperationUpdate(repTable, connection, treeMap, 234 conisderedId, lastSyncId, remoteServerName, /* bjt - add last sync id to arg list */ 235 dbHandler, bw, replicationType, 236 transactionLogType, mdi, 237 isFirstPass, isCurrentTableCyclic); 238 log.debug("bjt - create new OperationInsert object"); 239 operationInsert = new OperationInsert(repTable, connection, treeMap, 240 conisderedId, lastSyncId, remoteServerName, /* bjt - add last sync id to arg list */ 241 dbHandler, bw, replicationType, 242 transactionLogType, mdi, 243 isFirstPass, isCurrentTableCyclic, localName, remoteName); 244 //bjt close the ResultSets and statments 245 st.close(); 246 conisderedIdRS.close(); 247 } 248 catch (Exception ex) { 249 log.error(ex.getMessage(), ex); 250 throw new SAXException(ex.getMessage(), ex); 251 } 252 } 253 254 /** 255 * creating and firing a insert query. 256 * @throws RepException 257 */ 258 private void createInsertQuery() throws RepException { 259 try { 260 log.debug("Current Elemnent =" + currentElement); 261 operationInsert.execute(currentElement); 262 } 263 catch (Exception ex) { 264 log.error(ex, ex); 265 if (ex instanceof RepException) { 266 if ( ( (RepException) ex).getRepCode().equalsIgnoreCase("REP051")) { 267 RepException rex = new RepException("REP050", null); 268 ( (RepException) rex).SetStackTrace( (RepException) ex); 269 throw rex; 270 } 271 throw (RepException) ex; 272 } 273 else { 274 throw new RepException("REP057", new Object[] {ex.getMessage()}); 275 } 276 } 277 } 278 279 /** 280 * creating and firing a update query. 281 * @throws RepException 282 */ 283 private void createUpdateQuery() throws RepException { 284 try { 285 operationUpdate.execute(currentElement); 286 } 287 catch (Exception ex) { 288 log.error(ex.getMessage(), ex); 289 if (ex instanceof RepException) { 290 if ( ( (RepException) ex).getRepCode().equalsIgnoreCase("REP051")) { 291 RepException rex = new RepException("REP050", null); 292 rex.SetStackTrace( (RepException) ex); 293 throw rex; 294 } 295 throw (RepException) ex; 296 } 297 else { 298 throw new RepException("REP057", new Object[] {ex.getMessage()}); 299 } 300 } 301 } 302 303 /** 304 * creating and firing a delete query. 305 * @throws RepException 306 */ 307 private void createDeleteQuery() throws RepException { 308 try { 309 log.debug("Current Elemnent =" + currentElement); 310 operationDelete.execute(currentElement); 311 } 312 catch (Exception ex) { 313 log.error(ex.getMessage(), ex); 314 if (ex instanceof RepException) { 315 if ( ( (RepException) ex).getRepCode().equalsIgnoreCase("REP051")) { 316 RepException rex = new RepException("REP050", null); 317 rex.SetStackTrace( (RepException) ex); 318 throw rex; 319 } 320 throw (RepException) ex; 321 } 322 else { 323 throw new RepException("REP057", new Object[] {ex.getMessage()}); 324 } 325 } 326 } 327 328 private PreparedStatement makeUpdateConisderedForBookMarksTable() throws SQLException { 329 StringBuffer query = new StringBuffer(); 330 query.append(" UPDATE ").append(dbHandler.getBookMarkTableName()).append( 331 " set ").append(RepConstants.bookmark_ConisderedId5) 332 .append(" = ? where ").append(RepConstants.bookmark_LocalName1).append( 333 " = ? and ").append(RepConstants.bookmark_RemoteName2).append( 334 " = ? and ") 335 .append(RepConstants.bookmark_TableName3).append(" =? "); 336 return connection.prepareStatement(query.toString()); 337 } 338 339 public void setLocalName(String localName0) { 340 localName = localName0; 341 } 342 343 public void setRemoteName(String remoteName0) { 344 remoteName = remoteName0; 345 } 346 347 public void closeAllStatementAndResultset() { 348 try { 349 if (statement != null) 350 statement.close(); 351 /* bjt - connection.close() - end transaction first */ 352 } 353 catch (SQLException ex) { 354 } 355 } 356 357 /** 358 * used for debugging. shows values stored in a resultSet. 359 * @param rs 360 * @throws SQLException 361 */ 362 /* public static void showResultSet(ResultSet rs) throws SQLException { 363 ResultSetMetaData metaData = rs.getMetaData(); 364 int columnCount = metaData.getColumnCount(); 365 Object[] displayColumn = new Object[columnCount]; 366 for (int i = 1; i <= columnCount; i++) 367 displayColumn[i - 1] = metaData.getColumnName(i); 368 // System.out.println(Arrays.asList(displayColumn)); 369 while (rs.next()) { 370 Object[] columnValues = new Object[columnCount]; 371 for (int i = 1; i <= columnCount; i++) 372 columnValues[i - 1] = rs.getObject(i); 373 // System.out.println(Arrays.asList(columnValues)); 374 } 375 }*/ 376 }

