Dave Ward 27f6cb89b8 Merged V4.1-BUG-FIX to HEAD
40031: Fix from Dave Ward for ALF-15353 - Lock status is not showning on document details page for a document which is being edited online.
   40037: ALF-13609: Merged PATCHES/4.0.2 to V4.1-BUG-FIX (4.1.1)
      40032: ALF-13609: listSites() causes an exception for non-privileged users when no sites are present.    
         - Add catch for AccessDeniedException on getAllSetPermissions() call. Assumes private site for this condition.
   40075: ALF-13194: Make Share work again when guest authentication is disabled in the authentication chain
   - When share makes a call to the restrictions API with guest=true it must get a 401 response if there is no guest
   - Fix by Alex Mukha
   40112: ALF-9254: Merged V3.4-BUG-FIX (3.4.11) to V4.1-BUG-FIX (4.1.1)
      40111: ALF-15227 3.4 CLONE - Alfresco incapable of previewing text files including non Western European characters without custom configuration
         - Patched jooconverter to handle non western characters in text files, by using the same properties that JOD uses.
      40073: ALF-15227 3.4 CLONE - Alfresco incapable of previewing text files including non Western European characters without custom configuration
         - Refactored JodContentTransformer and OpenOfficeContentTransformerWorker. Moved common code into OOoContentTransformerHelper,
           including fixes that existed on only one or the other.
         - For text files, change file encoding from SHIT JIS (and others) to UFT-8, as OpenOffice/LibreOffice do not support this as
           an input. They do support it in other file types but not text. JOD now works, but OOo still has problems.
   40146: ALF-15030: Merged V3.4-BUG-FIX (3.4.11) to V4.1-BUG-FIX (4.1.1)
      40145: ALF-15411 CLONE pdf2swf ID Table overflow / This file is too complex to render- SWF only supports 65536 shapes at once
         - split swf.encoder.params into two parts rather than a comma separated list.
           Have tested against a number of Mike's test files. Quality appears the same.
   40151: ALF-15402: Upgrade yuicompressor used to compress JavaScript to 2.4.7, using the same version as the one we package
   40153: ALF-13998: 'No items' error is highlighted in red, even that is not sever error.
   40158: Merge DEV to V4.1-BUG-FIX
     ALF-14323 - CLONE - IMAP: Cannot attach two attachments with the same name.
   40162: Merged V4.1 (4.1.0) to V4.1-BUG-FIX (4.1.1) MORE TO FOLLOW
      39493: CloudSync: ALF-15203 - when creating a folder sync, do not setup sync for existing "working copy" nodes (only the original ones)
      39490: Changing the icon for creating a new folder in the cloud
      39486: Chinese translation update from Gloria, based on EN rev38987
      39485: Dutch translation update from Gloria, based on EN rev38987
      39483: Japanese translation update from Gloria, based on EN rev38987
      39482: German translation update from Gloria, based on EN rev38987
      39478: (ALF-15197) CloudSync: SyncAdminServiceImplTest.lockSSD failing - causing other tests and
      39470: CloudSync: ALF-15188 - Regress' in Unsync
      - further fallout (this time from ALF-14373 - moved syncTime to syncSetMemberNodeAspect)
      39465: ALF-15141 If a push takes a network over quota, a ContentQuotaException will be raised. Catch this on cloud, and return QUOTA_LIMIT_VIOLATION to the client
      39464: ALF-14847 Remove the obsolete old style audit token code
      39462: Remove unused imports, and improve log message/exception wrapping, for when the catch-all is enabled
      39461: The actions panel in the folder details page didn't receive the metadateRefresh event
      39454: CloudSync: ALF-15188 - Regress' in Unsync
      - fallout from ALF-14872
      - wip - fixes blocker but needs further investigation as to why remote Unsync is failing with "Content no longer exists on the remote system"
      - TODO: ALF-14655 + ALF-14712
      39452: Avoid NPE due to unboxing a null java.lang.Boolean
      39446: SyncTrackerComponent - rework code to set and reset remote system status.
      39445: Cloud Sync UI Updates:
         - Sync Status now shows transient Errors
         - Sync Status "More info" link has been removed
         - Text updates
      39444: removed a "hot" trace message.
      39443: ALF-14975 - Error if some files are locked while multi sync
      39442: ALF-14908: Update Sync status dialogue to include the local root folder for indirectly synced nodes.
      39441: Use SyncNodeException.wrapUnhandledException, so that the cause details are available for transport
      39440: ALF-15155 Have SyncNodeExceptions of type UNKNOWN transport back the causing exception's message, class and stacktraces, and have CloudSyncMemberNodeTransportImpl print a WARN for this when recevied
      39439: missed check in - just a message key
      39438: Interceptors on the CloudConnectorService will wrap raw exceptions, so ensure downstream code expects this
      39436: Fixes the problem when the default tenant is not enabled for sync and there are no secondary tenants
      39434: ALF-14980 - Services: auth errors on a per node basis
      39431: More - work around code for SyncTrackerComponent.
      39430: ALF-14531: F22 sub-task: Add create folder button to folder picker
      39428: ALF-15113 Remove the stubbed CloudSync subsystem.
      Although the subsystem config was gone, there was still some spring config which attempted to import it during bootstrap.
      39426: ALF-14598. This change should ensure that the syncOwner is correctly set on nodes pushed to cloud.
      39425: Put set and reset of sync failed attribute into its own transaction.
      39420: ALF-15167 - Version history sync status message displaying US date format
      39419: Work around for syncSetDefinitionTransport.pullChangedSSDs not returning RemoteSystemUnavailableException
      39418: Test code improvements. Using my new TemporaryMockOverride rule to clean up spring beans.
      39414: CloudSync: change annoying debug message to trace ...
      - ... we should not pollute the sync "debug" log with continuous stream of unhelpful messages ;-)
      39413: CloudSync: ALF-15130 - for checkout, copy sync aspect and properties to "Working Copy" (but not for non-checkout "Copy")
      - additional fix for directly synced node (issue raised by DW)
      39411: Updated the properties for cloud sync related messages
      39410: Fixes api mapping for POST cloud passthrough.
      39407: ALF-14906: Makes sync status dialogue working copy aware & provides link to original document.
      39400: some code was in an log if statement.
      39399: ALF-14980 - Services: Add {stuff} needed to display comms and auth errors on a per node basis.
      39397: Merged HEAD to BRANCHES/V4.1:
         39395: Adding a new JUnit rule to help with cleaning up spring singleton beans whose backend services have been mocked out.
      39386: ALF-14901: Fxx sub-task: UI - tgt folder picker should allow drill-down for sync-enabled Networks only
      39385: CloudSync: F24 - fix add "sub-folder" on target (when sync'ing sub-folders)
      - raised by MF
      39384: Rename the parent declarative webscript to AbstractCloudSyncDeclarativeWebScript, and add a new AbstractCloudSyncAbstractWebScript parent for the few sync related webscripts that need to be AbstractWebScript rather than DeclarativeWebScript
      39382: I like code that compiles. This code compiles.
      39380: Test code refactor. We've now got a green bar for AllSyncServiceTests.
      39378: More test refactoring in an attempt to get AllSyncServiceTests passing.
      Extracted common code and state from two REST API tests.
      39377: ALF-14901: Fxx sub-task: UI - tgt folder picker should allow drill-down for sync-enabled Networks only
      39376: Changes to tests. I'm trying to get AllSyncServiceTests to pass as a suite.
      This check-in fixes a few failures, now two remaining.
      39371: CloudSync: fix cloud fallout from new lic/key (ALF-14846) - pt 1
      39368: Italian translation update from Gloria, based on EN rev38987
      39367: French translation update from Gloria, based on EN rev38987
      39366: Spanish translation update from Gloria, based on EN rev38987
      39356: ALF-14906: "Sync Pending" status is shown immediately following a "Request Sync" action.
      39348: ALF-14530 Complete the implementation, and add a REST level unit test
      39347: ALF-14889: Adds proxy passthrough config for create folder webscript.
      39344: ALF-14373 Moved syncTime to syncSetMemberNodeAspect.
      There may be a little more to do in this task.
      39343: Hide the sync filters in the dashlets if the sync is disabled.
      39342: CloudSync: stop push looping due to unknown (non-transient) error !
      - related to ALF-14872 - eg. in this case ALF-15141 which is not yet explicitly handled ...
      - TODO: SyncNodeExceptionType.UNKNOWN should handle error message (+ stacktrace ?) - for push or pull (for latter, needs to be transported)
      39339: Unsync confirmation text for document/folder changed. The user will be informed that deleting a folder will also delete any content under this folder.
      39338: ALF-14909: Update Share delete confirmation dialogue to show extra confirmation text if the node is synced
      39337: Add example request JSON to the webscript description
      39335: ALF-14530 Webscript to create folders
      39328: stress that a cloud network is: FREE 10GB
      39322: ALF-14921: CloudSync - F63 / F64 - Recently Modified Dashlet Updates
      39320: ALF-14501 - allow UI to determine if sync has been requested on a node
      39316: ALF-14920: CloudSync - F61 / F62 - Synced content display on My Documents Dashlet
      39312: Debug messages.
      39308: Adds folder specific lock messages.
      39306: CloudSync: ALF-15130 - for checkout, copy sync aspect and properties to "Working Copy" (but not for non-checkout "Copy")
      39305: Turns off sync panel when sync is disabled.
      39304: CloudSync: minor: turn down log level
      39303: Updates the text to use the correct term for the cloud instance (Alfresco in the cloud).
      39300: Cloud Sync Evaluator config & Doc Lib banner updates:
         - ALF-14981: Adds support for sync:transientError aspect
         - ALF-14981: Adds Doc Lib banner for transient errors
         - ALF-15128: Corrects behaviours on working copies (WIP)
      39296: ALF-15025 - Always enable the sync change monitor policies - even when off.
      39292: ALF-15091 Add unit test covering the case of auditing and transporting MLText properties
      39291: ALF-15025 - Cloud Sync now depends upon the key in the license.   No key - no sync.
      39283: When fetching the properties to be transfered, mark us as being ML-aware as we want to transfer the full MLText object (and not just the current locale)
      39279: Adds back in property that went awol in r39265
      39275: ALF-15104 Switch the tenant information webscript to be an AbstractWebScript, to make extensions of the JSON (eg for Cloud) easier and cleaner
      39273: Switches off Sync filters if sync is off.
      39272: Adds support for evaluators to Doc Lib filters.
      39265: Merged /integrations/GoogleDocs/BRANCHES/THOR1_SPRINTS_GOOGLEDOCS to BRANCHES/V4.1
         36307 Fixed THOR-1402 "Need a callback option for Create Content menu"
            - Will be revisited to add better comments
         36350 Fixed THOR-1402 "Need a callback option for Create Content menu" part 2
            - Changed callback obj to match action object better: { nodeRef, node, jsNode }
            - Better code documentation
            - Removed dev/test code
            - Improved error config handling
         36358 THOR-1402 "Need a callback option for Create Content menu" part 3
            - Changed "link" parameter to "href" (instead of "page") to match actions.
         39256 Consistency fix of doclib & repo toolbar templates after work on THOR-1402
         39260 Bugfix for "destination" parameter not being resolved correctly THOR-1402
      39261: ALF-15056: Handle Multiple errors in Sync Status box
      39215: CloudSync: F4 - fix ALF-15106: non-deeply synced folders should not add subsequent child (sub-) folders to sync set
      39209: ALF-15113. Removing the unused, stub subsystem 'CloudSync'.
      39207: ALF-15015 follow-up: make sure the first enterprise test that runs has no specific license, since we just reset the database
      39184: Fixes broken sync URLs
      39180: ALF-15054: CSS Updates
      39171: Re-enable test (ALF-15096)
      39170: Missing commit, 400-499 errors need the response details (ALF-15096)
      39168: Completion of ALF-14335. This check-in removes the old URL patterns and so all clients must now be using the new /enterprise/sync URLs.
      39162: CloudSync: comment-out unit test pending ALF-15096
      39160: ALF-15054: CSS Updates
      39144: Have SyncChangeMonitorTest remove the mock when done, which allows several more tests to pass in the suite
      39114: Fixes: ALF-14990: Folder Picker issues (caused by multiple instances being displayed with different contexts)
      39113: ALF-14557: Auth Dialogue updates
      39112: ALF-15061: Makes Lock message and icon generic - not all locks are for local edits now.
      39107: ALF-15054: CSS Updates
      39097: Try to re-order tests to have more pass, and improve error detection in one
      39093: Add in the missing sync
      39091: CloudSync: ALF-15075 - Regress: unable to pull single node update (file sync)
      - follow-on fix to allow initial push :-)
      - fallout from ALF-14853
      39080: Complete conflict transport of exceptions unit tests
      39079: Fix webscript parent definitions, to avoid NPE on missing required service
      39077: Improve Pull error reporting, and add tests for the transport level catch/encoding/decoding/throw of exceptions (to compliment existing tests)
      39076: ALF-15013 ALF-15015: Reset database before running enterprise tests, otherwise SecurityTestSuite leaves it in a bad state
      39073: ALF-15050 test affescted by locked sync set implementation.
      39072: CloudSync: ALF-15075 - Regress: unable to pull single node update (file sync)
      - fallout from ALF-14853
      39068: ALF-14893 - work around order of versions issue.
      39066: Tweak how we switch to the default authenticator for one test
      39059: ALF-15054: Added the actions "Sync", "Unsync" and "Request sync" to the header of the sync panel
      39054: More debug for move node problem.
      39041: ALF-15064 : Sync locked nodes (on src) - need to be able to bypass lock when requesting sync ...
      39040: Turn off locked sync sets for SyncAdminServiceRestApiTest
      39034: Merged BRANCHES/DEV/FEATURES/CLOUD1_CLOUDSYNC to BRANCHES/V4.1:
         39030: CloudSync: ALF-14899 - cloud target Sync API should restrict to Enterprise Network(s) only
      39033: CloudSync: minor - fix failed node count (debug logging)
      39032: ALF-14557: CSS Fixes to Auth Dialogue (WIP)
      39024: ALF-14225: Adds tracking to URL.
      39018: If the other end sent their noderef, return it to them
      39011: ALF-14225: Refactor Welcome Dashlet to show 4 columns, the 4th one of which is always the cloud sign up text.
      39009: Extra validation before doing JSON parsing
      39008: ALF-15015 Avoid having a custom ServletAuthenticatorFactory trampled in a MT environment
      39005: Attach the sources for spring-webscripts-1.0.0-tests
      38991: update should not move node if localparentnoderef is not specified.
      38962: Added a new unit test for end to end conflict.
      38961: CloudSync: ALF-15040 / ALF-15021 - Uploading file larger than content limit (max file size) for given network (eg. 50 Mb to a Free Network) causes error loop
      - wip
      38960: ALF-15050 :
      CloudSync: failing test(s) - due to locking ?? (SyncAdminServiceImplTest / org.alfresco.enterprise.repo.sync.audit.SyncAuditServiceIntegrationTest)
      38958: CloudSync: fix NPE (CloudSyncConfirmPost line 139)
      38956: Chinese Translation for 4.1
      38955: box-shadow doesn't work with IE6-IE8. It was not possible to see the borders of the info balloon.
      38951: Removed "folder-sync.js" and "folder-sync.css" to avoid code duplication. The same methods and styles are defined in "document-sync.js" and "document-sync.css".
      38940: The sync panel in document details page were not refreshed when the document was synced or unsynced from the document details page.
      38937: ALF-14859: Adds Icons for cloud version (requires cloud overrides to display them)
      38935: ALF-15006: Adds the missing config required to include the actions-util.js file in the list of ones to be concatenated
      38929: Add a toString() method to aid debugging
      38928: ALF-14952: update Unsync dialog to enable UI option to allow user to request delete of remote nodes (ie. from target) 
      38925: Updates the sync status message logic a bit - now displays the sync attempted time if the first sync fails (previously showed "Sync pending")
      38922: ALF-14677 - Synced nodes marked as locked On Premise, need to be unlocked on unsync
      Also Locks created and deleted by sync set owner.
      38921: Removes the action util methods from the global name space and adds them to Alfresco.util
      38919: CloudSync: ALF-15040 / ALF-15021 - Uploading file larger than 50 Mb to a Free Network causes error loop
      38918: File size upload limit within ContentStore.
      - required for cloud sync (ALF-15040) 
      - fix default (no limit)
      38915: File size upload limit within ContentStore.
      - required for cloud sync (ALF-15040) 
      - fix merge issue (Spring config)
      38914: File size upload limit within ContentStore.
      - partial merge - "sourced from" THOR1+CLOUD1
      - required for cloud sync (ALF-15040)
         33055: File size upload limit within ContentStore 
         35995: Fix merge issue
      38912: Locking attribute on Sync Set - First cut - add new method on Lock Service + re-enable pull unit test.
      38906: The buttons won't be created on the cloud side, so avoid js error
      38905: CloudSync: test fix
      - fallout from r38888 (ALF-15029)
      38902: ALF-14549: CSS fix for window resizing problems
      38898: More unit test debug logging, to aid with making sense of the logs on the Bamboo-only failure
      38895: Extra debugging and checking, to help narrow down why this test fails on Bamboo
      38892: ALF-14908 (No need to pass the "siteId" with the URL)
      38890: We don't need to pass the "syncOwner" with the URL anymore. We receive the needed information from the server and this avoids an extra call to build the "syncOwnerFullName".
      38888: CloudSync: F4/F24 - ALF-15029 - working copies (eg. via Edit Offline ... within a folder sync) should not be synced !
      38887: ALF-14908: Checking "isDirectSync" before comparing the value, because "isDirectSync" can be undefined
      38886: ALF-14908: Update Sync status dialogue to include the local root folder for indirectly synced nodes
      38882: CloudSync: F13/F14/F24 - ALF-14778 - "request sync" of a folder/sub-folder SSMN
      - will request the sync of the folder node itself (whether failed or not)
      - recurse and request sync of all SSMNs below but only if failed (irrespective of SSD)
      38873: Reverses failed merge attempt in r38846.
      38872: ALF-14907: "localRootNodeName" added
      38871: Adds edition check before calling enterprise only webscript. Sets sync to OFF for non enterprise editions.
      38866: Have the setup methods try harder to ensure a clean, empty setup for the area under test, to avoid issues with other tests on Bamboo leaving test data behind which then confuses things
      38863: CloudSync: minor: improve SyncTracker logging (push/pull)
      38862: ALF-14335 consolidate Sync REST APIs.
        I've added new URLs to all sync webscripts (except cloud-sync.post.desc.xml as it's singshot) which start with '/enterprise/sync'
        I have not removed the existing URLs as I'll give the new ones time to go through the dev/QA/PM system. I will likely delete the old URLs in a week or so.
        I have also changed the URL patterns in code in all the places where I see an obvious and risk-free change. This may be them all.
      38855: Ignore testPull - does not work in automated build.
      38854: ALF-14549: Add Sync panel to Folder Details Page
      38851: Renamed the sync util methods
      38850: ALF-14549: Added a panel to folder details page
      38848: merge conflict fixed
      38846: Merged from integrations/GoogleDocs/BRANCHES/THOR1_SPRINTS_GOOGLEDOCS to alfresco/BRANCHES/V4.1:
         - 31695 THOR-367 - #2 Document Library
         - 36307 Fixed THOR-1402 "Need a callback option for Create Content menu"- Will be revisited to add better comments
         - 36350 Fixed THOR-1402 "Need a callback option for Create Content menu" part 2- Changed callback obj to match action object better: { nodeRef, node, jsNode }
         - 36358 THOR-1402 "Need a callback option for Create Content menu" part 3- Changed "link" parameter to "href" (instead of "page") to match actions.
      (Changes by Erik, required for Google Docs minus changes made to privatemodules )
      38844: I have changed all occurrences of 'master' and 'slave' to 'source' and 'target' and these are the terms we should use to identify the two Alfresco instances in future.
      I believe that the only place this has leaked out into the remote API is at syncsetdefinition.post, which had a 'lockMasterCopy' parameter. This is now renamed to 'lockSourceCopy'. However, as that parameter was not supported on the back end, existing client software should continue to work.
      38839: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38835: CloudSync: minor cleanup (remove some obsolete code)
         38838: ALF-14907 Adding syncOwner firstName, lastName, userName and local root nodeRef to the remotesyncednode.get webscript.
      38837: Extra sanity checks
      38805: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38775: CloudSync: F24 subtask - ALF-14853 - move nodes "within" existing sync folder hierarchy 
         38782: ALF-14549: Add Sync panel to Doc Details Page
         38784: ALF-14549: (css fix)
         38798: Cloud sync component test - try injecting (lower case) transport bean directly.
         38799: Fix for community builds which do not have enterprise/repository.properties
      38802: Remove dev webscript that was incorrectly merged across (reverse merges r35946)
      38774: Fix broken merge of r35436 from BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         - Extends Doc Lib indicator config to support javascript actions on icon click
      (method had been refactored for ALF-12955)
      38773: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38703: Sync Tracker Component - First integration test of end to end push.
         38704: CloudSync: F31/F32 - add option to request delete of node(s) on target when unsync'ing
         38706: CloudSync: F24 - fix "rename" of a synced subfolder
         38712: build fix?
         38713: missed check in
         38714: ALF-14549: Add Sync panel to Doc Details Page
         38737: Sync Tracker Component Test - New test knocked over by changes to add person service.
         38743: CloudSync: F24 sub-task: ALF-14731 - fix SyncTracker (PUSH) such that nodes are processed in event order (earliest event for each node)
         38761: ALF-14549 (Added a new evaluator so that the sync panel will be only shown when the node has been synced)
         38763: ALF-14549 (Reverting the code from r38761 because the sync panel should be shown whether or not the node is synced)
         38767: Sync Tracker Component test - first pull.
         38769: CloudSync: delete + ano '=> delete 
      38700: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38685: ALF-14910: Sync Status dialogue's {status} info needs to be rendered on the server
         38686: CloudSync: ALF-14779: push delete 
         38687: Fixes: ALF-14871 - Uses a server side redirect for view in cloud URL (rather than returning JSON) to avoid pop up blockers and funny new window behaviour associated with window.open
      38699: A few more little bits missing from merges
      38698: Enterprise Repository.Properties needs to be included in a way that works for community builds (which won't have one)
      38691: Enterprise shouldn't be in core community services
      38690: Avoid double merge issue
      38689: Couple of context changes that got lost in merging
      38688: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38527: ALF-14549: Add Sync panel to Doc Details Page
         38537: ALF-14549: Add Sync panel to Doc Details Page
         38551: CloudSync: F24 - includeSubFolders (on SSD)
         38553: Do extra valdiation of cloud URLs when setting on the connector, and handle re-doing the RemoteTicketService initialization automatically if the URL or Key is changed at runtime (eg by a unit test)
         38555: ALF-14534: Add "include subfolders" HTML checkbox to cloud folder picker
         38557: Fixes bug where folder picker may keep spinning when loading folders.
         38562: CloudSync: F24 - includeSubFolders (on SSD) 
         38563: ALF-14893 - Bug from sprint 4 demo with conflict versioning.
         38565: CloudSync: F24 - includeSubFolders (on SSD) 
         38568: Bug fix
         38571: ALF-14534: Add "include subfolders" HTML checkbox to cloud folder picker
         38605: ALF-14542: Add "Request Sync" button to sync info dialogue
         38617: ALF-14542: Add "Request Sync" button to sync info dialogue
         38620: Add NodeServicePolicies.BeforeMoveNodePolicy (4.1)
         38628: Add NodeServicePolicies.BeforeMoveNodePolicy (4.1)
         38629: ALF-14779: push delete 
         38656: ALF-14598 Removed syncCreatorPerson property from code & replaced it with syncCreatorUsername.
               The d:noderef property is temporarily retained in the content model in order not to break anyone's DBs. It will be removed in a week or so.
               SyncTrackerComponent uses this userName when considering pushes/pulls but does check if the person exists.
         38658: Hides the sync action in the repository view
         38660: CloudSync: minor (change log level)
         38661: ALF-14779: push delete 
         38671: CloudSync: quick workaround fix for syncCreatorUsername
      38684: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38248: CloudSync: ALF-14708 - fetch for pull error handling
         38250: CloudSync: fix test (AuditToken NPE)
         38253: Fixed web script voodo for /sync/config - working for real now.
         38255: ALF-14525: CloudSync: Folder Sync - UI to enable current folder in Document Library to be synced
         38256: ALF-14551: Evaluator to determine if indicator icon should be displayed
         38258: Bug fixing for indicators. Synced idicator should not be shown if the sync failed idicator is shown. Also PropertyValueEvaluator has been deleted. The same result can be achieved with ValueEvaluator.
         38263: CloudSync: F29/F38 - Unsync web script: minor improvement - make use of common isDirectSyncSetMemberNode
         38264: CloudSync: ALF-14708 - fetch for pull error handling
         38265: CloudSync: F24 - recursive folders (wip)
         38267: CloudSync: ALF-14788 (F29/F38 sub-task) unsync of node (file or folder) should auto re-sync if it is below ano' parent folder sync
         38270: ALF-14625 remove sync:conflict aspect and props.
         38271: ALF-14541: CloudSync: Folder Sync - ensure sync'ed folder on target does not appear in source selector (when choosing target folder)
         38273: FIxes: ALF-14789 - minor bug in sync status dialogue
         38286: CloudSync: update AuditToken transport (pt I)
         38291: CloudSync: ALF-14790 - F4 sub-task - for pull of new node from tgt to src
         38301: Cloud Sync Status webscript updates: Finishes off: ALF-14593.
         38304: Adds Share support for access to "Big Switch" to turn Cloud Sync on/off & change mode. From Kevin. ALF-14773
         38315: CloudSync: update AuditToken transport (pt II)
         38317: CloudSync: update AuditToken transport (pt III) - fix unit test
         38324: MT: fix InvalidNodeRefException.getNodeRef()
         38325: CloudSync: create SSD - minor: logging + header lic
         38326: CloudSync: delete SSD - fix "transport" (use param not body for delete method)
         38333: ALF-14373. Added syncOwner property to SSMN aspect - this is copied from the SSD noderef when the member node is synced
         38335: CloudSync: ALF-14455 - push the SSD_TO_DELETE event to target
         38350: ALF-14545: Add error message for sync failed
         38351: ALF-14545: Add error message for sync failed
         38352: Reverted last commit (Deleted properties by mistake)
         38353: ALF-14394  cloud sync: Error details need to be returned over web scripts.
         38357: ALF-14760 - CloudSync: file sync with permission failure - AccessDenied on target causes repeated loop on source .
         38358: ALF-14760 - CloudSync: file sync with permission failure - AccessDenied on target causes repeated loop on source .
         38359: CloudSync: F24 - recursive folders (wip)
         38361: Bug fix for ALF-14545 (Cannot get the sync info if the content was successfully synced)
         38363: Adds syncMode to JS controller and improves error catching if nodeRef can't be found.
         38366: ALF-14751 - Localise sync version message
         38370: ALF-14666 - CloudSync: REGRESS - push/pull *update* no longer seems to work (metadata or content)
         38371: added enterprise repository.properties
         38374: Bug fix for ALF-14545 (css fix)
         38376: CloudSync: pull - invalid node 
         38380: ALF-14550: Cloud view for sync info dialogue
         38386: Added the enterprise/repository.properties
         38390: CloudSync: pull of new (folder) node from tgt to src
         38392: ALF-14608 - Synced (pulled) content must record a path to the Cloud nodeAdd the remote path to the version message
         38403: CloudSync: test fix (CloudTransportWebScriptsTest testPullChangedNodesForSSD)
         38404: Beefed up null detection on adding path.
         38407: Cloud Sync Evaluator and permissions sweep
         38411: Added TARGET_FOLDER_NOT_FOUND for Sync Service Create
         38418: ALF-14615 - Add global properties for CloudSync feature
         38422: ALF-14552: Changed the icon
         38429: ALF-14679 - The TransportService must transfer the locale of a document on sync
         38436: Adds proper syncOwner display to sync status dialogue. ALF-14293
         38437: Cleans up syncMode JSON.
         38445: Fixes error time display (ALF-14293)
         38446: CloudSync: minor (F24) - prevent indirect folder move for now (in same way as indirect file) - ie. cannot unsync indirect node
         38449: Minor Sync Status:
              - fixes template issue
              - minor css updates
              - adds support for "you" rather than current user's fullname in dialogue
         38461: CloudSync: temp build/tests fix - fallout from r38418 (ALF-14615)
         38469: ALF-14525: CloudSync: Folder Sync - UI to enable current folder in Document Library to be synced.
         38474: ALF-14525: CloudSync: Folder Sync - UI to enable current folder in Document Library to be synced. (Fixed the problem with an evaluator rather then fixing it in the JS side)
      38682: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         38023: First pass at json based exception transport
         38036: CloudSync: F25.5 - directSync prop
         38045: CloudSync: fix couple of NPEs - one for SyncNodeException transport and one for F25.5 (existing node / unboxing)
         38046: CloudSync: follow-on to r38045 - F25.5 (existing node / unboxing)
         38047: CloudSync: follow-on fix for F25.5 / ALF-14695 (existing node / unboxing)
         38052: CloudSync: minor test fix - CloudTransportWebScriptsTest.testPushFolder
         38055: ALF-14604 - First cut of "doing the right thing" with versions.
         38056: CloudSync: F25.5 - directSync prop
         38057: CloudSync: (Folder) Unsync (F29 / F38) 
         38058: ALF-14604 - First cut of "doing the right thing" with versions.
         38059: Undo incorrect check in from r38055
         38061: ALF-14690 : Add time stamp property to sync:failed aspect.
         38062: ALF-14525: CloudSync: Folder Sync - UI to enable current folder in Document Library to be synced
         38064: Different message for sync conflict.  ALF-14607 : Synced (successfully pulled) content must lead to version creation
         38066: ALF-14541: CloudSync: Folder Sync - ensure sync'ed folder on target does not appear in source selector (when choosing target folder)
         38068: ALF-14690 - correction to model
         38073: Failing property was added
         38105: Sync Status updates:
              - Correct Handling for status text (minus missing syncOwner and errorTime properties)
              - Fixes link handling within the dialogue
              - Adds sync:failed banner to DocLib (as per wireframes)
         38106: s/Sync'ed/Synced/
         38107: return statement was missing
         38116: CloudSync: F4 (folder sync - immediate files) - ALF-14745: skip files that are already SSMNs
         38120: ALF-14555: Upload indicator icon and indicator config
         38121: ALF-14604 - Turn auto version off   (model defaults to true)
         38122: ALF-14525: Change the icon and the text for the button
         38125: Remove sync node ref on returning node not exists error from cloud.
         38132: Small bug fix - previous change to disable autoVersionOnUpdateOfProps was over-writing cm:modified
         38133: Adding javadoc of exception types so I know which one is which.
         38163: Adds link to DocDetails page (ALF-14546)
         38165: Better error handling if the remote nodeRef can't be found.
         38173: CloudSync: ALF-14501 (F13 / F14) - Request Sync
         38175: ALF-14556: Refactor dialogue to be based on the DAM info popup 
         38176: ALF-14556: Refactor dialogue to be based on the DAM info popup (Merge conflict fixed)
         38180: ALF-14540: Add "Request Sync" doc lib action
         38187: Changed the properties for Request sync
         38188: Fix for ALF-14657 Add targetParentNodeRef to remotesyncednode webscript.
         38191: ALF-14542: Add "Request Sync" button to sync info dialogue
         38199: ALF-14575 - Wire up big switch to turn on or off Cloud Sync
             - addition of the big switch - does nothing at the moment.
         38200: ALF-14540: Add "Request Sync" doc lib action
         38201: Sync Change Monitor not enabled if big switch is "OFF"
         38202: Sync Tracker does nothing if not on premise.
         38205: CloudSync: ALF-14708 - fetch for pull error handling (wip)
         38213: Correction to sync tracker component.
         38221: ALF-14271 Move the registration of Cloud with the RemoteTicketService to bootstrap, to avoid audit problems during init
         38235: Work in progress on Rest call for /sync/config
              (Hard coded ON_PREMISE - cant get ${syncMode} to work)
         38236: minor formatting
      38680: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         37715: Check in empty SyncTrackerComponentTest
         37716: ALF-14338 - extends unit test for SyncServiceImpl create method
         37717: Ignore imcomplete tests checked in by r37715
         37721: CloudSync: Folder Sync - ALF-14566: add behaviours to add/remove SSMN
         37724: Update SyncNodeException to use an enterprise-only message bundle for the exception detailed error message. This message can potentially also be re-used on the UI
         37728: Add unit tests for pushing a cm:folder through the transport. (Works much like an un-versioned node with no content changes)
         37734: Start to migrate the remote ssd creation calls out of SyncAdminService, and to CloudSyncSetDefinitionTransport, removing migration TODOs in the process
         37735: Migrate the deleteSSD remote call from SyncAdminImpl to CloudSyncSetDefinitionTransport
         37736: Have the deleteSSD transport layer properly handle/transport NoSuchSyncSetDefinitionException
         37737: Review and add SyncNodeException and NoSuchSyncSetDefinitionException to node level transport webscripts where needed
         37741: Refactor on-enterprise sync transport exception handling, to work for both push and pull cases, and start to support the same degree of handling for pull
         37767: CloudSync: Folder Sync: ALF-14590 - disallow individual unsync of file (or sub-folder) if member of a folder sync
         37785: CloudSync: fix mockito tests (ssmChangeManagementTest)
         37787: CloudSync: fix mocked unit test (nodeRef format + authorization)
         37791: CloudSync: fix more mocked unit test (nodeRef format + authorization)
         37797: The folder picker showed a second button without text when "secondaryTenants" was empty.
         37803: Ripped out adding sync:conflict aspect and implemented "cloud wins" conflict resolution.   
         37820: CloudSync: build/test fixes - TEMP ignore push/pull test - to see if it affects follow-on tests (or not)
         37823: CloudSync: Folder Sync - ALF-14566: add behaviours to add/remove SSMN
         37843: Typo correction
         37844: ALF-14580: View In Cloud action should open links in new window
         37846: ALF-14453: CloudSync: Create sync UI - shows site twice and also title shows "title.multi"
         37850: CloudCloudSync: Folder Sync: ALF-14624 - create file on target (within sync'ed folder) and then pull to source
         37870: ALF-14540: Add "Request Sync" doc lib action
         37871: ALF-14543: Add "Request Sync" multi-select action trigger
         37883: Support for transporting the node path, for use in messages and displays, and update the tests to cover this
         37888: "Sync to cloud" and "Request sync" actions were not available for multi-select action trigger
         37890: CloudSync: ALF-14647 - failing unit tests ...
         37894: CloudSync: ALF-14651 - after push, the source node may appear modified by "System (User)"
         37895: Temporary work around for Transport of SyncNodeException - exception does not contain "cause" its all "precondition failed".
         37902: ALF-14292: Add check box to disable auto-sync
         37903: ALF-14537: Add HTML checkbox to lock src copy 
         37908: CloudSync: SyncService.fetchForPull 500 error => map InvalidNodeRefException to SyncNodeException
         37909: CloudSync: ALF-14656 - create folders before files (when pushing a sync set)
         37912: ALF-14661 & ALF-14662: Add sync:syncSetMemberNode and sync:failed filters to Doc Lib.
         37922: Fix up exception messages - must be defined in the message file, not in comments
         37923: Tidy up a little the exception building
         37924: CloudSync: doFetchAndAction 500 error => map InvalidNodeRefException to SyncNodeException
         37944: Swallow SyncNodeException from PULL.
         37947: Adding aspects to the node as a requirement for ALF-14541
         37949: Cloud Sync F26/F93 (WIP): 
              - Adds View in Cloud link to location if it can't be retrieved: ALF-14464
              - Swaps dialogue date rendering from relativeDate to relativeTime w/ hover state: ALF-14539
              - Adds support for unsynced nodes: ALF-14528
         37951: ALF-14597: Remove previously needed UI conflict indicators
         37956: ALF-14554: Create evaluator & update existing evaluators
         37957: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              37952: Added new API methods to template Site helper - to retrieve Share URL stem and Share URL for a given site.
         37958: Adds shareURL to metadata object in node data webscript
         37961: More debug in SyncServiceImpl
         37964: CloudSync: ALF-14271: workaround startup error (init -> bootstrap sequence) for CloudConnectorService/RemoteAlfrescoTicketService
         37965: ALF-14666: CloudSync: REGRESS (?) - push update no longer seems to work (metadata or content)
         37967: ALF-14440 : Creating sync file when target already has a file of the same name -> causes 500 error
             Removed a TODO: It is correct to throw an exception rather than over-writing a node.
         37970: Fixes JSON that was broken in r37958
      38677: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         37534: Transport for double and float property values
         37537: CloudSync: SyncServiceImpl - minor: start to cleanup debug logging (to make it more useful / consistent)
         37538: Quick fix for the NullPointerException in ALF-14449.
         37539: CloudSync: ALF-14378 - pull sync changes - only the target nodeRef is required
         37540: Fix up the pull unit test, and add tests checking all the different kinds of property value transport
         37542: Add unit tests for notification of a conflict through the transport layer
         37553: ALF-14445 After changing the cloud url for use with the local loopback connector, re-init the service to ensure the url passes all the way down the stack
         37555: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              37554: Follow-on fix to ALF-9661 - do not fire update rule (onDeleteAssociation) if node also no longer exists
         37556: ALF-14445 After changing the cloud url for use with the local loopback connector, re-init the service to ensure the url passes all the way down the stack
         37558: Fixes "View In Cloud" link
         37563: Avoid exceptions in the logs for expected problem cases of Conflict and Not Currently Acceptable (cloud busy etc)
         37565: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              37564: Pull out some bits to constants, so downstream classes can more easily configure themselves
         37567: ALF-14356: Updates look and feel of user profile cloud sync panel as per wireframes.
         37574: Call version service to ensure cloud nodes are versioned.
         37575: ALF-14430 - First conflict on both ends.
         37576: CloudSync: ALF-13948 - F29 (Unsync)
         37597: Temporarily disable the failing SyncServiceImplTest.testCreate so we can get green builds
         37600: CloudSync: follow-on to r37597 (temporarily disable/ignore unit test)
         37611: Fix for: ALF-14461: Site manager can't unsync content.
         37616: CloudSync: SyncTracker (push) - ALF-14459: One failed sync causes subsequent (unrelated) syncs to fail
         37617: ALF-14464 - For now, slightly ignore "unauthorised" error when attempting to get cloud location.
         37619: Stub out some CloudSyncSetDefinitionTransport unit tests, and begin with testing handling of connector exceptions
         37622: Unit tests for exceptions from the connector for SyncMemberNodeTransport
         37629: ALF-14460 - Content edits of synced documents lead to failed syncs
         37631: Reinstate SyncServiceImplTest.create
         37639: CloudSync: ALF-14358 - REST API to get SyncSet Changes
         37640: CloudSync: ALF-14378 - SyncTracker PULL - remove x2 temp to lookup/set sourceNodeRef ...
         37650: CloudSync: ALF-14248 - remove auditing of "create SSD" (since it is now synchronous) and fix up unit tests and other related ref's
         37660: CloudSync: fix build/test (SyncAuditServiceRestApiTest.testGetSyncSetChanges) 
         37669: Enables folder sync actions in the UI
         37680: Support, and unit tests, for transporting multivalued node properties, and mltext node properties
         37682: ALF-14514 : Added aspect sync:failed
         37686: Add unit tests for the Sync Set Definition transport webscripts, and start on tests for the transport of cm:folder
         37688: ALF-14338 - Introduce SyncNodeException.
         37689: CloudSync: folder sync: ALF-14521 - update SyncSetDefinitionPost
         37698: Convert SyncNodeException to be backed by an Enum, so we can effectively transport the different types of problem. Adds an initial list of problem enums, which are message backed (but not yet in properties)
      38672: Fix up merge problems
      38665: ALF-13260: Mysql does an awful planification of ibatis "select_ChildAssocOfParentByName" query after some heavy load
         - improved "select_ChildAssocOfParentByName" where clause to engage existing index
      38662: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         37061: ALF-14265 - CloudSync: fix failing tests - Activiti/JBPM WorkflowRestApiTest*
         37071: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              35409: Merged HEAD to BRANCHES/DEV/V4.0-BUG-FIX:
                   35399: ALF-12874: Schema reference files are out of date.
         37072: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              35781: Fix for MySQL part of ALF-13150: Performance of Purging Empty Transactions (like 10M)
                   ALF-13839: MySQL: "Failed to purge txns" from DeletedNodeCleanupWorker
                   - Added MySQL override of the NodeDAO for this call with a dedicated DELETE ... JOIN ... for MySQL
         37077: Fix how we pull the mimetype and encoding of the content from the content type, and add unit tests for this
         37078: Reverse accidental property change
         37084: Cloud Sync Push - Work in progress.   Adds 2 new methods to the cloud sync member node transport.    And an "AuditToken" opaque type.
         37118: Implementation of ALF-14324. Get Cloud NodeRef, Network for specified local syncset member node.
         37132: ALF-14324 Changed API so that if a remotesyncednode has no matching remoteNodeRef (due to not being synced) then the JSON field is not rendered. It had been rendering an empty string.
         37133: ALF-14324. I forgot to check in the associated test code edit for previous checkin. (37132)
         37136: Cloud Logins need to occur on the default network (we have no others until after login)
         37139: Upgrade to Commons FileUpload 1.2.2, and add in the source
         37147: Start on the FileUpload support for the pull case, and begin sending appropriate request data
         37150: Added a package-info.java to document the main components of the feature. (Ongoing)
         37153: ALF-14324. Tweak to URL for remotesyncednode.get. NodeRef as query param, rather than template arg.
         37166: Refactor things to allow for re-use in the Pull code flow, and mostly implement the Pull code. Initial tests added, but needs a real service call to fetch the SyncNodeChangesInfo before the rest can be done
         37182: ALF-14334: update CloudSyncSetDefinitionTransport to call REST getSyncSetManifest
         37183: ALF-14334: fix "syncsetmanifest" descriptor
         37187: ALF-14334: fix build/unit test (tearDown)
         37198: Minor: test improvement - fix format of dummy nodeRef
         37201: Cloud Sync - Cut over sync jobs.
         37203: Changed cron expression.
         37206: CloudSyncTrackerComponent - minor locking changes.
         37220: SyncTrackerComponent.pushSyncSet - runAs syncCreator
         37221: Fixes broken JSON
         37227: Add the pull support method to SyncService, stub out some more tests, and add AuditToken related TODOs in appropriate places
         37229: Pull unit tests
         37237: CloudSync: ALF-14358 - REST API to get SyncSet Changes - list of target nodeRefs (with changes) for a given ssdId
         37238: CloudSync: ALF-14312 - REST API to get SyncSet Manifest
         37248: ALF-14287: Fixes Cloud Folder picker to work with real cloud instance.
         37249: Minor revision bump on JSON-Simple, and attach the source
         37251: Implement AuditToken, initially taking SyncChangeEvent objects and storing just the full list of audit IDs for them. AuditToken handles the JSON serialization itself, with the Transport delegating. Adds unit tests
         37262: ALF-14287: Fixes handling for invited networks
         37277: SyncTrackerComponent.pullSyncSet - runAs syncCreator
         37283: ALF-14287: Fixes bug when folder picker is loaded repeatedly.
         37285: Store OtherNodeRef as String on the cloud end.
         37286: Pass-Through URLs are decoded in the surf layer, so re-encode before requesting
         37290: Tweak URL encoding used to not escape /
         37294: Update teh json-simple dependency definition to match change yesterday
         37306: Update jar names in build files which hard code things
         37309: CloudSync: ALF-14358 - REST API to get SyncSet Changes - list of target nodeRefs (with changes) for a given ssdId
         37310: SyncTrackerComponent.pullSyncSet - TEMP change to determine/set the sourceNodeRef ...
         37314: Fixes build so that it adds client side cloud files to documentlibrary actions js
         37316: Stub out the webscript for accepting the confirmation of a pull
         37319: Add method to "confirm" (delete) audit ids from an AuditToken
         37322: Sync tracker component - Error processing for missing sync set owner
         37324: API updates for the Pull Confirm, and start on the transport
         37325: Fix compile error - apparent fallout from r37322 (missing svn up ?)
         37331: Implement the confirm pull logic in the webscript (calls SyncAuditService to do the real confirmation), and start on unit test for this (more to follow tomorrow)
         37342: Minor: SyncTrackerComponent
         37349: SyncTrackerComponent.pullSyncSet
         37355: CloudSync: SyncTracker - minor: debug logging is quiet when nothing to do ...
         37365: CloudSync: ALF-14358 - REST API to get SyncSet Changes
         37367: Ongoing work to SyncTrackerComponent.
         37376: cloud sync - TODO comment updates
         37379: ALF-14292 - Refactor cloud sync status code.
         37380: WIP - Doc Lib Synced Content Filters
         37381: WIP - View in cloud URL wrapper.
         37438: CloudSync: ALF-14358 - REST API to get SyncSet Changes
         37440: CloudSync: possible fix for failing unit test (SyncAuditServiceIntegrationTest.queryForSsdManifestAndDetails) -> disable jobs(sync tracker)
         37442: CloudSync: temporarily comment out CloudTransportWebScriptsTest.testConfirmPull unit test (NB is updating + fixing)
         37446: ALF-14396CloudSync: PULL - fix source modifier (currently appears as "System User")
         37461: Add equals method to allow easier unit testing, and a toString to help with debugging
         37462: Fix up the confirmPull transaction handling to solve the test failure, then expand out the unit testing to cover this new code
         37463: Set conflicted aspect on local node after pull conflict.
         37474: Fixes: ALF-14427: Adds missing icon for multi-select sync action.
         37476: ALF-14425 - When a synced node is copied, its syncSetMembeNode aspect must not be copied
         37486: Start of sync transport refactoring to support pushing conflict and unsync details
         37489: Enhances Balloon dialogue to detect other balloon pop ups and hide them to prevent overlapping balloons.
         37490: Initial transport support for pushing the details of a conflict over. (Tests to follow)
         37494: ALF-14289: Adds Conflict Icon and Balloon.
         37495: Stub out un-sync and push conflict tests, full checks to follow
         37496: Rework to SyncTrackerComponent to deal with conflicts only on pull.   And lock against push and pull of the same node at the same time.
         37500: CloudSync: ALF-13948 / ALF-14404 - F29 (Unsync)
         37501: Correction to previous check in.
         37504: Add unit tests for un-sync and delete
         37505: CloudSync: remove obsolete OnPremiseSyncJob (superceded by push/pull jobs)
         37507: Unit tests for Push Conflict
         37511: Fix for ALF-14428. Metadata are not extracted for synced nodes.
         37512: ALF-14279: Displays remote path, including network, site and document. (WIP: Links still need fixing...)
         37513: Addendum fix to ALF-14428. Now also sending cm:author and cm:geographic metadata
         37520: CloudSync: ALF-13948 / ALF-14404 - F29 (Unsync)
         37522: ALF-14283: Missed file from previous commit
         37527: SyncTrackerComponent - removed node locking.   Realized it was not cluster safe - so the stuff has to work without locking.    I think it does now.
         37528: ALF-14396  CloudSync: PULL - fix source modifier (currently appears as "System")
         37530: Cleans up the cloud folder picker init & removes bug with -default- getting sent as the networkId during SSD create.
      38659: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         36246: Start to wire up the transport and on-cloud services
         36250: Interface change to SyncService + beginnings of implementation.
         36251: Tweak webscript definitions, and add comments to explain a few bits
         36253: Start on unit tests for the transport - test framework and suitable mock services for testing
         36257: Start on the sync transport unit tests
         36258: Bit more on the cloud transport testing, and disable the bit for now that depends on more of the transport being implemented
         36261: Sync Service - More implementation.
         36280: Added aspect sync:synced to remember when we last successfully synced.
         36288: Implement a few more bits of the transport service, fix the way the charset and boundary information is sent, and a bit more of the tests
         36293: Nobble the sync webscripts in the unit test to use our mock service, then expand the tests to query+check the mock for what was sent through
         36305: First unit test of SyncService.create method.
         36315: Update the method signature on SyncAdminService, to match the pattern used by the other services WRT cloud credentials. Then, fix up credentials related TODOs in the service and webscript, and fix tests to match
         36319: Test basic integration between sync-sets and the cloud sync transport
         36353: Support for encoding and decoding non-content properties, and content properties which have been removed
         36359: ALF-13960. Partial implementation. REST API for the creation of SSDs on the Cloud.
         36360: Versions of the CloudConnector and CloudSyncOnCloud services suitable for unit tests
         36396: Tweak exception inheritence to better fit with transaction rollbacks, and finish the sync occurr/proceed unit tests
         36400: Expand the push sync unit test coverage, to include aspects and properties
         36401: adding toString method for better debug.
         36402: Sync Service: event suppression working so create method now does not report false conflicts.
         36403: More sync push tests, content parts still TODO
         36410: Fix for failing test cases on Bamboo.
         36414: Finish the push content unit tests, including a fix for a missing runAs, and an option not to tidy up temp files immediately so that the unit tests can still find their contents after the transaction
         36415: Add unit tests for SyncServiceImpl delete and remove from sync set.
         36417: Tweak to SyncAudit event disabling - centralised in SyncChangeMonitor. Required for upcoming changes in SyncAdminService
         36420: Preventing auditing of SSD_CREATED when creating Cloud SSDs.
         36429: Impl of ALF-14147. Create a CloudSync subsystem.
         36439: SyncService - unit test for update.
         36462: SyncService Impl - added tests for update content and setting cm:modified + fix for update which forgot to set modified.
         36557: Adding audit ids to SyncNodeChangesInfo. Part of ALF-13962.
         36558: ALF-13962 Some utility methods on SyncChangeEvent.
         36559: ALF-13962 Methods on SyncAdminService to check node membership.
         36561: ALF-13960 Ensure that syncsetdefinitions are created in a transaction.
         36567: ALF-13962. Conversion of audit entries into required SyncNodeChangesInfo object.
         36568: ALF-13962. package-info documentation.
         36571: ALF-13962. Expose the properties/aspects configured for tracking - as required by SsmnChangeManagement.
         36573: ALF-13962. Addition of extra property in sync model.
         36575: ALF-13960, ALF-13961, ALF-13963
         36586: Avoid sending dummy credentials when creating a sync set, as real ones are now supported
         36644: Fixes syntax error when files are concatenated.
         36807: Mark manually merged change
         36812: CloudSync: ALF-14250 - record source repo id (related to SSD) with all sync audit entries
         36848: CloudSync: ALF-14250 - record source repo id (related to SSD) with all sync audit entries
         36856: ALF-14270 Ensure that the sync:syncSetDefinition QName is forcefully created during system startup.
         36865: When storing cloud credentials, return information in the json to distinguish the two failure cases
         36866: When storing cloud credentials, return information in the json to distinguish the two failure cases
         36878: ALF-14270 Move the call to create the remote SSD from the audit event-handling code to a synchronous call within SyncAdminService.createMasterSyncSet()
         36897: Adds ALF-14286: Shows user a "validating" message whilst the auth details are being validated.
         36903: CloudSync: ALF-14250 - record source repo id (related to SSD) with all sync audit entries
         36914: ALF-13961 Minor tweak ro OnPremiseSyncJob (runas in order to have valid SecureContext).
         36916: Start to rename CloudSyncTransportService to CloudSyncMemberNodeTransport
         36918: Define the SSD Transport Service
         36919: Comments out UI toggles for features that don't (yet) exist deeper down the stack.
         36921: ALF-14297 This check-in completes the tests for change log entry aggregation and adds detection of non-uniform NodeRefs
         36924: Work in progress on sync push and pull jobs
         36926: Stub out a dummy implementation of CloudSyncSetDefinitionTransport. (Needs remote webscripts and service calls before it can be properly implemented)
         36931: Fix an autounboxing NullPointer error.
         36937: ALF-14262 CloudSync: fix failing test cases for CLOUDSYNCLOCAL2 branch
         36955: CloudSync: ALF-14298 - SyncAuditService: provide query to get ssd manifest for a given sourceRepoId 
         36967: Fix CloudTransportWebScriptTest unit tests - contract is null not empty
         36975: Some useful collection helper methods that I'm about to use elsewhere.
         36979: ALF-14297 Build fix. Refactor of SsmnChangeManagement to respect SyncNodeChangesInfo's use of null collections for 'no change'
         36980: Ensure audit entries are deleted on push (old sync job)
         36987: Push Job work in progress.
         37017: CloudSync: ALF-14312 - REST API (for SyncAuditService) - query to get SyncSet Manifest
         37028: Changes to SsmnChangeAggregation so that the ContentReaders are set correctly.
         37029: Fixes to failing test cases.
         37035: CloudSync: ALF-14298 / ALF-14312 - SyncAuditService: provide query to get SyncSet manifest
         37049: Fix failing rest unit test - wire the Mock Cloud Connector up to the WebScripts too, not just the services
      38655: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35946: Do not merge - dev helper webscript for checking chunking and multi-part requests are behaving correctly
         36016: Miscellanous minor improvements as part of tidyup.
         36017: Trivial changes to non-product code for demo.
         36088: Stub out how content changes will be handled
         36116: Version Labels, Stub (with a bad name...) service to check about sync allowed + intervals, and much more of the encode/send/webscript/decode code
         36157: SyncService methods - no-op implementation.
         36163: Fix typo in url generation
         36167: adds View In Cloud action
         36171: Support sending and getting the local and remote parent noderef (especially important for create)
         36175: Add json helper methods for common types
         36181: First cut of aspect sync:conflict to mark conflicted nodes.
         36182: Extend SyncService API.
         36195: Transport support for the list of aspects added/remove
         36201: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              36193: Pull out the Thread-local HttpClient creation from RemoteClient, and expose. Will go back into Surf at some point
              36194: Convert to using the ThreadLocal HttpClient instances, and some extra steps to ensure we always tidy up after ourselves now the instance is shared
         36205: Update Services to match new plan agreed yesterday, and start to wire the implementations up to the work Mark is doing
         36207: Finish the initial version of the sync push webscript, which largely uses other services to decode the request and have it actioned
         36208: Initial support for wrapping a delete/unsync call with all the details, before passing on to the SyncService to perform
         36209: Refactor the push webscript, so most of the logic for decoding the request is in a parent class, and then stub out the delete / unsync webscript built on top of the new common abstract parent
         36212: Build fix.
         36213: Trivial tweaks to test code.
         36214: Cleanup of temporary nodes created during test execution.
         36215: Changing syncChangeMonitor behaviour binding to onBootstrap rather than during spring init.
         36216: Moved audit model for SyncChanges into an enterprise folder.
         36217: Build fix (2)
      38653: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35543: Start on the Enterprise/Cloud simple Tenancy information webscript
         35551: Make it easier to override bits of TenantInformationGet
         35629: Mark merges that have been done
         35638: Mark merges that have been done
      38651: Mark revisions which were implicitly merged via 4.0bf
      38646: Mark revisions which were implicitly merged via 4.0bf
      38643: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35959: Stub out part of the cloud sync transport code and webscripts, which will handle getting changes between the on-premise and cloud repos
         36005: UI Updates for Cloud Sync Sprint 2:
              - Node Path Webscript (WIP)
              - Adds Sync Status Webscript
              - Adds Unsync option
              - Tweaks Doc Lib Indicator action call to include target element (makes it easier to position balloon dialogues).
         36006: Start on implementing the transport code, and a few tweaks to the plan as identified by the implementation so far
         36013: Broadened the aspect behaviour binding so that it captures all relevant aspect addition/removals.
         36015: Missing class from previous checkin (36013)
      38642: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35690: Merged BRANCHES/DEV/V4.0-BUG-FIX/ to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              35689: Add the NameSpace constants for the Links model
         35697: Improve Network detection, and avoid passing the network parameter on the URL to the cloud
         35701: Enable another URL for passthrough
         35713: Filling out the data in the REST APIs for POST & GET SyncSetDefinition.
         35717: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              35716: Make overriding just the Share URL easier (needed for Cloud installs)
      38641: Mark r35681 as already merged
      38640: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35615: Cloud Sync: Fixes URLs to temporary APIs.
         35642: Mostly implementation of syncsetmembership.delete.
         35644: Fixing a failing test case. More fixes to come...
         35662: Cloud Proxy Pass-Through for /slingshot/doclib2/node as /cloud/doclib2/node
         35681: Merged BRANCHES/DEV/V4.0-BUG-FIX/ to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              35679: Fix DataList QName hard-codings by pulling out to a proper Model Java Constants Interface
      38639: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35508: Sync Audit Service progress.
         35509: Fixing up some broken imports, no other changes.
         35510: Add some debug logging to the cloud connector service, and expand the WebScriptPassThrough tests and underlying auth helper
         35544: Remove accidental property change in last commit
         35561: Support proxying the Tenant Information webscript to the cloud as the current user
      38637: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35440: Better handling of requests with no request body
         35441: More Cloud Connector Pass-Through unit tests, including a dummy webscript (test only) which can be used to check who a request was proxied as
      38636: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35385: Stop aliasing local webscripts into cloud urls, we now have the proper pass-through proxy
         35387: Allow Enterprise Remote API tests to see Enterprise WebScripts - fix the Enterprise Remote API classpath in Eclipse, and add BaseEnterpriseWebScriptTest which brings up the server including the entprise context file
         35403: REST Unit Test for the Cloud Credentials CRUD WebScripts, and stub out the Cloud WebScript Pass-Through unit tests
         35436: Extends Doc Lib indicator config to support javascript actions on icon click
         35437: WIP: Indicator config, i18n string and stub function for Cloud Sync status display.
         35439: Support a special TESTING method, and have requests done explicitly as Guest if no cloud credentials exist
      38635: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35333: Start on enabling the Cloud Proxy PassThrough for certain key webscripts that the UI needs
         35363: Adjusts credentials success check following a change in the API last week.
         35382: Adds ability to delete Cloud credentials from the My Profile page.
         35383: Removes unused Sync Now function
         35384: Adds cloud folder picker JS to combined action files so that sync works without debug mode.
      38634: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35238: Implement the Cloud Credentials Get webscript, powered by the new services, and provide a cloud webscript helper superclass
         35282: Cloud Sync Audit.
         35283: Enable the credentials get/set webscripts to work (fixing an authentication issue), and initial work on proxy webscript
         35287: Cloud Sync Audit. Support for deletion of Sync Audit entries.
         35315: Service, WebScript and tests for deleting remote ticket based and cloud credentials
      38633: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         35236: Add the CloudConnectorService, which wraps the underlying remote services in a cloud specific way (base url, system id, key etc)
      38623: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         34882: First cut of SyncChangeMonitor feature.
         35027: Adds ability to select target network & plumbs in the options, makes it easy to add more options.
         35110: Adds support for hasAspects and notAspects attributes to Doc Lib multi-item select.
         35113: Cloud-Sync: Adds multi-file sync action.
         35122: A big chunk of Sync Audit Service work.
      38622: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         34717: Merged BRANCHES/DEV/CLOUDSYNCLOCAL to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34403: Adds DocLib action, indicator config and labels, along with start of evaluator config.
              34404: Adds action implementation & cloud folder picker alfresco module, with template webscript. Modifies build to include new js file in concatenated doclib action file.
              34405: Modifies the Global File picker to make the API calls more extendable (e.g. for use in Cloud Sync).
              34481: Adds ability to enter cloud auth details from user profile page. Needs a little bit of refactoring once the APIs have been finalised
              34482: Adds Work In Progress on Cloud Auth prompt
              34667: WIP: Mocked up APIs - formats mostly merged from demo
              34687: Initial cut of part of SyncAdminService which manages CRUD of SyncSetDefinitions.
              34688: The most basic documentation the webscript.
              34693: Action and Indicator icons from Linton
              34694: Inline Cloud Auth Details Dialogue
              34695: Cloud Synced Indicator updates
              34714: Creates sync set when a folder is chosen.
         34744: Fixes bug where multiple actions were triggered for each successive click on the Cloud Sync action
         34745: Updates Evaluator with name of actual aspect applied to items in a sync set.
         34757: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34289: Upgrading JUnit lib to 4.10 to get full Rules support.
              34317: Some initial documentation on JUnit Rules samples.
              34328: More JUnit rules fun. Added a new rule to help with the creation and automatic cleanup of temporary test nodes.
         34759: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34290: Fixing Eclipse settings following on from previous JUnit lib upgrade. (rev 34289)
              34297: Build fix. Eclipse project was still referring to the old JUnit lib.
         34765: Fixes a couple of typos before today's Sprint demo. Success and error messages now correctly display following sync action.
         34782: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34777: Added enhancement to TemporaryNodes rule to allow for dummy content.
         34806: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34805: Added a convenience method to the ApplicationContextInit @Rule to allow for easier spring overriding in test code.
         34825: Merged HEAD to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              34824: Utility methods to get details of property changes (map comparison).
      38619: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/V4.1:
         36805: Tweak exception inheritence to better fit with transaction rollbacks
         36806: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/DEV/V4.0-BUG-FIX:
              36556: A useful collection conversion utility method.
      38616: Merged BRANCHES/DEV/CLOUDSYNCLOCAL2 to BRANCHES/V4.1:
         36366: Tweak to implementation to ensure that on-authentication-failed, the status is updated within a r/w transaction.
         36374: Provide more specific exceptions from the Remote Connector Service for client and server errors
         37348: ALF-14386 - RemoteConnector: NPE if responseBody is null (eg. HTTP 204)
         37411: Merged BRANCHES/DEV/V4.0-BUG-FIX to BRANCHES/DEV/CLOUDSYNCLOCAL2:
              37410: ALF-14386 HttpClient returns a null byte array if there is no response body (eg 204), swap that for an empty array to avoid NPEs and better fit the interface contract
      38559: Merged PATCHES/V4.0.2 to V4.1
         38364: Merged V3.4-BUG-FIX to PATCHES/V4.0.2
            36421: ALF-14914: Fix for Mac Lion versioning issue. ALF-12792 (Part 1 of 2)
               Enable the InfoPassthru and Level2Oplocks server capability flags, InfoPassthru is the flag that fixes the Mac Lion versioning error.
               Added support for filesystems that do not implement the NTFS streams interface in the CIFS transact rename processing, for the Alfresco repo filesystem.
            36422: ALF-14914: Fix for Mac Lion versioning issue. ALF-12792 (Part 2 of 2)
               Enable the InfoPassthru and Level2Oplocks server capability flags, InfoPassthru is the flag that fixes the Mac Lion versioning error.
            36423: ALF-14915: Add support for file size tracking in the file state. ALF-13616 (Part 1 of 2)
            36424: ALF-14915: Fix for Mac MS Word file save issue. ALF-13616 (Part 2 of 2)
               Added live file size tracking to file writing/folder searches so the correct file size is returned before the file is closed.
            36491: ALF-14915: Added CIFS transact2 NT passthru levels for set end of file/set allocation size. ALF-13616.
               Also updated FileInfoLevel with the latest list of NT passthru information levels.
            36703: ALF-14916: Fix for Mac Office 2011 Powerpoint save fails on CIFS. ALF-13615.
         38367: Merged V4.0-BUG-FIX to PATCHES/V4.0.2
            37630: Process queued responses at the end of the thread request run, before re-enabling socket read events. ALF-14179, ALF-14180.
         38368: Merged V4.0-BUG-FIX to PATCHES/V4.0.2
            37067: ALF-13294	CIFS: When versionable aspect is active, using the Microsoft Word for Mac 2008 option "always create a backup copy" leads to document versions loss
      38244: ALF-14785: Merged V4.0-BUG-FIX to V4.1
         37482: ALF-14437: Merged HEAD to V4.0-BUG-FIX
            37388: ALF-13545: First attempt at digitally signing the Windows installers
            37391: ALF-13545: Fix quoting and output directory specification
            37393: ALF-13545: Correct deployment installer signcode command


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40271 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2012-08-10 07:55:53 +00:00

781 lines
26 KiB
Java

/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.imap;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import javax.mail.Flags;
import javax.mail.MessagingException;
import javax.mail.Flags.Flag;
import javax.mail.internet.MimeMessage;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ImapModel;
import org.alfresco.repo.imap.AlfrescoImapConst.ImapViewMode;
import org.alfresco.repo.imap.ImapService.FolderStatus;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.util.GUID;
import org.alfresco.util.Utf7;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.icegreen.greenmail.foedus.util.MsgRangeFilter;
import com.icegreen.greenmail.store.FolderException;
import com.icegreen.greenmail.store.FolderListener;
import com.icegreen.greenmail.store.MailFolder;
import com.icegreen.greenmail.store.MessageFlags;
import com.icegreen.greenmail.store.SimpleStoredMessage;
/**
* Implementation of greenmail MailFolder. It represents an Alfresco content folder and handles
* appendMessage, copyMessage, expunge (delete), getMessages, getMessage and so requests.
*
* @author Mike Shavnev
* @author David Ward
*/
public class AlfrescoImapFolder extends AbstractImapFolder implements Serializable
{
private static final long serialVersionUID = -7223111284066976111L;
private static Log logger = LogFactory.getLog(AlfrescoImapFolder.class);
/**
* Reference to the {@link FileInfo} object representing the folder.
*/
private final FileInfo folderInfo;
/**
* Name of the folder.
*/
private final String folderName;
private final String folderPath;
private final String userName;
private final int mountPointId;
/**
* Defines view mode.
*/
private final ImapViewMode viewMode;
/**
* Reference to the {@link ImapService} object.
*/
private final ImapService imapService;
/**
* Defines whether the folder is selectable or not.
*/
private final boolean selectable;
private final boolean extractAttachmentsEnabled;
/**
* Cached Folder status information, validated against a change token.
*/
private FolderStatus folderStatus;
private static final Flags PERMANENT_FLAGS = new Flags();
static
{
PERMANENT_FLAGS.add(Flags.Flag.ANSWERED);
PERMANENT_FLAGS.add(Flags.Flag.DELETED);
PERMANENT_FLAGS.add(Flags.Flag.DRAFT);
PERMANENT_FLAGS.add(Flags.Flag.FLAGGED);
PERMANENT_FLAGS.add(Flags.Flag.SEEN);
}
public boolean isExtractAttachmentsEnabled()
{
return extractAttachmentsEnabled;
}
/**
* Protected constructor for the hierarchy delimiter
*/
AlfrescoImapFolder(String userName, ServiceRegistry serviceRegistry)
{
this(null, userName, "", "", null, serviceRegistry, false, false, 0);
}
/**
* Constructs {@link AlfrescoImapFolder} object.
*
* @param qualifiedMailboxName - name of the mailbox (e.g. "admin" for admin user).
* @param folderInfo - reference to the {@link FileInfo} object representing the folder.
* @param folderName - name of the folder.
* @param viewMode - defines view mode. Can be one of the following: {@link AlfrescoImapConst#MODE_ARCHIVE} or {@link AlfrescoImapConst#MODE_VIRTUAL}.
* @param rootNodeRef - reference to the root node of the store where folder is placed.
* @param mountPointName - name of the mount point.
*/
public AlfrescoImapFolder(
FileInfo folderInfo,
String userName,
String folderName,
String folderPath,
ImapViewMode viewMode,
boolean extractAttachmentsEnabled,
ServiceRegistry serviceRegistry,
int mountPointId)
{
this(folderInfo, userName, folderName, folderPath, viewMode, serviceRegistry, null, extractAttachmentsEnabled, mountPointId);
}
/**
* Constructs {@link AlfrescoImapFolder} object.
*
* @param qualifiedMailboxName - name of the mailbox (e.g. "admin" for admin user).
* @param folderInfo - reference to the {@link FileInfo} object representing the folder.
* @param folderName - name of the folder.
* @param viewMode - defines view mode. Can be one of the following: {@link AlfrescoImapConst#MODE_ARCHIVE} or {@link AlfrescoImapConst#MODE_VIRTUAL}.
* @param rootNodeRef - reference to the root node of the store where folder is placed.
* @param mountPointName - name of the mount point.
* @param imapService - reference to the {@link ImapHelper} object.
* @param selectable - defines whether the folder is selectable or not.
*/
public AlfrescoImapFolder(
FileInfo folderInfo,
String userName,
String folderName,
String folderPath,
ImapViewMode viewMode,
ServiceRegistry serviceRegistry,
Boolean selectable,
boolean extractAttachmentsEnabled,
int mountPointId)
{
super(serviceRegistry);
this.folderInfo = folderInfo;
this.userName = userName;
this.folderName = folderName != null ? folderName : (folderInfo != null ? folderInfo.getName() : null);
this.folderPath = folderPath;
this.viewMode = viewMode != null ? viewMode : ImapViewMode.ARCHIVE;
this.extractAttachmentsEnabled = extractAttachmentsEnabled;
this.imapService = serviceRegistry.getImapService();
// MailFolder object can be null if it is used to obtain hierarchy delimiter by LIST command:
// Example:
// C: 2 list "" ""
// S: * LIST () "." ""
// S: 2 OK LIST completed.
if (folderInfo != null)
{
if (selectable == null)
{
// isSelectable();
Boolean storedSelectable = !serviceRegistry.getNodeService().hasAspect(folderInfo.getNodeRef(), ImapModel.ASPECT_IMAP_FOLDER_NONSELECTABLE);
if (storedSelectable == null)
{
this.selectable = true;
}
else
{
this.selectable = storedSelectable;
}
}
else
{
this.selectable = selectable;
}
}
else
{
this.selectable = false;
}
this.mountPointId = mountPointId;
}
/*
* (non-Javadoc)
* @see com.icegreen.greenmail.store.MailFolder#getFullName()
*/
@Override
public String getFullName()
{
return Utf7.encode(AlfrescoImapConst.USER_NAMESPACE + AlfrescoImapConst.HIERARCHY_DELIMITER + this.userName
+ AlfrescoImapConst.HIERARCHY_DELIMITER + getFolderPath(), Utf7.UTF7_MODIFIED);
}
/* (non-Javadoc)
* @see com.icegreen.greenmail.store.MailFolder#getName()
*/
@Override
public String getName()
{
return this.folderName;
}
/* (non-Javadoc)
* @see com.icegreen.greenmail.store.MailFolder#isSelectable()
*/
@Override
public boolean isSelectable()
{
return this.selectable;
}
/**
* Returns the contents of this folder.
*
* @return A sorted map of UIDs to FileInfo objects.
*/
private NavigableMap<Long, FileInfo> searchMails()
{
return getFolderStatus().search;
}
/**
* Invalidates the current cached state
*
* @return <code>true</code> if this instance is still valid for reuse
*/
public boolean reset()
{
this.folderStatus = null;
return new CommandCallback<Boolean>()
{
public Boolean command() throws Throwable
{
return serviceRegistry.getNodeService().exists(folderInfo.getNodeRef());
}
}.run(true);
}
protected FolderStatus getFolderStatus()
{
if (this.folderStatus == null)
{
CommandCallback<FolderStatus> command = new CommandCallback<FolderStatus>()
{
public FolderStatus command() throws Throwable
{
return imapService.getFolderStatus(userName, folderInfo.getNodeRef(), viewMode);
}
};
this.folderStatus = command.run();
}
return this.folderStatus;
}
/**
* Appends message to the folder.
*
* @param message - message.
* @param flags - message flags.
* @param internalDate - not used. Current date used instead.
*/
@Override
protected long appendMessageInternal(
MimeMessage message,
Flags flags,
Date internalDate)
throws FileExistsException, FileNotFoundException, IOException, MessagingException
{
long uid = createMimeMessageInFolder(this.folderInfo, message, flags);
// Invalidate current folder status
this.folderStatus = null;
return uid;
}
/**
* Copies message with the given UID to the specified {@link MailFolder}.
*
* @param uid - UID of the message
* @param toFolder - reference to the destination folder.
* @throws MessagingException
* @throws IOException
* @throws FileNotFoundException
* @throws FileExistsException
*/
@Override
protected void copyMessageInternal(
long uid, MailFolder toFolder)
throws MessagingException, FileExistsException, FileNotFoundException, IOException
{
AlfrescoImapFolder toImapMailFolder = (AlfrescoImapFolder) toFolder;
NodeRef destFolderNodeRef = toImapMailFolder.getFolderInfo().getNodeRef();
FileInfo sourceMessageFileInfo = searchMails().get(uid);
if (serviceRegistry.getNodeService().hasAspect(sourceMessageFileInfo.getNodeRef(), ImapModel.ASPECT_IMAP_CONTENT))
{
//Generate body of message
MimeMessage newMessage = new ImapModelMessage(sourceMessageFileInfo, serviceRegistry, true);
toImapMailFolder.appendMessageInternal(newMessage, imapService.getFlags(sourceMessageFileInfo), new Date());
}
else
{
serviceRegistry.getFileFolderService().copy(sourceMessageFileInfo.getNodeRef(), destFolderNodeRef, null);
}
}
/**
* Marks all messages in the folder as deleted using {@link Flags.Flag#DELETED} flag.
*/
@Override
public void deleteAllMessagesInternal() throws FolderException
{
if (isReadOnly())
{
throw new FolderException("Can't delete all - Permission denied");
}
for (Map.Entry<Long, FileInfo> entry : searchMails().entrySet())
{
imapService.setFlag(entry.getValue(), Flags.Flag.DELETED, true);
// comment out to physically remove content.
// fileFolderService.delete(fileInfo.getNodeRef());
}
}
/**
* Deletes messages marked with {@link Flags.Flag#DELETED}. Note that this message deletes all messages with this flag.
*/
@Override
protected void expungeInternal() throws FolderException
{
if (isReadOnly())
{
throw new FolderException("Can't expunge - Permission denied");
}
for (Map.Entry<Long, FileInfo> entry : searchMails().entrySet())
{
imapService.expungeMessage(entry.getValue());
}
}
/**
* Returns the MSN number of the first unseen message.
*
* @return MSN number of the first unseen message.
*/
@Override
public int getFirstUnseen()
{
return getFolderStatus().firstUnseen;
}
/**
* Returns message by its UID.
*
* @param uid - UID of the message.
* @return message.
* @throws MessagingException
*/
@Override
protected SimpleStoredMessage getMessageInternal(long uid) throws MessagingException
{
if (logger.isDebugEnabled())
{
logger.debug("[getMessageInternal] " + this);
}
FileInfo mesInfo = searchMails().get(uid);
if (mesInfo == null)
{
return null;
}
return imapService.getMessage(mesInfo);
}
/**
* Returns count of the messages in the folder.
*
* @return Count of the messages.
*/
@Override
public int getMessageCount()
{
return getFolderStatus().messageCount;
}
/**
* Returns UIDs of all messages in the folder.
*
* @return UIDS of the messages.
*/
@Override
public long[] getMessageUids()
{
if (logger.isDebugEnabled())
{
logger.debug("[getMessageUidsInternal] " + this);
}
Collection<Long> uidSet = searchMails().keySet();
long[] uids = new long[uidSet.size()];
int i = 0;
for (Long uid : uidSet)
{
uids[i++] = uid;
}
return uids;
}
/**
* Returns list of all messages in the folder.
*
* @return list of {@link SimpleStoredMessage} objects.
*/
@Override
protected List<SimpleStoredMessage> getMessagesInternal()
{
if (logger.isDebugEnabled())
{
logger.debug("[getMessagesInternal] " + this);
}
return convertToMessages(searchMails().values());
}
private List<SimpleStoredMessage> convertToMessages(Collection<FileInfo> fileInfos)
{
if (logger.isDebugEnabled())
{
logger.debug("[convertToMessages] " + this);
}
if (fileInfos == null || fileInfos.size() == 0)
{
logger.debug("[convertToMessages] - fileInfos is empty or null");
return Collections.emptyList();
}
List<SimpleStoredMessage> result = new LinkedList<SimpleStoredMessage>();
for (FileInfo fileInfo : fileInfos)
{
try
{
result.add(imapService.createImapMessage(fileInfo, false));
if (logger.isDebugEnabled())
{
logger.debug("[convertToMessages] Message added: " + fileInfo.getName());
}
}
catch (MessagingException e)
{
logger.warn("[convertToMessages] Invalid message! File name:" + fileInfo.getName(), e);
}
}
return result;
}
/**
* Returns list of messages by filter.
*
* @param msgRangeFilter - {@link MsgRangeFilter} object representing filter.
* @return list of filtered messages.
*/
@Override
protected List<SimpleStoredMessage> getMessagesInternal(MsgRangeFilter msgRangeFilter)
{
throw new UnsupportedOperationException("IMAP implementation doesn't support POP3 requests");
}
/**
* Returns message sequence number in the folder by its UID.
*
* @param uid - message UID.
* @return message sequence number.
* @throws FolderException if no message with given UID.
*/
@Override
public int getMsn(long uid) throws FolderException
{
NavigableMap<Long, FileInfo> messages = searchMails();
if (!messages.containsKey(uid))
{
throw new FolderException("No such message.");
}
return messages.headMap(uid, true).size();
}
/**
* Returns the list of messages that have no {@link Flags.Flag#DELETED} flag set for current user.
*
* @return the list of non-deleted messages.
*/
@Override
protected List<SimpleStoredMessage> getNonDeletedMessagesInternal()
{
if (logger.isDebugEnabled())
{
logger.debug("[getNonDeletedMessagesInternal] " + this);
}
List<SimpleStoredMessage> result = new ArrayList<SimpleStoredMessage>();
Collection<SimpleStoredMessage> values = getMessagesInternal();
for (SimpleStoredMessage message : values)
{
if (!getFlags(message).contains(Flags.Flag.DELETED))
{
result.add(message);
}
}
if (logger.isDebugEnabled() && folderInfo != null)
{
logger.debug(folderInfo.getName() + " - Non deleted messages count:" + result.size());
}
return result;
}
/**
* Returns permanent flags.
*
* @return {@link Flags} object containing flags.
*/
@Override
public Flags getPermanentFlags()
{
return PERMANENT_FLAGS;
}
/**
* Returns count of messages with {@link Flags.Flag#RECENT} flag.
* If {@code reset} parameter is {@code true} - removes {@link Flags.Flag#RECENT} flag from
* the message for current user.
*
* @param reset - if true the {@link Flags.Flag#RECENT} will be deleted for current user if exists.
* @return returns count of recent messages.
*/
@Override
public int getRecentCount(boolean reset)
{
int recent = getFolderStatus().recentCount;
if (reset && recent > 0)
{
CommandCallback<Void> command = new CommandCallback<Void>()
{
public Void command() throws Throwable
{
for (FileInfo fileInfo : folderStatus.search.values())
{
Flags flags = imapService.getFlags(fileInfo);
if (flags.contains(Flags.Flag.RECENT))
{
imapService.setFlag(fileInfo, Flags.Flag.RECENT, false);
}
}
return null;
}
};
command.run();
}
return recent;
}
/**
* Returns UIDNEXT value of the folder.
*
* @return UIDNEXT value.
*/
@Override
public long getUidNext()
{
NavigableMap<Long, FileInfo> search = getFolderStatus().search;
return search.isEmpty() ? 1 : search.lastKey() + 1;
}
/**
* Returns UIDVALIDITY value of the folder.
*
* @return UIDVALIDITY value.
*/
@Override
public long getUidValidity()
{
return getFolderStatus().uidValidity + mountPointId;
}
/**
* Returns count of the messages with {@link Flags.Flag#SEEN} in the folder for the current user.
*
* @return Count of the unseen messages for current user.
*/
@Override
public int getUnseenCount()
{
return getFolderStatus().unseenCount;
}
/**
* Replaces flags for the message with the given UID. If {@code addUid} is set to {@code true}
* {@link FolderListener} objects defined for this folder will be notified.
* {@code silentListener} can be provided - this listener wouldn't be notified.
*
* @param flags - new flags.
* @param uid - message UID.
* @param silentListener - listener that shouldn't be notified.
* @param addUid - defines whether or not listeners be notified.
* @throws FolderException
* @throws MessagingException
*/
@Override
protected void replaceFlagsInternal(
Flags flags,
long uid,
FolderListener silentListener,
boolean addUid)
throws FolderException, MessagingException
{
int msn = getMsn(uid);
FileInfo fileInfo = searchMails().get(uid);
imapService.setFlags(fileInfo, MessageFlags.ALL_FLAGS, false);
imapService.setFlags(fileInfo, flags, true);
Long uidNotification = addUid ? uid : null;
notifyFlagUpdate(msn, flags, uidNotification, silentListener);
}
/**
* Sets flags for the message with the given UID. If {@code addUid} is set to {@code true}
* {@link FolderListener} objects defined for this folder will be notified.
* {@code silentListener} can be provided - this listener wouldn't be notified.
*
* @param flags - new flags.
* @param value - flags value.
* @param uid - message UID.
* @param silentListener - listener that shouldn't be notified.
* @param addUid - defines whether or not listeners be notified.
* @throws MessagingException
* @throws FolderException
*/
@Override
protected void setFlagsInternal(
Flags flags,
boolean value,
long uid,
FolderListener silentListener,
boolean addUid)
throws MessagingException, FolderException
{
int msn = getMsn(uid);
FileInfo fileInfo = searchMails().get(uid);
imapService.setFlags(fileInfo, flags, value);
Long uidNotification = null;
if (addUid)
{
uidNotification = new Long(uid);
}
notifyFlagUpdate(msn, flags, uidNotification, silentListener);
}
private Flags getFlags(SimpleStoredMessage mess)
{
return ((AbstractMimeMessage) mess.getMimeMessage()).getFlags();
}
// ----------------------Getters and Setters----------------------------
public String getFolderPath()
{
return this.folderPath;
}
public FileInfo getFolderInfo()
{
return folderInfo;
}
/* (non-Javadoc)
* @see org.alfresco.repo.imap.AbstractImapFolder#isMarkedInternal()
*/
@Override
public boolean isMarked()
{
FolderStatus folderStatus = getFolderStatus();
return folderStatus.recentCount > 0 || folderStatus.unseenCount > 0;
}
/**
* Whether the folder is read-only for user.
*
* @return {@code boolean}
*/
@Override
protected boolean isReadOnly()
{
AccessStatus status = serviceRegistry.getPublicServiceAccessService().hasAccess(ServiceRegistry.NODE_SERVICE.getLocalName(), "createNode", folderInfo.getNodeRef(), null, null, null);
//serviceRegistry.getPermissionService().hasPermission(folderInfo.getNodeRef(), PermissionService.WRITE);
return status == AccessStatus.DENIED;
}
public ImapViewMode getViewMode()
{
return viewMode;
}
/**
* Creates the EML message in the specified folder.
*
* @param folderFileInfo The folder to create message in.
* @param message The original MimeMessage.
* @return ID of the new message created
* @throws FileNotFoundException
* @throws FileExistsException
* @throws MessagingException
* @throws IOException
*/
private long createMimeMessageInFolder(
FileInfo folderFileInfo,
MimeMessage message,
Flags flags)
throws FileExistsException, FileNotFoundException, IOException, MessagingException
{
String name = AlfrescoImapConst.MESSAGE_PREFIX + GUID.generate();
FileFolderService fileFolderService = serviceRegistry.getFileFolderService();
FileInfo messageFile = fileFolderService.create(folderFileInfo.getNodeRef(), name, ContentModel.TYPE_CONTENT);
final long newMessageUid = (Long) messageFile.getProperties().get(ContentModel.PROP_NODE_DBID);
name = AlfrescoImapConst.MESSAGE_PREFIX + newMessageUid + AlfrescoImapConst.EML_EXTENSION;
fileFolderService.rename(messageFile.getNodeRef(), name);
Flags newFlags = new Flags(flags);
newFlags.add(Flag.RECENT);
imapService.setFlags(messageFile, newFlags, true);
if (extractAttachmentsEnabled)
{
imapService.extractAttachments(messageFile.getNodeRef(), message);
}
// Force persistence of the message to the repository
new IncomingImapMessage(messageFile, serviceRegistry, message);
return newMessageUid;
}
}