1 18 19 package sync4j.server.engine; 20 21 import java.util.*; 22 import java.util.logging.Level ; 23 24 import java.sql.Timestamp ; 25 26 import sync4j.framework.engine.*; 27 import sync4j.framework.engine.source.SyncSource; 28 import sync4j.framework.security.Sync4jPrincipal; 29 import sync4j.framework.tools.beans.BeanFactory; 30 import sync4j.framework.core.*; 31 import sync4j.framework.database.Database; 32 import sync4j.framework.config.Configuration; 33 import sync4j.framework.config.ConfigurationConstants; 34 import sync4j.framework.server.*; 35 import sync4j.framework.server.store.*; 36 import sync4j.server.engine.Sync4jSource; 37 38 46 public class Sync4jSyncEngine 47 extends Sync4jEngine 48 implements java.io.Serializable , SyncEngine, ConfigurationConstants { 49 50 52 54 57 private ArrayList serverSources = new ArrayList(); 58 private ArrayList clientSources = new ArrayList(); 59 60 63 private java.util.Map operations = null; 64 65 68 private SyncOperationStatus[] operationStatus = null; 69 70 72 75 protected Sync4jSyncEngine() { 76 } 77 78 85 public Sync4jSyncEngine(Configuration configuration) { 86 super(configuration); 87 88 Sync4jSource[] sources = null; 92 93 try { 94 sources = (Sync4jSource[])store.read(Sync4jSource.class); 95 } catch (PersistentStoreException e) { 96 if (log.isLoggable(Level.SEVERE)) { 97 log.severe("Error reading registered sources: " + e.getMessage()); 98 } 99 100 log.throwing(getClass().getName(), "<init>", e); 101 } 102 103 for (int i=0; ((sources != null) && (i<sources.length)); ++i) { 104 if (log.isLoggable(Level.FINE)) { 105 log.fine("sources[" + i + "]: " + sources[i]); 106 } 107 108 try { 109 serverSources.add( 110 BeanFactory.getBeanInstance(configuration.getClassLoader(), sources[i].getConfig()) 111 ); 112 } catch (Exception e){ 113 String msg = "Unable to create sync source " 114 + sources[i] 115 + ": " 116 + e.getMessage(); 117 118 log.severe(msg); 119 log.throwing(getClass().getName(), "<init>", e); 120 } 121 } 122 123 124 SyncStrategy strategy = 128 (SyncStrategy)configuration.getClassInstance(CFG_STRATEGY_CLASS); 129 130 setStrategy(strategy); 131 132 if (log.isLoggable(Level.INFO)) { 133 log.info("Engine configuration:"); 134 log.info("store: " + store ); 135 log.info("officer: " + officer ); 136 log.info("strategy: " + strategy); 137 } 138 } 139 140 142 145 private SyncStrategy strategy = null; 146 147 152 public SyncStrategy getStrategy() { 153 return this.strategy; 154 } 155 156 159 public void setStrategy(SyncStrategy strategy) { 160 this.strategy = strategy; 161 } 162 163 164 167 private java.util.Map dbs = new HashMap(); 168 169 public void setDbs(java.util.Map dbs) { 170 if (this.dbs != null) { 171 this.dbs.clear(); 172 } else { 173 this.dbs = new HashMap(dbs.size()); 174 } 175 this.dbs.putAll(dbs); 176 } 177 178 public void setDbs(Database[] dbs) { 179 if (this.dbs == null) { 180 this.dbs = new HashMap(dbs.length); 181 } 182 183 for (int i=0; ((dbs != null) && (i<dbs.length)); ++i) { 184 this.dbs.put(dbs[i].getName(), dbs[i]); 185 } 186 } 187 188 public Database[] getDbs() { 189 if (this.dbs == null) { 190 return new Database[0]; 191 } 192 193 Iterator i = this.dbs.values().iterator(); 194 195 Database[] ret = new Database[this.dbs.size()]; 196 197 int j = 0; 198 while(i.hasNext()) { 199 ret[j++] = (Database)i.next(); 200 } 201 202 return ret; 203 } 204 205 208 private java.util.Map clientMappings = new HashMap(); 209 210 public void setClientMappings(java.util.Map clientMappings) { 211 this.clientMappings = clientMappings; 212 } 213 214 216 223 public void sync(Sync4jPrincipal principal) 224 throws Sync4jException { 225 log.info("Starting synchronization ..."); 226 227 SyncStrategy syncStrategy = getStrategy(); 228 229 SyncSource clientSource = null, serverSource = null; 230 Database db = null; 231 232 ArrayList status = new ArrayList(); 233 234 HashMap sourceMap = new HashMap(serverSources.size()); 239 240 Iterator s = serverSources.iterator(); 241 while(s.hasNext()) { 242 serverSource = (SyncSource)s.next(); 243 sourceMap.put(serverSource.getSourceURI(), serverSource); 244 } 245 246 250 operations = new HashMap(); 251 252 String uri = null; 253 Iterator c = clientSources.iterator(); 254 while(c.hasNext()) { 255 clientSource = (SyncSource)c.next(); 256 uri = clientSource.getSourceURI(); 257 258 serverSource = (SyncSource)sourceMap.get(uri); 259 db = (Database)dbs.get(clientSource.getSourceURI()); 260 261 SyncSource[] sources = new SyncSource[] { 262 serverSource, clientSource 263 }; 264 265 try { 266 Sync4jPrincipal p = (Sync4jPrincipal)db.getPrincipal(); 267 p.setId(principal.getId()); 268 269 serverSource.beginSync(p, db.getMethod()); 273 274 if ( (db.getMethod() == AlertCode.SLOW) 275 || (db.getMethod() == AlertCode.REFRESH_FROM_SERVER) 276 || (db.getStatusCode() == StatusCode.REFRESH_REQUIRED)) { 277 operations.put(uri, syncStrategy.prepareSlowSync(sources, p)); 278 } else { 279 LastTimestamp last = new LastTimestamp( 284 p.getId() , 285 db.getName() 286 ); 287 try { 288 store.read(last); 289 } catch (PersistentStoreException e) { 290 throw new SyncException("Error reading last timestamp", e); 291 } 292 Timestamp since = new Timestamp (last.start); 293 294 operations.put(uri, syncStrategy.prepareFastSync(sources, p, since)); 295 } 296 297 if (db.getStatusCode() == StatusCode.REFRESH_REQUIRED) { 302 db.setStatusCode(StatusCode.OK); 303 } 304 305 status.addAll( 309 Arrays.asList( 310 syncStrategy.sync((SyncOperation[])operations.get(uri)) 311 ) 312 ); 313 314 operationStatus = (SyncOperationStatus[])status.toArray(new SyncOperationStatus[0]); 315 316 serverSource.endSync(p); 320 321 log.info("Ending synchronization ..."); 322 323 syncStrategy.endSync(); 324 } catch (SyncException e) { 325 log.throwing(getClass().getName(), "sync", e); 326 throw new Sync4jException(e.getMessage(), e); 327 } 328 } } 330 331 338 public SyncOperation[] getSyncOperations(String uri) { 339 return (SyncOperation[])operations.get(uri); 340 } 341 342 351 public Status[] getModificationsStatusCommands(String msgId) { 352 353 if ((operationStatus == null) || (operationStatus.length == 0)) { 354 return new Status[0]; 355 } 356 357 return EngineHelper.generateStatusCommands( 358 operationStatus, 359 msgId, 360 cmdIdGenerator 361 ); 362 } 363 364 369 public void addClientSource(SyncSource source) { 370 log.finest("adding " + source); 371 372 clientSources.add(source); 373 } 374 375 380 public List getClientSources() { 381 return clientSources; 382 } 383 384 391 public SyncSource getClientSource(String name) { 392 Iterator i = clientSources.iterator(); 393 394 SyncSource s = null; 395 while (i.hasNext()) { 396 s = (SyncSource)i.next(); 397 398 if (s.getSourceURI().equals(name)) { 399 return s; 400 } 401 } 402 403 return null; 404 } 405 406 413 public SyncSource getServerSource(String name) { 414 Iterator i = serverSources.iterator(); 415 416 SyncSource s = null; 417 while (i.hasNext()) { 418 s = (SyncSource)i.next(); 419 420 if (s.getSourceURI().equals(name)) { 421 return s; 422 } 423 } 424 425 return null; 426 } 427 428 438 public DataStore databaseToDataStore(Database db) { 439 ContentTypeInfo contentTypeInfo 440 = new ContentTypeInfo(db.getType(), "-" ); 441 442 return new DataStore( 443 new SourceRef(db.getSource()) , 444 null , 445 -1 , 446 contentTypeInfo , 447 new ContentTypeInfo[] { contentTypeInfo } , 448 contentTypeInfo , 449 new ContentTypeInfo[] { contentTypeInfo } , 450 new DSMem(false, -1, -1) , 451 new SyncCap(new SyncType[] { SyncType.SLOW }) 452 ); 453 } 454 455 460 public CTCap[] getContentTypeCapabilities() { 461 return new CTCap[0]; 462 } 463 464 469 public Ext[] getExtensions() { 470 return new Ext[0]; 471 } 472 473 478 public DataStore[] getDatastores() { 479 DataStore[] ds = null; 480 ArrayList al = new ArrayList(); 481 482 Database db = null; 483 String uri = null; 484 Iterator i = dbs.values().iterator(); 485 while(i.hasNext()) { 486 db = (Database)i.next(); 487 uri = db.getName(); 488 489 SyncSource ss = getServerSource(uri); 490 491 if ( ss != null) { 492 al.add(EngineHelper.toDataStore(uri, ss.getInfo())); 493 } 494 } 495 496 int size = al.size(); 497 if (size == 0) { 498 ds = new DataStore[0]; 499 } else { 500 ds = (DataStore[])al.toArray(new DataStore[size]); 501 } 502 503 504 return ds; 505 } 506 507 508 518 public DevInf getServerCapabilities(VerDTD verDTD) { 519 DevInf devInf = 520 new DevInf( 521 verDTD, 522 configuration.getStringValue(CFG_ENGINE_MANIFACTURER, "Sync4j"), 523 configuration.getStringValue(CFG_ENGINE_MODELNAME, "Sync4j"), 524 configuration.getStringValue(CFG_ENGINE_OEM, null ), 525 configuration.getStringValue(CFG_ENGINE_FWVERSION, null ), 526 configuration.getStringValue(CFG_ENGINE_SWVERSION, null ), 527 configuration.getStringValue(CFG_ENGINE_HWVERSION, null ), 528 configuration.getStringValue(CFG_ENGINE_DEVICEID, "Sync4j"), 529 configuration.getStringValue(CFG_ENGINE_DEVICETYPE, "Server"), 530 getDatastores(), 531 getContentTypeCapabilities(), 532 getExtensions(), 533 false, 534 false, 535 false 536 ); 537 return devInf; 538 } 539 540 560 public void prepareDatabases(Sync4jPrincipal principal, 561 Database[] dbs , 562 SyncTimestamp next ) { 563 for (int i=0; ((dbs != null) && (i < dbs.length)); ++i) { 564 int statusCode = StatusCode.OK; 565 566 if (!checkServerDatabase(dbs[i])) { 567 statusCode = StatusCode.NOT_FOUND; 568 } else if (!checkDatabasePermissions(dbs[i])) { 569 statusCode = StatusCode.FORBIDDEN; 570 } 571 572 dbs[i].setStatusCode(statusCode); 573 574 if (statusCode == StatusCode.OK) { 578 LastTimestamp last = new LastTimestamp( 579 principal.getId(), 580 dbs[i].getName() 581 ); 582 583 try { 584 store.read(last); 585 dbs[i].setServerAnchor(new Anchor(last.tagClient, next.tagClient)); 586 } catch (NotFoundException e) { 587 last.tagServer = next.tagClient; 591 dbs[i].setServerAnchor(new Anchor(last.tagServer, next.tagClient)); 592 } catch(PersistentStoreException e) { 593 log.severe("Unable to retrieve timestamp from store"); 594 log.throwing(getClass().getName(), "prepareDatabases", e); 595 } 596 597 if ( !(last.tagServer.equals(dbs[i].getAnchor().getLast())) 598 && (dbs[i].getMethod() != AlertCode.REFRESH_FROM_SERVER)) { 599 if (log.isLoggable(Level.FINE)) { 600 log.fine( "Forcing slow sync for database " 601 + dbs[i].getName() 602 ); 603 log.fine( "Server last: " 604 + last.tagServer 605 + "; client last: " 606 + dbs[i].getAnchor().getLast() 607 ); 608 } 609 dbs[i].setMethod(AlertCode.SLOW); 610 } 611 } 612 } 613 } 614 615 626 public ItemizedCommand[] operationsToCommands(ClientMapping clientMapping, 627 SyncOperation[] operations , 628 String sourceName ) { 629 return EngineHelper.operationsToCommands( clientMapping , 630 operations , 631 sourceName , 632 cmdIdGenerator); 633 } 634 635 643 public void updateClientMappings(java.util.Map clientMappings, 644 SyncOperation[] operations , 645 boolean slowSync ) { 646 try { 647 EngineHelper.updateClientMappings(clientMappings, operations, slowSync); 648 } catch (Exception e) { 649 log.throwing(getClass().getName(), "updateClientMappings", e); 650 } 651 } 652 653 654 661 public void updateServerMappings(java.util.Map clientMappings, boolean slowSync) { 662 try { 663 EngineHelper.updateServerMappings(clientMappings, operationStatus, slowSync); 664 } catch (Exception e) { 665 log.throwing(getClass().getName(), "updateServerMappings", e); 666 } 667 } 668 669 686 public static SyncItem[] itemsToSyncItems(ClientMapping clientMapping, 687 SyncSource syncSource , 688 ModificationCommand cmd , 689 char state , 690 long timestamp ) { 691 692 return EngineHelper.itemsToSyncItems(clientMapping, syncSource, cmd, state, timestamp); 693 } 694 695 697 707 private boolean checkServerDatabase(Database db) { 708 if (log.isLoggable(Level.FINEST)) { 709 log.finest( "Checking if the database " 710 + db 711 + " is in the server database list " 712 + serverSources 713 ); 714 } 715 716 SyncSource source = null; 717 Iterator i = serverSources.iterator(); 718 while(i.hasNext()) { 719 source = (SyncSource)i.next(); 720 721 if (db.getName().equals(source.getSourceURI())) { 722 log.finest("Yes sir!"); 723 return true; 724 } 725 } 726 727 log.finest("Not found sir"); 728 729 return false; 733 } 734 735 742 private boolean checkDatabasePermissions(Database db) { 743 return authorize(db.getPrincipal(), db.getName()); 744 } 745 } | Popular Tags |