1 18 package sync4j.server.session; 19 20 import java.util.logging.Logger ; 21 import java.util.logging.Level ; 22 23 import java.util.*; 24 25 import sync4j.framework.config.ConfigurationConstants; 26 import sync4j.framework.core.*; 27 import sync4j.framework.database.Database; 28 import sync4j.framework.engine.SyncItemImpl; 29 import sync4j.framework.engine.SyncOperation; 30 import sync4j.framework.engine.SyncEngine; 31 import sync4j.framework.engine.SyncItemState; 32 import sync4j.framework.engine.MessageSizeCalculator; 33 import sync4j.framework.engine.source.MemorySyncSource; 34 import sync4j.framework.engine.source.SyncSource; 35 import sync4j.framework.engine.pipeline.MessageProcessingContext; 36 import sync4j.framework.logging.Sync4jLogger; 37 import sync4j.framework.protocol.*; 38 import sync4j.framework.security.*; 39 import sync4j.framework.server.Capabilities; 40 import sync4j.framework.server.ClientMapping; 41 import sync4j.framework.server.LastTimestamp; 42 import sync4j.framework.server.SyncTimestamp; 43 import sync4j.framework.server.error.ServerException; 44 import sync4j.framework.server.error.MappingException; 45 import sync4j.framework.server.error.ServerFailureException; 46 import sync4j.framework.server.error.InvalidCredentialsException; 47 import sync4j.framework.server.session.SessionHandler; 48 import sync4j.framework.server.session.SyncState; 49 import sync4j.framework.server.store.NotFoundException; 50 import sync4j.framework.server.store.PersistentStore; 51 import sync4j.framework.server.Sync4jDevice; 52 import sync4j.framework.tools.Base64; 53 54 import sync4j.server.config.Configuration; 55 import sync4j.server.engine.Sync4jEngine; 56 57 82 public class SyncSessionHandler 83 implements SessionHandler, 84 java.io.Serializable , 85 SecurityConstants, 86 ConfigurationConstants { 87 88 90 private int currentState = STATE_START; 91 92 private boolean slow = false; 96 97 102 public int getCurrentState() { 103 return currentState; 104 } 105 106 private long creationTimestamp = -1; 107 108 113 public long getCreationTimestamp() { 114 return creationTimestamp; 115 } 116 117 private transient Logger log = Sync4jLogger.getLogger("handler"); 118 119 122 private SyncTimestamp nextTimestamp = null; 123 124 private transient SyncInitialization syncInit = null; 125 private transient SyncModifications modifications = null; 126 127 130 private String clientDeviceId = null; 131 132 136 private Database[] dbs = null; 137 138 141 private String clientAuth = null; 142 143 146 private long messageSize = 0; 147 148 151 private MessageSizeCalculator sizeCalculator = null; 152 153 155 158 private String sessionId = null; 159 160 public String getSessionId() { 161 return this.sessionId; 162 } 163 164 167 private CommandIdGenerator cmdIdGenerator = new CommandIdGenerator(); 168 169 public void setCommandIdGenerator(CommandIdGenerator cmdIdGenerator) { 170 this.cmdIdGenerator = cmdIdGenerator; 171 } 172 173 public CommandIdGenerator getCommandIdGenerator() { 174 return this.cmdIdGenerator; 175 } 176 177 181 private void resetIdGenerator() { 182 cmdIdGenerator.reset(); 183 syncEngine.setCommandIdGenerator(cmdIdGenerator); 184 } 185 186 189 private SimpleIdGenerator msgIdGenerator = new SimpleIdGenerator(); 190 191 194 private String lastMsgIdFromClient = null; 195 196 199 private Sync4jEngine syncEngine = null; 200 201 204 private SyncState syncState = null; 205 206 207 public SyncEngine getSyncEngine() { 209 return this.syncEngine; 210 } 211 212 215 private boolean newSession = true; 216 217 public void setNew(boolean newSession) { 218 this.newSession = newSession; 219 } 220 221 public boolean isNew() { 222 return this.newSession; 223 } 224 225 230 public void setSizeCalculator(MessageSizeCalculator calculator) { 231 this.sizeCalculator = calculator; 232 } 233 234 236 239 public SyncSessionHandler() { 240 this.creationTimestamp = System.currentTimeMillis(); 241 this.syncEngine = new Sync4jEngine(Configuration.getConfiguration()); 242 } 243 244 247 public SyncSessionHandler(String sessionId) { 248 this(); 249 this.sessionId = sessionId; 250 } 251 252 254 259 public boolean isAuthenticated() { 260 return (syncState != null) && (syncState.authenticationState == AUTH_AUTHENTICATED); 261 } 262 263 269 public boolean isAccountExpired() { 270 return syncEngine.getOfficer().isAccountExpired(); 271 } 272 273 283 public SyncML processMessage(SyncML message, MessageProcessingContext context) 284 throws ProtocolException, InvalidCredentialsException, ServerFailureException { 285 SyncML response = null; 286 287 resetIdGenerator(); 291 292 msgIdGenerator.next(); 296 297 lastMsgIdFromClient = message.getSyncHdr().getMsgID(); 301 302 clientDeviceId = message.getSyncHdr().getSource().getLocURI(); 306 307 if (log.isLoggable(Level.FINEST)) { 308 log.finest("current state: " + getStateName(currentState)); 309 } 310 311 Chal chal = ProtocolUtil.getStatusChal(message); 312 313 try { 314 switch (currentState) { 315 case STATE_ERROR: case STATE_START: 317 nextTimestamp = new SyncTimestamp(); 318 nextTimestamp.start = System.currentTimeMillis(); 319 nextTimestamp.tagClient = String.valueOf(nextTimestamp.start); 320 321 syncState = new SyncState(); 322 323 syncEngine.setSyncTimestamp(new Date(nextTimestamp.start)); 324 325 Meta meta = message.getSyncHdr().getMeta(); 329 if (meta != null && meta.getMaxMsgSize() != null) { 330 syncState.maxMsgSize = meta.getMaxMsgSize().intValue(); 331 } 332 333 syncState.device = new Sync4jDevice(clientDeviceId); 339 try { 340 syncEngine.readDevice(syncState.device); 341 } catch (NotFoundException e) { 342 if (log.isLoggable(Level.WARNING)) { 343 log.warning( "Client device '" 344 + clientDeviceId 345 + "' not found. Authentication may fail." 346 ); 347 } 348 } 349 350 syncState.syncMLVerProto = 351 message.getSyncHdr().getVerProto().getVersion(); 352 syncEngine.setSyncMLVerProto(syncState.syncMLVerProto); 353 354 Cred cred = message.getSyncHdr().getCred(); 359 360 if (!checkClientAuth(cred)) { 361 syncState.loggedCredential = null; 366 syncState.authenticationState = AUTH_INVALID_CREDENTIALS; 367 368 if (cred == null) { 369 syncState.authenticationState = 370 syncState.AUTH_MISSING_CREDENTIALS; 371 } 372 } else { 373 if (login(message.getSyncHdr().getCred(), clientDeviceId)) { 374 if (log.isLoggable(Level.INFO)) { 375 log.info( syncState.loggedPrincipal.getUsername() 376 + '/' 377 + syncState.loggedPrincipal.getDeviceId() 378 + " logged in." 379 ); 380 } 381 if (syncState.loggedPrincipal.getId() == null) { 382 try { 383 syncEngine.readPrincipal(syncState.loggedPrincipal); 384 } catch (NotFoundException e) { 385 if (log.isLoggable(Level.INFO)) { 386 log.info("Authenticated principal not found:" + syncState.loggedPrincipal); 387 } 388 syncState.authenticationState = AUTH_INVALID_CREDENTIALS; 389 syncState.loggedCredential = null; 390 } 391 } 392 393 if (chal != null) { 399 if (Cred.AUTH_TYPE_MD5.equals(chal.getType())) { 400 syncState.device.setServerNonce(Base64.decode(chal.getNextNonce().getValue())); 401 syncEngine.storeDevice(syncState.device); 402 } 403 } 404 } else { 405 if (log.isLoggable(Level.INFO)) { 406 log.info("Authentication failed for device " 407 + clientDeviceId 408 + ". Make sure that the client used correct " 409 + "username and password and that there " 410 + "is a principal associating the user " 411 + " to the device. " 412 ); 413 } 414 syncState.authenticationState = AUTH_INVALID_CREDENTIALS; 415 syncState.loggedCredential = null; 416 } 417 } 418 419 moveTo(STATE_PKG1_RECEIVING); 420 421 case STATE_PKG1_RECEIVING: 422 423 response = processInitSyncMapMessage(message); 424 425 if (!isAuthenticated()) { 426 if (message.isLastMessage()) { 427 response.setLastMessage(); 428 } 429 moveTo(STATE_START); 430 } else { 431 if (message.isLastMessage()) { 432 moveTo(STATE_PKG3_RECEIVING); 433 if (syncState.cmdCache1.size() == 0) { 434 response.setLastMessage(); 435 } 436 } 437 } 438 439 break; 440 441 case STATE_PKG3_RECEIVING: 442 response = processInitSyncMapMessage(message); 443 444 if (message.isLastMessage()) { 445 moveTo(STATE_PKG3_RECEIVED); 446 if (syncState.cmdCache3.size() == 0) { 447 response.setLastMessage(); 448 } 449 } 450 451 break; 452 453 case STATE_PKG3_RECEIVED: 454 response = processInitSyncMapMessage(message); 455 456 if (syncState.cmdCache3.size() == 0) { 457 response.setLastMessage(); 458 moveTo(STATE_PKG1_RECEIVING); 459 } 460 461 break; 462 463 default: 464 logout(); 465 throw new ProtocolException("Illegal state: " + currentState); 466 } 467 468 if ((currentState != STATE_ERROR) && 469 (currentState != STATE_START) && 470 response.isLastMessage() && 471 (ProtocolUtil.noMoreResponse(response)) ) { 472 473 nextTimestamp.end = System.currentTimeMillis(); 474 moveTo(STATE_END); 475 } 476 477 } catch (ProtocolException e) { 478 log.throwing(getClass().getName(), "processMessage", e); 479 moveTo(STATE_ERROR); 480 throw e; 481 } catch (Throwable t) { 482 log.throwing(getClass().getName(), "processMessage", t); 483 moveTo(STATE_ERROR); 484 throw new ServerFailureException("Server error", t); 485 } 486 487 List commands = response.getSyncBody().getCommands(); 491 ProtocolUtil.updateCmdId(commands); 492 493 if (log.isLoggable(Level.FINEST)) { 494 log.finest("About returning message: " + Util.toXML(response)); 495 } 496 497 return response; 498 } 499 500 508 private boolean checkClientAuth(Cred cred) { 509 510 Officer officer = syncEngine.getOfficer(); 515 clientAuth = officer.getClientAuth(); 516 517 if (cred == null) { 518 syncState.authenticationState = syncState.AUTH_MISSING_CREDENTIALS; 519 return false; 520 } 521 522 String clientAuthSent = cred.getType(); 523 524 if (clientAuth.equalsIgnoreCase(clientAuthSent)) { 525 return true; 526 } 527 528 syncState.authenticationState = syncState.AUTH_INVALID_CREDENTIALS; 529 return false; 530 } 531 532 548 public SyncML processError(SyncML msg, Throwable error) 549 throws Sync4jException { 550 SyncHdr msgHeader = msg.getSyncHdr(); 551 552 Item[] items = new Item[0]; 553 int status = StatusCode.SERVER_FAILURE; 554 555 items = new Item[1]; 556 items[0] = new Item( 557 null, null, null, new ComplexData(error.getMessage()), 561 false ); 563 564 if (error instanceof ServerException) { 565 status = ((ServerException)error).getStatusCode(); 566 } 567 568 Status statusCommand = new Status( 569 cmdIdGenerator.next() , 570 msgHeader.getMsgID() , 571 "0" , 572 "SyncHdr" , 573 new TargetRef(msgHeader.getTarget()), 574 new SourceRef(msgHeader.getSource()), 575 null , 576 null , 577 new Data(status) , 578 new Item[0] 579 ); 580 581 String serverURI = syncEngine 582 .getConfiguration() 583 .getServerConfig() 584 .getEngineConfiguration() 585 .getServerURI(); 586 587 SyncHdr syncHeader = new SyncHdr ( 588 msgHeader.getVerDTD() , 589 msgHeader.getVerProto() , 590 msgHeader.getSessionID() , 591 msgHeader.getMsgID() , 592 new Target(msgHeader.getSource().getLocURI()), 593 new Source(serverURI) , 594 null , 595 false , 596 null , 597 null 598 ); 599 600 SyncBody syncBody = new SyncBody( 601 new AbstractCommand[] { statusCommand }, 602 true 603 ); 604 605 moveTo(STATE_ERROR); 606 607 return new SyncML(syncHeader, syncBody); 608 } 609 610 614 public void expire() { 615 logout(); 616 } 617 618 631 public void abort(int statusCode) { 632 moveTo(STATE_ERROR); 633 } 634 635 642 public void commit() { 643 assert (syncState.loggedPrincipal != null); 644 645 LastTimestamp last = null; 646 647 PersistentStore ps = syncEngine.getStore(); 648 649 Database[] dbsGen = syncEngine.getDbs(); 650 651 for (int i = 0; (dbsGen != null) && (i < dbsGen.length); ++i) { 652 if (dbsGen[i].getStatusCode() != StatusCode.OK) { 653 continue; 657 } 658 last = new LastTimestamp( 659 syncState.loggedPrincipal.getId(), 660 dbsGen[i].getName(), 661 dbsGen[i].getAnchor().getNext(), 662 dbsGen[i].getServerAnchor().getNext(), 663 nextTimestamp.start, 664 nextTimestamp.end 665 ); 666 667 if (log.isLoggable(Level.FINEST)) { 668 log.finest("Commiting database " 669 + dbsGen[i].getName() 670 + " ( " 671 + last 672 + " )" 673 ); 674 } 675 676 try { 677 boolean stored = ps.store(last); 678 if (log.isLoggable(Level.FINEST)) { 679 log.finest("LastTimeStamp stored: " + stored); 680 } 681 } catch (Sync4jException e) { 682 log.severe("Error in saving persistent data"); 683 log.throwing(getClass().getName(), "commit", e); 684 } 685 } 686 } 687 688 690 700 private SyncML processInitSyncMapMessage(SyncML message) 701 throws ProtocolException { 702 SyncInitialization init = null; 703 SyncModifications sync = null; 704 SyncMapping map = null; 705 SyncML response = null; 706 SyncHdr header = null; 707 708 String msgId = msgIdGenerator.current(); 709 710 if (ProtocolUtil.isInitMessage(message)) { 714 init = processInitMessage(message); 715 header = init.getResponseHeader(msgId); 716 } 717 718 if (!isAuthenticated()) { 724 response = init.getResponseMessage(msgId); 725 } else { 726 727 Chal chal = ProtocolUtil.getStatusChal(message); 733 if (chal != null) { 734 if (Cred.AUTH_TYPE_MD5.equals(chal.getType())) { 735 syncState.device.setServerNonce(Base64.decode(chal.getNextNonce().getValue())); 736 syncEngine.storeDevice(syncState.device); 737 } 738 } 739 740 if (ProtocolUtil.isSyncMessage(message)) { 744 sync = processSyncMessage(message); 745 if (header == null) { 746 header = sync.getResponseHeader(msgId); 747 } 748 } 749 750 if (ProtocolUtil.isMapMessage(message) || ProtocolUtil.noMoreResponse(message)) { 754 map = processMapMessage(message); 755 if (header == null) { 756 header = map.getResponseHeader(msgId); 757 } 758 } 759 760 if ((init != null) && (sync != null)) { 765 if (message.isLastMessage()) { 766 moveTo(STATE_PKG3_RECEIVED); 767 } else { 768 moveTo(STATE_PKG3_RECEIVING); 769 } 770 } 771 772 syncEngine.storeMappings(); 777 778 AbstractCommand[] cmdToSend = null; 782 if (checkMaxMsgSize()) { 783 messageSize = sizeCalculator.getSize(header) 784 + sizeCalculator.getSyncBodyOverhead() 785 + sizeCalculator.getRespURIOverhead() 786 ; 787 cmdToSend = commandsToSend(init, sync, map); 788 } else { 789 cmdToSend = new AbstractCommand[1]; 790 791 Status status = (Status)init.getResponseCommands(msgId).get(0); 792 793 status.setData(new Data(StatusCode.SYNCHRONIZATION_FAILED)); 794 795 cmdToSend[0] = status; 796 797 if (log.isLoggable(Level.INFO)) { 798 log.info( "The MaxMsgSize (" 799 + syncState.maxMsgSize 800 + ") is smaller than the minimum message size " 801 + "supported by the server. The session will abort." 802 ); 803 } 804 } 805 806 try { 807 response = new SyncML( 808 header, 809 new SyncBody(cmdToSend, false) 810 ); 811 } catch (RepresentationException e) { 812 throw new ProtocolException(e.getMessage()); 813 } 814 } 815 816 return response; 817 } 818 819 836 private SyncInitialization processInitMessage(SyncML message) 837 throws ProtocolException { 838 if (log.isLoggable(Level.FINEST)) { 839 log.finest("Processing the initialization commands"); 840 } 841 842 try { 843 syncInit = new SyncInitialization(message.getSyncHdr() , 844 message.getSyncBody()); 845 846 syncState.addClientAlerts(syncInit.getClientAlerts()); 850 851 syncInit.setIdGenerator(cmdIdGenerator); 852 853 syncInit.setClientAuth(clientAuth); 858 859 if (clientAuth.equalsIgnoreCase(Cred.AUTH_TYPE_MD5)) { 863 NextNonce nonce = ProtocolUtil.generateNextNonce(); 864 syncInit.setNextNonce(nonce); 865 syncState.device.setClientNonce(nonce.getValue()); 866 syncEngine.storeDevice(syncState.device); 867 } 868 869 if (isAuthenticated()) { 870 syncInit.setAuthorizedStatusCode(StatusCode.AUTHENTICATION_ACCEPTED); 871 872 syncInit.setClientCapabilitiesRequired(false); 873 874 processClientCapabilities(syncInit.getClientDeviceInfo()); 878 879 dbs = syncInit.getDatabasesToBeSynchronized(syncState.loggedPrincipal); 885 886 syncEngine.prepareDatabases(syncState.loggedPrincipal, dbs, nextTimestamp); 892 893 if (log.isLoggable(Level.FINEST)) { 894 log.finest("Requested databases: " + Arrays.asList(dbs)); 895 } 896 897 boolean noDataSource = true; 899 ArrayList dbList = new ArrayList(); 900 for (int i = 0; ((dbs != null) && (i < dbs.length)); ++i) { 901 syncInit.setStatusCodeForCommand( 902 dbs[i].getAlertCommand(), 903 dbs[i].getStatusCode() 904 ); 905 906 if (dbs[i].isOkStatusCode()) { 907 noDataSource = false; 908 syncEngine.addClientSource( 909 new MemorySyncSource( 910 dbs[i].getName(), 911 null, 912 dbs[i].getSource().getLocURI()) 913 ); 914 915 Meta m = ((Item)dbs[i].getAlertCommand().getItems().get(0)).getMeta(); 916 if (m != null) { 917 Long l = m.getMaxObjSize(); 918 if (l != null) { 919 syncState.maxObjSize = l.longValue(); 920 } else { 921 syncState.maxObjSize = 0; 922 } 923 } 924 dbList.add(dbs[i]); 925 } 926 } 927 dbs = (Database[])dbList.toArray(new Database[dbList.size()]); 928 929 syncEngine.setDbs(dbs); 930 931 syncInit.setDatabases(dbs); 936 937 syncInit.setServerCapabilities( 941 syncEngine.getServerCapabilities(syncInit.getDTDVersion()) 942 ); 943 } else { 944 if (isAccountExpired()) { 945 syncInit.setAuthorizedStatusCode(StatusCode.PAYMENT_REQUIRED); 946 } else if (syncState.authenticationState == AUTH_MISSING_CREDENTIALS) { 947 syncInit.setAuthorizedStatusCode(StatusCode.MISSING_CREDENTIALS); 948 } else if (syncState.authenticationState == AUTH_INVALID_CREDENTIALS) { 949 syncInit.setAuthorizedStatusCode(StatusCode.INVALID_CREDENTIALS); 950 } else { 951 syncInit.setAuthorizedStatusCode(StatusCode.FORBIDDEN); 952 } 953 } 954 955 Chal chal = getChal(message); 964 965 String serverAuth = syncEngine.getOfficer().getServerAuth(); 966 967 if (chal == null) { 968 if (serverAuth.equalsIgnoreCase(Cred.AUTH_NONE)) { 969 syncInit.setServerCredentials(null); 970 syncState.serverAuthenticationState = AUTH_AUTHENTICATED; 971 } else { 972 if (syncState.serverAuthenticationState != AUTH_ACCEPTED) { 973 Meta meta = new Meta(); 974 meta.setType(serverAuth); 975 meta.setNextNonce(new NextNonce(Base64.encode( 976 syncState.device.getServerNonce())) 977 ); 978 979 chal = new Chal(meta); 980 syncInit.setServerCredentials( 981 syncEngine.getServerCredentials(chal, syncState.device) 982 ); 983 } 984 } 985 } else { 986 Cred cred = checkServerAuthentication(message); 987 if (cred != null) { 988 syncInit.setServerCredentials(cred); 989 } 990 } 991 992 return syncInit; 993 994 } catch (Sync4jException e) { 995 throw new ProtocolException(e); 996 } 997 } 998 999 1006 private boolean checkMaxMsgSize() { 1007 final long minMsgSize = syncEngine 1008 .getConfiguration() 1009 .getServerConfig() 1010 .getEngineConfiguration() 1011 .getMinMaxMsgSize(); 1012 1013 if (log.isLoggable(Level.FINEST)) { 1014 log.finest( "Checking if MaxMsgSize is larger than the minimum " 1015 + "size supported by the server (" 1016 + minMsgSize 1017 + ")" 1018 ); 1019 } 1020 1021 return ((syncState.maxMsgSize == 0) || (syncState.maxMsgSize >= minMsgSize)); 1022 } 1023 1024 1030 private void checkSizeCapabilities() { 1031 AbstractCommand[] cmds = 1036 (AbstractCommand[])syncState.cmdCache1.toArray(new AbstractCommand[0]); 1037 Status statusGet = (Status)ProtocolUtil.filterCommands( 1038 cmds, 1039 Status.class, 1040 Get.COMMAND_NAME 1041 ); 1042 1043 if (statusGet != null) { 1044 ArrayList results = ProtocolUtil.filterCommands( 1045 cmds, 1046 Results.class 1047 ); 1048 1049 if (results.size() > 0) { 1050 long sizeCap = sizeCalculator.getSyncMLOverhead() 1054 + sizeCalculator.getSyncBodyOverhead() 1055 + sizeCalculator.getSize((Results)results.get(0)); 1056 if (sizeCap > syncState.maxMsgSize) { 1057 if (log.isLoggable(Level.INFO)) { 1058 log.info("Capabilities too big!"); 1059 } 1060 statusGet.setData(new Data(StatusCode.REQUESTED_ENTITY_TOO_LARGE)); 1061 1062 syncState.cmdCache1.remove(results); 1063 } 1064 } 1065 } 1066 } 1067 1068 1079 private Chal getChal(final SyncML msg) { 1080 Chal chal = ProtocolUtil.getStatusChal(msg); 1081 if (chal != null) { 1082 if (log.isLoggable(Level.FINEST)) { 1083 log.finest("Challenged server authentication with scheme " + chal.getType()); 1084 } 1085 } 1086 1087 return chal; 1088 } 1089 1090 1100 private Cred checkServerAuthentication(SyncML msg) 1101 throws ProtocolException { 1102 String serverAuth = syncEngine.getOfficer().getServerAuth(); 1103 int headerStatusCode = ProtocolUtil.getHeaderStatusCode(msg); 1104 if (headerStatusCode == -1) { 1105 return null; 1106 } 1107 1108 if ( (headerStatusCode == StatusCode.INVALID_CREDENTIALS || 1109 headerStatusCode == StatusCode.MISSING_CREDENTIALS)) { 1110 if ( 1111 (serverAuth.equalsIgnoreCase(Cred.AUTH_TYPE_MD5) ) && 1112 (syncState.serverAuthenticationState == AUTH_UNAUTHENTICATED) 1113 ) { 1114 syncState.serverAuthenticationState = AUTH_RETRY_1; 1115 return syncEngine.getServerCredentials(getChal(msg), syncState.device); 1116 } else { 1117 throw new ProtocolException("Unable to authenticate the client"); 1118 } 1119 } else if (headerStatusCode == StatusCode.AUTHENTICATION_ACCEPTED) { 1120 if (log.isLoggable(Level.FINEST)) { 1124 log.finest("Server logged (code 212)"); 1125 } 1126 syncState.serverAuthenticationState = AUTH_ACCEPTED; 1127 } else { 1128 if (log.isLoggable(Level.FINEST)) { 1132 log.finest("Server auhenticated (code 200)"); 1133 } 1134 syncState.serverAuthenticationState = AUTH_AUTHENTICATED; 1135 return syncEngine.getServerCredentials(getChal(msg), syncState.device); 1136 } 1137 return null; 1138 } 1139 1140 1150 private SyncModifications processSyncMessage(SyncML syncRequest) 1151 throws ProtocolException { 1152 1153 if (log.isLoggable(Level.FINEST)) { 1154 log.finest("Processing the given synchronization message"); 1155 log.finest("client sources: " + syncEngine.getClientSources()); 1156 } 1157 1158 try { 1159 modifications = 1160 new SyncModifications(syncRequest.getSyncHdr() , 1161 syncRequest.getSyncBody(), 1162 syncEngine.getDbs()); 1163 1164 Sync[] syncCommands = modifications.getClientSyncCommands(); 1165 1166 checkMaxObjSizeIntoSync(syncCommands); 1170 1171 if (syncRequest.isLastMessage()) { 1175 syncEngine.setLastMessage(true); 1176 } 1177 1178 List responseCommands = processModifications(modifications); 1179 1180 if (syncState.getListStatusCmdNotProcessed() != null) { 1184 responseCommands.addAll(syncState.getListStatusCmdNotProcessed()); 1185 syncState.clearListStatusCmdNotProcessed(); 1186 } 1187 1188 if (log.isLoggable(Level.FINEST)) { 1189 log.finest("responseCommands: " + responseCommands); 1190 } 1191 1192 modifications.setIdGenerator(cmdIdGenerator); 1193 modifications.setFlag(Flags.FLAG_ALL_RESPONSES_REQUIRED); 1194 1195 Status[] statusSyncs = (Status[])ProtocolUtil.filterCommands( 1196 responseCommands, 1197 new String []{ Status.COMMAND_NAME } 1198 ).toArray(new Status[0]); 1199 1200 modifications.setClientModificationsStatus(statusSyncs); 1201 1202 1205 AbstractCommand[] serverModifications = 1208 (AbstractCommand[])ProtocolUtil.filterCommands( 1209 responseCommands, 1210 new String []{Sync.COMMAND_NAME} 1211 ).toArray(new AbstractCommand[0]); 1212 1213 modifications.setServerModifications(serverModifications); 1218 1219 return modifications; 1220 1221 } catch (Sync4jException e) { 1222 throw new ProtocolException(e); 1223 } 1224 } 1225 1226 1234 private boolean checkSize(AbstractCommand cmd) { 1235 return (syncState.maxMsgSize != 0) && 1236 ( (messageSize + sizeCalculator.getCommandSize(cmd)) < syncState.maxMsgSize); 1237 } 1238 1239 1247 private boolean checkSize(long size) { 1248 return (syncState.maxMsgSize != 0) && 1249 ( (messageSize + size) < syncState.maxMsgSize); 1250 } 1251 1252 1261 private boolean checkSize(long size, long msgSize) { 1262 return (syncState.maxMsgSize != 0) && 1263 ( (msgSize + size) < syncState.maxMsgSize); 1264 } 1265 1266 1272 private void checkMaxObjSizeIntoSync(Sync[] syncCmds) { 1273 if (syncCmds != null && syncCmds.length > 0) { 1274 if (syncCmds[0].getMeta() != null && 1278 syncCmds[0].getMeta().getMaxObjSize() != null 1279 ) { 1280 syncState.maxObjSize = syncCmds[0].getMeta().getMaxObjSize().longValue(); 1281 } 1282 } 1283 } 1284 1285 1296 private List processModifications(SyncModifications modifications) 1297 throws Sync4jException { 1298 Sync[] syncCommands = modifications.getClientSyncCommands(); 1299 1300 ArrayList responseCommands = new ArrayList(); 1301 1302 if ((syncCommands == null) || (syncCommands.length == 0)) { 1303 return responseCommands; 1307 } 1308 1309 SyncHdr header = modifications.getSyncHeader(); 1310 String msgId = header.getMsgID() ; 1311 boolean headerNoResponse = header.isNoResp() ; 1312 1313 syncEngine.setCommandIdGenerator(cmdIdGenerator); 1314 1315 1321 Status[] statusCommands = 1322 (Status[])ProtocolUtil.filterCommands( 1323 modifications.getClientCommands(), 1324 Status.class 1325 ).toArray(new Status[0]); 1326 1327 if ((syncCommands != null) && (syncCommands.length>0)) { 1332 checkForReceivedLargeObject(syncCommands); 1333 } 1334 1335 prepareMemorySources(syncCommands, statusCommands); 1340 1341 try { 1342 syncEngine.sync(syncState.loggedPrincipal); 1343 } catch (Sync4jException e) { 1344 log.throwing(getClass().getName(), "processModifications", e); 1345 1346 if (log.isLoggable(Level.SEVERE)) { 1347 log.severe(e.getMessage()); 1348 } 1349 } 1350 1351 if (headerNoResponse == false) { 1355 responseCommands.addAll(statusForSyncs(syncCommands)); 1359 1360 Status[] operationStatus = 1364 syncEngine.getModificationsStatusCommands(msgId); 1365 1366 for (int i=0; i<operationStatus.length; ++i) { 1367 responseCommands.add(operationStatus[i]); 1368 } 1369 } 1370 1371 1376 Database[] dbs = syncEngine.getDbs(); 1377 ItemizedCommand[] commands = null; 1378 String uri = null; 1379 for (int i = 0; (i < dbs.length); ++i) { 1380 if (AlertCode.isClientOnlyCode(dbs[i].getMethod())) { 1384 continue; 1385 } 1386 1387 uri = dbs[i].getName(); 1388 1389 SyncOperation[] operations = syncEngine.getSyncOperations(uri); 1390 commands = syncEngine.operationsToCommands(operations, uri, slow); 1391 Long noc = isNumberOfChangesSupported() 1392 ? new Long (commands.length) 1393 : null 1394 ; 1395 responseCommands.add( 1396 new Sync( 1397 cmdIdGenerator.next(), 1398 false, 1399 null, 1400 dbs[i].getTarget(), 1401 dbs[i].getSource(), 1402 null, 1403 noc, 1404 commands 1405 ) 1406 ); 1407 syncEngine.resetSyncOperations(uri); 1408 } 1410 syncEngine.updateServerMappings(slow); 1414 1415 return responseCommands; 1416 } 1417 1418 1425 private SyncMapping processMapMessage(SyncML message) 1426 throws ProtocolException { 1427 if (log.isLoggable(Level.INFO)) { 1428 log.info("Handling mapping ..."); 1429 } 1430 1431 try { 1432 SyncMapping mapping = new SyncMapping( 1433 message.getSyncHdr(), 1434 message.getSyncBody() 1435 ); 1436 1437 mapping.setIdGenerator(cmdIdGenerator); 1438 1439 if (log.isLoggable(Level.INFO)) { 1440 log.info("Performing mapping ..."); 1441 } 1442 1443 String uri = null; 1444 1445 sync4j.framework.core.Map[] mapCommands = mapping.getMapCommands(); 1446 MapItem[] mapItems = null ; 1447 for (int j=0; ((mapCommands != null) && (j<mapCommands.length)); ++j) { 1448 uri = mapCommands[j].getTarget().getLocURI(); 1449 mapItems = 1450 (MapItem[])mapCommands[j].getMapItems().toArray( 1451 new MapItem[0]); 1452 1453 for (int i = 0; i < mapItems.length; i++) { 1454 MapItem mapItem = mapItems[i]; 1455 1456 String guid = mapItem.getTarget().getLocURI(); 1458 String luid = mapItem.getSource().getLocURI(); 1459 syncEngine.updateMapping(uri, guid, luid); 1460 } 1461 } 1462 1463 return mapping; 1464 1465 } catch (Sync4jException e) { 1466 throw new ProtocolException(e); 1467 } 1468 } 1469 1470 1476 private void moveTo(int state) { 1477 if (log.isLoggable(Level.FINEST)) { 1478 log.finest("moving to state " + getStateName(state)); 1479 } 1480 currentState = state; 1481 } 1482 1483 1497 private void prepareMemorySources(Sync[] syncCommands, Status[] statusCommands) { 1498 1499 List sources = syncEngine.getClientSources(); 1500 1501 HashMap dbMap = new HashMap(); 1505 for (int i=0; ((syncEngine.getDbs() != null) && (i<syncEngine.getDbs().length)); ++i) { 1506 dbMap.put((syncEngine.getDbs())[i].getName(), (syncEngine.getDbs())[i]); 1507 } 1508 1509 int method; 1514 slow = false; 1515 Target target = null; 1516 MemorySyncSource mss = null; 1517 AbstractCommand[] modifications = null; 1518 for (int i = sources.size(); i > 0; --i) { 1519 if (log.isLoggable(Level.FINEST)) { 1520 log.finest("Preparing " 1521 + syncEngine.getClientSources().get(i - 1) 1522 + " with " 1523 + Arrays.asList(syncCommands) 1524 ); 1525 } 1526 1527 mss = (MemorySyncSource) sources.get(i - 1); 1528 1529 String uri = mss.getSourceURI(); 1530 1531 modifications = new AbstractCommand[0]; 1532 ArrayList alModifications = new ArrayList(); 1533 1534 for (int j = 0; ((syncCommands != null) && (j < syncCommands.length)); ++j) { 1538 target = syncCommands[j].getTarget(); 1539 if ((target != null) && (uri.equals(target.getLocURI()))) { 1540 if (syncCommands[j].getCommands() != null) { 1541 alModifications.addAll(syncCommands[j].getCommands()); 1542 } 1543 } 1544 } 1545 1546 modifications = (AbstractCommand[])alModifications.toArray(new AbstractCommand[0]); 1547 1548 method = ((Database)dbMap.get(uri)).getMethod(); 1549 slow = ((method == AlertCode.SLOW) || (method == AlertCode.REFRESH_FROM_SERVER)); 1550 1551 if (!slow) { 1552 String targetRef = null; 1553 String statusCode = null; 1554 ArrayList targetRefs = null; 1555 for (int k=0; statusCommands!=null && k<statusCommands.length; k++) { 1556 targetRefs = statusCommands[k].getTargetRef(); 1557 if (targetRefs == null || targetRefs.size() == 0) { 1558 continue; 1559 } 1560 targetRef = ((TargetRef)targetRefs.get(0)).getValue(); 1561 if ((targetRef != null) && (uri.equals(targetRef))) { 1562 statusCode = statusCommands[k].getData().getData(); 1563 if (statusCode.equals("" + StatusCode.REFRESH_REQUIRED)) { 1564 slow = true; 1565 ((Database)dbMap.get(uri)).setStatusCode(StatusCode.REFRESH_REQUIRED); 1566 } 1567 break; 1568 } 1569 } 1570 } 1571 1572 prepareMemorySource(mss, modifications, slow); 1573 } 1574 } 1575 1576 1588 private void prepareMemorySource(MemorySyncSource source , 1589 AbstractCommand[] commands, 1590 boolean slowSync) { 1591 ArrayList deleted = new ArrayList(); 1592 ArrayList created = new ArrayList(); 1593 ArrayList updated = new ArrayList(); 1594 1595 ClientMapping guidluid = null; 1596 1597 guidluid = (ClientMapping)syncEngine.getMapping( 1604 syncState.loggedPrincipal, 1605 source.getSourceURI(), 1606 slowSync 1607 ); 1608 1609 String name = null; 1610 for (int i = 0; ((commands != null) && (i < commands.length)); ++i) { 1611 if (commands[i] == null) { 1612 continue; 1613 } 1614 name = commands[i].getName(); 1615 if (slowSync && !Delete.COMMAND_NAME.equals(name)) { 1616 List items = Arrays.asList( 1617 syncEngine.itemsToSyncItems( 1618 source, 1619 (ModificationCommand)commands[i], 1620 SyncItemState.SYNCHRONIZED, 1621 nextTimestamp.start 1622 ) 1623 ); 1624 updated.addAll(items); 1625 1626 continue; 1627 } 1628 if (Add.COMMAND_NAME.equals(commands[i].getName())) { 1629 created.addAll( 1630 Arrays.asList( 1631 syncEngine.itemsToSyncItems( 1632 source, 1633 (ModificationCommand)commands[i], 1634 SyncItemState.NEW, 1635 nextTimestamp.start 1636 ) 1637 ) 1638 ); 1639 continue; 1640 } 1641 1642 if (Delete.COMMAND_NAME.equals(commands[i].getName())) { 1643 deleted.addAll( 1644 Arrays.asList( 1645 syncEngine.itemsToSyncItems( 1646 source, 1647 (ModificationCommand)commands[i], 1648 SyncItemState.DELETED, 1649 nextTimestamp.start 1650 ) 1651 ) 1652 ); 1653 continue; 1654 } 1655 1656 if (Replace.COMMAND_NAME.equals(commands[i].getName())) { 1657 updated.addAll( 1658 Arrays.asList( 1659 syncEngine.itemsToSyncItems( 1660 source, 1661 (ModificationCommand)commands[i], 1662 SyncItemState.UPDATED, 1663 nextTimestamp.start 1664 ) 1665 ) 1666 ); 1667 continue; 1668 } 1669 } 1670 1671 source.initialize(deleted, created, updated); 1672 1673 if (syncEngine.isLastMessage()) { 1674 source.setExistingItems(createItemsFromMapping(source)); 1675 } 1676 } 1677 1678 1685 private List statusForSyncs(Sync[] syncCommands) { 1686 ArrayList ret = new ArrayList(); 1687 1688 String uri = null; 1689 Target target = null; 1690 Source source = null; 1691 TargetRef targetRef = null; 1692 SourceRef sourceRef = null; 1693 int statusCode = StatusCode.OK; 1694 String statusMessage = ""; 1695 Item[] items = null; 1696 1697 for (int i = 0; ( (syncCommands != null ) 1698 && (i < syncCommands.length)); ++i) { 1699 1700 target = syncCommands[i].getTarget(); 1701 source = syncCommands[i].getSource(); 1702 1703 uri = (target==null) ? null : target.getLocURI(); 1707 if ((uri == null) || (syncEngine.getClientSource(uri) != null)) { 1708 statusCode = syncEngine.getClientSourceStatus(uri); 1709 statusMessage = syncEngine.getClientStatusMessage(uri); 1710 } else { 1711 statusCode = StatusCode.NOT_FOUND; 1712 statusMessage = null; 1713 } 1714 1715 targetRef = (target == null) ? null : new TargetRef(uri); 1716 1717 sourceRef = (source == null) ? null : new SourceRef(syncCommands[i].getSource()); 1718 1719 if (statusMessage != null) { 1724 items = new Item[] { 1725 new Item(null, null, null, new ComplexData(statusMessage), false) 1726 }; 1727 } else { 1728 items = new Item[0]; 1729 } 1730 1731 ret.add( 1732 new Status( 1733 cmdIdGenerator.next(), 1734 lastMsgIdFromClient, 1735 syncCommands[i].getCmdID().getCmdID(), 1736 syncCommands[i].COMMAND_NAME, 1737 targetRef, 1738 sourceRef, 1739 null, 1740 null, 1741 new Data(statusCode), 1742 items 1743 ) 1744 ); 1745 } 1747 return ret; 1748 } 1749 1750 1757 private boolean login(Cred credential, String deviceId) { 1758 logout(); 1762 1763 if (credential == null) { 1764 syncState.authenticationState = AUTH_MISSING_CREDENTIALS; 1765 return false; 1766 } 1767 1768 Sync4jPrincipal p = Sync4jPrincipal.fromCredential( 1769 credential.getData(), 1770 credential.getType(), 1771 deviceId 1772 ); 1773 Authentication auth = credential.getAuthentication(); 1774 auth.setDeviceId(deviceId); 1775 auth.setSyncMLVerProto(syncState.syncMLVerProto); 1776 NextNonce nn = new NextNonce(syncState.device.getClientNonce()); 1777 auth.setNextNonce(nn); 1778 1779 if (syncEngine.login(credential)) { 1780 if (clientAuth.equalsIgnoreCase(Cred.AUTH_TYPE_MD5)) { 1781 p.setUsername(credential.getAuthentication().getUsername()); 1782 } 1783 1784 p.setId(credential.getAuthentication().getPrincipalId()); 1788 1789 if (syncEngine.authorize(p, SecurityConstants.RESOURCE_SESSION)) { 1790 1791 syncState.loggedCredential = credential; 1792 syncState.loggedPrincipal = p ; 1793 1794 syncState.authenticationState = AUTH_AUTHENTICATED; 1795 1796 return true; 1797 } 1798 } 1799 return false; 1800 } 1801 1802 1805 private void logout() { 1806 if (isAuthenticated()) { 1807 syncEngine.logout(syncState.loggedCredential); 1808 } 1809 syncState.authenticationState = AUTH_INVALID_CREDENTIALS; 1810 syncState.loggedCredential = null; 1811 syncState.loggedPrincipal = null; 1812 } 1813 1814 1819 public void endSession() { 1820 commit(); 1821 logout(); 1822 } 1823 1824 private String getStateName(int state) { 1825 String stateName = "STATE_UNKNOWN"; 1826 1827 switch (state) { 1828 case STATE_START : stateName = "STATE_START" ; break; 1829 case STATE_END : stateName = "STATE_END" ; break; 1830 case STATE_PKG1_RECEIVING : stateName = "STATE_PKG1_RECEIVING" ; break; 1831 case STATE_PKG1_RECEIVED : stateName = "STATE_PKG1_RECEIVED" ; break; 1832 case STATE_PKG3_RECEIVING : stateName = "STATE_PKG3_RECEIVING" ; break; 1833 case STATE_PKG3_RECEIVED : stateName = "STATE_PKG3_RECEIVED" ; break; 1834 case STATE_ERROR : stateName = "STATE_ERROR" ; break; 1835 default : stateName = "STATE_UNKNOWN" ; break; 1836 } 1837 1838 return stateName; 1839 } 1840 1841 public SyncState getSyncState() { 1842 return this.syncState; 1843 } 1844 1845 1855 private void checkForReceivedLargeObject(Sync[] syncs) { 1856 if (log.isLoggable(Level.FINEST)) { 1857 log.finest("Checking if there are data to add to previous data"); 1858 } 1859 1860 Item lo = null; 1861 1862 if (syncState.receivedLargeObject != null) { 1863 Item item = 1864 ProtocolUtil.getSyncItem(syncs, syncState.receivedLargeObject); 1865 1866 if (item == null) { 1867 if (log.isLoggable(Level.WARNING)) { 1868 log.warning("The end of data for a chuncked objects has NOT been received!"); 1869 } 1870 1871 createAlert(AlertCode.NO_END_OF_DATA); 1872 1873 syncState.receivedLargeObject = null; 1874 syncState.sizeOfReceivedLargeObject = null; 1875 syncState.syncLocURI = null; 1876 syncState.itemLocURI = null; 1877 1878 return; 1879 } else { 1880 if (!item.isMoreData()) { 1881 syncState.receivedLargeObject = null; 1885 } 1886 } 1887 } 1888 1889 if (syncState.receivedLargeObject == null) { 1890 int i = 0; 1891 for (i=0; (lo == null) && (i<syncs.length); ++i) { 1892 lo = ProtocolUtil.getLargeObject(syncs[i].getCommands()); 1893 } 1894 1895 if (lo == null) { 1896 return; 1900 } 1901 1902 String loURI = (lo.getSource() != null) 1903 ? lo.getSource().getLocURI() 1904 : lo.getTarget().getLocURI() 1905 ; 1906 1907 syncState.receivedLargeObject = syncs[i-1].getTarget().getLocURI() 1908 + '/' 1909 + loURI 1910 ; 1911 return; 1912 } 1913 } 1914 1915 private void createAlert(int alertCode) { 1916 if (syncState.receivedLargeObject == null) { 1917 return; 1918 } 1919 1920 int p = syncState.receivedLargeObject.lastIndexOf('/'); 1921 1922 if (p<0) { 1923 return; 1924 } 1925 1926 String uri = syncState.receivedLargeObject.substring(p+1); 1927 1928 Item item = new Item(new Target(uri), null, null, null, false); 1929 ArrayList items = new ArrayList(1); 1930 items.add(item); 1931 1932 syncState.cmdCache3.add( 1933 new Alert( 1934 cmdIdGenerator.next(), 1935 false, 1936 null, 1937 alertCode, 1938 (Item[])(items.toArray(new Item[0])) 1939 ) 1940 ); 1941 } 1942 1943 1957 private AbstractCommand[] commandsToSend(SyncInitialization init, 1958 SyncModifications sync, 1959 SyncMapping map ) 1960 throws ProtocolException { 1961 1962 if (init != null) { 1966 syncState.cmdCache1.addAll(init.getResponseCommands(msgIdGenerator.current())); 1967 } 1968 1969 if (sync != null) { 1970 List commands = sync.getResponseCommands(msgIdGenerator.current()); 1971 List status = ProtocolUtil.filterCommands(commands, new String [] { Status.COMMAND_NAME }); 1972 syncState.cmdCache1.addAll(status); 1973 commands.removeAll(status); 1974 1975 syncState.cmdCache3.addAll(commands); 1976 ProtocolUtil.mergeSyncCommands(syncState.cmdCache3); 1981 } 1982 1983 if (map != null) { 1984 List commands = map.getResponseCommands(msgIdGenerator.current()); 1985 List status = ProtocolUtil.filterCommands(commands, new String [] { Status.COMMAND_NAME }); 1986 syncState.cmdCache1.addAll(status); 1987 commands.removeAll(status); 1988 syncState.cmdCache3.addAll(commands); 1989 } 1990 1991 ProtocolUtil.removeHeaderStatus(syncState.cmdCache1); 1992 1993 List cache = null; AbstractCommand[] allCmds = null; 1999 AbstractCommand[] statuses = null; 2000 AbstractCommand[] commands = null; 2001 2002 cache = new ArrayList(); 2003 2004 cache.addAll(syncState.cmdCache1); 2009 if (currentState == STATE_PKG3_RECEIVED) { 2010 cache.addAll(syncState.cmdCache3); 2011 } 2012 2013 allCmds = (AbstractCommand[]) 2014 cache.toArray(new AbstractCommand[cache.size()]); 2015 2016 ArrayList statusList = ProtocolUtil.filterCommands(allCmds, Status.class); 2017 ArrayList commandList = ProtocolUtil.inverseFilterCommands(allCmds, Status.class); 2018 2019 statuses = ProtocolUtil.sortStatusCommand(statusList); 2020 commands = 2021 (AbstractCommand[])commandList.toArray(new AbstractCommand[commandList.size()]); 2022 2023 checkSizeCapabilities(); 2028 2029 commandList = new ArrayList(); 2033 for (int i=0; i<statuses.length; ++i) { 2034 if (!checkSize(statuses[i])) { 2035 return (AbstractCommand[])commandList.toArray(new AbstractCommand[0]); 2036 } 2037 2038 messageSize += sizeCalculator.getCommandSize(statuses[i]); 2039 commandList.add(statuses[i]); 2040 syncState.cmdCache1.remove(statuses[i]); 2041 } 2042 2043 for (int i=0; i<commands.length; ++i) { 2044 if (!checkSize(commands[i])) { 2045 if (commands[i] instanceof Sync) { 2046 Sync s = splitSync((Sync)commands[i]); 2047 commandList.add(s); 2048 messageSize += sizeCalculator.getCommandSize(s); 2049 } 2050 2051 return (AbstractCommand[])commandList.toArray(new AbstractCommand[0]); 2052 } 2053 2054 messageSize += sizeCalculator.getCommandSize(commands[i]); 2055 commandList.add(commands[i]); 2056 syncState.cmdCache1.remove(commands[i]); 2057 syncState.cmdCache3.remove(commands[i]); 2058 } 2059 2060 return (AbstractCommand[])commandList.toArray(new AbstractCommand[0]); 2061 } 2062 2063 2073 private Sync splitSync(Sync cmd) { 2074 ArrayList commands = cmd.getCommands(); 2075 2076 boolean lo = isLargeObjectSupported(); 2083 if (lo && (syncState.maxObjSize > 0)) { 2084 removeTooBigCommands(commands, syncState.maxObjSize); 2085 } else if (!lo) { 2086 removeTooBigCommands(commands, syncState.maxMsgSize - sizeCalculator.getMsgSizeOverhead()); 2087 } 2088 2089 Sync newSync = new Sync( cmdIdGenerator.next(), 2090 cmd.isNoResp(), 2091 cmd.getCred(), 2092 cmd.getTarget(), 2093 cmd.getSource(), 2094 cmd.getMeta(), 2095 null, 2096 new AbstractCommand[0]); 2097 2098 ArrayList newCommands = new ArrayList(); 2099 2100 long syncSize = sizeCalculator.getCommandSize(newSync); 2101 long tmpMessageSize = messageSize; 2102 2103 int howManyCommands = commands.size(); 2104 2105 Iterator i = commands.iterator(); 2106 while (i.hasNext()) { 2107 AbstractCommand c = (AbstractCommand)i.next(); 2108 2109 if (!checkSize(syncSize + sizeCalculator.getCommandSize(c), tmpMessageSize)) { 2110 break; 2111 } 2112 2113 newCommands.add(c); 2114 tmpMessageSize += sizeCalculator.getCommandSize(c); 2115 } 2116 2117 commands.removeAll(newCommands); 2118 2119 if (lo && (howManyCommands > 0) && (howManyCommands == commands.size())) { 2124 ItemizedCommand c = (ItemizedCommand)commands.get(0); 2125 newCommands.add(nextLOChunk(cmd, c, tmpMessageSize)); 2126 if (((Item)c.getItems().get(0)).getData().getData().length() == 0) { 2127 commands.remove(c); 2128 } 2129 } 2130 2131 if (cmd.getNumberOfChanges() != null) { 2135 cmd.setNumberOfChanges(new Long (commands.size())); 2136 newSync.setNumberOfChanges(new Long (newCommands.size())); 2137 } 2138 2139 newSync.setCommands((AbstractCommand[])newCommands.toArray(new AbstractCommand[0])); 2140 2141 return newSync; 2142 } 2143 2144 2151 private boolean isLastMessage() { 2152 return ((currentState == STATE_PKG1_RECEIVED) && (syncState.cmdCache1.size() == 0)) 2153 || ((currentState == STATE_PKG3_RECEIVED) && (syncState.cmdCache3.size() == 0)) 2154 ; 2155 } 2156 2157 2162 private void processClientCapabilities(DevInf devInfo) { 2163 if (devInfo != null) { 2164 syncState.devInf = devInfo; 2165 } 2166 } 2167 2168 2174 private void removeTooBigCommands(List commands, long size) { 2175 ArrayList remove = new ArrayList(); 2176 2177 Iterator i = commands.iterator(); 2178 while(i.hasNext()) { 2179 ItemizedCommand c = (ItemizedCommand)i.next(); 2180 Item item = (Item)c.getItems().get(0); 2181 Data d = item.getData(); 2182 if ((d != null) && (d.getData().length() > size)) { 2183 if (log.isLoggable(Level.WARNING)) { 2184 log.warning( "Item " 2185 + item.getSource().getLocURI() 2186 + " is bigger than the maximum allowed size (" 2187 + size 2188 + "). It is removed from the list of commands to send." 2189 ); 2190 } 2191 remove.add(c); 2192 } 2193 } 2194 commands.removeAll(remove); 2195 } 2196 2197 2209 private ItemizedCommand nextLOChunk(Sync sync, ItemizedCommand cmd, long msgSize) { 2210 if (!(cmd instanceof Add) && !(cmd instanceof Replace)) { 2211 return null; 2215 } 2216 2217 Item item = (Item)cmd.getItems().get(0); 2218 2219 Data data = item.getData(); 2220 String dataValue = data.getData(); 2221 int dataLength = dataValue.length(); 2222 2223 ItemizedCommand chunk = null; 2224 2225 Item chunkItem = new Item(item.getTarget() , 2226 item.getSource() , 2227 null , 2228 new ComplexData(""), 2229 false ); 2230 2231 String chunkURI = null; 2232 if (cmd instanceof Add) { 2233 chunk = new Add(cmd.getCmdID() , 2234 cmd.isNoResp() , 2235 cmd.getCred() , 2236 cmd.getMeta() , 2237 new Item[] { chunkItem }); 2238 chunkURI = chunkItem.getSource().getLocURI(); 2239 } else if (cmd instanceof Replace) { 2240 chunk = new Replace(cmd.getCmdID() , 2241 cmd.isNoResp() , 2242 cmd.getCred() , 2243 cmd.getMeta() , 2244 new Item[] { chunkItem }); 2245 chunkURI = chunkItem.getTarget().getLocURI(); 2246 } 2247 2248 String loURI = sync.getSource().getLocURI() 2249 + '/' 2250 + chunkURI 2251 ; 2252 if (!loURI.equals(syncState.sendingLOURI)) { 2253 Meta m = cmd.getMeta(); 2254 if (m == null) { 2255 m = new Meta(); 2256 } 2257 2258 Meta chunkMeta = new Meta(); 2259 chunkMeta.setType(m.getType()); 2260 chunkMeta.setSize(new Long (dataLength)); 2261 2262 chunk.setMeta(chunkMeta); 2263 2264 syncState.sendingLOURI = loURI; 2265 } else { 2266 chunk.setMeta(null); 2267 } 2268 2269 int chunkLength = 2273 (int)(syncState.maxMsgSize - (msgSize + sizeCalculator.getMsgSizeOverhead())); 2274 if (dataLength < chunkLength) { 2275 chunkItem.getData().setData(dataValue); 2276 chunkItem.setMoreData(Boolean.FALSE); 2277 item.getData().setData(""); 2278 } else { 2279 chunkItem.getData().setData(dataValue.substring(0, chunkLength)); 2280 chunkItem.setMoreData(Boolean.TRUE); 2281 item.getData().setData(dataValue.substring(chunkLength)); 2282 } 2283 2284 return chunk; 2285 } 2286 2287 2293 private boolean isLargeObjectSupported() { 2294 return 2295 (syncState.maxObjSize > 0) 2296 || 2297 ((syncState.devInf != null) && syncState.devInf.isSupportLargeObjs()) 2298 || 2299 syncState.device.getCapabilities().isSupportLargeObject() 2300 ; 2301 } 2302 2303 2309 private boolean isNumberOfChangesSupported() { 2310 if (syncState.devInf != null) { 2311 return syncState.devInf.isSupportNumberOfChanges(); 2312 } 2313 2314 return syncState.device.getCapabilities().isSupportNumberOfChanges(); 2315 } 2316 2317 2324 private List createItemsFromMapping(SyncSource source) { 2325 ClientMapping m = syncEngine.getMapping(source.getSourceURI()); 2326 2327 ArrayList items = new ArrayList(); 2328 2329 if (m == null) { 2330 if (log.isLoggable(Level.SEVERE)) { 2331 log.severe( "Client mapping not found for " 2332 + source.getSourceURI() 2333 + '!' 2334 ); 2335 return items; 2336 } 2337 } 2338 2339 java.util.Map map = m.getMapping(); 2340 2341 Iterator i = map.keySet().iterator(); 2342 Object key = null; 2343 while (i.hasNext()) { 2344 key = i.next(); 2345 items.add( 2346 new SyncItemImpl(source, key, map.get(key), SyncItemState.SYNCHRONIZED) 2347 ); 2348 } 2349 2350 return items; 2351 } 2352} 2353 | Popular Tags |