1 19 20 package sync4j.server.session; 21 22 import java.util.*; 23 import java.util.logging.Level ; 24 import java.util.logging.Logger ; 25 26 import sync4j.framework.config.Configuration; 27 import sync4j.framework.config.ConfigurationConstants; 28 import sync4j.framework.core.*; 29 import sync4j.framework.engine.dm.DeviceDMState; 30 import sync4j.framework.engine.dm.ManagementException; 31 import sync4j.framework.engine.dm.ManagementProcessor; 32 import sync4j.framework.engine.dm.Util; 33 import sync4j.framework.logging.Sync4jLogger; 34 import sync4j.framework.logging.Sync4jLoggerName; 35 import sync4j.framework.protocol.*; 36 import sync4j.framework.security.Officer; 37 import sync4j.framework.security.SecurityConstants; 38 import sync4j.framework.security.Sync4jPrincipal; 39 import sync4j.framework.server.Sync4jDevice; 40 import sync4j.framework.server.SyncTimestamp; 41 import sync4j.framework.server.dm.ProcessorSelector; 42 import sync4j.framework.server.error.InvalidCredentialsException; 43 import sync4j.framework.server.error.ServerException; 44 import sync4j.framework.server.error.ServerFailureException; 45 import sync4j.framework.server.session.ManagementState; 46 import sync4j.framework.server.session.SessionHandler; 47 import sync4j.framework.server.store.NotFoundException; 48 import sync4j.framework.server.store.PersistentStoreException; 49 import sync4j.framework.tools.Base64; 50 import sync4j.framework.tools.SimpleIdGenerator; 51 import sync4j.framework.tools.SizeCalculator; 52 53 import sync4j.server.engine.dm.ManagementEngine; 54 55 76 public class ManagementSessionHandler 77 implements SessionHandler, java.io.Serializable , 78 SecurityConstants, ConfigurationConstants { 79 80 82 public static final int STATE_INITIALIZATION_PROCESSING = 0x0010; 87 public static final int STATE_INITIALIZATION_PROCESSED = 0x0011; 88 public static final int STATE_MANAGEMENT_PROCESSING = 0x0012; 89 public static final int STATE_MANAGEMENT_PROCESSED = 0x0013; 90 public static final int STATE_MANAGEMENT_COMPLETION = 0x0014; 91 public static final int STATE_CLIENT_UNAUTHORIZED = 0x0016; 92 93 94 public static final int STATE_WAITING_MORE_MSG = 0x0015; 101 102 private static final String [] MANAGEMENT_COMMANDS 104 = {"Add", "Alert", "Copy", "Delete", "Exec" ,"Get", "Replace", "Atomic", "Sequence"}; 105 106 110 private static final double TOLLERANCE_MAX_MSG_SIZE = 0.85d; 111 112 113 115 private int currentState = STATE_START; 116 117 122 public int getCurrentState() { 123 return currentState; 124 } 125 126 private long creationTimestamp = -1; 127 128 133 public long getCreationTimestamp() { 134 return creationTimestamp; 135 } 136 137 private transient Logger log = 138 Sync4jLogger.getLogger(Sync4jLoggerName.HANDLER); 139 140 private transient ManagementInitialization init = null; 141 private transient ManagementActions actions = null; 142 143 146 private ManagementState sessionState = null; 147 148 151 private ManagementProcessor processor = null; 152 153 156 private String serverAuthType = null; 157 158 161 private String supportedAuthType = null; 162 163 166 private String clientAuthType = null; 167 168 171 private ManagementEngine engine = null; 172 173 176 private String mimeType = null; 177 178 181 public void setMimeType(String mimeType) { 182 this.mimeType = mimeType; 183 } 184 185 188 private boolean newSession = true; 192 193 197 private ArrayList addStatus = null; 198 private ArrayList addAbsCmd = null; 199 200 203 private long maxSizeAvailable = 0; 204 205 206 208 213 public String getSessionId() { 214 return sessionState.getSessionId(); 215 } 216 217 222 public Sync4jDevice getDevice() { 223 return sessionState.device; 224 } 225 226 227 231 private void resetIdGenerator() { 232 engine.getCommandIdGenerator().reset(); 233 } 234 235 238 private SimpleIdGenerator msgIdGenerator = new SimpleIdGenerator(); 239 240 242 245 public ManagementSessionHandler() { 246 creationTimestamp = System.currentTimeMillis(); 247 init(); 248 } 249 250 255 public ManagementSessionHandler(String sessionId) { 256 this(); 257 sessionState.sessionId = sessionId; 258 } 259 260 262 267 public void setNew(boolean newSession) { 268 this.newSession = newSession; 269 } 270 271 276 public boolean isNew() { 277 return this.newSession; 278 } 279 280 285 public boolean isAuthenticated() { 286 return sessionState.authenticationState == AUTH_AUTHENTICATED; 287 } 288 289 301 public SyncML processMessage(SyncML message) 302 throws ProtocolException, InvalidCredentialsException, ServerFailureException { 303 String deviceId = null; 304 SyncML response = null; 305 306 resetIdGenerator(); 310 311 msgIdGenerator.next(); 315 316 sessionState.lastMsgIdFromClient = message.getSyncHdr().getMsgID(); 320 321 deviceId = message.getSyncHdr().getSource().getLocURI(); 325 326 if (log.isLoggable(Level.FINE)) { 327 log.fine("device id: " + deviceId); 328 log.fine("current state: " + getStateName(currentState)); 329 } 330 Meta meta = message.getSyncHdr().getMeta(); 334 if (meta != null) { 335 Long maxMsgSize = meta.getMaxMsgSize(); 336 if (maxMsgSize != null) { 337 sessionState.setMaxMsgSize(maxMsgSize.longValue()); 338 } 339 340 Long maxObjSize = meta.getMaxObjSize(); 341 if (maxObjSize != null) { 342 sessionState.setMaxObjSize(maxObjSize.longValue()); 343 } 344 } 345 346 try { 347 switch (currentState) { 348 case STATE_ERROR: case STATE_END: 350 case STATE_START: 351 case STATE_CLIENT_UNAUTHORIZED: 352 sessionState.reset(); 353 354 sessionState.nextTimestamp = new SyncTimestamp( 355 System.currentTimeMillis() 356 ); 357 358 sessionState.device = new Sync4jDevice(deviceId); 363 engine.readDevice(sessionState.device); 364 365 sessionState.syncMLVerProto = 366 message.getSyncHdr().getVerProto().getVersion(); 367 this.engine.setSyncMLVerProto(sessionState.syncMLVerProto); 368 369 if (currentState != STATE_CLIENT_UNAUTHORIZED) { 370 moveTo(STATE_INITIALIZATION_PROCESSING); 371 } 372 case STATE_INITIALIZATION_PROCESSING: 373 if (!isAuthenticated()) { 377 378 Cred cred = message.getSyncHdr().getCred(); 383 if (!checkAuthType(cred)) { 384 sessionState.loggedCredential = null; 389 } else { 390 login(cred, deviceId); 391 392 if (isAuthenticated()) { 393 try { 394 engine.readPrincipal(sessionState.loggedPrincipal); 395 } catch (NotFoundException e) { 396 if (log.isLoggable(Level.INFO)) { 397 log.info("Authenticated principal not found: " + sessionState.loggedPrincipal); 398 } 399 sessionState.authenticationState = AUTH_INVALID_CREDENTIALS; 400 sessionState.loggedCredential = null; 401 } 402 } 403 } 404 } 405 406 boolean clientAuthenticated = isAuthenticated(); 407 boolean chalNotRequired = false; 408 409 if (!clientAuthenticated && (currentState == STATE_CLIENT_UNAUTHORIZED)) { 410 chalNotRequired = true; 415 } 416 417 response = processInitMessage(message, chalNotRequired); 418 419 if (!clientAuthenticated) { 420 if (currentState == STATE_CLIENT_UNAUTHORIZED) { 421 response.setLastMessage(true); 422 moveTo(STATE_ERROR); 423 } else { 424 moveTo(STATE_CLIENT_UNAUTHORIZED); 425 } 426 break; 427 } 428 429 if (message.getSyncBody().isFinalMsg()) { 430 moveTo(STATE_INITIALIZATION_PROCESSED); 431 } else { 432 break; 433 } 434 435 case STATE_INITIALIZATION_PROCESSED: 436 checkServerAuthentication(message); 442 443 if ( (sessionState.started == false) || 444 ( 445 (sessionState.serverAuthenticationState != AUTH_AUTHENTICATED) && 446 (sessionState.serverAuthenticationState != AUTH_ACCEPTED) 447 ) 448 ) { 449 init.setFlag(Flags.FLAG_FINAL_MESSAGE); 450 451 if (addAbsCmd != null) { 461 if (sessionState.getSplittedCommand() != null) { 462 if (addAbsCmd.contains(sessionState.getSplittedCommand())) { 463 mergeData(); 464 sessionState.setSplittedCommand(null); 465 sessionState.setNextDataToSend(null); 466 } 467 } 468 sessionState.addCmdOut(0, addAbsCmd); 469 } 470 471 AbstractCommand[] allClientCommands = 473 (AbstractCommand[])(message.getSyncBody()).getCommands().toArray( 474 new AbstractCommand[0]); 475 476 init.addClientCommand(allClientCommands); 477 478 response = startManagementSession(message); 479 480 if (init.isSessionAbortRequired()) { 481 483 if (log.isLoggable(Level.INFO)) { 484 log.info("Session aborted by client"); 485 } 486 487 response.setLastMessage(true); 488 sessionState.nextTimestamp.end = System.currentTimeMillis(); 489 sessionState.dmstate.state = DeviceDMState.STATE_ABORTED; 490 endSession(); 491 moveTo(STATE_SESSION_ABORTED); 492 break; 493 } 494 495 sessionState.started = true; 496 497 if (ProtocolUtil.noMoreResponse(response)) { 498 moveTo(STATE_MANAGEMENT_COMPLETION); 499 sessionState.nextTimestamp.end = System.currentTimeMillis(); 500 endSession(); 501 moveTo(STATE_END); 502 } 503 break; 504 } else { 505 moveTo(STATE_MANAGEMENT_PROCESSING); 506 } 507 508 case STATE_MANAGEMENT_PROCESSING: 509 510 response = processManagementMessage(message); 511 512 if (actions.isSessionAbortRequired()) { 513 515 if (log.isLoggable(Level.INFO)) { 516 log.info("Session aborted by client"); 517 } 518 519 response.setLastMessage(true); 520 sessionState.nextTimestamp.end = System.currentTimeMillis(); 521 sessionState.dmstate.state = DeviceDMState.STATE_ABORTED; 522 endSession(); 523 moveTo(STATE_SESSION_ABORTED); 524 525 break; 526 } 527 528 if (ProtocolUtil.noMoreResponse(response)) { 529 moveTo(STATE_MANAGEMENT_PROCESSED); 530 moveTo(STATE_MANAGEMENT_COMPLETION); 531 } else { 532 break; 533 } 534 535 case STATE_MANAGEMENT_COMPLETION: 536 sessionState.nextTimestamp.end = System.currentTimeMillis(); 537 538 response.setLastMessage(true); 539 540 endSession(); 541 542 moveTo(STATE_END); 543 break; 544 545 default: 546 endSession(); 547 throw new ProtocolException( "Illegal state: " 548 + getStateName(currentState) 549 + '(' 550 + currentState 551 + ')' 552 ); 553 } 554 } catch (ProtocolException e) { 555 if (sessionState.dmstate != null) { 556 sessionState.dmstate.state = DeviceDMState.STATE_ERROR; 557 } 558 endSession(); 559 log.throwing(getClass().getName(), "processMessage", e); 560 moveTo(STATE_ERROR); 561 throw e; 562 } catch (NotFoundException e) { 563 if (sessionState.dmstate != null) { 564 sessionState.dmstate.state = DeviceDMState.STATE_ERROR; 565 } 566 endSession(); 567 log.throwing(getClass().getName(), "processMessage", e); 568 moveTo(STATE_ERROR); 569 throw new InvalidCredentialsException("Invalid credential error", e); 570 } catch (PersistentStoreException e) { 571 if (sessionState.dmstate != null) { 572 sessionState.dmstate.state = DeviceDMState.STATE_ERROR; 573 } 574 endSession(); 575 log.throwing(getClass().getName(), "processMessage", e); 576 moveTo(STATE_ERROR); 577 throw new ServerFailureException("Persistent store error", e); 578 } catch (ManagementException e) { 579 if (sessionState.dmstate != null) { 580 sessionState.dmstate.state = DeviceDMState.STATE_ERROR; 581 } 582 endSession(); 583 log.throwing(getClass().getName(), "processMessage", e); 584 moveTo(STATE_ERROR); 585 throw new ServerFailureException("Management error", e); 586 } catch (Throwable t) { 587 if (sessionState.dmstate != null) { 588 sessionState.dmstate.state = DeviceDMState.STATE_ERROR; 589 } 590 endSession(); 591 log.throwing(getClass().getName(), "processMessage", t); 592 moveTo(STATE_ERROR); 593 } 594 595 List commands = response.getSyncBody().getCommands(); 596 ProtocolUtil.updateCmdId(commands); 597 return response; 598 } 599 600 616 public SyncML processError(SyncML msg, Throwable error) 617 throws Sync4jException { 618 SyncHdr msgHeader = msg.getSyncHdr(); 619 620 int status = StatusCode.SERVER_FAILURE; 621 622 if (error instanceof ServerException) { 623 status = ((ServerException)error).getStatusCode(); 624 } 625 626 Item item = new Item( 627 new Target(msgHeader.getSource().getLocURI()), 628 new Source(msgHeader.getTarget().getLocURI()), 629 null , 630 new ComplexData(error.getMessage()) , 631 false 632 ); 633 634 Status statusCommand = new Status( 635 engine.getCommandIdGenerator().next(), 636 msgHeader.getMsgID() , 637 "0" , 638 "SyncHdr" , 639 new TargetRef(msgHeader.getTarget()) , 640 new SourceRef(msgHeader.getSource()) , 641 null , 642 null , 643 new Data(status) , 644 new Item[] { item } 645 ); 646 647 String serverURI = 648 Configuration.getConfiguration().getStringValue(CFG_SERVER_URI); 649 SyncHdr syncHeader = new SyncHdr ( 650 msgHeader.getVerDTD() , 651 msgHeader.getVerProto() , 652 msgHeader.getSessionID() , 653 msgIdGenerator.current() , 654 new Target(msgHeader.getSource().getLocURI()), 655 new Source(serverURI) , 656 null , 657 false , 658 null , 659 null 660 ); 661 662 SyncBody syncBody = new SyncBody( 663 new AbstractCommand[] { statusCommand }, 664 true 665 ); 666 667 moveTo(STATE_ERROR); 668 669 return new SyncML(syncHeader, syncBody); 670 } 671 672 676 677 public void expire() { 678 logout(); 679 } 680 681 692 public void abort(int statusCode) { 693 if (statusCode != StatusCode.SESSION_ABORTED) { 694 moveTo(STATE_ERROR); 695 } 696 } 697 698 703 public void endSession() { 704 logout(); 705 706 if (sessionState.dmstate != null) { 707 708 switch (sessionState.dmstate.state) { 709 710 case DeviceDMState.STATE_COMPLETED: 711 712 engine.deleteDeviceDMState(sessionState.dmstate); 713 try { 714 processor.endSession(DeviceDMState.STATE_COMPLETED); 715 } catch (ManagementException e) { 716 if (log.isLoggable(Level.SEVERE)) { 717 log.severe("Error calling endSession: " + e.getMessage()); 718 } 719 log.throwing("ManagementSessionHandler", "endSession", e); 720 } 721 break; 722 723 case DeviceDMState.STATE_ABORTED: 724 725 try { 726 processor.endSession(DeviceDMState.STATE_ABORTED); 727 } catch (ManagementException e) { 728 if (log.isLoggable(Level.SEVERE)) { 729 log.severe("Error calling endSession: " + e.getMessage()); 730 } 731 log.throwing("ManagementSessionHandler", "endSession", e); 732 } 733 734 default: 735 sessionState.dmstate.end = new Date(sessionState.nextTimestamp.end); 736 engine.storeDeviceDMState(sessionState.dmstate); 737 } 738 739 } 740 } 741 742 749 public void commit() { 750 sessionState.dmstate.end = new Date(System.currentTimeMillis()); 751 752 if (log.isLoggable(Level.FINE)) { 753 log.fine("Committing state: " + sessionState.dmstate); 754 } 755 756 engine.storeDeviceDMState(sessionState.dmstate); 757 } 758 759 761 764 private void init() { 765 sessionState = new ManagementState(); 766 767 engine = new ManagementEngine(Configuration.getConfiguration()); 768 } 769 770 780 private SyncML processInitMessage(SyncML request, boolean chalNotRequired) 781 throws ProtocolException, ManagementException { 782 792 SyncBody syncBody = request.getSyncBody(); 793 ArrayList allClientCommands = syncBody.getCommands(); 794 List replaceCommands = ProtocolUtil.filterCommands(allClientCommands, new String [] {"Replace"}); 795 796 if (replaceCommands.size() == 0) { 797 if (sessionState.devInfReplaceCommand != null) { 798 allClientCommands.add(sessionState.devInfReplaceCommand); 799 syncBody.setCommands((AbstractCommand[])allClientCommands.toArray(new AbstractCommand[0])); 800 } 801 } else { 802 sessionState.devInfReplaceCommand = (Replace)replaceCommands.get(0); 803 } 804 805 init = new ManagementInitialization(request.getSyncHdr(), 806 request.getSyncBody()); 807 808 init.setIdGenerator(engine.getCommandIdGenerator()); 809 810 init.setServerAuthType(serverAuthType); 815 816 init.setSupportedAuthType(supportedAuthType); 817 818 init.setClientAuthType(clientAuthType); 819 820 if (request.getSyncBody().isFinalMsg()) { 821 init.setFlag(Flags.FLAG_FINAL_MESSAGE); 822 } else { 823 init.unsetFlag(Flags.FLAG_FINAL_MESSAGE); 824 } 825 826 if (clientAuthType != null && !chalNotRequired) { 831 if (clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_MD5) || 832 clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_HMAC)) { 833 834 NextNonce nonce = ProtocolUtil.generateNextNonce(); 835 sessionState.device.setClientNonce(nonce.getValue()); 836 init.setNextNonce(nonce); 837 engine.storeDevice(sessionState.device); 838 839 } 840 841 } 842 843 if (!isAuthenticated()) { 844 845 switch (sessionState.authenticationState) { 846 case AUTH_MISSING_CREDENTIALS: 847 init.setAuthorizedStatusCode(StatusCode.MISSING_CREDENTIALS); 848 849 852 if (serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_MD5) || 853 serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_HMAC)) { 854 if (!chalNotRequired) { 855 NextNonce nonce = ProtocolUtil.generateNextNonce(); 856 sessionState.device.setClientNonce(nonce.getValue()); 857 init.setNextNonce(nonce); 858 engine.storeDevice(sessionState.device); 859 } 860 } 861 862 break; 863 case AUTH_INVALID_CREDENTIALS: 864 init.setAuthorizedStatusCode(StatusCode.INVALID_CREDENTIALS); 865 866 869 if (serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_MD5) || 870 serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_HMAC)) { 871 if (!chalNotRequired) { 872 NextNonce nonce = ProtocolUtil.generateNextNonce(); 873 sessionState.device.setClientNonce(nonce.getValue()); 874 init.setNextNonce(nonce); 875 engine.storeDevice(sessionState.device); 876 } 877 } 878 879 break; 880 default: 881 init.setAuthorizedStatusCode(StatusCode.FORBIDDEN); 882 } 883 } else { 884 if (Constants.AUTH_TYPE_HMAC.equalsIgnoreCase(clientAuthType)) { 885 init.setAuthorizedStatusCode(StatusCode.OK); 889 } else { 890 init.setAuthorizedStatusCode(StatusCode.AUTHENTICATION_ACCEPTED); 891 } 892 Alert alert = init.getClientAlert(); 896 897 if (alert != null) { 898 sessionState.type = alert.getData(); 899 } 900 } 901 902 if (sessionState.serverAuthenticationState != AUTH_ACCEPTED) { 906 init.setServerCredentials( 907 engine.getServerCredentials(getChal(request), sessionState.device) 908 ); 909 } 910 if (chalNotRequired) { 911 init.setFlag(Flags.FLAG_CHAL_NOT_REQUIRED); 912 } else { 913 init.unsetFlag(Flags.FLAG_CHAL_NOT_REQUIRED); 914 } 915 SyncML response = init.getResponse(msgIdGenerator.current()); 916 917 return response; 918 } 919 920 929 private SyncML processManagementMessage(SyncML request) throws ProtocolException, 930 ManagementException { 931 932 storeServerNonce(ProtocolUtil.getStatusChal(request)); 936 937 actions = new ManagementActions(request.getSyncHdr(), 938 request.getSyncBody()); 939 940 actions.setClientAuthType(clientAuthType); 941 actions.setIdGenerator(engine.getCommandIdGenerator()); 942 943 boolean serverAbortRequired = false; 948 949 if (Constants.AUTH_TYPE_HMAC.equalsIgnoreCase(serverAuthType)) { 950 Chal chal = getMessageChal(request); 954 if (chal == null) { 955 if (log.isLoggable(Level.FINEST)) { 959 log.finest("Server abort the session because the client has not sent the next nonce"); 960 } 961 962 serverAbortRequired = true; 963 } 964 } 965 966 Cred clientCred = null; 971 if (Constants.AUTH_TYPE_HMAC.equalsIgnoreCase(clientAuthType)) { 972 NextNonce nonce = ProtocolUtil.generateNextNonce(); 976 sessionState.device.setClientNonce(nonce.getValue()); 977 actions.setNextNonce(nonce); 978 engine.storeDevice(sessionState.device); 979 980 clientCred = request.getSyncHdr().getCred(); 984 Officer officer = engine.getOfficer(); 985 986 if (!officer.authenticate(clientCred)) { 987 988 if (log.isLoggable(Level.FINEST)) { 989 log.finest("Server abort the session because the credential sent by the client is not valid"); 990 } 991 992 serverAbortRequired = true; 993 } 994 } 995 996 997 if (serverAbortRequired) { 998 if (sessionState.serverAuthenticationState != AUTH_ACCEPTED) { 1005 actions.setServerCredentials( 1006 engine.getServerCredentials(getChal(request), sessionState.device) 1007 ); 1008 } 1009 actions.setFlag(Flags.FLAG_SERVER_ABORT_REQUIRED); 1010 actions.setFlag(Flags.FLAG_FINAL_MESSAGE); 1011 1012 sessionState.nextTimestamp.end = System.currentTimeMillis(); 1013 sessionState.dmstate.state = DeviceDMState.STATE_ABORTED; 1014 endSession(); 1015 moveTo(STATE_SESSION_ABORTED); 1016 SyncML response = actions.getResponse(msgIdGenerator.current()); 1017 response.setLastMessage(true); 1018 return response; 1019 1020 } 1021 1022 boolean alertCode1222sentFromTheClient = false; 1023 boolean alertCode1222requiredFromTheClient = false; 1024 1025 List commandToCache = ProtocolUtil.filterCommands( 1030 request.getSyncBody().getCommands(), 1031 new String []{ Status.COMMAND_NAME, Results.COMMAND_NAME } 1032 ); 1033 1034 checkForReceivedLargeObject(commandToCache); 1035 1036 sessionState.addClientCommands((AbstractCommand[])commandToCache.toArray(new AbstractCommand[0])); 1037 1038 if (!request.getSyncBody().isFinalMsg()) { 1043 1044 Alert alert = ProtocolUtil.searchAlertCommand(request.getSyncBody(), AlertCode.MORE_DATA); 1050 if (alert != null) { 1051 alertCode1222sentFromTheClient = true; 1055 } else { 1056 actions.setFlag(Flags.FLAG_MORE_MSG_REQUIRED); 1060 alertCode1222requiredFromTheClient = true; 1061 1062 Item itemWithLargeObject = ProtocolUtil.getLargeObject(commandToCache); 1063 1064 if (itemWithLargeObject != null) { 1065 sessionState.setReceivedLargeObject(itemWithLargeObject.getData().getData()); 1066 Long size = sync4j.framework.core.Util.getItemSize(itemWithLargeObject); 1067 if (size != null) { 1068 sessionState.setSizeOfReceivedLargeObject(size); 1069 } else { 1070 if (sessionState.getSizeOfReceivedLargeObject() == null) { 1071 sessionState.setSizeOfReceivedLargeObject(new Long (-1)); 1074 } 1075 } 1076 } else { 1077 sessionState.setReceivedLargeObject(null); 1082 sessionState.setSizeOfReceivedLargeObject(null); 1083 } 1084 } 1085 1086 } else { 1087 actions.setFlag(Flags.FLAG_FINAL_MESSAGE); 1088 actions.setClientCommands(sessionState.getClientCommands()); 1092 if (sessionState.getCmdOut() == null || sessionState.getCmdOut().size() == 0) { 1096 processor.setOperationResults( 1103 Util.operationResults( 1104 actions.getClientCommands(), String.valueOf(StatusCode.CHUNKED_ITEM_ACCEPTED)) 1105 ); 1106 sessionState.clearClientCommands(); 1107 } 1108 1109 sessionState.setReceivedLargeObject(null); 1112 } 1113 1114 actions.setFlag(Flags.FLAG_ALL_RESPONSES_REQUIRED); 1115 1116 if (!actions.isSessionAbortRequired() && !alertCode1222requiredFromTheClient && !alertCode1222sentFromTheClient) { 1121 LinkedList commandInCache = sessionState.getCmdOut(); 1125 if (log.isLoggable(Level.FINER)) { 1126 log.finer("command in cache: " + commandInCache.size()); 1127 } 1128 if (commandInCache.size() != 0) { 1129 AbstractCommand[] newCommands = (AbstractCommand[])commandInCache.toArray(new 1130 AbstractCommand[] {}); 1131 actions.setManagementCommands(newCommands); 1132 sessionState.removeCmdOut(commandInCache); 1136 if (log.isLoggable(Level.FINER)) { 1137 log.finer("Num. of managementCommands in actions: " + 1138 actions.getManagementCommands().length); 1139 } 1140 } else { 1141 if (log.isLoggable(Level.FINER)) { 1145 log.finer("Call getNextOperations for new operation"); 1146 } 1147 1148 actions.setManagementCommands( 1149 Util.managementOperations2commands( 1150 processor.getNextOperations(), 1151 engine.getCommandIdGenerator() 1152 ) 1153 ); 1154 } 1155 } else if (alertCode1222sentFromTheClient) { 1156 AbstractCommand previousCommand = sessionState.getSplittedCommand(); 1161 1162 if (previousCommand == null) { 1163 throw new ProtocolException("No more data to send"); 1164 } 1165 Item item = (Item)((ItemizedCommand)previousCommand).getItems().get(0); 1171 item.getData().setData(sessionState.getNextDataToSend()); 1172 1173 Meta meta = item.getMeta(); 1178 if (meta != null) { 1179 meta.setSize(null); 1180 } 1181 1182 item.setMoreData(Boolean.FALSE); 1184 1185 LinkedList commandInCache = sessionState.getCmdOut(); 1186 1187 commandInCache.addFirst(previousCommand); 1191 1192 AbstractCommand[] newCommands = (AbstractCommand[])commandInCache.toArray(new 1193 AbstractCommand[] {}); 1194 actions.setManagementCommands(newCommands); 1195 } 1196 1197 if (sessionState.serverAuthenticationState != AUTH_ACCEPTED) { 1201 actions.setServerCredentials( 1202 engine.getServerCredentials(getChal(request), sessionState.device) 1203 ); 1204 } 1205 1206 actions.setMimeType(mimeType); 1207 SyncML response = actions.getResponse(msgIdGenerator.current()); 1208 1209 if (alertCode1222requiredFromTheClient) { 1210 return response; 1215 } 1216 1217 clearCache(); 1221 cacheCommands(response); 1222 1223 if (log.isLoggable(Level.FINEST)) { 1224 log.finest("Hypothetical response: " + sync4j.framework.core.Util.toXML(response)); 1225 } 1226 SyncHdr syncHdr = response.getSyncHdr(); 1230 SyncBody syncBody = response.getSyncBody(); 1231 long sizeSyncHdr = 0, sizeSyncBody = 0; 1232 1233 1237 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1238 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1239 sizeSyncHdr = SizeCalculator.getWBXMLSize(syncHdr); 1240 sizeSyncBody = SizeCalculator.getWBXMLSize(syncBody); 1241 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1242 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1243 sizeSyncHdr = SizeCalculator.getXMLSize(syncHdr); 1244 sizeSyncBody = SizeCalculator.getXMLSize(syncBody); 1245 } 1246 1247 if (log.isLoggable(Level.FINER)) { 1248 log.finer("maxMsgSize: " + sessionState.getMaxMsgSize()); 1249 log.finer("sizeSyncHdr: " + sizeSyncHdr); 1250 log.finer("sizeSyncBody: " + sizeSyncBody); 1251 } 1252 1253 sessionState.setOverheadHdr(sizeSyncHdr); 1254 maxSizeAvailable = (int)(sessionState.getMaxMsgSize() * TOLLERANCE_MAX_MSG_SIZE); 1255 1256 if ( (maxSizeAvailable >= sizeSyncHdr + sizeSyncBody || 1262 maxSizeAvailable == 0) && 1263 sessionState.getStatusCmdOut().size() == 0 && 1264 sessionState.getAlertCmdOut().size() == 0 && 1265 sessionState.getCmdOut().size() == 0 1266 ) { 1267 return response; 1268 } 1269 1270 try { 1276 response = createNextMsg(response); 1277 } catch (Sync4jException e) { 1278 throw new ProtocolException(e); 1279 } 1280 1281 return response; 1282 } 1283 1284 1290 private void moveTo(int state) { 1291 if (log.isLoggable(Level.FINE)) { 1292 log.fine("moving to state " + getStateName(state)); 1293 } 1294 currentState = state; 1295 } 1296 1297 1298 1305 private boolean login(Cred credential, String deviceId) { 1306 logout(); 1310 1311 if (credential == null) { 1316 sessionState.authenticationState = AUTH_MISSING_CREDENTIALS; 1317 1318 return false; 1319 } 1320 1321 clientAuthType = credential.getType(); 1322 Sync4jPrincipal p = Sync4jPrincipal.fromCredential(credential.getData(), 1323 credential.getType(), 1324 deviceId ); 1325 if (clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_MD5) || 1330 clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_HMAC)) { 1331 1332 NextNonce nonce = new NextNonce(sessionState.device.getClientNonce()); 1333 1334 Authentication auth = credential.getAuthentication(); 1335 auth.setNextNonce(nonce); 1336 auth.setDeviceId(deviceId); 1337 } 1338 1339 try { 1340 Officer officer = engine.getOfficer(); 1341 if (officer.authenticate(credential)) { 1342 if (clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_MD5) || 1347 clientAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_HMAC)) { 1348 p.setUsername(credential.getAuthentication().getUsername()); 1349 } 1350 1351 if (officer.authorize(p, RESOURCE_MANAGEMENT)) { 1352 1353 sessionState.loggedCredential = credential; 1354 sessionState.loggedPrincipal = p ; 1355 1356 sessionState.authenticationState = AUTH_AUTHENTICATED; 1357 1358 return true; 1359 } 1360 } 1361 } catch (Exception e) { 1362 if (log.isLoggable(Level.SEVERE)) { 1363 log.severe("Unable to login due to the error: " + e.getMessage()); 1364 } 1365 log.throwing(getClass().getName(), "login", e); 1366 } 1367 1368 return false; 1369 } 1370 1371 1374 private void logout() { 1375 sessionState.authenticationState = AUTH_INVALID_CREDENTIALS; 1376 sessionState.loggedCredential = null; 1377 sessionState.loggedPrincipal = null; 1378 } 1379 1380 1392 private SyncML startManagementSession(SyncML requestMessage) 1393 throws ProtocolException, ManagementException { 1394 1395 storeServerNonce(ProtocolUtil.getStatusChal(requestMessage)); 1399 1400 String sessionId = requestMessage.getSyncHdr().getSessionID().getSessionID(); 1401 1402 Configuration c = Configuration.getConfiguration(); 1407 1408 sessionState.dmstate = new DeviceDMState(init.getDevInfo().getDevId()); 1413 sessionState.dmstate.mssid = init.getSessionId(); 1414 if (!engine.resolveDMState(sessionState.dmstate, sessionState.device)) { 1415 sessionState.dmstate.id = null; 1419 sessionState.dmstate.mssid = init.getSessionId(); 1420 } 1421 1422 if (addAbsCmd == null) { 1427 ProcessorSelector selector = 1428 (ProcessorSelector)c.getBeanInstance(CFG_SERVER_DM_SELECTOR); 1429 1430 processor = selector.getProcessor(sessionState.dmstate, init.getDevInfo()); 1431 1432 if (processor == null) { 1433 throw new ManagementException("No management processor could be selected!"); 1434 } 1435 1436 if (sessionState.dmstate.state == DeviceDMState.STATE_NOTIFIED) { 1437 sessionState.dmstate.state = DeviceDMState.STATE_IN_PROGRESS; 1441 } 1442 } 1443 1444 Alert alert = init.getClientAlert(); 1448 1449 if (alert != null) { 1450 sessionState.type = alert.getData(); 1451 } 1452 1453 if (addAbsCmd == null) { 1458 sessionState.dmstate.start = new Date(System.currentTimeMillis()); 1459 processor.beginSession( 1463 sessionId, 1464 sessionState.loggedPrincipal, 1465 sessionState.type, 1466 init.getDevInfo(), 1467 sessionState.dmstate 1468 ); 1469 1470 if (!init.isSessionAbortRequired()) { 1471 init.setManagementCommands( 1475 Util.managementOperations2commands( 1476 processor.getNextOperations(), 1477 engine.getCommandIdGenerator() 1478 ) 1479 ); 1480 } 1481 } 1482 1483 init.setRequest(requestMessage); 1485 if (requestMessage.getSyncBody().isFinalMsg()) { 1486 init.setFlag(Flags.FLAG_FINAL_MESSAGE); 1487 } else { 1488 init.unsetFlag(Flags.FLAG_FINAL_MESSAGE); 1489 } 1490 1491 SyncML response = init.getResponse(msgIdGenerator.current()); 1492 1493 SyncHdr syncHdr = response.getSyncHdr(); 1497 SyncBody syncBody = response.getSyncBody(); 1498 long sizeSyncHdr = 0, sizeSyncBody = 0; 1499 1500 1504 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1505 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1506 sizeSyncHdr = SizeCalculator.getWBXMLSize(syncHdr); 1507 sizeSyncBody = SizeCalculator.getWBXMLSize(syncBody); 1508 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1509 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1510 sizeSyncHdr = SizeCalculator.getXMLSize(syncHdr); 1511 sizeSyncBody = SizeCalculator.getXMLSize(syncBody); 1512 } 1513 1514 if (log.isLoggable(Level.FINER)) { 1515 log.finer("maxMsgSize: " + sessionState.getMaxMsgSize()); 1516 log.finer("sizeSyncHdr: " + sizeSyncHdr); 1517 log.finer("sizeSyncBody: " + sizeSyncBody); 1518 } 1519 1520 sessionState.setOverheadHdr(sizeSyncHdr); 1521 maxSizeAvailable = sessionState.getMaxMsgSize(); 1522 1523 checkMaxMsgSize(response); 1528 1529 if ( (maxSizeAvailable >= sizeSyncHdr + sizeSyncBody || 1535 maxSizeAvailable == 0) && 1536 sessionState.getStatusCmdOut().size() == 0 && 1537 sessionState.getAlertCmdOut().size() == 0 && 1538 sessionState.getCmdOut().size() == 0 1539 ) { 1540 return response; 1541 } 1542 1543 clearCache(); 1544 cacheCommands(response); 1548 1549 if (log.isLoggable(Level.FINEST)) { 1550 log.finest("Hypothetical response: " + sync4j.framework.core.Util.toXML(response)); 1551 } 1552 1553 try { 1559 response = createNextMsg(response); 1560 } catch (Sync4jException e) { 1561 throw new ProtocolException(e); 1562 } 1563 1564 return response; 1565 1566 } 1567 1568 1575 private boolean checkAuthType(Cred cred) { 1576 Officer officer = engine.getOfficer(); 1577 1578 serverAuthType = officer.getAuthType(); 1579 supportedAuthType = officer.getSupportedAuthType(); 1580 1581 if (cred == null) { 1582 if (officer.isGuestEnabled()) { 1583 sessionState.authenticationState = sessionState.AUTH_AUTHENTICATED; 1584 } else { 1585 sessionState.authenticationState = sessionState.AUTH_MISSING_CREDENTIALS; 1586 } 1587 return officer.isGuestEnabled(); 1588 } 1589 1590 String clientAuthType = cred.getType(); 1591 1592 if (supportedAuthType.indexOf(clientAuthType) != -1) { 1593 return true; 1594 } 1595 1596 sessionState.authenticationState = sessionState.AUTH_INVALID_CREDENTIALS; 1597 1598 return false; 1599 } 1600 1601 1610 private Chal getMessageChal(SyncML message) { 1611 Status[] statusCmds = 1612 (Status[])ProtocolUtil.filterCommands( 1613 message.getSyncBody().getCommands(), 1614 new String []{ Status.COMMAND_NAME } 1615 ).toArray(new Status[0]); 1616 1617 for (int i = 0; statusCmds != null && i < statusCmds.length; i++) { 1618 if ("0".equals(statusCmds[i].getCmdRef()) && 1619 "SyncHdr".equals(statusCmds[i].getCmd())) { 1620 1621 return statusCmds[i].getChal(); 1622 } 1623 } 1624 1625 return null; 1626 } 1627 1628 1640 private Chal getChal(final SyncML msg) { 1641 Chal chal = getMessageChal(msg); 1642 1643 1644 if (chal == null) { 1645 if (sessionState.serverAuthenticationState != AUTH_ACCEPTED) { 1649 if (serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_NONE)) { 1653 return null; 1654 } 1655 1656 Meta meta = new Meta(); 1657 meta.setType(serverAuthType); 1658 meta.setFormat(Constants.FORMAT_CLEAR); 1659 meta.setNextNonce(new NextNonce(sessionState.device.getServerNonce())); 1660 chal = new Chal(meta); 1661 1662 } 1663 } else { 1664 if (log.isLoggable(Level.FINE)) { 1665 log.fine("Challenged server authentication with scheme " + chal.getType()); 1666 } 1667 } 1668 1669 return chal; 1670 } 1671 1672 1682 private void checkServerAuthentication(SyncML msg) throws ProtocolException { 1683 int headerStatusCode = ProtocolUtil.getHeaderStatusCode(msg); 1684 if (headerStatusCode == -1) { 1685 return; 1686 } 1687 1688 if ( (headerStatusCode == StatusCode.INVALID_CREDENTIALS || 1689 headerStatusCode == StatusCode.MISSING_CREDENTIALS)) { 1690 1691 1703 1704 String authRequiredFromClient = null; 1705 Chal chal = getChal(msg); 1706 1707 if (chal != null) { 1708 authRequiredFromClient = chal.getType(); 1709 } 1710 1711 if (serverAuthType.equalsIgnoreCase(Constants.AUTH_TYPE_BASIC) && 1712 authRequiredFromClient.equalsIgnoreCase(Constants.AUTH_TYPE_BASIC)) { 1713 1714 throw new ProtocolException("Unable to authenticate to the client"); 1715 1716 } else if (!authRequiredFromClient.equalsIgnoreCase(serverAuthType)) { 1717 serverAuthType = authRequiredFromClient; 1718 1719 init.setServerCredentials( 1720 engine.getServerCredentials(chal, sessionState.device) 1721 ); 1722 sessionState.serverAuthenticationState = AUTH_RETRY_1; 1723 1724 } else if (authRequiredFromClient.equalsIgnoreCase(serverAuthType) && 1725 sessionState.serverAuthenticationState == AUTH_UNAUTHENTICATED) { 1726 init.setServerCredentials( 1727 engine.getServerCredentials(chal, sessionState.device) 1728 ); 1729 sessionState.serverAuthenticationState = AUTH_RETRY_1; 1730 } else { 1731 throw new ProtocolException("Unable to authenticate to the client"); 1732 } 1733 1734 return; 1735 } else if (headerStatusCode == StatusCode.AUTHENTICATION_ACCEPTED) { 1736 if (log.isLoggable(Level.FINE)) { 1740 log.fine("Server logged (code 212)"); 1741 } 1742 sessionState.serverAuthenticationState = AUTH_ACCEPTED; 1743 } else { 1744 if (log.isLoggable(Level.FINE)) { 1748 log.fine("Server auhenticated (code 200)"); 1749 } 1750 sessionState.serverAuthenticationState = AUTH_AUTHENTICATED; 1751 } 1752 } 1753 1754 1760 private void storeServerNonce(Chal chal) { 1761 if (chal == null) { 1762 return; 1763 } 1764 1765 if (Constants.AUTH_TYPE_MD5.equals(chal.getType()) || 1766 Constants.AUTH_TYPE_HMAC.equals(chal.getType())) { 1767 1768 NextNonce nonce = chal.getNextNonce(); 1769 if (nonce != null) { 1770 sessionState.device.setServerNonce(Base64.decode(nonce.getValue())); 1771 engine.storeDevice(sessionState.device); 1772 } 1773 } 1774 } 1775 1776 1783 private String getStateName(int state) { 1784 String stateName = "STATE_UNKNOWN"; 1785 1786 switch (state) { 1787 case STATE_START : stateName = "STATE_START" ; break; 1788 case STATE_END : stateName = "STATE_END" ; break; 1789 case STATE_ERROR : stateName = "STATE_ERROR" ; break; 1790 case STATE_INITIALIZATION_PROCESSING : stateName = "STATE_INITIALIZATION_PROCESSING" ; break; 1791 case STATE_INITIALIZATION_PROCESSED : stateName = "STATE_INITIALIZATION_PROCESSED" ; break; 1792 case STATE_MANAGEMENT_PROCESSING : stateName = "STATE_MANAGEMENT_PROCESSING" ; break; 1793 case STATE_MANAGEMENT_PROCESSED : stateName = "STATE_MANAGEMENT_PROCESSED" ; break; 1794 case STATE_MANAGEMENT_COMPLETION : stateName = "STATE_MANAGEMENT_COMPLETION" ; break; 1795 case STATE_SESSION_ABORTED : stateName = "STATE_SESSION_ABORTED" ; break; 1796 1797 default : stateName = "STATE_UNKNOWN" ; break; 1798 } 1799 1800 return stateName; 1801 } 1802 1803 1806 private void clearCache() { 1807 sessionState.getAlertCmdOut().clear(); 1808 sessionState.getStatusCmdOut().clear(); 1809 sessionState.getCmdOut().clear(); 1810 } 1811 1812 1815 private void cacheCommands(SyncML response) { 1816 List statusCmdOut = ProtocolUtil.filterCommands( 1820 response.getSyncBody().getCommands(), 1821 new String [] {Status.COMMAND_NAME} 1822 ); 1823 List listStatus = Arrays.asList(ProtocolUtil.sortStatusCommand( 1827 statusCmdOut.toArray(new Status[0])) 1828 ); 1829 sessionState.addStatusCmdOut(listStatus); 1833 1834 Status statusSyncHdr = ProtocolUtil.filterStatus( 1835 (Status[])listStatus.toArray(new Status[0]), 1836 Status.class, 1837 "SyncHdr" 1838 ); 1839 1840 1844 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1845 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1846 sessionState.setSizeStatusSyncHdr(SizeCalculator.getWBXMLSize(statusSyncHdr)); 1847 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1848 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1849 sessionState.setSizeStatusSyncHdr(SizeCalculator.getXMLSize(statusSyncHdr)); 1850 } 1851 1852 sessionState.setStatusSyncHdr(statusSyncHdr); 1857 1858 ArrayList removeStatus = new ArrayList(); 1862 removeStatus.add(statusSyncHdr); 1863 sessionState.removeStatusCmdOut(removeStatus); 1864 1865 List cmdOut = ProtocolUtil.filterCommands( 1870 response.getSyncBody().getCommands(), 1871 MANAGEMENT_COMMANDS 1872 ); 1873 1874 List listCmd = Arrays.asList(ProtocolUtil.sortAbstractCommand( 1878 cmdOut.toArray(new AbstractCommand[0])) 1879 ); 1880 sessionState.addCmdOut(new LinkedList(listCmd)); 1884 } 1885 1886 1893 private SyncML createNextMsg(SyncML syncML) throws Sync4jException { 1894 1895 if (log.isLoggable(Level.FINEST)) { 1896 log.finest("Create Next Message"); 1897 } 1898 1899 long sizeSyncHdr = sessionState.getOverheadHdr(); 1900 long sizeStatusSyncHdr = sessionState.getSizeStatusSyncHdr(); 1901 1902 maxSizeAvailable = sessionState.getMaxMsgSize() - 1903 sizeSyncHdr - 1904 sizeStatusSyncHdr ; 1905 1906 1907 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1908 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1909 maxSizeAvailable -= SizeCalculator.getWBXMLOverheadSyncML(); 1910 maxSizeAvailable -= SizeCalculator.getWBXMLOverheadSyncBody(); 1911 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1912 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1913 maxSizeAvailable -= SizeCalculator.getXMLOverheadSyncML(); 1914 maxSizeAvailable -= SizeCalculator.getXMLOverheadSyncBody(); 1915 } 1916 1917 if (log.isLoggable(Level.FINEST)) { 1921 log.finest("How many Status can I include into the response?"); 1922 } 1923 howManyStatus(sessionState.getStatusCmdOut()); 1924 1925 sessionState.removeStatusCmdOut(addStatus); 1926 1927 if (log.isLoggable(Level.FINEST)) { 1931 log.finest("How many AbstractCommand can I include into the response?"); 1932 } 1933 howManyAbstractCommand(); 1934 1935 sessionState.removeCmdOut(addAbsCmd); 1936 1937 int size = addStatus.size() + addAbsCmd.size(); 1938 ArrayList commandList = new ArrayList(size); 1939 commandList.addAll(addStatus); 1940 commandList.addAll(addAbsCmd); 1941 1942 AbstractCommand[] absCommands = 1943 (AbstractCommand[])commandList.toArray(new AbstractCommand[size]); 1944 1945 boolean isFinal = (sessionState.getNextDataToSend() == null); 1947 SyncBody responseBody = new SyncBody(absCommands, isFinal); 1948 1949 if (log.isLoggable(Level.FINEST)) { 1950 log.finest("status in cache after creation: " + sessionState.getStatusCmdOut().size()); 1951 log.finest("alert in cache after creation: " + sessionState.getAlertCmdOut().size()); 1952 log.finest("command in cache after creation: " + sessionState.getCmdOut().size()); 1953 } 1954 1955 SyncML newResponse = new SyncML(syncML.getSyncHdr(), responseBody); 1956 1957 if (log.isLoggable(Level.FINEST)) { 1958 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1959 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1960 size = (int) SizeCalculator.getWBXMLSize(newResponse); 1961 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1962 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1963 size = (int) SizeCalculator.getXMLSize(newResponse); 1964 } 1965 log.finest("Response size: " + size); 1966 } 1967 1968 return newResponse; 1969 } 1970 1971 1974 private void howManyStatus(List allStatus) { 1975 addStatus = new ArrayList(); 1976 addStatus.add(sessionState.getStatusSyncHdr()); 1977 1978 int x = 0; 1982 Status status = null; 1983 long size = 0; 1984 for (int i = 0; allStatus != null && i < allStatus.size(); i++) { 1985 status = (Status)allStatus.get(i); 1986 size = 0; 1990 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 1991 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 1992 size = SizeCalculator.getWBXMLSize(status); 1993 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 1994 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 1995 size = SizeCalculator.getXMLSize(status); 1996 } 1997 1998 if (maxSizeAvailable - size >= 0) { 2000 addStatus.add( (Status)allStatus.get(i)); 2001 maxSizeAvailable -= size; 2002 x++; 2003 } else { 2004 break; 2005 } 2006 } 2007 2008 if (log.isLoggable(Level.FINEST)) { 2009 log.finest("Number of Status inserted: " + x); 2010 } 2011 } 2012 2013 2014 2017 private void howManyAbstractCommand() { 2018 addAbsCmd = new ArrayList(); 2019 boolean isCmdWithLargeObject =false; 2020 2021 int x = 0; 2025 LinkedList allCmd = sessionState.getCmdOut(); 2026 2027 if (maxSizeAvailable > 0 && 2028 sessionState.getStatusCmdOut().size() == 0 && 2029 sessionState.getAlertCmdOut().size() == 0) { 2030 2031 long size = 0; 2032 AbstractCommand cmd = null; 2033 for (int i = 0; allCmd != null && i < allCmd.size(); i++) { 2034 size = 0; 2035 cmd = (AbstractCommand)allCmd.get(i); 2036 2037 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 2038 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 2039 size = SizeCalculator.getCommandWBXMLSize(cmd); 2040 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 2041 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 2042 size = SizeCalculator.getCommandXMLSize(cmd); 2043 } 2044 2045 if (maxSizeAvailable - size >= 0) { 2047 addAbsCmd.add( cmd ); 2048 maxSizeAvailable -= size; 2049 if (cmd == sessionState.getSplittedCommand()) { 2050 sessionState.setSplittedCommand(null); 2054 sessionState.setNextDataToSend(null); 2055 } 2056 x++; 2057 } else { 2058 2059 isCmdWithLargeObject = checkForSplitData(cmd, maxSizeAvailable); 2060 2061 if (i == 0) { 2069 2070 if (!isCmdWithLargeObject) { 2071 if (log.isLoggable(Level.INFO)) { 2072 log.info("The command " + cmd + " is too large (" + size + 2073 " bytes)"); 2074 } 2075 sessionState.removeCmdOut(cmd); 2076 } else { 2077 addAbsCmd.add(cmd); 2078 x++; 2079 if (sessionState.getNextDataToSend() == null) { 2080 continue; 2084 } else { 2085 break; 2086 } 2087 } 2088 } else { 2089 if (!isCmdWithLargeObject) { 2090 break; 2095 } else { 2096 addAbsCmd.add(cmd); 2101 x++; 2102 if (sessionState.getNextDataToSend() == null) { 2103 continue; 2107 } else { 2108 break; 2109 } 2110 } 2111 } 2112 break; 2113 } 2114 } 2115 } 2116 if (log.isLoggable(Level.FINEST)) { 2117 log.finest("Number of AbstractCommand inserted: " + x); 2118 } 2119 2120 } 2121 2122 2129 private boolean checkForSplitData(AbstractCommand cmd, long sizeAvailable) { 2130 Item itemToSplit = null; 2131 if (cmd instanceof ItemizedCommand) { 2135 if (((ItemizedCommand)cmd).getItems().size() != 1) { 2136 if (log.isLoggable(Level.FINER)) { 2137 log.finer("Command with more items isn't splittable"); 2138 } 2139 return false; 2140 } else { 2141 itemToSplit = (Item)((ItemizedCommand)cmd).getItems().get(0); 2142 } 2143 } else { 2144 if (log.isLoggable(Level.FINER)) { 2145 log.finer("Command isn't a ItemizedCommand then it isn't splittable"); 2146 } 2147 return false; 2148 } 2149 2150 Data data = itemToSplit.getData(); 2151 if (data == null) { 2152 return false; 2153 } 2154 String dataValue = data.getData(); 2155 if (dataValue == null) { 2156 return false; 2157 } 2158 2159 Object dataToSplit = dataValue; 2160 boolean isBinaryData = false; 2161 int lengthDataToSplit = 0; 2162 2163 Meta meta = itemToSplit.getMeta(); 2164 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 2165 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 2166 2167 if (meta != null) { 2168 String format = meta.getFormat(); 2169 if (format != null && format.equalsIgnoreCase("b64")) { 2170 isBinaryData = true; 2171 dataToSplit = Base64.decode( ( (String )dataToSplit).getBytes()); 2172 lengthDataToSplit = ( (byte[])dataToSplit).length; 2173 } 2174 2175 } 2176 } 2177 2178 if (!isBinaryData) { 2179 lengthDataToSplit = ((String )dataToSplit).length(); 2180 } 2181 2182 long maxObjSize = sessionState.getMaxObjSize(); 2183 if (maxObjSize != 0 && lengthDataToSplit > maxObjSize) { 2184 if (log.isLoggable(Level.FINER)) { 2185 log.finer("The dimension of the data is greater of the maxObjSize"); 2186 } 2187 return false; 2189 } 2190 if (sessionState.getNextDataToSend() == dataValue) { 2194 } else { 2199 if (meta == null) { 2203 meta = new Meta(); 2204 itemToSplit.setMeta(meta); 2205 } 2206 2207 meta.setSize(new Long (lengthDataToSplit)); 2208 } 2209 2210 int sizeAvailableForData = calculateDataSizeAvailable(sizeAvailable, cmd, itemToSplit); 2211 2212 if (sizeAvailableForData <= 0) { 2213 return false; 2217 } 2218 2219 sessionState.setSplittedCommand(cmd); 2220 2221 Object newData = null; 2222 int lengthNewData = 0; 2223 2224 if (isBinaryData) { 2225 if (sizeAvailableForData > lengthDataToSplit) { 2226 sizeAvailableForData = lengthDataToSplit; 2228 newData = dataToSplit; 2229 } else { 2230 newData = new byte[sizeAvailableForData]; 2231 System.arraycopy(dataToSplit, 0, newData, 0, sizeAvailableForData); 2232 } 2233 lengthNewData = sizeAvailableForData; 2234 } else { 2235 newData = ((String )dataToSplit).substring(0, sizeAvailableForData); 2236 lengthNewData = ((String )newData).length(); 2237 } 2238 2239 if (isBinaryData) { 2240 newData = new String (Base64.encode((byte[])newData)); 2241 } 2242 itemToSplit.getData().setData((String )newData); 2243 2244 if (sizeAvailableForData >= lengthDataToSplit) { 2245 sessionState.setNextDataToSend(null); 2247 itemToSplit.setMoreData(Boolean.FALSE); 2248 } else { 2249 String dataNotSent = null; 2253 if (isBinaryData) { 2254 byte[] byteNotSent = new byte[lengthDataToSplit - sizeAvailableForData]; 2255 System.arraycopy(dataToSplit, sizeAvailableForData, byteNotSent, 0, lengthDataToSplit - sizeAvailableForData); 2256 dataNotSent = new String (Base64.encode((byte[])byteNotSent)); 2257 } else { 2258 dataNotSent = ((String )dataToSplit).substring(sizeAvailableForData); 2259 2260 } 2261 itemToSplit.setMoreData(Boolean.TRUE); 2262 sessionState.setNextDataToSend(dataNotSent); 2263 } 2264 2265 return true; 2266 } 2267 2268 2276 private int calculateDataSizeAvailable(long commandSizeAvailable, AbstractCommand cmd, Item item) { 2277 ComplexData itemData = item.getData(); 2281 item.setData(new ComplexData("")); 2282 2283 long commandSize = -1; 2284 2285 if (Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType) || 2286 Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType)) { 2287 commandSize = SizeCalculator.getCommandWBXMLSize(cmd); 2288 } else if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 2289 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 2290 commandSize = SizeCalculator.getCommandXMLSize(cmd); 2291 } 2292 2293 int sizeAvailableForMoreData = (int)(commandSizeAvailable - commandSize); 2294 item.setData(itemData); 2298 return sizeAvailableForMoreData; 2299 } 2300 2301 2309 private void checkForReceivedLargeObject(List clientCommands) throws ProtocolException { 2310 String previousReceivedLargeObject = sessionState.getReceivedLargeObject(); 2311 2312 if (previousReceivedLargeObject == null) { 2313 return; 2314 } 2315 2316 ArrayList results = ProtocolUtil.filterCommands((AbstractCommand[])(clientCommands.toArray(new AbstractCommand[0])), Results.class); 2321 if (results.size() == 0) { 2322 throw new ProtocolException("Error awaiting more data from the client - No Results in the request"); 2323 } 2324 2325 Results result = (Results)results.get(0); 2330 Item item = (Item)result.getItems().get(0); 2331 2332 boolean isReceivedItemWithBinaryData = sync4j.framework.core.Util.isItemWithBinaryData(item); 2333 2334 String receivedData = item.getData().getData(); 2335 2336 if (isReceivedItemWithBinaryData) { 2337 if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 2341 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 2342 isReceivedItemWithBinaryData = false; 2343 } 2344 } 2345 2346 if (isReceivedItemWithBinaryData) { 2347 byte[] previousData = Base64.decode(previousReceivedLargeObject.getBytes()); 2348 byte[] bReceivedData = Base64.decode(receivedData.getBytes()); 2349 byte[] newData = new byte[previousData.length + bReceivedData.length]; 2350 System.arraycopy(previousData, 0, newData, 0, previousData.length); 2351 System.arraycopy(bReceivedData, 0, newData, previousData.length, bReceivedData.length); 2352 item.getData().setData(new String (Base64.encode(newData))); 2353 } else { 2354 String newData = previousReceivedLargeObject + receivedData; 2355 item.getData().setData(newData); 2356 } 2357 Meta meta = item.getMeta(); 2363 if (meta == null) { 2364 meta = new Meta(); 2365 item.setMeta(meta); 2366 } 2367 meta.setSize(sessionState.getSizeOfReceivedLargeObject()); 2368 } 2369 2370 2375 private void mergeData() { 2376 AbstractCommand cmd = sessionState.getSplittedCommand(); 2377 Item itemSplitted = (Item)(((ItemizedCommand)cmd).getItems()).get(0); 2381 boolean isBinary = sync4j.framework.core.Util.isItemWithBinaryData(itemSplitted); 2382 2383 if (isBinary) { 2384 if (Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType) || 2388 Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType)) { 2389 isBinary = false; 2390 } 2391 } 2392 2393 if (isBinary) { 2394 byte[] previousData = Base64.decode(itemSplitted.getData().getData().getBytes()); 2395 byte[] nextData = Base64.decode(sessionState.getNextDataToSend().getBytes()); 2396 byte[] newData = new byte[previousData.length + nextData.length]; 2397 System.arraycopy(previousData, 0, newData, 0, previousData.length); 2398 System.arraycopy(nextData, 0, newData, previousData.length, nextData.length); 2399 itemSplitted.getData().setData(new String (Base64.encode(newData))); 2400 } else { 2401 String previousData = itemSplitted.getData().getData(); 2402 String nextData = sessionState.getNextDataToSend(); 2403 String newData = previousData + nextData; 2404 itemSplitted.getData().setData(newData); 2405 } 2406 } 2407 2408 2415 private void checkMaxMsgSize(SyncML response) { 2416 if (log.isLoggable(Level.FINEST)) { 2417 log.finest("Check if the MaxMsgSize is larger of the minimal " + 2418 "size of the messages of the server"); 2419 } 2420 long minMsgSize = 0; 2421 if (sessionState.getMaxMsgSize() != 0) { 2422 if (Constants.MIMETYPE_SYNCMLDS_WBXML.equals(mimeType) || 2423 Constants.MIMETYPE_SYNCMLDM_WBXML.equals(mimeType)) { 2424 minMsgSize = Long.parseLong(engine.getConfiguration().getStringValue(engine.CFG_MIN_MSGSIZE_WBXML)); 2425 } else if (Constants.MIMETYPE_SYNCMLDS_XML.equals(mimeType) || 2426 Constants.MIMETYPE_SYNCMLDM_XML.equals(mimeType)) { 2427 minMsgSize = Long.parseLong(engine.getConfiguration().getStringValue(engine.CFG_MIN_MSGSIZE_XML)); 2428 } 2429 if (sessionState.getMaxMsgSize() < minMsgSize) { 2430 Status statusHdr = (Status)response.getSyncBody().getCommands().get(0); 2431 statusHdr.setData(new Data(StatusCode.COMMAND_FAILED)); 2432 2433 if (log.isLoggable(Level.INFO)) { 2434 log.info("The MaxMsgSize is smaller than minimum size " + 2435 "that the server response could have!"); 2436 log.info("The server will not answer to some message " + 2437 "of the client."); 2438 } 2439 } 2440 } 2441 } 2442} 2443 | Popular Tags |