From 19fcf2c41194ff3e8ccd5a386265f150acbaa63d Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Fri, 3 Jun 2016 16:45:04 +0000 Subject: [PATCH] Merged 5.2.N (5.2.1) to HEAD (5.2) 125783 rmunteanu: Merged 5.1.N (5.1.2) to 5.2.N (5.2.1) 125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2) 125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@127809 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../opencmis/AbstractBaseUrlGenerator.java | 342 +- .../opencmis/AtomPubCMISDispatcher.java | 54 +- .../alfresco/opencmis/BaseUrlGenerator.java | 38 +- .../opencmis/BrowserCMISDispatcher.java | 54 +- .../org/alfresco/opencmis/CMISDispatcher.java | 34 +- .../opencmis/CMISDispatcherRegistry.java | 190 +- .../opencmis/CMISDispatcherRegistryImpl.java | 116 +- .../opencmis/CMISHttpServletRequest.java | 1078 ++-- .../opencmis/CMISServletDispatcher.java | 786 +-- .../org/alfresco/opencmis/CMISWebScript.java | 72 +- .../opencmis/DefaultBaseUrlGenerator.java | 98 +- .../opencmis/DefaultPathGenerator.java | 60 +- .../org/alfresco/opencmis/PathGenerator.java | 30 +- .../opencmis/ProxyBaseUrlGenerator.java | 152 +- .../PublicApiAlfrescoCmisService.java | 400 +- .../PublicApiAlfrescoCmisServiceFactory.java | 66 +- .../PublicApiAtomPubCMISDispatcher.java | 40 +- .../PublicApiBrowserCMISDispatcher.java | 42 +- .../PublicApiCMISHttpServletRequest.java | 82 +- .../opencmis/PublicApiPathGenerator.java | 76 +- .../SysAdminParamsBaseUrlGenerator.java | 130 +- .../java/org/alfresco/repo/SessionUser.java | 50 +- .../repo/surf/policy/SurfConfigCleaner.java | 154 +- .../repo/utils/FacesImageResolver.java | 66 +- .../repo/web/auth/TenantAuthentication.java | 26 +- .../repo/web/scripts/BufferedRequest.java | 730 +-- .../repo/web/scripts/BufferedResponse.java | 462 +- .../web/scripts/ExtensibilityContainer.java | 844 +-- .../repo/web/scripts/RepoClassPathStore.java | 114 +- .../repo/web/scripts/RepositoryContainer.java | 1444 ++--- .../web/scripts/RepositoryImageResolver.java | 110 +- .../scripts/RepositoryScriptProcessor.java | 360 +- .../RepositoryScriptProcessorFactory.java | 56 +- .../web/scripts/RepositoryServerModel.java | 234 +- .../scripts/RepositoryTemplateProcessor.java | 472 +- .../RepositoryTemplateProcessorFactory.java | 56 +- .../web/scripts/admin/NodeBrowserPost.java | 2708 ++++---- .../web/scripts/audit/AuditEntryDelete.java | 170 +- .../repo/web/scripts/bean/ADMRemoteStore.java | 2172 +++---- .../web/scripts/bean/AbstractLoginBean.java | 180 +- .../repo/web/scripts/bean/Authentication.java | 76 +- .../web/scripts/bean/BaseRemoteStore.java | 1082 ++-- .../repo/web/scripts/bean/KeywordSearch.java | 778 +-- .../alfresco/repo/web/scripts/bean/Login.java | 92 +- .../repo/web/scripts/bean/LoginPost.java | 148 +- .../repo/web/scripts/bean/SearchEngines.java | 370 +- .../repo/web/scripts/bean/SearchProxy.java | 632 +- .../alfresco/repo/web/scripts/bean/Touch.java | 50 +- ...AbstractBulkFileSystemImportWebScript.java | 390 +- .../BulkFilesystemImportStatusWebScript.java | 126 +- .../copy/BulkFilesystemImportWebScript.java | 370 +- .../comments/AbstractCommentsWebScript.java | 648 +- .../web/scripts/comments/CommentDelete.java | 226 +- .../config/OpenSearchConfigElement.java | 518 +- .../config/OpenSearchElementReader.java | 190 +- .../repo/web/scripts/content/StreamACP.java | 436 +- .../web/scripts/content/StreamJMXDump.java | 202 +- .../scripts/dictionary/AssociationGet.java | 86 +- .../scripts/dictionary/AssociationsGet.java | 68 +- .../repo/web/scripts/dictionary/ClassGet.java | 62 +- .../web/scripts/dictionary/ClassesGet.java | 62 +- .../web/scripts/dictionary/DictionaryGet.java | 218 +- .../dictionary/DictionaryWebServiceBase.java | 714 +-- .../web/scripts/dictionary/PropertiesGet.java | 70 +- .../web/scripts/dictionary/PropertyGet.java | 90 +- .../web/scripts/dictionary/SubClassesGet.java | 120 +- .../web/scripts/metadata/BulkMetadataGet.java | 332 +- .../scripts/person/ChangePasswordPost.java | 238 +- .../JSR168PortletAuthenticatorFactory.java | 322 +- .../web/scripts/solr/AlfrescoModelGet.java | 150 +- .../web/scripts/solr/AlfrescoModelsDiff.java | 220 +- .../web/scripts/solr/GetNodesParameters.java | 246 +- .../repo/web/scripts/solr/NodeMetaData.java | 180 +- .../repo/web/scripts/solr/PropertyValue.java | 92 +- .../solr/SOLRAuthenticationFilter.java | 520 +- .../repo/web/scripts/solr/SOLRSerializer.java | 912 +-- .../AbstractSubscriptionServiceWebScript.java | 380 +- .../SubscriptionServiceFollowPost.java | 60 +- .../SubscriptionServiceFollowersCountGet.java | 42 +- .../SubscriptionServiceFollowersGet.java | 54 +- .../SubscriptionServiceFollowingCountGet.java | 42 +- .../SubscriptionServiceFollowingGet.java | 54 +- .../SubscriptionServiceFollowsPost.java | 70 +- .../SubscriptionServicePrivateListGet.java | 42 +- .../SubscriptionServicePrivateListPut.java | 66 +- .../SubscriptionServiceUnfollowPost.java | 60 +- .../workflow/WorkflowInstanceDiagramGet.java | 134 +- .../alfresco/repo/web/util/PagingCursor.java | 860 +-- .../alfresco/repo/web/util/paging/Cursor.java | 260 +- .../alfresco/repo/web/util/paging/Page.java | 144 +- .../repo/web/util/paging/PagedCursor.java | 400 +- .../repo/web/util/paging/PagedResults.java | 166 +- .../alfresco/repo/web/util/paging/Paging.java | 572 +- .../repo/web/util/paging/WindowedCursor.java | 376 +- .../repo/webdav/ExceptionHandler.java | 176 +- .../auth/BaseNTLMAuthenticationFilter.java | 2172 +++---- .../org/alfresco/rest/api/Activities.java | 48 +- .../java/org/alfresco/rest/api/Comments.java | 36 +- .../org/alfresco/rest/api/Favourites.java | 96 +- .../rest/api/NetworkWebScriptGet.java | 186 +- .../java/org/alfresco/rest/api/Networks.java | 28 +- .../rest/api/NetworksWebScriptGet.java | 200 +- .../org/alfresco/rest/api/NodeRatings.java | 30 +- source/java/org/alfresco/rest/api/Nodes.java | 534 +- source/java/org/alfresco/rest/api/People.java | 42 +- .../org/alfresco/rest/api/Preferences.java | 22 +- .../api/PublicApiAuthenticatorFactory.java | 522 +- .../api/PublicApiDeclarativeRegistry.java | 872 +-- .../rest/api/PublicApiHttpServletRequest.java | 180 +- .../api/PublicApiRepositoryContainer.java | 212 +- .../api/PublicApiTenantAuthentication.java | 160 +- ...ublicApiTenantWebScriptServletRequest.java | 102 +- ...ublicApiTenantWebScriptServletRuntime.java | 256 +- .../rest/api/PublicApiWebScriptServlet.java | 90 +- .../rest/api/SiteMembershipRequests.java | 112 +- source/java/org/alfresco/rest/api/Sites.java | 102 +- source/java/org/alfresco/rest/api/Tags.java | 38 +- .../rest/api/impl/ActivitiesImpl.java | 314 +- .../alfresco/rest/api/impl/CommentsImpl.java | 460 +- .../api/impl/DefaultExceptionHandler.java | 60 +- .../rest/api/impl/ExceptionHandler.java | 12 +- .../rest/api/impl/ExceptionInterceptor.java | 92 +- .../alfresco/rest/api/impl/ExcludedTypes.java | 182 +- .../rest/api/impl/FavouritesImpl.java | 650 +- .../rest/api/impl/LegacyExceptionHandler.java | 48 +- .../alfresco/rest/api/impl/NetworksImpl.java | 174 +- .../rest/api/impl/NodeRatingsImpl.java | 268 +- .../org/alfresco/rest/api/impl/NodesImpl.java | 5660 ++++++++--------- .../alfresco/rest/api/impl/PeopleImpl.java | 646 +- .../rest/api/impl/PreferencesImpl.java | 132 +- ...iteMembershipRequestsExceptionHandler.java | 36 +- .../api/impl/SiteMembershipRequestsImpl.java | 890 +-- .../org/alfresco/rest/api/impl/SitesImpl.java | 2064 +++--- .../org/alfresco/rest/api/impl/TagsImpl.java | 376 +- .../java/org/alfresco/rest/api/impl/Util.java | 180 +- .../AbstractActivitySummaryProcessor.java | 238 +- .../activities/ActivitySummaryParser.java | 336 +- .../activities/ActivitySummaryProcessor.java | 26 +- .../ActivitySummaryProcessorRegistry.java | 24 +- .../BaseActivitySummaryProcessor.java | 192 +- .../CommentsActivitySummaryProcessor.java | 14 +- .../DiscussionsActivitySummaryProcessor.java | 34 +- ...cumentLibraryActivitySummaryProcessor.java | 12 +- .../SiteActivitySummaryProcessor.java | 36 +- ...SubscriptionsActivitySummaryProcessor.java | 52 +- .../node/ratings/AbstractRatingScheme.java | 422 +- .../node/ratings/FiveStarRatingScheme.java | 158 +- .../impl/node/ratings/LikesRatingScheme.java | 200 +- .../api/impl/node/ratings/RatingScheme.java | 22 +- .../org/alfresco/rest/api/model/Activity.java | 280 +- .../org/alfresco/rest/api/model/Company.java | 166 +- .../org/alfresco/rest/api/model/Document.java | 272 +- .../rest/api/model/DocumentRatingSummary.java | 10 +- .../rest/api/model/DocumentTarget.java | 80 +- .../alfresco/rest/api/model/Favourite.java | 110 +- .../rest/api/model/FavouriteSite.java | 62 +- .../rest/api/model/FiveStarRatingSummary.java | 64 +- .../org/alfresco/rest/api/model/Folder.java | 138 +- .../alfresco/rest/api/model/FolderTarget.java | 78 +- .../rest/api/model/LikesRatingSummary.java | 48 +- .../alfresco/rest/api/model/MemberOfSite.java | 292 +- .../org/alfresco/rest/api/model/Network.java | 74 +- .../alfresco/rest/api/model/NetworkImpl.java | 278 +- .../alfresco/rest/api/model/NodeRating.java | 240 +- .../org/alfresco/rest/api/model/Person.java | 444 +- .../rest/api/model/PersonNetwork.java | 214 +- .../alfresco/rest/api/model/Preference.java | 198 +- .../org/alfresco/rest/api/model/Quota.java | 132 +- .../org/alfresco/rest/api/model/Site.java | 298 +- .../rest/api/model/SiteContainer.java | 184 +- .../alfresco/rest/api/model/SiteMember.java | 222 +- .../rest/api/model/SiteMembershipRequest.java | 318 +- .../alfresco/rest/api/model/SiteTarget.java | 80 +- .../java/org/alfresco/rest/api/model/Tag.java | 202 +- .../org/alfresco/rest/api/model/Target.java | 22 +- .../alfresco/rest/api/model/UserRating.java | 84 +- .../api/networks/NetworksEntityResource.java | 74 +- .../rest/api/nodes/NodeRatingsRelation.java | 162 +- .../rest/api/nodes/NodeTagsRelation.java | 110 +- .../api/people/PersonActivitiesRelation.java | 124 +- .../people/PersonFavouriteSitesRelation.java | 176 +- .../api/people/PersonFavouritesRelation.java | 160 +- .../api/people/PersonNetworksRelation.java | 104 +- .../api/people/PersonPreferencesRelation.java | 122 +- .../PersonSiteMembershipRequestsRelation.java | 152 +- .../api/sites/SiteContainersRelation.java | 112 +- .../rest/api/sites/SiteMembersRelation.java | 238 +- .../rest/api/tags/TagsEntityResource.java | 110 +- .../rest/framework/BinaryProperties.java | 36 +- .../framework/core/ResourceInspectorUtil.java | 334 +- .../NodeRefDeserializer.java | 96 +- .../jacksonextensions/NodeRefSerializer.java | 50 +- .../RestApiStringDeserializer.java | 62 +- .../jacksonextensions/TargetDeserializer.java | 196 +- .../interfaces/BinaryResourceAction.java | 238 +- .../resource/content/BasicContentInfo.java | 24 +- .../resource/content/BinaryProperty.java | 204 +- .../resource/content/BinaryResource.java | 22 +- .../resource/content/ContentInfo.java | 22 +- .../resource/content/ContentInfoImpl.java | 88 +- .../resource/content/FileBinaryResource.java | 96 +- .../resource/content/NodeBinaryResource.java | 124 +- .../parameters/InvalidSelectException.java | 40 +- .../where/InvalidQueryException.java | 62 +- .../resource/parameters/where/Query.java | 36 +- .../parameters/where/QueryHelper.java | 528 +- .../resource/parameters/where/QueryImpl.java | 70 +- .../alfresco/web/app/servlet/HTTPProxy.java | 260 +- .../web/app/servlet/HTTPProxyServlet.java | 220 +- .../alfresco/web/scripts/WebScriptUtils.java | 214 +- .../opencmis/OpenCMISClientContext.java | 154 +- .../alfresco/repo/web/scripts/LoginTest.java | 460 +- .../ReadOnlyTransactionInGetRestApiTest.java | 324 +- .../web/scripts/comment/CommentsApiTest.java | 1114 ++-- .../web/scripts/content/MimetypesGetTest.java | 130 +- .../dictionary/DictionaryRestApiTest.java | 1860 +++--- .../web/scripts/search/PersonSearchTest.java | 236 +- .../web/scripts/solr/SOLRWebScriptTest.java | 1588 ++--- .../SubscriptionServiceRestApiTest.java | 576 +- .../repo/web/util/AbstractJettyComponent.java | 478 +- .../repo/web/util/HttpRangeProcessorTest.java | 148 +- .../repo/web/util/JettyComponent.java | 22 +- .../repo/web/util/PagingCursorTest.java | 634 +- .../repo/web/util/paging/PagingTest.java | 694 +- .../AbstractEnterpriseOpenCMIS10TCKTest.java | 10 +- .../AbstractEnterpriseOpenCMIS11TCKTest.java | 266 +- .../AbstractEnterpriseOpenCMISTCKTest.java | 86 +- .../rest/api/tests/AbstractTestApi.java | 412 +- .../rest/api/tests/AbstractTestFixture.java | 472 +- .../org/alfresco/rest/api/tests/ApiTest.java | 108 +- .../rest/api/tests/CMISTCKJettyComponent.java | 62 +- .../org/alfresco/rest/api/tests/Cleanup.java | 26 +- .../rest/api/tests/CloudPersonInfo.java | 46 +- .../api/tests/EnterpriseJettyComponent.java | 62 +- .../tests/EnterprisePublicApiTestFixture.java | 110 +- .../rest/api/tests/EnterpriseTestApi.java | 32 +- .../rest/api/tests/EnterpriseTestFixture.java | 98 +- .../alfresco/rest/api/tests/PersonInfo.java | 196 +- .../rest/api/tests/PublicApiDateFormat.java | 54 +- .../api/tests/PublicApiJettyComponent.java | 170 +- .../rest/api/tests/PublicApiTestContext.java | 262 +- .../alfresco/rest/api/tests/RepoService.java | 3878 +++++------ .../rest/api/tests/RestApiHttpClient.java | 800 +-- .../rest/api/tests/TestActivities.java | 1708 ++--- .../org/alfresco/rest/api/tests/TestCMIS.java | 4892 +++++++------- .../alfresco/rest/api/tests/TestCMISAPI.java | 54 +- .../api/tests/TestEnterpriseAtomPubTCK.java | 388 +- .../rest/api/tests/TestFavouriteSites.java | 1042 +-- .../rest/api/tests/TestFavourites.java | 3370 +++++----- .../alfresco/rest/api/tests/TestFixture.java | 44 +- .../alfresco/rest/api/tests/TestNetworks.java | 882 +-- .../rest/api/tests/TestNodeComments.java | 1604 ++--- .../rest/api/tests/TestNodeRatings.java | 1000 +-- .../alfresco/rest/api/tests/TestPeople.java | 178 +- .../rest/api/tests/TestPersonSites.java | 1472 ++--- .../rest/api/tests/TestPublicApi128.java | 320 +- .../api/tests/TestPublicApiAtomPub10TCK.java | 276 +- .../api/tests/TestPublicApiAtomPub11TCK.java | 90 +- .../api/tests/TestPublicApiBrowser11TCK.java | 78 +- .../rest/api/tests/TestPublicApiCaching.java | 120 +- .../rest/api/tests/TestRemovePermissions.java | 796 +-- .../rest/api/tests/TestSiteContainers.java | 648 +- .../rest/api/tests/TestSiteMembers.java | 1128 ++-- .../api/tests/TestSiteMembershipRequests.java | 2842 ++++----- .../alfresco/rest/api/tests/TestSites.java | 628 +- .../org/alfresco/rest/api/tests/TestTags.java | 1170 ++-- .../rest/api/tests/TestUserPreferences.java | 602 +- .../rest/api/tests/client/AbstractHttp.java | 288 +- .../api/tests/client/AuthenticatedHttp.java | 788 +-- .../client/AuthenticationDetailsProvider.java | 88 +- .../api/tests/client/HttpClientProvider.java | 44 +- .../rest/api/tests/client/HttpResponse.java | 384 +- .../alfresco/rest/api/tests/client/Pair.java | 108 +- .../api/tests/client/PublicApiClient.java | 4358 ++++++------- .../api/tests/client/PublicApiException.java | 50 +- .../api/tests/client/PublicApiHttpClient.java | 2566 ++++---- .../rest/api/tests/client/RequestContext.java | 150 +- .../client/SharedHttpClientProvider.java | 150 +- ...UserAuthenticationDetailsProviderImpl.java | 146 +- .../rest/api/tests/client/UserData.java | 160 +- .../api/tests/client/UserDataService.java | 14 +- .../api/tests/client/data/Activities.java | 174 +- .../client/data/ActivitiesParameters.java | 58 +- .../rest/api/tests/client/data/Activity.java | 388 +- .../api/tests/client/data/AssertUtil.java | 64 +- .../rest/api/tests/client/data/CMISNode.java | 442 +- .../rest/api/tests/client/data/Comment.java | 668 +- .../rest/api/tests/client/data/Company.java | 224 +- .../api/tests/client/data/ContentData.java | 156 +- .../rest/api/tests/client/data/Document.java | 84 +- .../tests/client/data/ExpectedComparison.java | 12 +- .../rest/api/tests/client/data/Favourite.java | 514 +- .../api/tests/client/data/FavouriteSite.java | 146 +- .../tests/client/data/FavouritesTarget.java | 18 +- .../client/data/FileFavouriteTarget.java | 102 +- .../rest/api/tests/client/data/Folder.java | 86 +- .../client/data/FolderFavouriteTarget.java | 100 +- .../api/tests/client/data/FolderNode.java | 446 +- .../client/data/InvalidFavouriteTarget.java | 220 +- .../rest/api/tests/client/data/JSONAble.java | 16 +- .../api/tests/client/data/MemberOfSite.java | 430 +- .../rest/api/tests/client/data/Network.java | 26 +- .../api/tests/client/data/NetworkImpl.java | 430 +- .../rest/api/tests/client/data/Node.java | 838 +-- .../api/tests/client/data/NodeRating.java | 526 +- .../rest/api/tests/client/data/Person.java | 958 +-- .../api/tests/client/data/PersonNetwork.java | 346 +- .../api/tests/client/data/Preference.java | 264 +- .../rest/api/tests/client/data/Quota.java | 112 +- .../rest/api/tests/client/data/Site.java | 38 +- .../api/tests/client/data/SiteContainer.java | 228 +- .../client/data/SiteFavouriteTarget.java | 100 +- .../rest/api/tests/client/data/SiteImpl.java | 680 +- .../api/tests/client/data/SiteMember.java | 478 +- .../client/data/SiteMembershipRequest.java | 444 +- .../rest/api/tests/client/data/SiteRole.java | 14 +- .../rest/api/tests/client/data/Status.java | 178 +- .../rest/api/tests/client/data/Tag.java | 326 +- .../tests/api/mocks3/CameraShyFlocket.java | 60 +- .../framework/tests/api/mocks3/Flock.java | 130 +- .../tests/api/mocks3/FlockEntityResource.java | 100 +- .../framework/tests/api/mocks3/Flocket.java | 64 +- .../api/mocks3/FlocketEntityResource.java | 82 +- .../tests/core/ExceptionResolverTests.java | 200 +- .../framework/tests/core/ParamsExtender.java | 92 +- 325 files changed, 59952 insertions(+), 59952 deletions(-) diff --git a/source/java/org/alfresco/opencmis/AbstractBaseUrlGenerator.java b/source/java/org/alfresco/opencmis/AbstractBaseUrlGenerator.java index 0abdd508ea..09bdce9ce2 100644 --- a/source/java/org/alfresco/opencmis/AbstractBaseUrlGenerator.java +++ b/source/java/org/alfresco/opencmis/AbstractBaseUrlGenerator.java @@ -1,171 +1,171 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.repo.tenant.TenantUtil; - -/** - * Generates an OpenCMIS base url based on the request, repository id and binding. - * - * @author steveglover - * - */ -public abstract class AbstractBaseUrlGenerator implements BaseUrlGenerator -{ - private boolean overrideContext; - private String contextOverride; - private boolean overrideServletPath; - private String servletPathOverride; - private PathGenerator pathGenerator; - - public void setPathGenerator(PathGenerator pathGenerator) - { - this.pathGenerator = pathGenerator; - } - - public void setOverrideContext(boolean overrideContext) - { - this.overrideContext = overrideContext; - } - - private String fixup(String urlSegment) - { - StringBuilder sb = new StringBuilder(); - int beginIndex = 0; - int endIndex = urlSegment.length(); - if(urlSegment != null) - { - if(!urlSegment.equals("") && !urlSegment.startsWith("/")) - { - sb.append("/"); - } - if(urlSegment.endsWith("/")) - { - endIndex -= 1; - } - } - sb.append(urlSegment.substring(beginIndex, endIndex)); - return sb.toString(); - } - - public void setContextOverride(String contextOverride) - { - this.contextOverride = fixup(contextOverride); - } - - public void setOverrideServletPath(boolean overrideServletPath) - { - this.overrideServletPath = overrideServletPath; - } - - public void setServletPathOverride(String servletPathOverride) - { - this.servletPathOverride = fixup(servletPathOverride); - } - - protected abstract String getServerPath(HttpServletRequest request); - - public String getContextPath(HttpServletRequest httpReq) - { - if(overrideContext) - { - return contextOverride; - } - else - { - return httpReq.getContextPath(); - } - } - - public String getServletPath(HttpServletRequest req) - { - if(overrideServletPath) - { - return servletPathOverride; - } - else - { - return req.getServletPath(); - } - } - - @Override - public String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id) - { - StringBuilder url = new StringBuilder(); - - String contextPath = getContextPath(req); - if(contextPath != null && !contextPath.equals("")) - { - url.append(contextPath); - } - - String servletPath = getServletPath(req); - if(servletPath != null && !servletPath.equals("")) - { - url.append(servletPath); - url.append("/"); - } - - if(url.length() == 0 || url.charAt(0) != '/') - { - url.append("/"); - } - - if(repositoryId != null) - { - url.append(repositoryId == null ? TenantUtil.DEFAULT_TENANT : repositoryId); - url.append("/"); - } - - if(operation != null) - { - url.append(operation); - url.append("/"); - } - - if(id != null) - { - url.append(id); - } - - int length = url.length(); - if(length > 0 && url.charAt(length - 1) == '/') - { - url.deleteCharAt(length - 1); - } - - return url.toString(); - } - - @Override - public String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding) - { - StringBuilder url = new StringBuilder(); - String serverPath = getServerPath(req); - url.append(serverPath); - - String contextPath = getContextPath(req); - if(contextPath != null && !contextPath.equals("")) - { - url.append(contextPath); - } - - String servletPath = getServletPath(req); - if(servletPath != null && !servletPath.equals("")) - { - url.append(servletPath); - url.append("/"); - } - - if(url.length() > 0 && url.charAt(url.length() - 1) != '/') - { - url.append("/"); - } - - pathGenerator.generatePath(req, url, repositoryId, binding); - - return url.toString(); - } -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.repo.tenant.TenantUtil; + +/** + * Generates an OpenCMIS base url based on the request, repository id and binding. + * + * @author steveglover + * + */ +public abstract class AbstractBaseUrlGenerator implements BaseUrlGenerator +{ + private boolean overrideContext; + private String contextOverride; + private boolean overrideServletPath; + private String servletPathOverride; + private PathGenerator pathGenerator; + + public void setPathGenerator(PathGenerator pathGenerator) + { + this.pathGenerator = pathGenerator; + } + + public void setOverrideContext(boolean overrideContext) + { + this.overrideContext = overrideContext; + } + + private String fixup(String urlSegment) + { + StringBuilder sb = new StringBuilder(); + int beginIndex = 0; + int endIndex = urlSegment.length(); + if(urlSegment != null) + { + if(!urlSegment.equals("") && !urlSegment.startsWith("/")) + { + sb.append("/"); + } + if(urlSegment.endsWith("/")) + { + endIndex -= 1; + } + } + sb.append(urlSegment.substring(beginIndex, endIndex)); + return sb.toString(); + } + + public void setContextOverride(String contextOverride) + { + this.contextOverride = fixup(contextOverride); + } + + public void setOverrideServletPath(boolean overrideServletPath) + { + this.overrideServletPath = overrideServletPath; + } + + public void setServletPathOverride(String servletPathOverride) + { + this.servletPathOverride = fixup(servletPathOverride); + } + + protected abstract String getServerPath(HttpServletRequest request); + + public String getContextPath(HttpServletRequest httpReq) + { + if(overrideContext) + { + return contextOverride; + } + else + { + return httpReq.getContextPath(); + } + } + + public String getServletPath(HttpServletRequest req) + { + if(overrideServletPath) + { + return servletPathOverride; + } + else + { + return req.getServletPath(); + } + } + + @Override + public String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id) + { + StringBuilder url = new StringBuilder(); + + String contextPath = getContextPath(req); + if(contextPath != null && !contextPath.equals("")) + { + url.append(contextPath); + } + + String servletPath = getServletPath(req); + if(servletPath != null && !servletPath.equals("")) + { + url.append(servletPath); + url.append("/"); + } + + if(url.length() == 0 || url.charAt(0) != '/') + { + url.append("/"); + } + + if(repositoryId != null) + { + url.append(repositoryId == null ? TenantUtil.DEFAULT_TENANT : repositoryId); + url.append("/"); + } + + if(operation != null) + { + url.append(operation); + url.append("/"); + } + + if(id != null) + { + url.append(id); + } + + int length = url.length(); + if(length > 0 && url.charAt(length - 1) == '/') + { + url.deleteCharAt(length - 1); + } + + return url.toString(); + } + + @Override + public String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding) + { + StringBuilder url = new StringBuilder(); + String serverPath = getServerPath(req); + url.append(serverPath); + + String contextPath = getContextPath(req); + if(contextPath != null && !contextPath.equals("")) + { + url.append(contextPath); + } + + String servletPath = getServletPath(req); + if(servletPath != null && !servletPath.equals("")) + { + url.append(servletPath); + url.append("/"); + } + + if(url.length() > 0 && url.charAt(url.length() - 1) != '/') + { + url.append("/"); + } + + pathGenerator.generatePath(req, url, repositoryId, binding); + + return url.toString(); + } +} diff --git a/source/java/org/alfresco/opencmis/AtomPubCMISDispatcher.java b/source/java/org/alfresco/opencmis/AtomPubCMISDispatcher.java index ccd8a792e8..807bdc86a5 100644 --- a/source/java/org/alfresco/opencmis/AtomPubCMISDispatcher.java +++ b/source/java/org/alfresco/opencmis/AtomPubCMISDispatcher.java @@ -1,27 +1,27 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServlet; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; - -/** - * Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet. - * - * @author steveglover - * - */ -public class AtomPubCMISDispatcher extends CMISServletDispatcher -{ - @Override - protected Binding getBinding() - { - return Binding.atom; - } - - protected HttpServlet getServlet() - { - HttpServlet servlet = new CmisAtomPubServlet(); - return servlet; - } -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServlet; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; + +/** + * Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet. + * + * @author steveglover + * + */ +public class AtomPubCMISDispatcher extends CMISServletDispatcher +{ + @Override + protected Binding getBinding() + { + return Binding.atom; + } + + protected HttpServlet getServlet() + { + HttpServlet servlet = new CmisAtomPubServlet(); + return servlet; + } +} diff --git a/source/java/org/alfresco/opencmis/BaseUrlGenerator.java b/source/java/org/alfresco/opencmis/BaseUrlGenerator.java index ce2e30b472..688c4b5287 100644 --- a/source/java/org/alfresco/opencmis/BaseUrlGenerator.java +++ b/source/java/org/alfresco/opencmis/BaseUrlGenerator.java @@ -1,19 +1,19 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; - -/** - * Generates an OpenCMIS base url based on the request, repository id and binding. - * - * @author steveglover - * - */ -public interface BaseUrlGenerator -{ - String getContextPath(HttpServletRequest httpReq); - String getServletPath(HttpServletRequest req); - String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding); - String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id); -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; + +/** + * Generates an OpenCMIS base url based on the request, repository id and binding. + * + * @author steveglover + * + */ +public interface BaseUrlGenerator +{ + String getContextPath(HttpServletRequest httpReq); + String getServletPath(HttpServletRequest req); + String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding); + String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id); +} diff --git a/source/java/org/alfresco/opencmis/BrowserCMISDispatcher.java b/source/java/org/alfresco/opencmis/BrowserCMISDispatcher.java index 456091aa83..eae1f11b93 100644 --- a/source/java/org/alfresco/opencmis/BrowserCMISDispatcher.java +++ b/source/java/org/alfresco/opencmis/BrowserCMISDispatcher.java @@ -1,27 +1,27 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServlet; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet; - -/** - * Dispatches OpenCMIS requests to the OpenCMIS Browser Binding servlet. - * - * @author steveglover - * - */ -public class BrowserCMISDispatcher extends CMISServletDispatcher -{ - @Override - protected Binding getBinding() - { - return Binding.browser; - } - - protected HttpServlet getServlet() - { - HttpServlet servlet = new CmisBrowserBindingServlet(); - return servlet; - } -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServlet; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet; + +/** + * Dispatches OpenCMIS requests to the OpenCMIS Browser Binding servlet. + * + * @author steveglover + * + */ +public class BrowserCMISDispatcher extends CMISServletDispatcher +{ + @Override + protected Binding getBinding() + { + return Binding.browser; + } + + protected HttpServlet getServlet() + { + HttpServlet servlet = new CmisBrowserBindingServlet(); + return servlet; + } +} diff --git a/source/java/org/alfresco/opencmis/CMISDispatcher.java b/source/java/org/alfresco/opencmis/CMISDispatcher.java index 9e26249e2d..a52f8ebe4a 100644 --- a/source/java/org/alfresco/opencmis/CMISDispatcher.java +++ b/source/java/org/alfresco/opencmis/CMISDispatcher.java @@ -1,17 +1,17 @@ -package org.alfresco.opencmis; - -import java.io.IOException; - -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * Dispatches OpenCMIS requests to the appropriate handler. - * - * @author steveglover - * - */ -public interface CMISDispatcher -{ - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException; -} +package org.alfresco.opencmis; + +import java.io.IOException; + +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * Dispatches OpenCMIS requests to the appropriate handler. + * + * @author steveglover + * + */ +public interface CMISDispatcher +{ + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException; +} diff --git a/source/java/org/alfresco/opencmis/CMISDispatcherRegistry.java b/source/java/org/alfresco/opencmis/CMISDispatcherRegistry.java index 49a7002556..4b6b822286 100644 --- a/source/java/org/alfresco/opencmis/CMISDispatcherRegistry.java +++ b/source/java/org/alfresco/opencmis/CMISDispatcherRegistry.java @@ -1,95 +1,95 @@ -package org.alfresco.opencmis; - -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * A registry of OpenCMIS bindings to dispatchers. - * - * @author steveglover - * - */ -public interface CMISDispatcherRegistry -{ - /* - * Supported CMIS bindings - */ - public static enum Binding - { - atom, browser; - - public BindingType getOpenCmisBinding() - { - BindingType bindingType = null; - - if(this == atom) - { - bindingType = BindingType.ATOMPUB; - } - else if(this == browser) - { - bindingType = BindingType.BROWSER; - } - - return bindingType; - } - }; - - public static class Endpoint - { - private Binding binding; - private String version; - - public Endpoint(Binding binding, String version) - { - super(); - this.binding = binding; - this.version = version; - } - - public Binding getBinding() - { - return binding; - } - - public String getVersion() - { - return version; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((binding == null) ? 0 : binding.hashCode()); - result = prime * result - + ((version == null) ? 0 : version.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Endpoint other = (Endpoint) obj; - if (binding != other.binding) - return false; - if (version == null) { - if (other.version != null) - return false; - } else if (!version.equals(other.version)) - return false; - return true; - } - } - - public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher); - public CMISDispatcher getDispatcher(WebScriptRequest req); -} +package org.alfresco.opencmis; + +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * A registry of OpenCMIS bindings to dispatchers. + * + * @author steveglover + * + */ +public interface CMISDispatcherRegistry +{ + /* + * Supported CMIS bindings + */ + public static enum Binding + { + atom, browser; + + public BindingType getOpenCmisBinding() + { + BindingType bindingType = null; + + if(this == atom) + { + bindingType = BindingType.ATOMPUB; + } + else if(this == browser) + { + bindingType = BindingType.BROWSER; + } + + return bindingType; + } + }; + + public static class Endpoint + { + private Binding binding; + private String version; + + public Endpoint(Binding binding, String version) + { + super(); + this.binding = binding; + this.version = version; + } + + public Binding getBinding() + { + return binding; + } + + public String getVersion() + { + return version; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((binding == null) ? 0 : binding.hashCode()); + result = prime * result + + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Endpoint other = (Endpoint) obj; + if (binding != other.binding) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + } + + public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher); + public CMISDispatcher getDispatcher(WebScriptRequest req); +} diff --git a/source/java/org/alfresco/opencmis/CMISDispatcherRegistryImpl.java b/source/java/org/alfresco/opencmis/CMISDispatcherRegistryImpl.java index 7e8dc323ff..4633bd3d8a 100644 --- a/source/java/org/alfresco/opencmis/CMISDispatcherRegistryImpl.java +++ b/source/java/org/alfresco/opencmis/CMISDispatcherRegistryImpl.java @@ -1,59 +1,59 @@ -package org.alfresco.opencmis; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * A registry of OpenCMIS bindings to dispatchers. - * - * @author steveglover - * - */ -public class CMISDispatcherRegistryImpl implements CMISDispatcherRegistry -{ - private Map registry = new HashMap(); - - @Override - public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher) - { - registry.put(endpoint, dispatcher); - } - - @Override - public CMISDispatcher getDispatcher(WebScriptRequest req) - { - CMISDispatcher dispatcher = null; - - Match match = req.getServiceMatch(); - Map templateVars = match.getTemplateVars(); - String bindingStr = templateVars.get("binding"); - String apiVersion = templateVars.get("apiVersion"); - if(bindingStr != null && apiVersion != null) - { - Binding binding = null; - try - { - binding = Binding.valueOf(bindingStr); - } - catch(IllegalArgumentException e) - { - // nothing to do, binding remains null - } - - if(binding != null) - { - Endpoint endpoint = new Endpoint(binding, apiVersion); - dispatcher = registry.get(endpoint); - } - else - { - // TODO - } - } - - return dispatcher; - } +package org.alfresco.opencmis; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * A registry of OpenCMIS bindings to dispatchers. + * + * @author steveglover + * + */ +public class CMISDispatcherRegistryImpl implements CMISDispatcherRegistry +{ + private Map registry = new HashMap(); + + @Override + public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher) + { + registry.put(endpoint, dispatcher); + } + + @Override + public CMISDispatcher getDispatcher(WebScriptRequest req) + { + CMISDispatcher dispatcher = null; + + Match match = req.getServiceMatch(); + Map templateVars = match.getTemplateVars(); + String bindingStr = templateVars.get("binding"); + String apiVersion = templateVars.get("apiVersion"); + if(bindingStr != null && apiVersion != null) + { + Binding binding = null; + try + { + binding = Binding.valueOf(bindingStr); + } + catch(IllegalArgumentException e) + { + // nothing to do, binding remains null + } + + if(binding != null) + { + Endpoint endpoint = new Endpoint(binding, apiVersion); + dispatcher = registry.get(endpoint); + } + else + { + // TODO + } + } + + return dispatcher; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/opencmis/CMISHttpServletRequest.java b/source/java/org/alfresco/opencmis/CMISHttpServletRequest.java index dc770e300c..c2fa1c9539 100644 --- a/source/java/org/alfresco/opencmis/CMISHttpServletRequest.java +++ b/source/java/org/alfresco/opencmis/CMISHttpServletRequest.java @@ -1,540 +1,540 @@ -package org.alfresco.opencmis; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletInputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; -import org.alfresco.service.descriptor.Descriptor; -import org.apache.chemistry.opencmis.commons.impl.Constants; -import org.apache.chemistry.opencmis.server.shared.Dispatcher; -import org.apache.commons.collections.map.HashedMap; -import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WrappingWebScriptRequest; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; - -/** - * Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS. - */ -@SuppressWarnings("rawtypes") -public class CMISHttpServletRequest implements HttpServletRequest -{ - protected WebScriptRequest req; - protected HttpServletRequest httpReq; - protected String networkId; - protected String operation; - protected String id; // object id (or path for browser binding) - protected String serviceName; - protected BaseUrlGenerator baseUrlGenerator; - protected Binding binding; - protected Descriptor currentDescriptor; - - public CMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator, Binding binding, Descriptor currentDescriptor, - TenantAdminService tenantAdminService) - { - this.req = req; - this.serviceName = serviceName; - this.baseUrlGenerator = baseUrlGenerator; - this.binding = binding; - - String pathInfo = req.getPathInfo(); - WebScriptRequest baseReq = getBaseRequest(req); - if(!pathInfo.startsWith("/cmis") && (baseReq instanceof TenantWebScriptServletRequest)) - { - TenantWebScriptServletRequest servletReq = (TenantWebScriptServletRequest)baseReq; - - String tenant = servletReq.getTenant(); - if(tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) - { - String user = AuthenticationUtil.getFullyAuthenticatedUser(); - String domain = tenantAdminService.getUserDomain(user); - if(domain == null || domain.equals(TenantService.DEFAULT_DOMAIN)) - { - this.networkId = tenant; - } - else - { - this.networkId = domain; - } - } - else - { - this.networkId = tenant; - } - } - - Match match = req.getServiceMatch(); - Map templateVars = match.getTemplateVars(); - - HttpServletRequest httpReq = WebScriptServletRuntime.getHttpServletRequest(req); - this.httpReq = httpReq; - this.operation = templateVars.get("operation"); - this.id = templateVars.get("id"); - - addAttributes(); - } - - /* - * Recursively unwrap req if it is a WrappingWebScriptRequest - */ - private WebScriptRequest getBaseRequest(WebScriptRequest req) - { - WebScriptRequest ret = req; - while(ret instanceof WrappingWebScriptRequest) - { - WrappingWebScriptRequest wrapping = (WrappingWebScriptRequest)req; - ret = wrapping.getNext(); - } - return ret; - } - - protected void addAttributes() - { - if(networkId != null) - { - httpReq.setAttribute(Constants.PARAM_REPOSITORY_ID, networkId); - } - httpReq.setAttribute("serviceName", serviceName); - } - - @Override - public Object getAttribute(String arg0) - { - if(arg0.equals(Dispatcher.BASE_URL_ATTRIBUTE)) - { - return baseUrlGenerator.getBaseUrl(this, networkId, binding); - } - else - { - return httpReq.getAttribute(arg0); - } - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration getAttributeNames() - { - Enumeration e = httpReq.getAttributeNames(); - List attrNames = new ArrayList(); - while(e.hasMoreElements()) - { - attrNames.add(e.nextElement()); - } - attrNames.add(Dispatcher.BASE_URL_ATTRIBUTE); - final Iterator it = attrNames.iterator(); - - return new Enumeration() - { - public boolean hasMoreElements() - { - return it.hasNext(); - } - - public Object nextElement() - { - return it.next(); - } - }; - } - - @Override - public String getCharacterEncoding() - { - return httpReq.getCharacterEncoding(); - } - - @Override - public int getContentLength() - { - return httpReq.getContentLength(); - } - - @Override - public String getContentType() - { - return httpReq.getContentType(); - } - - @Override - public ServletInputStream getInputStream() throws IOException - { - return httpReq.getInputStream(); - } - - @Override - public String getLocalAddr() - { - return httpReq.getLocalAddr(); - } - - @Override - public String getLocalName() - { - return httpReq.getLocalName(); - } - - @Override - public int getLocalPort() - { - return httpReq.getLocalPort(); - } - - @Override - public Locale getLocale() - { - return httpReq.getLocale(); - } - - @Override - public Enumeration getLocales() - { - return httpReq.getLocales(); - } - - @Override - public String getParameter(String arg0) - { - if(arg0.equals(Constants.PARAM_REPOSITORY_ID)) - { - return networkId; - } - return httpReq.getParameter(arg0); - } - - @SuppressWarnings("unchecked") - @Override - public Map getParameterMap() - { - Map map = httpReq.getParameterMap(); - Map ret = new HashedMap(map); - if(networkId != null) - { - ret.put(Constants.PARAM_REPOSITORY_ID, new String[] { networkId }); - } - return ret; - } - - @SuppressWarnings("unchecked") - @Override - public Enumeration getParameterNames() - { - final Enumeration e = httpReq.getParameterNames(); - List l = new ArrayList(); - while(e.hasMoreElements()) - { - l.add(e.nextElement()); - } - if(networkId != null) - { - l.add(Constants.PARAM_REPOSITORY_ID); - } - final Iterator it = l.iterator(); - Enumeration ret = new Enumeration() - { - @Override - public boolean hasMoreElements() - { - return it.hasNext(); - } - - @Override - public Object nextElement() - { - return it.next(); - } - }; - - return ret; - } - - @Override - public String[] getParameterValues(String arg0) - { - return httpReq.getParameterValues(arg0); - } - - @Override - public String getProtocol() - { - return httpReq.getProtocol(); - } - - @Override - public BufferedReader getReader() throws IOException - { - return httpReq.getReader(); - } - - @SuppressWarnings("deprecation") - @Override - public String getRealPath(String arg0) - { - return httpReq.getRealPath(arg0); - } - - @Override - public String getRemoteAddr() - { - return httpReq.getRemoteAddr(); - } - - @Override - public String getRemoteHost() - { - return httpReq.getRemoteHost(); - } - - @Override - public int getRemotePort() - { - return httpReq.getRemotePort(); - } - - @Override - public RequestDispatcher getRequestDispatcher(String arg0) - { - return httpReq.getRequestDispatcher(arg0); - } - - @Override - public String getScheme() - { - return httpReq.getScheme(); - } - - @Override - public String getServerName() - { - return httpReq.getServerName(); - } - - @Override - public int getServerPort() - { - return httpReq.getServerPort(); - } - - @Override - public boolean isSecure() - { - return httpReq.isSecure(); - } - - @Override - public void removeAttribute(String arg0) - { - httpReq.removeAttribute(arg0); - } - - @Override - public void setAttribute(String arg0, Object arg1) - { - httpReq.setAttribute(arg0, arg1); - } - - @Override - public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException - { - httpReq.setCharacterEncoding(arg0); - } - - @Override - public String getAuthType() - { - return httpReq.getAuthType(); - } - - @Override - public String getContextPath() - { - String contextPath = baseUrlGenerator.getContextPath(httpReq); - return contextPath; - } - - @Override - public Cookie[] getCookies() - { - return httpReq.getCookies(); - } - - @Override - public long getDateHeader(String arg0) - { - return httpReq.getDateHeader(arg0); - } - - @Override - public String getHeader(String arg0) - { - return httpReq.getHeader(arg0); - } - - @Override - public Enumeration getHeaderNames() - { - return httpReq.getHeaderNames(); - } - - @Override - public Enumeration getHeaders(String arg0) - { - return httpReq.getHeaders(arg0); - } - - @Override - public int getIntHeader(String arg0) - { - return httpReq.getIntHeader(arg0); - } - - @Override - public String getMethod() - { - return httpReq.getMethod(); - } - - @Override - public String getPathInfo() - { - StringBuilder sb = new StringBuilder("/"); - sb.append(networkId == null ? TenantUtil.DEFAULT_TENANT : networkId); - if(operation != null) - { - sb.append("/"); - sb.append(operation); - } - return sb.toString(); - } - - @Override - public String getPathTranslated() - { - return httpReq.getPathTranslated(); - } - - @Override - public String getQueryString() - { - StringBuilder queryString = new StringBuilder(); - String reqQueryString = httpReq.getQueryString(); - - if(networkId != null && networkId.length() > 0) - { - if (reqQueryString == null) - { - queryString.append("repositoryId="); - queryString.append(networkId); - } - else - { - queryString.append(reqQueryString); - queryString.append("&repositoryId="); - queryString.append(networkId); - } - return queryString.toString(); - } - else - { - return reqQueryString; - } - } - - @Override - public String getRemoteUser() - { - return httpReq.getRemoteUser(); - } - - @Override - public String getRequestURI() - { - String requestURI = baseUrlGenerator.getRequestURI(httpReq, networkId, operation, id); - return requestURI; - } - - @Override - public StringBuffer getRequestURL() - { - return httpReq.getRequestURL(); - } - - @Override - public String getRequestedSessionId() - { - return httpReq.getRequestedSessionId(); - } - - @Override - public String getServletPath() - { - String servletPath = baseUrlGenerator.getServletPath(httpReq); - return servletPath; - } - - @Override - public HttpSession getSession() - { - return httpReq.getSession(); - } - - @Override - public HttpSession getSession(boolean arg0) - { - return httpReq.getSession(arg0); - } - - @Override - public Principal getUserPrincipal() - { - return httpReq.getUserPrincipal(); - } - - @Override - public boolean isRequestedSessionIdFromCookie() - { - return httpReq.isRequestedSessionIdFromCookie(); - } - - @Override - public boolean isRequestedSessionIdFromURL() - { - return httpReq.isRequestedSessionIdFromURL(); - } - - @Override - public boolean isRequestedSessionIdFromUrl() - { - return httpReq.isRequestedSessionIdFromURL(); - } - - @Override - public boolean isRequestedSessionIdValid() - { - return httpReq.isRequestedSessionIdValid(); - } - - @Override - public boolean isUserInRole(String arg0) - { - return httpReq.isUserInRole(arg0); - } +package org.alfresco.opencmis; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; +import org.alfresco.service.descriptor.Descriptor; +import org.apache.chemistry.opencmis.commons.impl.Constants; +import org.apache.chemistry.opencmis.server.shared.Dispatcher; +import org.apache.commons.collections.map.HashedMap; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WrappingWebScriptRequest; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + +/** + * Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS. + */ +@SuppressWarnings("rawtypes") +public class CMISHttpServletRequest implements HttpServletRequest +{ + protected WebScriptRequest req; + protected HttpServletRequest httpReq; + protected String networkId; + protected String operation; + protected String id; // object id (or path for browser binding) + protected String serviceName; + protected BaseUrlGenerator baseUrlGenerator; + protected Binding binding; + protected Descriptor currentDescriptor; + + public CMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator, Binding binding, Descriptor currentDescriptor, + TenantAdminService tenantAdminService) + { + this.req = req; + this.serviceName = serviceName; + this.baseUrlGenerator = baseUrlGenerator; + this.binding = binding; + + String pathInfo = req.getPathInfo(); + WebScriptRequest baseReq = getBaseRequest(req); + if(!pathInfo.startsWith("/cmis") && (baseReq instanceof TenantWebScriptServletRequest)) + { + TenantWebScriptServletRequest servletReq = (TenantWebScriptServletRequest)baseReq; + + String tenant = servletReq.getTenant(); + if(tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) + { + String user = AuthenticationUtil.getFullyAuthenticatedUser(); + String domain = tenantAdminService.getUserDomain(user); + if(domain == null || domain.equals(TenantService.DEFAULT_DOMAIN)) + { + this.networkId = tenant; + } + else + { + this.networkId = domain; + } + } + else + { + this.networkId = tenant; + } + } + + Match match = req.getServiceMatch(); + Map templateVars = match.getTemplateVars(); + + HttpServletRequest httpReq = WebScriptServletRuntime.getHttpServletRequest(req); + this.httpReq = httpReq; + this.operation = templateVars.get("operation"); + this.id = templateVars.get("id"); + + addAttributes(); + } + + /* + * Recursively unwrap req if it is a WrappingWebScriptRequest + */ + private WebScriptRequest getBaseRequest(WebScriptRequest req) + { + WebScriptRequest ret = req; + while(ret instanceof WrappingWebScriptRequest) + { + WrappingWebScriptRequest wrapping = (WrappingWebScriptRequest)req; + ret = wrapping.getNext(); + } + return ret; + } + + protected void addAttributes() + { + if(networkId != null) + { + httpReq.setAttribute(Constants.PARAM_REPOSITORY_ID, networkId); + } + httpReq.setAttribute("serviceName", serviceName); + } + + @Override + public Object getAttribute(String arg0) + { + if(arg0.equals(Dispatcher.BASE_URL_ATTRIBUTE)) + { + return baseUrlGenerator.getBaseUrl(this, networkId, binding); + } + else + { + return httpReq.getAttribute(arg0); + } + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration getAttributeNames() + { + Enumeration e = httpReq.getAttributeNames(); + List attrNames = new ArrayList(); + while(e.hasMoreElements()) + { + attrNames.add(e.nextElement()); + } + attrNames.add(Dispatcher.BASE_URL_ATTRIBUTE); + final Iterator it = attrNames.iterator(); + + return new Enumeration() + { + public boolean hasMoreElements() + { + return it.hasNext(); + } + + public Object nextElement() + { + return it.next(); + } + }; + } + + @Override + public String getCharacterEncoding() + { + return httpReq.getCharacterEncoding(); + } + + @Override + public int getContentLength() + { + return httpReq.getContentLength(); + } + + @Override + public String getContentType() + { + return httpReq.getContentType(); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + return httpReq.getInputStream(); + } + + @Override + public String getLocalAddr() + { + return httpReq.getLocalAddr(); + } + + @Override + public String getLocalName() + { + return httpReq.getLocalName(); + } + + @Override + public int getLocalPort() + { + return httpReq.getLocalPort(); + } + + @Override + public Locale getLocale() + { + return httpReq.getLocale(); + } + + @Override + public Enumeration getLocales() + { + return httpReq.getLocales(); + } + + @Override + public String getParameter(String arg0) + { + if(arg0.equals(Constants.PARAM_REPOSITORY_ID)) + { + return networkId; + } + return httpReq.getParameter(arg0); + } + + @SuppressWarnings("unchecked") + @Override + public Map getParameterMap() + { + Map map = httpReq.getParameterMap(); + Map ret = new HashedMap(map); + if(networkId != null) + { + ret.put(Constants.PARAM_REPOSITORY_ID, new String[] { networkId }); + } + return ret; + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration getParameterNames() + { + final Enumeration e = httpReq.getParameterNames(); + List l = new ArrayList(); + while(e.hasMoreElements()) + { + l.add(e.nextElement()); + } + if(networkId != null) + { + l.add(Constants.PARAM_REPOSITORY_ID); + } + final Iterator it = l.iterator(); + Enumeration ret = new Enumeration() + { + @Override + public boolean hasMoreElements() + { + return it.hasNext(); + } + + @Override + public Object nextElement() + { + return it.next(); + } + }; + + return ret; + } + + @Override + public String[] getParameterValues(String arg0) + { + return httpReq.getParameterValues(arg0); + } + + @Override + public String getProtocol() + { + return httpReq.getProtocol(); + } + + @Override + public BufferedReader getReader() throws IOException + { + return httpReq.getReader(); + } + + @SuppressWarnings("deprecation") + @Override + public String getRealPath(String arg0) + { + return httpReq.getRealPath(arg0); + } + + @Override + public String getRemoteAddr() + { + return httpReq.getRemoteAddr(); + } + + @Override + public String getRemoteHost() + { + return httpReq.getRemoteHost(); + } + + @Override + public int getRemotePort() + { + return httpReq.getRemotePort(); + } + + @Override + public RequestDispatcher getRequestDispatcher(String arg0) + { + return httpReq.getRequestDispatcher(arg0); + } + + @Override + public String getScheme() + { + return httpReq.getScheme(); + } + + @Override + public String getServerName() + { + return httpReq.getServerName(); + } + + @Override + public int getServerPort() + { + return httpReq.getServerPort(); + } + + @Override + public boolean isSecure() + { + return httpReq.isSecure(); + } + + @Override + public void removeAttribute(String arg0) + { + httpReq.removeAttribute(arg0); + } + + @Override + public void setAttribute(String arg0, Object arg1) + { + httpReq.setAttribute(arg0, arg1); + } + + @Override + public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException + { + httpReq.setCharacterEncoding(arg0); + } + + @Override + public String getAuthType() + { + return httpReq.getAuthType(); + } + + @Override + public String getContextPath() + { + String contextPath = baseUrlGenerator.getContextPath(httpReq); + return contextPath; + } + + @Override + public Cookie[] getCookies() + { + return httpReq.getCookies(); + } + + @Override + public long getDateHeader(String arg0) + { + return httpReq.getDateHeader(arg0); + } + + @Override + public String getHeader(String arg0) + { + return httpReq.getHeader(arg0); + } + + @Override + public Enumeration getHeaderNames() + { + return httpReq.getHeaderNames(); + } + + @Override + public Enumeration getHeaders(String arg0) + { + return httpReq.getHeaders(arg0); + } + + @Override + public int getIntHeader(String arg0) + { + return httpReq.getIntHeader(arg0); + } + + @Override + public String getMethod() + { + return httpReq.getMethod(); + } + + @Override + public String getPathInfo() + { + StringBuilder sb = new StringBuilder("/"); + sb.append(networkId == null ? TenantUtil.DEFAULT_TENANT : networkId); + if(operation != null) + { + sb.append("/"); + sb.append(operation); + } + return sb.toString(); + } + + @Override + public String getPathTranslated() + { + return httpReq.getPathTranslated(); + } + + @Override + public String getQueryString() + { + StringBuilder queryString = new StringBuilder(); + String reqQueryString = httpReq.getQueryString(); + + if(networkId != null && networkId.length() > 0) + { + if (reqQueryString == null) + { + queryString.append("repositoryId="); + queryString.append(networkId); + } + else + { + queryString.append(reqQueryString); + queryString.append("&repositoryId="); + queryString.append(networkId); + } + return queryString.toString(); + } + else + { + return reqQueryString; + } + } + + @Override + public String getRemoteUser() + { + return httpReq.getRemoteUser(); + } + + @Override + public String getRequestURI() + { + String requestURI = baseUrlGenerator.getRequestURI(httpReq, networkId, operation, id); + return requestURI; + } + + @Override + public StringBuffer getRequestURL() + { + return httpReq.getRequestURL(); + } + + @Override + public String getRequestedSessionId() + { + return httpReq.getRequestedSessionId(); + } + + @Override + public String getServletPath() + { + String servletPath = baseUrlGenerator.getServletPath(httpReq); + return servletPath; + } + + @Override + public HttpSession getSession() + { + return httpReq.getSession(); + } + + @Override + public HttpSession getSession(boolean arg0) + { + return httpReq.getSession(arg0); + } + + @Override + public Principal getUserPrincipal() + { + return httpReq.getUserPrincipal(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() + { + return httpReq.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() + { + return httpReq.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() + { + return httpReq.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdValid() + { + return httpReq.isRequestedSessionIdValid(); + } + + @Override + public boolean isUserInRole(String arg0) + { + return httpReq.isUserInRole(arg0); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/opencmis/CMISServletDispatcher.java b/source/java/org/alfresco/opencmis/CMISServletDispatcher.java index 1b4d8ad5d3..c00fb88fc7 100644 --- a/source/java/org/alfresco/opencmis/CMISServletDispatcher.java +++ b/source/java/org/alfresco/opencmis/CMISServletDispatcher.java @@ -1,393 +1,393 @@ -package org.alfresco.opencmis; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.opencmis.CMISDispatcherRegistry.Endpoint; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.service.descriptor.Descriptor; -import org.alfresco.service.descriptor.DescriptorService; -import org.apache.chemistry.opencmis.commons.enums.CmisVersion; -import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory; -import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener; -import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; - -/** - * Dispatches OpenCMIS requests to a servlet e.g. the OpenCMIS AtomPub servlet. - * - * @author steveglover - * - */ -public abstract class CMISServletDispatcher implements CMISDispatcher -{ - private DescriptorService descriptorService; - private Descriptor currentDescriptor; - protected CmisServiceFactory cmisServiceFactory; - protected HttpServlet servlet; - protected CMISDispatcherRegistry registry; - protected String serviceName; - protected BaseUrlGenerator baseUrlGenerator; - protected String version; - protected CmisVersion cmisVersion; - protected TenantAdminService tenantAdminService; - - public void setTenantAdminService(TenantAdminService tenantAdminService) - { - this.tenantAdminService = tenantAdminService; - } - - public void setDescriptorService(DescriptorService descriptorService) - { - this.descriptorService = descriptorService; - } - - public void setVersion(String version) - { - this.version = version; - } - - public void setBaseUrlGenerator(BaseUrlGenerator baseUrlGenerator) - { - this.baseUrlGenerator = baseUrlGenerator; - } - - public void setRegistry(CMISDispatcherRegistry registry) - { - this.registry = registry; - } - - public void setCmisServiceFactory(CmisServiceFactory cmisServiceFactory) - { - this.cmisServiceFactory = cmisServiceFactory; - } - - public void setServiceName(String serviceName) - { - this.serviceName = serviceName; - } - - public String getServiceName() - { - return serviceName; - } - - public void setCmisVersion(String cmisVersion) - { - this.cmisVersion = CmisVersion.fromValue(cmisVersion); - } - - protected synchronized Descriptor getCurrentDescriptor() - { - if(this.currentDescriptor == null) - { - this.currentDescriptor = descriptorService.getCurrentRepositoryDescriptor(); - } - - return this.currentDescriptor; - } - - public void init() - { - Endpoint endpoint = new Endpoint(getBinding(), version); - registry.registerDispatcher(endpoint, this); - - try - { - // fake the CMIS servlet - ServletConfig config = getServletConfig(); - this.servlet = getServlet(); - servlet.init(config); - } - catch(ServletException e) - { - throw new AlfrescoRuntimeException("Failed to initialise CMIS servlet dispatcher", e); - } - } - - /* - * Implement getBinding to provide the appropriate CMIS binding. - */ - protected abstract Binding getBinding(); - - /* - * Implement getServlet to provide the appropriate servlet implementation. - */ - protected abstract HttpServlet getServlet(); - - protected Object getServletAttribute(String attrName) - { - if(attrName.equals(CmisRepositoryContextListener.SERVICES_FACTORY)) - { - return cmisServiceFactory; - } - - return null; - } - - protected ServletConfig getServletConfig() - { - ServletConfig config = new CMISServletConfig(); - return config; - } - - protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) - { - String serviceName = getServiceName(); - CMISHttpServletRequest httpReqWrapper = new CMISHttpServletRequest(req, serviceName, baseUrlGenerator, - getBinding(), currentDescriptor, tenantAdminService); - return httpReqWrapper; - } - - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - try - { - HttpServletResponse httpResp = WebScriptServletRuntime.getHttpServletResponse(res); - - // fake a servlet request. - CMISHttpServletRequest httpReqWrapper = getHttpRequest(req); - - servlet.service(httpReqWrapper, httpResp); - } - catch(ServletException e) - { - throw new AlfrescoRuntimeException("", e); - } - } - - /** - * Fake a CMIS servlet config. - * - * @author steveglover - * - */ - @SuppressWarnings("rawtypes") - private class CMISServletConfig implements ServletConfig - { - private List parameterNames = new ArrayList(); - - @SuppressWarnings("unchecked") - CMISServletConfig() - { - parameterNames.add(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER); - parameterNames.add(CmisAtomPubServlet.PARAM_CMIS_VERSION); - } - - @Override - public String getInitParameter(String arg0) - { - if(arg0.equals(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER)) - { - return "org.alfresco.opencmis.PublicApiCallContextHandler"; - } - else if(arg0.equals(CmisAtomPubServlet.PARAM_CMIS_VERSION)) - { - return (cmisVersion != null ? cmisVersion.value() : CmisVersion.CMIS_1_0.value()); - } - return null; - } - - @Override - public Enumeration getInitParameterNames() - { - final Iterator it = parameterNames.iterator(); - - Enumeration e = new Enumeration() - { - @Override - public boolean hasMoreElements() - { - return it.hasNext(); - } - - @Override - public Object nextElement() - { - return it.next(); - } - }; - return e; - } - - // fake a servlet context. Note that getAttribute is the only method that the servlet uses, - // hence the other methods are not implemented. - @Override - public ServletContext getServletContext() - { - return new ServletContext() - { - - @Override - public Object getAttribute(String arg0) - { - return getServletAttribute(arg0); - } - - @Override - public Enumeration getAttributeNames() - { - return null; - } - - @Override - public String getContextPath() - { - return null; - } - - @Override - public ServletContext getContext(String arg0) - { - return null; - } - - @Override - public String getInitParameter(String arg0) - { - return null; - } - - @Override - public Enumeration getInitParameterNames() - { - return null; - } - - @Override - public int getMajorVersion() - { - return 0; - } - - @Override - public String getMimeType(String arg0) - { - return null; - } - - @Override - public int getMinorVersion() - { - return 0; - } - - @Override - public RequestDispatcher getNamedDispatcher(String arg0) - { - return null; - } - - @Override - public String getRealPath(String arg0) - { - return null; - } - - @Override - public RequestDispatcher getRequestDispatcher(String arg0) - { - return null; - } - - @Override - public URL getResource(String arg0) throws MalformedURLException - { - return null; - } - - @Override - public InputStream getResourceAsStream(String arg0) - { - return null; - } - - @Override - public Set getResourcePaths(String arg0) - { - return null; - } - - @Override - public String getServerInfo() - { - return null; - } - - @Override - public Servlet getServlet(String arg0) throws ServletException - { - return null; - } - - @Override - public String getServletContextName() - { - return null; - } - - @Override - public Enumeration getServletNames() - { - return null; - } - - @Override - public Enumeration getServlets() - { - return null; - } - - @Override - public void log(String arg0) - { - } - - @Override - public void log(Exception arg0, String arg1) - { - } - - @Override - public void log(String arg0, Throwable arg1) - { - } - - @Override - public void removeAttribute(String arg0) - { - } - - @Override - public void setAttribute(String arg0, Object arg1) - { - } - }; - } - - @Override - public String getServletName() - { - return "OpenCMIS"; - } - } -} +package org.alfresco.opencmis; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.opencmis.CMISDispatcherRegistry.Endpoint; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.service.descriptor.Descriptor; +import org.alfresco.service.descriptor.DescriptorService; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory; +import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener; +import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + +/** + * Dispatches OpenCMIS requests to a servlet e.g. the OpenCMIS AtomPub servlet. + * + * @author steveglover + * + */ +public abstract class CMISServletDispatcher implements CMISDispatcher +{ + private DescriptorService descriptorService; + private Descriptor currentDescriptor; + protected CmisServiceFactory cmisServiceFactory; + protected HttpServlet servlet; + protected CMISDispatcherRegistry registry; + protected String serviceName; + protected BaseUrlGenerator baseUrlGenerator; + protected String version; + protected CmisVersion cmisVersion; + protected TenantAdminService tenantAdminService; + + public void setTenantAdminService(TenantAdminService tenantAdminService) + { + this.tenantAdminService = tenantAdminService; + } + + public void setDescriptorService(DescriptorService descriptorService) + { + this.descriptorService = descriptorService; + } + + public void setVersion(String version) + { + this.version = version; + } + + public void setBaseUrlGenerator(BaseUrlGenerator baseUrlGenerator) + { + this.baseUrlGenerator = baseUrlGenerator; + } + + public void setRegistry(CMISDispatcherRegistry registry) + { + this.registry = registry; + } + + public void setCmisServiceFactory(CmisServiceFactory cmisServiceFactory) + { + this.cmisServiceFactory = cmisServiceFactory; + } + + public void setServiceName(String serviceName) + { + this.serviceName = serviceName; + } + + public String getServiceName() + { + return serviceName; + } + + public void setCmisVersion(String cmisVersion) + { + this.cmisVersion = CmisVersion.fromValue(cmisVersion); + } + + protected synchronized Descriptor getCurrentDescriptor() + { + if(this.currentDescriptor == null) + { + this.currentDescriptor = descriptorService.getCurrentRepositoryDescriptor(); + } + + return this.currentDescriptor; + } + + public void init() + { + Endpoint endpoint = new Endpoint(getBinding(), version); + registry.registerDispatcher(endpoint, this); + + try + { + // fake the CMIS servlet + ServletConfig config = getServletConfig(); + this.servlet = getServlet(); + servlet.init(config); + } + catch(ServletException e) + { + throw new AlfrescoRuntimeException("Failed to initialise CMIS servlet dispatcher", e); + } + } + + /* + * Implement getBinding to provide the appropriate CMIS binding. + */ + protected abstract Binding getBinding(); + + /* + * Implement getServlet to provide the appropriate servlet implementation. + */ + protected abstract HttpServlet getServlet(); + + protected Object getServletAttribute(String attrName) + { + if(attrName.equals(CmisRepositoryContextListener.SERVICES_FACTORY)) + { + return cmisServiceFactory; + } + + return null; + } + + protected ServletConfig getServletConfig() + { + ServletConfig config = new CMISServletConfig(); + return config; + } + + protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) + { + String serviceName = getServiceName(); + CMISHttpServletRequest httpReqWrapper = new CMISHttpServletRequest(req, serviceName, baseUrlGenerator, + getBinding(), currentDescriptor, tenantAdminService); + return httpReqWrapper; + } + + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + try + { + HttpServletResponse httpResp = WebScriptServletRuntime.getHttpServletResponse(res); + + // fake a servlet request. + CMISHttpServletRequest httpReqWrapper = getHttpRequest(req); + + servlet.service(httpReqWrapper, httpResp); + } + catch(ServletException e) + { + throw new AlfrescoRuntimeException("", e); + } + } + + /** + * Fake a CMIS servlet config. + * + * @author steveglover + * + */ + @SuppressWarnings("rawtypes") + private class CMISServletConfig implements ServletConfig + { + private List parameterNames = new ArrayList(); + + @SuppressWarnings("unchecked") + CMISServletConfig() + { + parameterNames.add(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER); + parameterNames.add(CmisAtomPubServlet.PARAM_CMIS_VERSION); + } + + @Override + public String getInitParameter(String arg0) + { + if(arg0.equals(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER)) + { + return "org.alfresco.opencmis.PublicApiCallContextHandler"; + } + else if(arg0.equals(CmisAtomPubServlet.PARAM_CMIS_VERSION)) + { + return (cmisVersion != null ? cmisVersion.value() : CmisVersion.CMIS_1_0.value()); + } + return null; + } + + @Override + public Enumeration getInitParameterNames() + { + final Iterator it = parameterNames.iterator(); + + Enumeration e = new Enumeration() + { + @Override + public boolean hasMoreElements() + { + return it.hasNext(); + } + + @Override + public Object nextElement() + { + return it.next(); + } + }; + return e; + } + + // fake a servlet context. Note that getAttribute is the only method that the servlet uses, + // hence the other methods are not implemented. + @Override + public ServletContext getServletContext() + { + return new ServletContext() + { + + @Override + public Object getAttribute(String arg0) + { + return getServletAttribute(arg0); + } + + @Override + public Enumeration getAttributeNames() + { + return null; + } + + @Override + public String getContextPath() + { + return null; + } + + @Override + public ServletContext getContext(String arg0) + { + return null; + } + + @Override + public String getInitParameter(String arg0) + { + return null; + } + + @Override + public Enumeration getInitParameterNames() + { + return null; + } + + @Override + public int getMajorVersion() + { + return 0; + } + + @Override + public String getMimeType(String arg0) + { + return null; + } + + @Override + public int getMinorVersion() + { + return 0; + } + + @Override + public RequestDispatcher getNamedDispatcher(String arg0) + { + return null; + } + + @Override + public String getRealPath(String arg0) + { + return null; + } + + @Override + public RequestDispatcher getRequestDispatcher(String arg0) + { + return null; + } + + @Override + public URL getResource(String arg0) throws MalformedURLException + { + return null; + } + + @Override + public InputStream getResourceAsStream(String arg0) + { + return null; + } + + @Override + public Set getResourcePaths(String arg0) + { + return null; + } + + @Override + public String getServerInfo() + { + return null; + } + + @Override + public Servlet getServlet(String arg0) throws ServletException + { + return null; + } + + @Override + public String getServletContextName() + { + return null; + } + + @Override + public Enumeration getServletNames() + { + return null; + } + + @Override + public Enumeration getServlets() + { + return null; + } + + @Override + public void log(String arg0) + { + } + + @Override + public void log(Exception arg0, String arg1) + { + } + + @Override + public void log(String arg0, Throwable arg1) + { + } + + @Override + public void removeAttribute(String arg0) + { + } + + @Override + public void setAttribute(String arg0, Object arg1) + { + } + }; + } + + @Override + public String getServletName() + { + return "OpenCMIS"; + } + } +} diff --git a/source/java/org/alfresco/opencmis/CMISWebScript.java b/source/java/org/alfresco/opencmis/CMISWebScript.java index d228361341..a483c0d8a9 100644 --- a/source/java/org/alfresco/opencmis/CMISWebScript.java +++ b/source/java/org/alfresco/opencmis/CMISWebScript.java @@ -1,36 +1,36 @@ -package org.alfresco.opencmis; - -import java.io.IOException; - -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * An Alfresco web script that handles dispatch of OpenCMIS requests. - * - * @author steveglover - * - */ -public class CMISWebScript extends AbstractWebScript -{ - private CMISDispatcherRegistry registry; - - public void setRegistry(CMISDispatcherRegistry registry) - { - this.registry = registry; - } - - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - CMISDispatcher dispatcher = registry.getDispatcher(req); - if(dispatcher == null) - { - res.setStatus(404); - } - else - { - dispatcher.execute(req, res); - } - } -} +package org.alfresco.opencmis; + +import java.io.IOException; + +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * An Alfresco web script that handles dispatch of OpenCMIS requests. + * + * @author steveglover + * + */ +public class CMISWebScript extends AbstractWebScript +{ + private CMISDispatcherRegistry registry; + + public void setRegistry(CMISDispatcherRegistry registry) + { + this.registry = registry; + } + + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + CMISDispatcher dispatcher = registry.getDispatcher(req); + if(dispatcher == null) + { + res.setStatus(404); + } + else + { + dispatcher.execute(req, res); + } + } +} diff --git a/source/java/org/alfresco/opencmis/DefaultBaseUrlGenerator.java b/source/java/org/alfresco/opencmis/DefaultBaseUrlGenerator.java index f5c614c38c..9f20b88c98 100644 --- a/source/java/org/alfresco/opencmis/DefaultBaseUrlGenerator.java +++ b/source/java/org/alfresco/opencmis/DefaultBaseUrlGenerator.java @@ -1,49 +1,49 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -/** - * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port - * are overridden by a property from repository.properties or in an override file. - * - * @author steveglover - * - */ -public class DefaultBaseUrlGenerator extends AbstractBaseUrlGenerator -{ - private boolean overrideServer; - private String serverOverride; - - public DefaultBaseUrlGenerator() - { - } - - public void setOverrideServer(boolean overrideServer) - { - this.overrideServer = overrideServer; - } - - public void setServerOverride(String serverOverride) - { - this.serverOverride = serverOverride; - } - - protected String getServerPath(HttpServletRequest request) - { - if(overrideServer) - { - return serverOverride; - } - else - { - StringBuilder sb = new StringBuilder(); - sb.append(request.getScheme()); - sb.append("://"); - sb.append(request.getServerName()); - sb.append(":"); - sb.append(request.getServerPort()); - return sb.toString(); - } - } - -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +/** + * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port + * are overridden by a property from repository.properties or in an override file. + * + * @author steveglover + * + */ +public class DefaultBaseUrlGenerator extends AbstractBaseUrlGenerator +{ + private boolean overrideServer; + private String serverOverride; + + public DefaultBaseUrlGenerator() + { + } + + public void setOverrideServer(boolean overrideServer) + { + this.overrideServer = overrideServer; + } + + public void setServerOverride(String serverOverride) + { + this.serverOverride = serverOverride; + } + + protected String getServerPath(HttpServletRequest request) + { + if(overrideServer) + { + return serverOverride; + } + else + { + StringBuilder sb = new StringBuilder(); + sb.append(request.getScheme()); + sb.append("://"); + sb.append(request.getServerName()); + sb.append(":"); + sb.append(request.getServerPort()); + return sb.toString(); + } + } + +} diff --git a/source/java/org/alfresco/opencmis/DefaultPathGenerator.java b/source/java/org/alfresco/opencmis/DefaultPathGenerator.java index 4b0e13ad60..ae693bb735 100644 --- a/source/java/org/alfresco/opencmis/DefaultPathGenerator.java +++ b/source/java/org/alfresco/opencmis/DefaultPathGenerator.java @@ -1,30 +1,30 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.repo.tenant.TenantUtil; - -/** - * Default generator for OpenCMIS paths based on the repositoryId and binding. - * - * @author steveglover - * - */ -public class DefaultPathGenerator implements PathGenerator -{ - public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding) - { - url.append(binding.toString()); - url.append("/"); - if(repositoryId != null) - { - url.append(repositoryId); - } - else - { - url.append(TenantUtil.DEFAULT_TENANT); - } - } - -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.repo.tenant.TenantUtil; + +/** + * Default generator for OpenCMIS paths based on the repositoryId and binding. + * + * @author steveglover + * + */ +public class DefaultPathGenerator implements PathGenerator +{ + public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding) + { + url.append(binding.toString()); + url.append("/"); + if(repositoryId != null) + { + url.append(repositoryId); + } + else + { + url.append(TenantUtil.DEFAULT_TENANT); + } + } + +} diff --git a/source/java/org/alfresco/opencmis/PathGenerator.java b/source/java/org/alfresco/opencmis/PathGenerator.java index cf9d03f81a..0c19d797af 100644 --- a/source/java/org/alfresco/opencmis/PathGenerator.java +++ b/source/java/org/alfresco/opencmis/PathGenerator.java @@ -1,16 +1,16 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; - -/** - * Generates an OpenCMIS path based on the repositoryId and binding. - * - * @author steveglover - * - */ -public interface PathGenerator -{ - public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding); +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; + +/** + * Generates an OpenCMIS path based on the repositoryId and binding. + * + * @author steveglover + * + */ +public interface PathGenerator +{ + public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding); } \ No newline at end of file diff --git a/source/java/org/alfresco/opencmis/ProxyBaseUrlGenerator.java b/source/java/org/alfresco/opencmis/ProxyBaseUrlGenerator.java index e7301fb6a5..89139791db 100644 --- a/source/java/org/alfresco/opencmis/ProxyBaseUrlGenerator.java +++ b/source/java/org/alfresco/opencmis/ProxyBaseUrlGenerator.java @@ -1,76 +1,76 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -/** - * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port - * are overridden by any proxy http header parameters, if present. - * - * @author steveglover - * - */ -public class ProxyBaseUrlGenerator extends AbstractBaseUrlGenerator -{ - public static final String FORWARDED_HOST_HEADER = "X-Forwarded-Host"; - public static final String FORWARDED_PROTO_HEADER = "X-Forwarded-Proto"; - public static final String HTTPS_SCHEME = "https"; - public static final String HTTP_SCHEME = "http"; - - @Override - protected String getServerPath(HttpServletRequest request) - { - String scheme = request.getHeader(FORWARDED_PROTO_HEADER); - String serverName; - int serverPort; - - if (!HTTP_SCHEME.equalsIgnoreCase(scheme) && !HTTPS_SCHEME.equalsIgnoreCase(scheme)) - { - scheme = request.getScheme(); - } - - serverName = request.getServerName(); - serverPort = request.getServerPort(); - - String host = request.getHeader(FORWARDED_HOST_HEADER); - if ((host != null) && (host.length() > 0)) - { - int index = host.indexOf(':'); - if (index < 0) - { - serverName = host; - serverPort = getDefaultPort(scheme); - } - else - { - serverName = host.substring(0, index); - try - { - serverPort = Integer.parseInt(host.substring(index + 1)); - } - catch (NumberFormatException e) - { - serverPort = getDefaultPort(scheme); - } - } - } - - StringBuilder sb = new StringBuilder(); - sb.append(scheme); - sb.append("://"); - sb.append(serverName); - sb.append(":"); - sb.append(serverPort); - return sb.toString(); - } - - private int getDefaultPort(String scheme) - { - if (HTTPS_SCHEME.equalsIgnoreCase(scheme)) - { - return 443; - } - - return 80; - } - -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +/** + * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port + * are overridden by any proxy http header parameters, if present. + * + * @author steveglover + * + */ +public class ProxyBaseUrlGenerator extends AbstractBaseUrlGenerator +{ + public static final String FORWARDED_HOST_HEADER = "X-Forwarded-Host"; + public static final String FORWARDED_PROTO_HEADER = "X-Forwarded-Proto"; + public static final String HTTPS_SCHEME = "https"; + public static final String HTTP_SCHEME = "http"; + + @Override + protected String getServerPath(HttpServletRequest request) + { + String scheme = request.getHeader(FORWARDED_PROTO_HEADER); + String serverName; + int serverPort; + + if (!HTTP_SCHEME.equalsIgnoreCase(scheme) && !HTTPS_SCHEME.equalsIgnoreCase(scheme)) + { + scheme = request.getScheme(); + } + + serverName = request.getServerName(); + serverPort = request.getServerPort(); + + String host = request.getHeader(FORWARDED_HOST_HEADER); + if ((host != null) && (host.length() > 0)) + { + int index = host.indexOf(':'); + if (index < 0) + { + serverName = host; + serverPort = getDefaultPort(scheme); + } + else + { + serverName = host.substring(0, index); + try + { + serverPort = Integer.parseInt(host.substring(index + 1)); + } + catch (NumberFormatException e) + { + serverPort = getDefaultPort(scheme); + } + } + } + + StringBuilder sb = new StringBuilder(); + sb.append(scheme); + sb.append("://"); + sb.append(serverName); + sb.append(":"); + sb.append(serverPort); + return sb.toString(); + } + + private int getDefaultPort(String scheme) + { + if (HTTPS_SCHEME.equalsIgnoreCase(scheme)) + { + return 443; + } + + return 80; + } + +} diff --git a/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisService.java b/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisService.java index f4e8711b91..7a999302e7 100644 --- a/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisService.java +++ b/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisService.java @@ -1,200 +1,200 @@ -package org.alfresco.opencmis; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.tenant.Network; -import org.alfresco.repo.tenant.NetworksService; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.util.FileFilterMode; -import org.alfresco.util.FileFilterMode.Client; -import org.apache.chemistry.opencmis.commons.data.Acl; -import org.apache.chemistry.opencmis.commons.data.ContentStream; -import org.apache.chemistry.opencmis.commons.data.ExtensionsData; -import org.apache.chemistry.opencmis.commons.data.Properties; -import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; -import org.apache.chemistry.opencmis.commons.enums.VersioningState; -import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; -import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; -import org.apache.chemistry.opencmis.commons.spi.Holder; - -/** - * Override OpenCMIS service object - for public api - * - * @author sglover - * @since PublicApi1.0 - */ -public class PublicApiAlfrescoCmisService extends AlfrescoCmisServiceImpl -{ - protected CMISConnector connector; - protected TenantAdminService tenantAdminService; - protected NetworksService networksService; - - public PublicApiAlfrescoCmisService(CMISConnector connector, TenantAdminService tenantAdminService, NetworksService networksService) - { - super(connector); - - this.connector = connector; - this.networksService = networksService; - this.tenantAdminService = tenantAdminService; - } - - @Override - public String create(String repositoryId, Properties properties, String folderId, - ContentStream contentStream, VersioningState versioningState, - List policies, ExtensionsData extension) - { - FileFilterMode.setClient(Client.cmis); - try - { - return super.create( - repositoryId, - properties, - folderId, - contentStream, - versioningState, - policies, - extension); - } - finally - { - FileFilterMode.clearClient(); - } - } - - - /** - * Overridden to capture content upload for publishing to analytics service. - */ - @Override - public String createDocument(String repositoryId, Properties properties, String folderId, - ContentStream contentStream, VersioningState versioningState, - List policies, Acl addAces, Acl removeAces, ExtensionsData extension) - { - String newId = super.createDocument( - repositoryId, - properties, - folderId, - contentStream, - versioningState, - policies, - addAces, - removeAces, - extension); - return newId; - } - - /** - * Overridden to capture content upload for publishing to analytics service. - */ - @Override - public void setContentStream(String repositoryId, Holder objectId, - Boolean overwriteFlag, Holder changeToken, ContentStream contentStream, - ExtensionsData extension) - { - FileFilterMode.setClient(Client.cmis); - try - { - super.setContentStream(repositoryId, objectId, overwriteFlag, changeToken, contentStream, extension); - } - finally - { - FileFilterMode.clearClient(); - } - } - - @Override - public List getRepositoryInfos(ExtensionsData extension) - { - // for currently authenticated user - PagingResults networks = networksService.getNetworks(new PagingRequest(0, Integer.MAX_VALUE)); - List page = networks.getPage(); - final List repoInfos = new ArrayList(page.size() + 1); - for (Network network : page) - { - repoInfos.add(getRepositoryInfo(network)); - } - return repoInfos; - } - - @Override - public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension) - { - Network network = null; - - try - { - checkRepositoryId(repositoryId); - network = networksService.getNetwork(repositoryId); - } - catch(Exception e) - { - // ACE-2540: Avoid information leak. Same response if repository does not exist or if user is not a member - throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!"); - } - - return getRepositoryInfo(network); - } - - private RepositoryInfo getRepositoryInfo(final Network network) - { - final String networkId = network.getTenantDomain(); - final String tenantDomain = (networkId.equals(TenantUtil.SYSTEM_TENANT) || networkId.equals(TenantUtil.DEFAULT_TENANT)) ? TenantService.DEFAULT_DOMAIN : networkId; - - return TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - public RepositoryInfo doWork() - { - RepositoryInfoImpl repoInfo = (RepositoryInfoImpl)connector.getRepositoryInfo(getContext().getCmisVersion()); - - repoInfo.setId(!networkId.equals("") ? networkId : TenantUtil.SYSTEM_TENANT); - repoInfo.setName(tenantDomain); - repoInfo.setDescription(tenantDomain); - - return repoInfo; - } - }, tenantDomain); - } - - @Override - public void checkRepositoryId(String repositoryId) - { - if(repositoryId.equals(TenantUtil.DEFAULT_TENANT) || repositoryId.equals(TenantUtil.SYSTEM_TENANT)) - { - // TODO check for super admin - return; - } - - if(!tenantAdminService.existsTenant(repositoryId) || !tenantAdminService.isEnabledTenant(repositoryId)) - { - throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!"); - } - } - - @Override - public void beforeCall() - { - // NOTE: Don't invoke super beforeCall to exclude authentication which is already supported by - // Web Script F/W - //super.beforeCall(); - } - - @Override - public void afterCall() - { - // NOTE: Don't invoke super afterCall to exclude authentication which is already supported by - // Web Script F/W - //super.afterCall(); - } - - @Override - public void close() - { - super.close(); - } -} +package org.alfresco.opencmis; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.tenant.Network; +import org.alfresco.repo.tenant.NetworksService; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.util.FileFilterMode; +import org.alfresco.util.FileFilterMode.Client; +import org.apache.chemistry.opencmis.commons.data.Acl; +import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.apache.chemistry.opencmis.commons.data.ExtensionsData; +import org.apache.chemistry.opencmis.commons.data.Properties; +import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; +import org.apache.chemistry.opencmis.commons.spi.Holder; + +/** + * Override OpenCMIS service object - for public api + * + * @author sglover + * @since PublicApi1.0 + */ +public class PublicApiAlfrescoCmisService extends AlfrescoCmisServiceImpl +{ + protected CMISConnector connector; + protected TenantAdminService tenantAdminService; + protected NetworksService networksService; + + public PublicApiAlfrescoCmisService(CMISConnector connector, TenantAdminService tenantAdminService, NetworksService networksService) + { + super(connector); + + this.connector = connector; + this.networksService = networksService; + this.tenantAdminService = tenantAdminService; + } + + @Override + public String create(String repositoryId, Properties properties, String folderId, + ContentStream contentStream, VersioningState versioningState, + List policies, ExtensionsData extension) + { + FileFilterMode.setClient(Client.cmis); + try + { + return super.create( + repositoryId, + properties, + folderId, + contentStream, + versioningState, + policies, + extension); + } + finally + { + FileFilterMode.clearClient(); + } + } + + + /** + * Overridden to capture content upload for publishing to analytics service. + */ + @Override + public String createDocument(String repositoryId, Properties properties, String folderId, + ContentStream contentStream, VersioningState versioningState, + List policies, Acl addAces, Acl removeAces, ExtensionsData extension) + { + String newId = super.createDocument( + repositoryId, + properties, + folderId, + contentStream, + versioningState, + policies, + addAces, + removeAces, + extension); + return newId; + } + + /** + * Overridden to capture content upload for publishing to analytics service. + */ + @Override + public void setContentStream(String repositoryId, Holder objectId, + Boolean overwriteFlag, Holder changeToken, ContentStream contentStream, + ExtensionsData extension) + { + FileFilterMode.setClient(Client.cmis); + try + { + super.setContentStream(repositoryId, objectId, overwriteFlag, changeToken, contentStream, extension); + } + finally + { + FileFilterMode.clearClient(); + } + } + + @Override + public List getRepositoryInfos(ExtensionsData extension) + { + // for currently authenticated user + PagingResults networks = networksService.getNetworks(new PagingRequest(0, Integer.MAX_VALUE)); + List page = networks.getPage(); + final List repoInfos = new ArrayList(page.size() + 1); + for (Network network : page) + { + repoInfos.add(getRepositoryInfo(network)); + } + return repoInfos; + } + + @Override + public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension) + { + Network network = null; + + try + { + checkRepositoryId(repositoryId); + network = networksService.getNetwork(repositoryId); + } + catch(Exception e) + { + // ACE-2540: Avoid information leak. Same response if repository does not exist or if user is not a member + throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!"); + } + + return getRepositoryInfo(network); + } + + private RepositoryInfo getRepositoryInfo(final Network network) + { + final String networkId = network.getTenantDomain(); + final String tenantDomain = (networkId.equals(TenantUtil.SYSTEM_TENANT) || networkId.equals(TenantUtil.DEFAULT_TENANT)) ? TenantService.DEFAULT_DOMAIN : networkId; + + return TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + public RepositoryInfo doWork() + { + RepositoryInfoImpl repoInfo = (RepositoryInfoImpl)connector.getRepositoryInfo(getContext().getCmisVersion()); + + repoInfo.setId(!networkId.equals("") ? networkId : TenantUtil.SYSTEM_TENANT); + repoInfo.setName(tenantDomain); + repoInfo.setDescription(tenantDomain); + + return repoInfo; + } + }, tenantDomain); + } + + @Override + public void checkRepositoryId(String repositoryId) + { + if(repositoryId.equals(TenantUtil.DEFAULT_TENANT) || repositoryId.equals(TenantUtil.SYSTEM_TENANT)) + { + // TODO check for super admin + return; + } + + if(!tenantAdminService.existsTenant(repositoryId) || !tenantAdminService.isEnabledTenant(repositoryId)) + { + throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!"); + } + } + + @Override + public void beforeCall() + { + // NOTE: Don't invoke super beforeCall to exclude authentication which is already supported by + // Web Script F/W + //super.beforeCall(); + } + + @Override + public void afterCall() + { + // NOTE: Don't invoke super afterCall to exclude authentication which is already supported by + // Web Script F/W + //super.afterCall(); + } + + @Override + public void close() + { + super.close(); + } +} diff --git a/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisServiceFactory.java b/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisServiceFactory.java index d58dd0a59a..5a74e0f9f8 100644 --- a/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisServiceFactory.java +++ b/source/java/org/alfresco/opencmis/PublicApiAlfrescoCmisServiceFactory.java @@ -1,33 +1,33 @@ -package org.alfresco.opencmis; - -import org.alfresco.repo.tenant.NetworksService; -import org.alfresco.repo.tenant.TenantAdminService; - -/** - * Override factory for OpenCMIS service objects - for public api - * - * @author steveglover - * @author janv - * @since PublicApi1.0 - */ -public class PublicApiAlfrescoCmisServiceFactory extends AlfrescoCmisServiceFactory -{ - private TenantAdminService tenantAdminService; - private NetworksService networksService; - - public void setNetworksService(NetworksService networksService) - { - this.networksService = networksService; - } - - public void setTenantAdminService(TenantAdminService tenantAdminService) - { - this.tenantAdminService = tenantAdminService; - } - - @Override - protected AlfrescoCmisService getCmisServiceTarget(CMISConnector connector) - { - return new PublicApiAlfrescoCmisService(connector, tenantAdminService, networksService); - } -} +package org.alfresco.opencmis; + +import org.alfresco.repo.tenant.NetworksService; +import org.alfresco.repo.tenant.TenantAdminService; + +/** + * Override factory for OpenCMIS service objects - for public api + * + * @author steveglover + * @author janv + * @since PublicApi1.0 + */ +public class PublicApiAlfrescoCmisServiceFactory extends AlfrescoCmisServiceFactory +{ + private TenantAdminService tenantAdminService; + private NetworksService networksService; + + public void setNetworksService(NetworksService networksService) + { + this.networksService = networksService; + } + + public void setTenantAdminService(TenantAdminService tenantAdminService) + { + this.tenantAdminService = tenantAdminService; + } + + @Override + protected AlfrescoCmisService getCmisServiceTarget(CMISConnector connector) + { + return new PublicApiAlfrescoCmisService(connector, tenantAdminService, networksService); + } +} diff --git a/source/java/org/alfresco/opencmis/PublicApiAtomPubCMISDispatcher.java b/source/java/org/alfresco/opencmis/PublicApiAtomPubCMISDispatcher.java index edf148af5c..2a2df153be 100644 --- a/source/java/org/alfresco/opencmis/PublicApiAtomPubCMISDispatcher.java +++ b/source/java/org/alfresco/opencmis/PublicApiAtomPubCMISDispatcher.java @@ -1,21 +1,21 @@ -package org.alfresco.opencmis; - -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet. - * - * @author steveglover - * - */ -public class PublicApiAtomPubCMISDispatcher extends AtomPubCMISDispatcher -{ - @Override - protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) - { - String serviceName = getServiceName(); - CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName, baseUrlGenerator, - getBinding(), getCurrentDescriptor(), tenantAdminService); - return httpReqWrapper; - } +package org.alfresco.opencmis; + +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet. + * + * @author steveglover + * + */ +public class PublicApiAtomPubCMISDispatcher extends AtomPubCMISDispatcher +{ + @Override + protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) + { + String serviceName = getServiceName(); + CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName, baseUrlGenerator, + getBinding(), getCurrentDescriptor(), tenantAdminService); + return httpReqWrapper; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/opencmis/PublicApiBrowserCMISDispatcher.java b/source/java/org/alfresco/opencmis/PublicApiBrowserCMISDispatcher.java index a87f103331..c0084a5e70 100644 --- a/source/java/org/alfresco/opencmis/PublicApiBrowserCMISDispatcher.java +++ b/source/java/org/alfresco/opencmis/PublicApiBrowserCMISDispatcher.java @@ -1,21 +1,21 @@ -package org.alfresco.opencmis; - -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Cloud-specific browser binding OpenCMIS dispatcher. - * - * @author steveglover - * - */ -public class PublicApiBrowserCMISDispatcher extends BrowserCMISDispatcher -{ - @Override - protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) - { - String serviceName = getServiceName(); - CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName, - baseUrlGenerator, getBinding(), getCurrentDescriptor(), tenantAdminService); - return httpReqWrapper; - } -} +package org.alfresco.opencmis; + +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Cloud-specific browser binding OpenCMIS dispatcher. + * + * @author steveglover + * + */ +public class PublicApiBrowserCMISDispatcher extends BrowserCMISDispatcher +{ + @Override + protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req) + { + String serviceName = getServiceName(); + CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName, + baseUrlGenerator, getBinding(), getCurrentDescriptor(), tenantAdminService); + return httpReqWrapper; + } +} diff --git a/source/java/org/alfresco/opencmis/PublicApiCMISHttpServletRequest.java b/source/java/org/alfresco/opencmis/PublicApiCMISHttpServletRequest.java index 0c4798bf16..f326a9cd1a 100644 --- a/source/java/org/alfresco/opencmis/PublicApiCMISHttpServletRequest.java +++ b/source/java/org/alfresco/opencmis/PublicApiCMISHttpServletRequest.java @@ -1,42 +1,42 @@ -package org.alfresco.opencmis; - -import java.util.Map; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.service.descriptor.Descriptor; -import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS. - */ -public class PublicApiCMISHttpServletRequest extends CMISHttpServletRequest -{ - public PublicApiCMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator, - Binding binding, Descriptor currentDescriptor, TenantAdminService tenantAdminService) - { - super(req, serviceName, baseUrlGenerator, binding, currentDescriptor, tenantAdminService); - } - - protected void addAttributes() - { - super.addAttributes(); - - Match match = req.getServiceMatch(); - Map templateVars = match.getTemplateVars(); - String apiScope = templateVars.get("apiScope"); - String apiVersion = templateVars.get("apiVersion"); - - if(apiScope != null) - { - httpReq.setAttribute("apiScope", apiScope); - } - - if(apiVersion != null) - { - httpReq.setAttribute("apiVersion", apiVersion); - } - } - +package org.alfresco.opencmis; + +import java.util.Map; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.service.descriptor.Descriptor; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS. + */ +public class PublicApiCMISHttpServletRequest extends CMISHttpServletRequest +{ + public PublicApiCMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator, + Binding binding, Descriptor currentDescriptor, TenantAdminService tenantAdminService) + { + super(req, serviceName, baseUrlGenerator, binding, currentDescriptor, tenantAdminService); + } + + protected void addAttributes() + { + super.addAttributes(); + + Match match = req.getServiceMatch(); + Map templateVars = match.getTemplateVars(); + String apiScope = templateVars.get("apiScope"); + String apiVersion = templateVars.get("apiVersion"); + + if(apiScope != null) + { + httpReq.setAttribute("apiScope", apiScope); + } + + if(apiVersion != null) + { + httpReq.setAttribute("apiVersion", apiVersion); + } + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/opencmis/PublicApiPathGenerator.java b/source/java/org/alfresco/opencmis/PublicApiPathGenerator.java index 0b297412fe..92a9a5dc18 100644 --- a/source/java/org/alfresco/opencmis/PublicApiPathGenerator.java +++ b/source/java/org/alfresco/opencmis/PublicApiPathGenerator.java @@ -1,38 +1,38 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; - -/** - * Cloud generator for OpenCMIS paths based on the repositoryId and binding. - * - * @author steveglover - * - */ -public class PublicApiPathGenerator implements PathGenerator -{ - public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding) - { - url.append("{repositoryId}"); - url.append("/"); - - String scope = (String)req.getAttribute("apiScope"); - String serviceName = (String)req.getAttribute("serviceName"); - String apiVersion = (String)req.getAttribute("apiVersion"); - if(scope == null) - { - scope = "public"; - } - url.append(scope); - url.append("/"); - url.append(serviceName); - url.append("/"); - url.append("versions"); - url.append("/"); - url.append(apiVersion); - url.append("/"); - url.append(binding.toString()); - } - -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; + +/** + * Cloud generator for OpenCMIS paths based on the repositoryId and binding. + * + * @author steveglover + * + */ +public class PublicApiPathGenerator implements PathGenerator +{ + public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding) + { + url.append("{repositoryId}"); + url.append("/"); + + String scope = (String)req.getAttribute("apiScope"); + String serviceName = (String)req.getAttribute("serviceName"); + String apiVersion = (String)req.getAttribute("apiVersion"); + if(scope == null) + { + scope = "public"; + } + url.append(scope); + url.append("/"); + url.append(serviceName); + url.append("/"); + url.append("versions"); + url.append("/"); + url.append(apiVersion); + url.append("/"); + url.append(binding.toString()); + } + +} diff --git a/source/java/org/alfresco/opencmis/SysAdminParamsBaseUrlGenerator.java b/source/java/org/alfresco/opencmis/SysAdminParamsBaseUrlGenerator.java index c31a45798e..70c2348e2f 100644 --- a/source/java/org/alfresco/opencmis/SysAdminParamsBaseUrlGenerator.java +++ b/source/java/org/alfresco/opencmis/SysAdminParamsBaseUrlGenerator.java @@ -1,65 +1,65 @@ -package org.alfresco.opencmis; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.repo.admin.SysAdminParams; - -/** - * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port - * are overridden by sys admin parameters. - * - * @author steveglover - * - */ -public class SysAdminParamsBaseUrlGenerator extends AbstractBaseUrlGenerator -{ - private SysAdminParams sysAdminParams; - - protected String getServerPath(HttpServletRequest request) - { - StringBuilder sb = new StringBuilder(); - sb.append(getServerScheme(request)); - sb.append("://"); - sb.append(getServerName(request)); - sb.append(":"); - sb.append(getServerPort(request)); - return sb.toString(); - } - - protected String getServerScheme(HttpServletRequest request) - { - String scheme = sysAdminParams.getAlfrescoProtocol(); - if (scheme == null) - { - scheme = request.getScheme(); - } - scheme = request.getScheme(); - return scheme; - } - - protected String getServerName(HttpServletRequest request) - { - String hostname = sysAdminParams.getAlfrescoHost(); - if (hostname == null) - { - hostname = request.getScheme(); - } - hostname = request.getServerName(); - return hostname; - } - - protected int getServerPort(HttpServletRequest request) - { - Integer port = sysAdminParams.getAlfrescoPort(); - if (port == null) - { - port = request.getServerPort(); - } - if (port == null) - { - port = request.getServerPort(); - } - return port; - } - -} +package org.alfresco.opencmis; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.repo.admin.SysAdminParams; + +/** + * Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port + * are overridden by sys admin parameters. + * + * @author steveglover + * + */ +public class SysAdminParamsBaseUrlGenerator extends AbstractBaseUrlGenerator +{ + private SysAdminParams sysAdminParams; + + protected String getServerPath(HttpServletRequest request) + { + StringBuilder sb = new StringBuilder(); + sb.append(getServerScheme(request)); + sb.append("://"); + sb.append(getServerName(request)); + sb.append(":"); + sb.append(getServerPort(request)); + return sb.toString(); + } + + protected String getServerScheme(HttpServletRequest request) + { + String scheme = sysAdminParams.getAlfrescoProtocol(); + if (scheme == null) + { + scheme = request.getScheme(); + } + scheme = request.getScheme(); + return scheme; + } + + protected String getServerName(HttpServletRequest request) + { + String hostname = sysAdminParams.getAlfrescoHost(); + if (hostname == null) + { + hostname = request.getScheme(); + } + hostname = request.getServerName(); + return hostname; + } + + protected int getServerPort(HttpServletRequest request) + { + Integer port = sysAdminParams.getAlfrescoPort(); + if (port == null) + { + port = request.getServerPort(); + } + if (port == null) + { + port = request.getServerPort(); + } + return port; + } + +} diff --git a/source/java/org/alfresco/repo/SessionUser.java b/source/java/org/alfresco/repo/SessionUser.java index caee50b64a..d707a9fee6 100644 --- a/source/java/org/alfresco/repo/SessionUser.java +++ b/source/java/org/alfresco/repo/SessionUser.java @@ -1,26 +1,26 @@ -package org.alfresco.repo; - -import java.io.Serializable; - -/** - * Contract implemented by any object that represents an Alfresco "user" that - * can be persisted in an HTTP Session. - * - * @author Kevin Roast - */ -public interface SessionUser extends Serializable -{ - /** - * Return the user name - * - * @return user name - */ - String getUserName(); - - /** - * Return the ticket - * - * @return ticket - */ - String getTicket(); +package org.alfresco.repo; + +import java.io.Serializable; + +/** + * Contract implemented by any object that represents an Alfresco "user" that + * can be persisted in an HTTP Session. + * + * @author Kevin Roast + */ +public interface SessionUser extends Serializable +{ + /** + * Return the user name + * + * @return user name + */ + String getUserName(); + + /** + * Return the ticket + * + * @return ticket + */ + String getTicket(); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/surf/policy/SurfConfigCleaner.java b/source/java/org/alfresco/repo/surf/policy/SurfConfigCleaner.java index 1563348829..2f18281513 100644 --- a/source/java/org/alfresco/repo/surf/policy/SurfConfigCleaner.java +++ b/source/java/org/alfresco/repo/surf/policy/SurfConfigCleaner.java @@ -1,77 +1,77 @@ -package org.alfresco.repo.surf.policy; - -import java.util.List; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; -import org.alfresco.repo.policy.JavaBehaviour; -import org.alfresco.repo.policy.PolicyComponent; -import org.alfresco.repo.web.scripts.bean.ADMRemoteStore; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * Delete Node Policy to remove surf-config files for a deleted user. - * - * @author Dmitry Velichkevich - * @author Kevin Roast - */ -public class SurfConfigCleaner extends ADMRemoteStore implements BeforeDeleteNodePolicy -{ - private PolicyComponent policyComponent; - - public void init() - { - this.policyComponent.bindClassBehaviour( - BeforeDeleteNodePolicy.QNAME, - ContentModel.TYPE_PERSON, - new JavaBehaviour(this, BeforeDeleteNodePolicy.QNAME.getLocalName())); - } - - @Override - public void beforeDeleteNode(NodeRef nodeRef) - { - final String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME); - final NodeRef componentsRef = getGlobalComponentsNodeRef(); - final NodeRef usersFolderRef = getGlobalUserFolderNodeRef(); - - // Remove the user Surf config folder, contains dynamic page definitions such as dashboard.xml - // For example, qname path to user folder: - // /app:company_home/st:sites/cm:surf-config/cm:pages/cm:user/cm:admin - // ^^^^^ encoded username - if (usersFolderRef != null) - { - NodeRef userFolderNodeRef = nodeService.getChildByName(usersFolderRef, ContentModel.ASSOC_CONTAINS, encodePath(userName)); - if (userFolderNodeRef != null) - { - // CLOUD-2053: Need to set as temporary to delete node instead of archiving. - nodeService.addAspect(userFolderNodeRef, ContentModel.ASPECT_TEMPORARY, null); - nodeService.deleteNode(userFolderNodeRef); - } - } - - // Remove each component Surf config file related to the user, such as the dashboard dashlet component references - // For example, qname path to user component file: - // /app:company_home/st:sites/cm:surf-config/cm:components/cm:page.component-1-1.user~admin~dashboard.xml - // ^^^^^ encoded username - if (componentsRef != null) - { - List configNodes = getFileNodes( - fileFolderService.getFileInfo(componentsRef), - buildUserConfigSearchPattern(userName), - true).getPage(); - - for (FileInfo fileInfo : configNodes) - { - // CLOUD-2053: Need to set as temporary to delete node instead of archiving. - nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_TEMPORARY, null); - nodeService.deleteNode(fileInfo.getNodeRef()); - } - } - } - - public void setPolicyComponent(PolicyComponent policyComponent) - { - this.policyComponent = policyComponent; - } -} +package org.alfresco.repo.surf.policy; + +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy; +import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.web.scripts.bean.ADMRemoteStore; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Delete Node Policy to remove surf-config files for a deleted user. + * + * @author Dmitry Velichkevich + * @author Kevin Roast + */ +public class SurfConfigCleaner extends ADMRemoteStore implements BeforeDeleteNodePolicy +{ + private PolicyComponent policyComponent; + + public void init() + { + this.policyComponent.bindClassBehaviour( + BeforeDeleteNodePolicy.QNAME, + ContentModel.TYPE_PERSON, + new JavaBehaviour(this, BeforeDeleteNodePolicy.QNAME.getLocalName())); + } + + @Override + public void beforeDeleteNode(NodeRef nodeRef) + { + final String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME); + final NodeRef componentsRef = getGlobalComponentsNodeRef(); + final NodeRef usersFolderRef = getGlobalUserFolderNodeRef(); + + // Remove the user Surf config folder, contains dynamic page definitions such as dashboard.xml + // For example, qname path to user folder: + // /app:company_home/st:sites/cm:surf-config/cm:pages/cm:user/cm:admin + // ^^^^^ encoded username + if (usersFolderRef != null) + { + NodeRef userFolderNodeRef = nodeService.getChildByName(usersFolderRef, ContentModel.ASSOC_CONTAINS, encodePath(userName)); + if (userFolderNodeRef != null) + { + // CLOUD-2053: Need to set as temporary to delete node instead of archiving. + nodeService.addAspect(userFolderNodeRef, ContentModel.ASPECT_TEMPORARY, null); + nodeService.deleteNode(userFolderNodeRef); + } + } + + // Remove each component Surf config file related to the user, such as the dashboard dashlet component references + // For example, qname path to user component file: + // /app:company_home/st:sites/cm:surf-config/cm:components/cm:page.component-1-1.user~admin~dashboard.xml + // ^^^^^ encoded username + if (componentsRef != null) + { + List configNodes = getFileNodes( + fileFolderService.getFileInfo(componentsRef), + buildUserConfigSearchPattern(userName), + true).getPage(); + + for (FileInfo fileInfo : configNodes) + { + // CLOUD-2053: Need to set as temporary to delete node instead of archiving. + nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_TEMPORARY, null); + nodeService.deleteNode(fileInfo.getNodeRef()); + } + } + } + + public void setPolicyComponent(PolicyComponent policyComponent) + { + this.policyComponent = policyComponent; + } +} diff --git a/source/java/org/alfresco/repo/utils/FacesImageResolver.java b/source/java/org/alfresco/repo/utils/FacesImageResolver.java index f6bc2b56ea..486f71c756 100644 --- a/source/java/org/alfresco/repo/utils/FacesImageResolver.java +++ b/source/java/org/alfresco/repo/utils/FacesImageResolver.java @@ -1,33 +1,33 @@ -package org.alfresco.repo.utils; - -import javax.faces.context.FacesContext; - -import org.alfresco.repo.web.scripts.FileTypeImageUtils; -import org.alfresco.service.cmr.repository.FileTypeImageSize; -import org.alfresco.service.cmr.repository.TemplateImageResolver; - -/** - * Default implementation of {@link TemplateImageResolver} interface, based on {@link FileTypeImageUtils} utility. It relies on availability of {@link FacesContext} instance - * - * @author Dmitry Velichkevich - */ -public class FacesImageResolver implements TemplateImageResolver -{ - private static final long serialVersionUID = 1L; - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.TemplateImageResolver#resolveImagePathForName(java.lang.String, org.alfresco.service.cmr.repository.FileTypeImageSize) - */ - @Override - public String resolveImagePathForName(String filename, FileTypeImageSize size) - { - if (FacesContext.getCurrentInstance() != null) - { - return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size); - } - else - { - return null; - } - } -} +package org.alfresco.repo.utils; + +import javax.faces.context.FacesContext; + +import org.alfresco.repo.web.scripts.FileTypeImageUtils; +import org.alfresco.service.cmr.repository.FileTypeImageSize; +import org.alfresco.service.cmr.repository.TemplateImageResolver; + +/** + * Default implementation of {@link TemplateImageResolver} interface, based on {@link FileTypeImageUtils} utility. It relies on availability of {@link FacesContext} instance + * + * @author Dmitry Velichkevich + */ +public class FacesImageResolver implements TemplateImageResolver +{ + private static final long serialVersionUID = 1L; + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.TemplateImageResolver#resolveImagePathForName(java.lang.String, org.alfresco.service.cmr.repository.FileTypeImageSize) + */ + @Override + public String resolveImagePathForName(String filename, FileTypeImageSize size) + { + if (FacesContext.getCurrentInstance() != null) + { + return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size); + } + else + { + return null; + } + } +} diff --git a/source/java/org/alfresco/repo/web/auth/TenantAuthentication.java b/source/java/org/alfresco/repo/web/auth/TenantAuthentication.java index 712dcedf37..c7adabc02a 100644 --- a/source/java/org/alfresco/repo/web/auth/TenantAuthentication.java +++ b/source/java/org/alfresco/repo/web/auth/TenantAuthentication.java @@ -1,13 +1,13 @@ -package org.alfresco.repo.web.auth; - -public interface TenantAuthentication -{ - /** - * Authenticate user against tenant - * - * @param username String - * @param tenant String - * @return true => authenticated, false => not authenticated - */ - boolean authenticateTenant(String username, String tenant); -} +package org.alfresco.repo.web.auth; + +public interface TenantAuthentication +{ + /** + * Authenticate user against tenant + * + * @param username String + * @param tenant String + * @return true => authenticated, false => not authenticated + */ + boolean authenticateTenant(String username, String tenant); +} diff --git a/source/java/org/alfresco/repo/web/scripts/BufferedRequest.java b/source/java/org/alfresco/repo/web/scripts/BufferedRequest.java index 2e2d3cd706..3e56627af4 100644 --- a/source/java/org/alfresco/repo/web/scripts/BufferedRequest.java +++ b/source/java/org/alfresco/repo/web/scripts/BufferedRequest.java @@ -1,365 +1,365 @@ -package org.alfresco.repo.web.scripts; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream; -import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.webscripts.Description.FormatStyle; -import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.Runtime; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WrappingWebScriptRequest; -import org.springframework.util.FileCopyUtils; - -public class BufferedRequest implements WrappingWebScriptRequest -{ - private ThresholdOutputStreamFactory streamFactory; - private WebScriptRequest req; - private File requestBody; - private InputStream contentStream; - private BufferedReader contentReader; - - public BufferedRequest(WebScriptRequest req, ThresholdOutputStreamFactory streamFactory) - { - this.req = req; - this.streamFactory = streamFactory; - } - - private InputStream bufferInputStream() throws IOException - { - ThresholdOutputStream bufferStream = streamFactory.newOutputStream(); - - try - { - FileCopyUtils.copy(req.getContent().getInputStream(), bufferStream); - } - catch (IOException e) - { - bufferStream.destroy(); // remove temp file - throw e; - } - - return bufferStream.getInputStream(); - } - - public void reset() - { - if (contentStream != null) - { - try - { - contentStream.close(); - } - catch (Exception e) - { - } - contentStream = null; - } - if (contentReader != null) - { - try - { - contentReader.close(); - } - catch (Exception e) - { - } - contentReader = null; - } - } - - public void close() - { - reset(); - if (requestBody != null) - { - try - { - requestBody.delete(); - } - catch (Exception e) - { - } - requestBody = null; - } - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WrappingWebScriptRequest#getNext() - */ - @Override - public WebScriptRequest getNext() - { - return req; - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#forceSuccessStatus() - */ - @Override - public boolean forceSuccessStatus() - { - return req.forceSuccessStatus(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getAgent() - */ - @Override - public String getAgent() - { - return req.getAgent(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getContent() - */ - @Override - public Content getContent() - { - final Content wrapped = req.getContent(); - return new Content(){ - - @Override - public String getContent() throws IOException - { - return wrapped.getContent(); - } - - @Override - public String getEncoding() - { - return wrapped.getEncoding(); - } - - @Override - public String getMimetype() - { - return wrapped.getMimetype(); - } - - - @Override - public long getSize() - { - return wrapped.getSize(); - } - - @Override - public InputStream getInputStream() - { - if (BufferedRequest.this.contentReader != null) - { - throw new IllegalStateException("Reader in use"); - } - if (BufferedRequest.this.contentStream == null) - { - try - { - BufferedRequest.this.contentStream = bufferInputStream(); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - return BufferedRequest.this.contentStream; - } - - @Override - public BufferedReader getReader() throws IOException - { - if (BufferedRequest.this.contentStream != null) - { - throw new IllegalStateException("Input Stream in use"); - } - if (BufferedRequest.this.contentReader == null) - { - String encoding = wrapped.getEncoding(); - InputStream in = bufferInputStream(); - BufferedRequest.this.contentReader = new BufferedReader(new InputStreamReader(in, encoding == null ? "ISO-8859-1" : encoding)); - } - return BufferedRequest.this.contentReader; - } - }; - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getContentType() - */ - @Override - public String getContentType() - { - return req.getContentType(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getContextPath() - */ - @Override - public String getContextPath() - { - return req.getContextPath(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getExtensionPath() - */ - @Override - public String getExtensionPath() - { - return req.getExtensionPath(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getFormat() - */ - @Override - public String getFormat() - { - return req.getFormat(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getFormatStyle() - */ - @Override - public FormatStyle getFormatStyle() - { - return req.getFormatStyle(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeader(java.lang.String) - */ - @Override - public String getHeader(String name) - { - return req.getHeader(name); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderNames() - */ - @Override - public String[] getHeaderNames() - { - return req.getHeaderNames(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderValues(java.lang.String) - */ - @Override - public String[] getHeaderValues(String name) - { - return req.getHeaderValues(name); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getJSONCallback() - */ - @Override - public String getJSONCallback() - { - return req.getJSONCallback(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameter(java.lang.String) - */ - @Override - public String getParameter(String name) - { - return req.getParameter(name); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterNames() - */ - @Override - public String[] getParameterNames() - { - return req.getParameterNames(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterValues(java.lang.String) - */ - @Override - public String[] getParameterValues(String name) - { - return req.getParameterValues(name); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getPathInfo() - */ - @Override - public String getPathInfo() - { - return req.getPathInfo(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getQueryString() - */ - @Override - public String getQueryString() - { - return req.getQueryString(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getRuntime() - */ - @Override - public Runtime getRuntime() - { - return req.getRuntime(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getServerPath() - */ - @Override - public String getServerPath() - { - return req.getServerPath(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceContextPath() - */ - @Override - public String getServiceContextPath() - { - return req.getServiceContextPath(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceMatch() - */ - @Override - public Match getServiceMatch() - { - return req.getServiceMatch(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getServicePath() - */ - @Override - public String getServicePath() - { - return req.getServicePath(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#getURL() - */ - @Override - public String getURL() - { - return req.getURL(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#isGuest() - */ - @Override - public boolean isGuest() - { - return req.isGuest(); - } - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptRequest#parseContent() - */ - @Override - public Object parseContent() - { - return req.parseContent(); - } -} +package org.alfresco.repo.web.scripts; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream; +import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.Description.FormatStyle; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.Runtime; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WrappingWebScriptRequest; +import org.springframework.util.FileCopyUtils; + +public class BufferedRequest implements WrappingWebScriptRequest +{ + private ThresholdOutputStreamFactory streamFactory; + private WebScriptRequest req; + private File requestBody; + private InputStream contentStream; + private BufferedReader contentReader; + + public BufferedRequest(WebScriptRequest req, ThresholdOutputStreamFactory streamFactory) + { + this.req = req; + this.streamFactory = streamFactory; + } + + private InputStream bufferInputStream() throws IOException + { + ThresholdOutputStream bufferStream = streamFactory.newOutputStream(); + + try + { + FileCopyUtils.copy(req.getContent().getInputStream(), bufferStream); + } + catch (IOException e) + { + bufferStream.destroy(); // remove temp file + throw e; + } + + return bufferStream.getInputStream(); + } + + public void reset() + { + if (contentStream != null) + { + try + { + contentStream.close(); + } + catch (Exception e) + { + } + contentStream = null; + } + if (contentReader != null) + { + try + { + contentReader.close(); + } + catch (Exception e) + { + } + contentReader = null; + } + } + + public void close() + { + reset(); + if (requestBody != null) + { + try + { + requestBody.delete(); + } + catch (Exception e) + { + } + requestBody = null; + } + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WrappingWebScriptRequest#getNext() + */ + @Override + public WebScriptRequest getNext() + { + return req; + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#forceSuccessStatus() + */ + @Override + public boolean forceSuccessStatus() + { + return req.forceSuccessStatus(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getAgent() + */ + @Override + public String getAgent() + { + return req.getAgent(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getContent() + */ + @Override + public Content getContent() + { + final Content wrapped = req.getContent(); + return new Content(){ + + @Override + public String getContent() throws IOException + { + return wrapped.getContent(); + } + + @Override + public String getEncoding() + { + return wrapped.getEncoding(); + } + + @Override + public String getMimetype() + { + return wrapped.getMimetype(); + } + + + @Override + public long getSize() + { + return wrapped.getSize(); + } + + @Override + public InputStream getInputStream() + { + if (BufferedRequest.this.contentReader != null) + { + throw new IllegalStateException("Reader in use"); + } + if (BufferedRequest.this.contentStream == null) + { + try + { + BufferedRequest.this.contentStream = bufferInputStream(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + return BufferedRequest.this.contentStream; + } + + @Override + public BufferedReader getReader() throws IOException + { + if (BufferedRequest.this.contentStream != null) + { + throw new IllegalStateException("Input Stream in use"); + } + if (BufferedRequest.this.contentReader == null) + { + String encoding = wrapped.getEncoding(); + InputStream in = bufferInputStream(); + BufferedRequest.this.contentReader = new BufferedReader(new InputStreamReader(in, encoding == null ? "ISO-8859-1" : encoding)); + } + return BufferedRequest.this.contentReader; + } + }; + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getContentType() + */ + @Override + public String getContentType() + { + return req.getContentType(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getContextPath() + */ + @Override + public String getContextPath() + { + return req.getContextPath(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getExtensionPath() + */ + @Override + public String getExtensionPath() + { + return req.getExtensionPath(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getFormat() + */ + @Override + public String getFormat() + { + return req.getFormat(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getFormatStyle() + */ + @Override + public FormatStyle getFormatStyle() + { + return req.getFormatStyle(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeader(java.lang.String) + */ + @Override + public String getHeader(String name) + { + return req.getHeader(name); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderNames() + */ + @Override + public String[] getHeaderNames() + { + return req.getHeaderNames(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderValues(java.lang.String) + */ + @Override + public String[] getHeaderValues(String name) + { + return req.getHeaderValues(name); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getJSONCallback() + */ + @Override + public String getJSONCallback() + { + return req.getJSONCallback(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameter(java.lang.String) + */ + @Override + public String getParameter(String name) + { + return req.getParameter(name); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterNames() + */ + @Override + public String[] getParameterNames() + { + return req.getParameterNames(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterValues(java.lang.String) + */ + @Override + public String[] getParameterValues(String name) + { + return req.getParameterValues(name); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getPathInfo() + */ + @Override + public String getPathInfo() + { + return req.getPathInfo(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getQueryString() + */ + @Override + public String getQueryString() + { + return req.getQueryString(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getRuntime() + */ + @Override + public Runtime getRuntime() + { + return req.getRuntime(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getServerPath() + */ + @Override + public String getServerPath() + { + return req.getServerPath(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceContextPath() + */ + @Override + public String getServiceContextPath() + { + return req.getServiceContextPath(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceMatch() + */ + @Override + public Match getServiceMatch() + { + return req.getServiceMatch(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getServicePath() + */ + @Override + public String getServicePath() + { + return req.getServicePath(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#getURL() + */ + @Override + public String getURL() + { + return req.getURL(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#isGuest() + */ + @Override + public boolean isGuest() + { + return req.isGuest(); + } + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptRequest#parseContent() + */ + @Override + public Object parseContent() + { + return req.parseContent(); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/BufferedResponse.java b/source/java/org/alfresco/repo/web/scripts/BufferedResponse.java index 263b53bcfb..66344f25d4 100644 --- a/source/java/org/alfresco/repo/web/scripts/BufferedResponse.java +++ b/source/java/org/alfresco/repo/web/scripts/BufferedResponse.java @@ -1,231 +1,231 @@ -package org.alfresco.repo.web.scripts; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.surf.util.StringBuilderWriter; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.Runtime; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.WrappingWebScriptResponse; - -/** - * Transactional Buffered Response - */ -public class BufferedResponse implements WrappingWebScriptResponse -{ - // Logger - protected static final Log logger = LogFactory.getLog(BufferedResponse.class); - - private WebScriptResponse res; - private int bufferSize; - private ByteArrayOutputStream outputStream = null; - private StringBuilderWriter outputWriter = null; - - - /** - * Construct - * - * @param res WebScriptResponse - * @param bufferSize int - */ - public BufferedResponse(WebScriptResponse res, int bufferSize) - { - this.res = res; - this.bufferSize = bufferSize; - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WrappingWebScriptResponse#getNext() - */ - public WebScriptResponse getNext() - { - return res; - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#addHeader(java.lang.String, java.lang.String) - */ - public void addHeader(String name, String value) - { - res.addHeader(name, value); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String) - */ - public String encodeScriptUrl(String url) - { - return res.encodeScriptUrl(url); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String) - */ - public String getEncodeScriptUrlFunction(String name) - { - return res.getEncodeScriptUrlFunction(name); - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptResponse#encodeResourceUrl(java.lang.String) - */ - public String encodeResourceUrl(String url) - { - return res.encodeResourceUrl(url); - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.WebScriptResponse#getEncodeResourceUrlFunction(java.lang.String) - */ - public String getEncodeResourceUrlFunction(String name) - { - return res.getEncodeResourceUrlFunction(name); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream() - */ - public OutputStream getOutputStream() throws IOException - { - if (outputStream == null) - { - if (outputWriter != null) - { - throw new AlfrescoRuntimeException("Already buffering output writer"); - } - this.outputStream = new ByteArrayOutputStream(bufferSize); - } - return outputStream; - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#getRuntime() - */ - public Runtime getRuntime() - { - return res.getRuntime(); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#getWriter() - */ - public Writer getWriter() throws IOException - { - if (outputWriter == null) - { - if (outputStream != null) - { - throw new AlfrescoRuntimeException("Already buffering output stream"); - } - outputWriter = new StringBuilderWriter(bufferSize); - } - return outputWriter; - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#reset() - */ - public void reset() - { - if (outputStream != null) - { - outputStream.reset(); - } - else if (outputWriter != null) - { - outputWriter = null; - } - res.reset(); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#setCache(org.alfresco.web.scripts.Cache) - */ - public void setCache(Cache cache) - { - res.setCache(cache); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String) - */ - public void setContentType(String contentType) - { - res.setContentType(contentType); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#setContentEncoding(java.lang.String) - */ - public void setContentEncoding(String contentEncoding) - { - res.setContentEncoding(contentEncoding); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#setHeader(java.lang.String, java.lang.String) - */ - public void setHeader(String name, String value) - { - res.setHeader(name, value); - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptResponse#setStatus(int) - */ - public void setStatus(int status) - { - res.setStatus(status); - } - - /** - * Write buffered response to underlying response - */ - public void writeResponse() - { - try - { - if (logger.isDebugEnabled() && outputStream != null) - { - logger.debug("Writing Transactional response: size=" + outputStream.size()); - } - - if (outputWriter != null) - { - outputWriter.flush(); - res.getWriter().write(outputWriter.toString()); - } - else if (outputStream != null) - { - if (logger.isDebugEnabled()) - logger.debug("Writing Transactional response: size=" + outputStream.size()); - - outputStream.flush(); - outputStream.writeTo(res.getOutputStream()); - } - } - catch (IOException e) - { - throw new AlfrescoRuntimeException("Failed to commit buffered response", e); - } - } -} +package org.alfresco.repo.web.scripts; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.StringBuilderWriter; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Runtime; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.WrappingWebScriptResponse; + +/** + * Transactional Buffered Response + */ +public class BufferedResponse implements WrappingWebScriptResponse +{ + // Logger + protected static final Log logger = LogFactory.getLog(BufferedResponse.class); + + private WebScriptResponse res; + private int bufferSize; + private ByteArrayOutputStream outputStream = null; + private StringBuilderWriter outputWriter = null; + + + /** + * Construct + * + * @param res WebScriptResponse + * @param bufferSize int + */ + public BufferedResponse(WebScriptResponse res, int bufferSize) + { + this.res = res; + this.bufferSize = bufferSize; + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WrappingWebScriptResponse#getNext() + */ + public WebScriptResponse getNext() + { + return res; + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#addHeader(java.lang.String, java.lang.String) + */ + public void addHeader(String name, String value) + { + res.addHeader(name, value); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String) + */ + public String encodeScriptUrl(String url) + { + return res.encodeScriptUrl(url); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String) + */ + public String getEncodeScriptUrlFunction(String name) + { + return res.getEncodeScriptUrlFunction(name); + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptResponse#encodeResourceUrl(java.lang.String) + */ + public String encodeResourceUrl(String url) + { + return res.encodeResourceUrl(url); + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.WebScriptResponse#getEncodeResourceUrlFunction(java.lang.String) + */ + public String getEncodeResourceUrlFunction(String name) + { + return res.getEncodeResourceUrlFunction(name); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream() + */ + public OutputStream getOutputStream() throws IOException + { + if (outputStream == null) + { + if (outputWriter != null) + { + throw new AlfrescoRuntimeException("Already buffering output writer"); + } + this.outputStream = new ByteArrayOutputStream(bufferSize); + } + return outputStream; + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#getRuntime() + */ + public Runtime getRuntime() + { + return res.getRuntime(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#getWriter() + */ + public Writer getWriter() throws IOException + { + if (outputWriter == null) + { + if (outputStream != null) + { + throw new AlfrescoRuntimeException("Already buffering output stream"); + } + outputWriter = new StringBuilderWriter(bufferSize); + } + return outputWriter; + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#reset() + */ + public void reset() + { + if (outputStream != null) + { + outputStream.reset(); + } + else if (outputWriter != null) + { + outputWriter = null; + } + res.reset(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#setCache(org.alfresco.web.scripts.Cache) + */ + public void setCache(Cache cache) + { + res.setCache(cache); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String) + */ + public void setContentType(String contentType) + { + res.setContentType(contentType); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#setContentEncoding(java.lang.String) + */ + public void setContentEncoding(String contentEncoding) + { + res.setContentEncoding(contentEncoding); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#setHeader(java.lang.String, java.lang.String) + */ + public void setHeader(String name, String value) + { + res.setHeader(name, value); + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptResponse#setStatus(int) + */ + public void setStatus(int status) + { + res.setStatus(status); + } + + /** + * Write buffered response to underlying response + */ + public void writeResponse() + { + try + { + if (logger.isDebugEnabled() && outputStream != null) + { + logger.debug("Writing Transactional response: size=" + outputStream.size()); + } + + if (outputWriter != null) + { + outputWriter.flush(); + res.getWriter().write(outputWriter.toString()); + } + else if (outputStream != null) + { + if (logger.isDebugEnabled()) + logger.debug("Writing Transactional response: size=" + outputStream.size()); + + outputStream.flush(); + outputStream.writeTo(res.getOutputStream()); + } + } + catch (IOException e) + { + throw new AlfrescoRuntimeException("Failed to commit buffered response", e); + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/ExtensibilityContainer.java b/source/java/org/alfresco/repo/web/scripts/ExtensibilityContainer.java index 3f4b098535..311ebf0f50 100644 --- a/source/java/org/alfresco/repo/web/scripts/ExtensibilityContainer.java +++ b/source/java/org/alfresco/repo/web/scripts/ExtensibilityContainer.java @@ -1,422 +1,422 @@ -package org.alfresco.repo.web.scripts; - -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.ResourceBundle; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.dom4j.Element; -import org.springframework.extensions.config.ConfigImpl; -import org.springframework.extensions.config.ConfigSection; -import org.springframework.extensions.config.ConfigService; -import org.springframework.extensions.config.evaluator.Evaluator; -import org.springframework.extensions.config.xml.XMLConfigService; -import org.springframework.extensions.config.xml.elementreader.ConfigElementReader; -import org.springframework.extensions.surf.extensibility.BasicExtensionModule; -import org.springframework.extensions.surf.extensibility.ExtensibilityModel; -import org.springframework.extensions.surf.extensibility.HandlesExtensibility; -import org.springframework.extensions.surf.extensibility.WebScriptExtensibilityModuleHandler; -import org.springframework.extensions.surf.extensibility.impl.ExtensibilityModelImpl; -import org.springframework.extensions.surf.extensibility.impl.MarkupDirective; -import org.springframework.extensions.webscripts.Authenticator; -import org.springframework.extensions.webscripts.ExtendedScriptConfigModel; -import org.springframework.extensions.webscripts.ExtendedTemplateConfigModel; -import org.springframework.extensions.webscripts.ScriptConfigModel; -import org.springframework.extensions.webscripts.TemplateConfigModel; -import org.springframework.extensions.webscripts.WebScriptPropertyResourceBundle; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - *

A simple extensibility {@link org.springframework.extensions.webscripts.Container} for processing WebScripts. This extends the {@link RepositoryContainer} and - * implements the {@link HandlesExtensibility} interface to provide extensibility capabilities.

- * - * @author David Draper - */ -public class ExtensibilityContainer extends RepositoryContainer implements HandlesExtensibility -{ - private static final Log logger = LogFactory.getLog(ExtensibilityContainer.class); - - public boolean isExtensibilitySuppressed() - { - return false; - } - - /** - *

Opens a new {@link ExtensibilityModel}, defers execution to the extended {@link RepositoryContainer} and - * then closes the {@link ExtensibilityModel}.

- */ - @Override - public void executeScript(WebScriptRequest scriptReq, - WebScriptResponse scriptRes, - Authenticator auth) throws IOException - { - ExtensibilityModel extModel = this.openExtensibilityModel(); - try - { - super.executeScript(scriptReq, scriptRes, auth); - } - finally - { - // It's only necessary to close the model if it's actually been used. Not all WebScripts will make use of the - // model. An example of this would be the StreamContent WebScript. It is important not to attempt to close - // an unused model since the WebScript executed may have already flushed the response if it has overridden - // the default .execute() method. - if (this.modelUsed.get()) - { - try - { - this.closeExtensibilityModel(extModel, scriptRes.getWriter()); - } - catch (IOException e) - { - logger.error("An error occurred getting the Writer when closing an ExtensibilityModel", e); - } - } - } - } - - /** - *

This keeps track of whether or not the {@link ExtensibilityModel} for the current thread has been used. The - * thread local value will only be set to true if the getCurrentExtensibilityModel method - * is called.

- */ - private ThreadLocal modelUsed = new ThreadLocal(); - - /** - *

A {@link WebScriptExtensibilityModuleHandler} is required for retrieving information on what - * {@link BasicExtensionModule} instances have been configured and the extension files that need - * to be processed. This variable should be set thorugh the Spring application context configuration.

- */ - private WebScriptExtensibilityModuleHandler extensibilityModuleHandler = null; - - /** - *

Sets the {@link WebScriptExtensibilityModuleHandler} for this {@link org.springframework.extensions.webscripts.Container}.

- * @param extensibilityModuleHandler WebScriptExtensibilityModuleHandler - */ - public void setExtensibilityModuleHandler(WebScriptExtensibilityModuleHandler extensibilityModuleHandler) - { - this.extensibilityModuleHandler = extensibilityModuleHandler; - } - - /** - *

Maintains a list of all the {@link ExtensibilityModel} instances being used across all the - * available threads.

- */ - private ThreadLocal extensibilityModel = new ThreadLocal(); - - /** - *

Creates a new {@link ExtensibilityModel} and sets it on the current thread - */ - public ExtensibilityModel openExtensibilityModel() - { - if (logger.isDebugEnabled()) - { - logger.debug("Opening for thread: " + Thread.currentThread().getName()); - } - this.extendedBundleCache.set(new HashMap()); - this.evaluatedModules.set(null); - this.fileBeingProcessed.set(null); - this.globalConfig.set(null); - this.sections.set(null); - this.sectionsByArea.set(null); - - ExtensibilityModel model = new ExtensibilityModelImpl(null, this); - this.extensibilityModel.set(model); - this.modelUsed.set(Boolean.FALSE); - return model; - } - - /** - *

Flushes the {@link ExtensibilityModel} provided and sets its parent as the current {@link ExtensibilityModel} - * for the current thread.

- */ - public void closeExtensibilityModel(ExtensibilityModel model, Writer out) - { - if (logger.isDebugEnabled()) - { - logger.debug("Closing for thread: " + Thread.currentThread().getName()); - } - - model.flushModel(out); - this.modelUsed.set(Boolean.FALSE); - this.extensibilityModel.set(null); - } - - /** - *

Returns the {@link ExtensibilityModel} for the current thread.

- */ - public ExtensibilityModel getCurrentExtensibilityModel() - { - if (logger.isDebugEnabled()) - { - logger.debug("Getting current for thread: " + Thread.currentThread().getName()); - } - this.modelUsed.set(Boolean.TRUE); - return this.extensibilityModel.get(); - } - - /** - *

This method is implemented to perform no action as it is not necessary for a standalone WebScript - * container to add dependencies for processing.

- */ - public void updateExtendingModuleDependencies(String pathBeingProcessed, Map model) - { - // NOT REQUIRED FOR STANDALONE WEBSCRIPT CONTAINER - } - - /** - *

A thread-safe cache of extended {@link ResourceBundle} instances for the current request.

- */ - private ThreadLocal> extendedBundleCache = new ThreadLocal>(); - - /** - *

Checks the cache to see if it has cached an extended bundle (that is a basic {@link ResourceBundle} that - * has had extension modules applied to it. Extended bundles can only be safely cached once per request as the modules - * applied can vary for each request.

- * - * @param webScriptId The id of the WebScript to retrieve the extended bundle for. - * @return A cached bundle or null if the bundle has not previously been cached. - */ - public ResourceBundle getCachedExtendedBundle(String webScriptId) - { - ResourceBundle cachedExtendedBundle = null; - Map threadLocal = this.extendedBundleCache.get(); - if (threadLocal != null) - { - cachedExtendedBundle = this.extendedBundleCache.get().get(webScriptId); - } - return cachedExtendedBundle; - } - - /** - *

Adds a new extended bundle to the cache. An extended bundle is a WebScript {@link ResourceBundle} that has had - * {@link ResourceBundle} instances merged into it from extension modules that have been applied. These can only be cached - * for the lifetime of the request as different modules may be applied to the same WebScript for different requests.

- * - * @param webScriptId The id of the WebScript to cache the extended bundle against. - * @param extensionBundle The extended bundle to cache. - */ - public void addExtensionBundleToCache(String webScriptId, WebScriptPropertyResourceBundle extensionBundle) - { - Map threadLocal = this.extendedBundleCache.get(); - if (threadLocal == null) - { - // This should never be the case because when a new model is opened this value should be reset - // but we will double-check to avoid the potential of NPEs... - threadLocal = new HashMap(); - this.extendedBundleCache.set(threadLocal); - } - threadLocal.put(webScriptId, extensionBundle); - } - - /** - *

A {@link ThreadLocal} reference to the file currently being processed in the model. - */ - private ThreadLocal fileBeingProcessed = new ThreadLocal(); - - /** - *

Returns the path of the file currently being processed in the model by the current thread. - * This information is primarily provided for the purposes of generating debug information.

- * - * @return The path of the file currently being processed. - */ - public String getFileBeingProcessed() - { - return this.fileBeingProcessed.get(); - } - - /** - *

Sets the path of the file currently being processed in the model by the current thread. - * This information should be collected to assist with providing debug information.

- * @param file The path of the file currently being processed. - */ - public void setFileBeingProcessed(String file) - { - this.fileBeingProcessed.set(file); - } - - /** - *

Retrieves an files for the evaluated modules that are extending the WebScript files being processed.

- */ - public List getExtendingModuleFiles(String pathBeingProcessed) - { - List extendingModuleFiles = new ArrayList(); - for (BasicExtensionModule module: this.getEvaluatedModules()) - { - extendingModuleFiles.addAll(this.extensibilityModuleHandler.getExtendingModuleFiles(module, pathBeingProcessed)); - } - return extendingModuleFiles; - } - - /** - *

The list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable to - * this RequestContext. This is set to null when during instantiation and is only - * properly set the first time the getEvaluatedModules method is invoked. This ensures - * that module evaluation only occurs once per request.

- */ - private ThreadLocal> evaluatedModules = new ThreadLocal>(); - - /** - *

Retrieve the list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable - * for the current request. If this list has not yet been populated then use the {@link org.springframework.extensions.surf.extensibility.ExtensibilityModuleHandler} - * configured in the Spring application context to evaluate them.

- * - * @return A list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that are applicable to the current request. - */ - public List getEvaluatedModules() - { - List evaluatedModules = this.evaluatedModules.get(); - if (evaluatedModules == null) - { - if (this.extensibilityModuleHandler == null) - { - if (logger.isErrorEnabled()) - { - logger.error("No 'extensibilityModuleHandler' has been configured for this request context. Extensions cannot be processed"); - } - evaluatedModules = new ArrayList(); - this.evaluatedModules.set(evaluatedModules); - } - else - { - evaluatedModules = this.extensibilityModuleHandler.getExtensionModules(); - this.evaluatedModules.set(evaluatedModules); - } - } - return evaluatedModules; - } - - /** - *

This is a local {@link ConfigImpl} instance that will only be used when extension modules are employed. It will - * initially be populated with the default "static" global configuration taken from the {@link ConfigService} associated - * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include global configuration provided by extension modules that - * have been evaluated to be applied to the current request.

- */ - private ThreadLocal globalConfig = new ThreadLocal(); - - /** - *

This map represents {@link ConfigSection} instances mapped by area. It will only be used when extension modules are - * employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated - * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated - * to be applied to the current request.

- */ - private ThreadLocal>> sectionsByArea = new ThreadLocal>>(); - - /** - *

A list of {@link ConfigSection} instances that are only applicable to the current request. It will only be used when extension modules are - * employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated - * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated - * to be applied to the current request.

- */ - private ThreadLocal> sections = new ThreadLocal>(); - - /** - *

Creates a new {@link ExtendedScriptConfigModel} instance using the local configuration generated for this request. - * If configuration for the request will be generated if it does not yet exist. It is likely that this method will be - * called multiple times within the context of a single request and although the configuration containers will always - * be the same a new {@link ExtendedScriptConfigModel} instance will always be created as the the supplied xmlConfig - * string could be different for each call (because each WebScript invoked in the request will supply different - * configuration.

- */ - public ScriptConfigModel getExtendedScriptConfigModel(String xmlConfig) - { - if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null) - { - this.getConfigExtensions(); - } - return new ExtendedScriptConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); - } - - /** - *

Creates a new {@link TemplateConfigModel} instance using the local configuration generated for this request. - * If configuration for the request will be generated if it does not yet exist. It is likely that this method will be - * called multiple times within the context of a single request and although the configuration containers will always - * be the same a new {@link TemplateConfigModel} instance will always be created as the the supplied xmlConfig - * string could be different for each call (because each WebScript invoked in the request will supply different - * configuration.

- */ - public TemplateConfigModel getExtendedTemplateConfigModel(String xmlConfig) - { - if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null) - { - this.getConfigExtensions(); - } - return new ExtendedTemplateConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); - } - - /** - *

Creates and populates the request specific configuration container objects (globalConfig, sectionsByArea & - * sections with a combination of the default static configuration (taken from files accessed by the {@link ConfigService}) and - * dynamic configuration taken from extension modules evaluated for the current request.

- */ - private void getConfigExtensions() - { - // Extended configuration is only possible if config service is an XMLConfigService... - // - // ...also, it's only necessary to populate the configuration containers if they have not already been populated. This test should also - // be carried out by the two methods ("getExtendedTemplateConfigModel" & "getExtendedTemplateConfigModel") to prevent duplication - // of effort... but in case other methods attempt to access it we will make these additional tests. - if (getConfigService() instanceof XMLConfigService && this.globalConfig == null && this.sectionsByArea == null && this.sections == null) - { - // Cast the config service for ease of access - XMLConfigService xmlConfigService = (XMLConfigService) getConfigService(); - - // Get the current configuration from the ConfigService - we don't want to permanently pollute - // the standard configuration with additions from the modules... - this.globalConfig.set(new ConfigImpl((ConfigImpl)xmlConfigService.getGlobalConfig())); // Make a copy of the current global config - - // Initialise these with the config service values... - this.sectionsByArea.set(new HashMap>(xmlConfigService.getSectionsByArea())); - this.sections.set(new ArrayList(xmlConfigService.getSections())); - - // Check to see if there are any modules that we need to apply... - List evaluatedModules = this.getEvaluatedModules(); - if (evaluatedModules != null && !evaluatedModules.isEmpty()) - { - for (BasicExtensionModule currModule: evaluatedModules) - { - for (Element currentConfigElement: currModule.getConfigurations()) - { - // Set up containers for our request specific configuration - this will contain data taken from the evaluated modules... - Map parsedElementReaders = new HashMap(); - Map parsedEvaluators = new HashMap(); - List parsedConfigSections = new ArrayList(); - - // Parse and process the parses configuration... - String currentArea = xmlConfigService.parseFragment(currentConfigElement, parsedElementReaders, parsedEvaluators, parsedConfigSections); - for (Map.Entry entry : parsedEvaluators.entrySet()) - { - // add the evaluators to the config service - parsedEvaluators.put(entry.getKey(), entry.getValue()); - } - for (Map.Entry entry : parsedElementReaders.entrySet()) - { - // add the element readers to the config service - parsedElementReaders.put(entry.getKey(), entry.getValue()); - } - for (ConfigSection section : parsedConfigSections) - { - // Update local configuration with our updated data... - xmlConfigService.addConfigSection(section, currentArea, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); - } - } - } - } - } - } - - /** - *

Adds the <{@code}@markup> directive to the container which allows FreeMarker templates to be extended.

- */ - public void addExtensibilityDirectives(Map freeMarkerModel, ExtensibilityModel extModel) - { - MarkupDirective mud = new MarkupDirective("markup", extModel); - freeMarkerModel.put("markup", mud); - } -} +package org.alfresco.repo.web.scripts; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.dom4j.Element; +import org.springframework.extensions.config.ConfigImpl; +import org.springframework.extensions.config.ConfigSection; +import org.springframework.extensions.config.ConfigService; +import org.springframework.extensions.config.evaluator.Evaluator; +import org.springframework.extensions.config.xml.XMLConfigService; +import org.springframework.extensions.config.xml.elementreader.ConfigElementReader; +import org.springframework.extensions.surf.extensibility.BasicExtensionModule; +import org.springframework.extensions.surf.extensibility.ExtensibilityModel; +import org.springframework.extensions.surf.extensibility.HandlesExtensibility; +import org.springframework.extensions.surf.extensibility.WebScriptExtensibilityModuleHandler; +import org.springframework.extensions.surf.extensibility.impl.ExtensibilityModelImpl; +import org.springframework.extensions.surf.extensibility.impl.MarkupDirective; +import org.springframework.extensions.webscripts.Authenticator; +import org.springframework.extensions.webscripts.ExtendedScriptConfigModel; +import org.springframework.extensions.webscripts.ExtendedTemplateConfigModel; +import org.springframework.extensions.webscripts.ScriptConfigModel; +import org.springframework.extensions.webscripts.TemplateConfigModel; +import org.springframework.extensions.webscripts.WebScriptPropertyResourceBundle; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + *

A simple extensibility {@link org.springframework.extensions.webscripts.Container} for processing WebScripts. This extends the {@link RepositoryContainer} and + * implements the {@link HandlesExtensibility} interface to provide extensibility capabilities.

+ * + * @author David Draper + */ +public class ExtensibilityContainer extends RepositoryContainer implements HandlesExtensibility +{ + private static final Log logger = LogFactory.getLog(ExtensibilityContainer.class); + + public boolean isExtensibilitySuppressed() + { + return false; + } + + /** + *

Opens a new {@link ExtensibilityModel}, defers execution to the extended {@link RepositoryContainer} and + * then closes the {@link ExtensibilityModel}.

+ */ + @Override + public void executeScript(WebScriptRequest scriptReq, + WebScriptResponse scriptRes, + Authenticator auth) throws IOException + { + ExtensibilityModel extModel = this.openExtensibilityModel(); + try + { + super.executeScript(scriptReq, scriptRes, auth); + } + finally + { + // It's only necessary to close the model if it's actually been used. Not all WebScripts will make use of the + // model. An example of this would be the StreamContent WebScript. It is important not to attempt to close + // an unused model since the WebScript executed may have already flushed the response if it has overridden + // the default .execute() method. + if (this.modelUsed.get()) + { + try + { + this.closeExtensibilityModel(extModel, scriptRes.getWriter()); + } + catch (IOException e) + { + logger.error("An error occurred getting the Writer when closing an ExtensibilityModel", e); + } + } + } + } + + /** + *

This keeps track of whether or not the {@link ExtensibilityModel} for the current thread has been used. The + * thread local value will only be set to true if the getCurrentExtensibilityModel method + * is called.

+ */ + private ThreadLocal modelUsed = new ThreadLocal(); + + /** + *

A {@link WebScriptExtensibilityModuleHandler} is required for retrieving information on what + * {@link BasicExtensionModule} instances have been configured and the extension files that need + * to be processed. This variable should be set thorugh the Spring application context configuration.

+ */ + private WebScriptExtensibilityModuleHandler extensibilityModuleHandler = null; + + /** + *

Sets the {@link WebScriptExtensibilityModuleHandler} for this {@link org.springframework.extensions.webscripts.Container}.

+ * @param extensibilityModuleHandler WebScriptExtensibilityModuleHandler + */ + public void setExtensibilityModuleHandler(WebScriptExtensibilityModuleHandler extensibilityModuleHandler) + { + this.extensibilityModuleHandler = extensibilityModuleHandler; + } + + /** + *

Maintains a list of all the {@link ExtensibilityModel} instances being used across all the + * available threads.

+ */ + private ThreadLocal extensibilityModel = new ThreadLocal(); + + /** + *

Creates a new {@link ExtensibilityModel} and sets it on the current thread + */ + public ExtensibilityModel openExtensibilityModel() + { + if (logger.isDebugEnabled()) + { + logger.debug("Opening for thread: " + Thread.currentThread().getName()); + } + this.extendedBundleCache.set(new HashMap()); + this.evaluatedModules.set(null); + this.fileBeingProcessed.set(null); + this.globalConfig.set(null); + this.sections.set(null); + this.sectionsByArea.set(null); + + ExtensibilityModel model = new ExtensibilityModelImpl(null, this); + this.extensibilityModel.set(model); + this.modelUsed.set(Boolean.FALSE); + return model; + } + + /** + *

Flushes the {@link ExtensibilityModel} provided and sets its parent as the current {@link ExtensibilityModel} + * for the current thread.

+ */ + public void closeExtensibilityModel(ExtensibilityModel model, Writer out) + { + if (logger.isDebugEnabled()) + { + logger.debug("Closing for thread: " + Thread.currentThread().getName()); + } + + model.flushModel(out); + this.modelUsed.set(Boolean.FALSE); + this.extensibilityModel.set(null); + } + + /** + *

Returns the {@link ExtensibilityModel} for the current thread.

+ */ + public ExtensibilityModel getCurrentExtensibilityModel() + { + if (logger.isDebugEnabled()) + { + logger.debug("Getting current for thread: " + Thread.currentThread().getName()); + } + this.modelUsed.set(Boolean.TRUE); + return this.extensibilityModel.get(); + } + + /** + *

This method is implemented to perform no action as it is not necessary for a standalone WebScript + * container to add dependencies for processing.

+ */ + public void updateExtendingModuleDependencies(String pathBeingProcessed, Map model) + { + // NOT REQUIRED FOR STANDALONE WEBSCRIPT CONTAINER + } + + /** + *

A thread-safe cache of extended {@link ResourceBundle} instances for the current request.

+ */ + private ThreadLocal> extendedBundleCache = new ThreadLocal>(); + + /** + *

Checks the cache to see if it has cached an extended bundle (that is a basic {@link ResourceBundle} that + * has had extension modules applied to it. Extended bundles can only be safely cached once per request as the modules + * applied can vary for each request.

+ * + * @param webScriptId The id of the WebScript to retrieve the extended bundle for. + * @return A cached bundle or null if the bundle has not previously been cached. + */ + public ResourceBundle getCachedExtendedBundle(String webScriptId) + { + ResourceBundle cachedExtendedBundle = null; + Map threadLocal = this.extendedBundleCache.get(); + if (threadLocal != null) + { + cachedExtendedBundle = this.extendedBundleCache.get().get(webScriptId); + } + return cachedExtendedBundle; + } + + /** + *

Adds a new extended bundle to the cache. An extended bundle is a WebScript {@link ResourceBundle} that has had + * {@link ResourceBundle} instances merged into it from extension modules that have been applied. These can only be cached + * for the lifetime of the request as different modules may be applied to the same WebScript for different requests.

+ * + * @param webScriptId The id of the WebScript to cache the extended bundle against. + * @param extensionBundle The extended bundle to cache. + */ + public void addExtensionBundleToCache(String webScriptId, WebScriptPropertyResourceBundle extensionBundle) + { + Map threadLocal = this.extendedBundleCache.get(); + if (threadLocal == null) + { + // This should never be the case because when a new model is opened this value should be reset + // but we will double-check to avoid the potential of NPEs... + threadLocal = new HashMap(); + this.extendedBundleCache.set(threadLocal); + } + threadLocal.put(webScriptId, extensionBundle); + } + + /** + *

A {@link ThreadLocal} reference to the file currently being processed in the model. + */ + private ThreadLocal fileBeingProcessed = new ThreadLocal(); + + /** + *

Returns the path of the file currently being processed in the model by the current thread. + * This information is primarily provided for the purposes of generating debug information.

+ * + * @return The path of the file currently being processed. + */ + public String getFileBeingProcessed() + { + return this.fileBeingProcessed.get(); + } + + /** + *

Sets the path of the file currently being processed in the model by the current thread. + * This information should be collected to assist with providing debug information.

+ * @param file The path of the file currently being processed. + */ + public void setFileBeingProcessed(String file) + { + this.fileBeingProcessed.set(file); + } + + /** + *

Retrieves an files for the evaluated modules that are extending the WebScript files being processed.

+ */ + public List getExtendingModuleFiles(String pathBeingProcessed) + { + List extendingModuleFiles = new ArrayList(); + for (BasicExtensionModule module: this.getEvaluatedModules()) + { + extendingModuleFiles.addAll(this.extensibilityModuleHandler.getExtendingModuleFiles(module, pathBeingProcessed)); + } + return extendingModuleFiles; + } + + /** + *

The list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable to + * this RequestContext. This is set to null when during instantiation and is only + * properly set the first time the getEvaluatedModules method is invoked. This ensures + * that module evaluation only occurs once per request.

+ */ + private ThreadLocal> evaluatedModules = new ThreadLocal>(); + + /** + *

Retrieve the list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable + * for the current request. If this list has not yet been populated then use the {@link org.springframework.extensions.surf.extensibility.ExtensibilityModuleHandler} + * configured in the Spring application context to evaluate them.

+ * + * @return A list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that are applicable to the current request. + */ + public List getEvaluatedModules() + { + List evaluatedModules = this.evaluatedModules.get(); + if (evaluatedModules == null) + { + if (this.extensibilityModuleHandler == null) + { + if (logger.isErrorEnabled()) + { + logger.error("No 'extensibilityModuleHandler' has been configured for this request context. Extensions cannot be processed"); + } + evaluatedModules = new ArrayList(); + this.evaluatedModules.set(evaluatedModules); + } + else + { + evaluatedModules = this.extensibilityModuleHandler.getExtensionModules(); + this.evaluatedModules.set(evaluatedModules); + } + } + return evaluatedModules; + } + + /** + *

This is a local {@link ConfigImpl} instance that will only be used when extension modules are employed. It will + * initially be populated with the default "static" global configuration taken from the {@link ConfigService} associated + * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include global configuration provided by extension modules that + * have been evaluated to be applied to the current request.

+ */ + private ThreadLocal globalConfig = new ThreadLocal(); + + /** + *

This map represents {@link ConfigSection} instances mapped by area. It will only be used when extension modules are + * employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated + * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated + * to be applied to the current request.

+ */ + private ThreadLocal>> sectionsByArea = new ThreadLocal>>(); + + /** + *

A list of {@link ConfigSection} instances that are only applicable to the current request. It will only be used when extension modules are + * employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated + * with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated + * to be applied to the current request.

+ */ + private ThreadLocal> sections = new ThreadLocal>(); + + /** + *

Creates a new {@link ExtendedScriptConfigModel} instance using the local configuration generated for this request. + * If configuration for the request will be generated if it does not yet exist. It is likely that this method will be + * called multiple times within the context of a single request and although the configuration containers will always + * be the same a new {@link ExtendedScriptConfigModel} instance will always be created as the the supplied xmlConfig + * string could be different for each call (because each WebScript invoked in the request will supply different + * configuration.

+ */ + public ScriptConfigModel getExtendedScriptConfigModel(String xmlConfig) + { + if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null) + { + this.getConfigExtensions(); + } + return new ExtendedScriptConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); + } + + /** + *

Creates a new {@link TemplateConfigModel} instance using the local configuration generated for this request. + * If configuration for the request will be generated if it does not yet exist. It is likely that this method will be + * called multiple times within the context of a single request and although the configuration containers will always + * be the same a new {@link TemplateConfigModel} instance will always be created as the the supplied xmlConfig + * string could be different for each call (because each WebScript invoked in the request will supply different + * configuration.

+ */ + public TemplateConfigModel getExtendedTemplateConfigModel(String xmlConfig) + { + if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null) + { + this.getConfigExtensions(); + } + return new ExtendedTemplateConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); + } + + /** + *

Creates and populates the request specific configuration container objects (globalConfig, sectionsByArea & + * sections with a combination of the default static configuration (taken from files accessed by the {@link ConfigService}) and + * dynamic configuration taken from extension modules evaluated for the current request.

+ */ + private void getConfigExtensions() + { + // Extended configuration is only possible if config service is an XMLConfigService... + // + // ...also, it's only necessary to populate the configuration containers if they have not already been populated. This test should also + // be carried out by the two methods ("getExtendedTemplateConfigModel" & "getExtendedTemplateConfigModel") to prevent duplication + // of effort... but in case other methods attempt to access it we will make these additional tests. + if (getConfigService() instanceof XMLConfigService && this.globalConfig == null && this.sectionsByArea == null && this.sections == null) + { + // Cast the config service for ease of access + XMLConfigService xmlConfigService = (XMLConfigService) getConfigService(); + + // Get the current configuration from the ConfigService - we don't want to permanently pollute + // the standard configuration with additions from the modules... + this.globalConfig.set(new ConfigImpl((ConfigImpl)xmlConfigService.getGlobalConfig())); // Make a copy of the current global config + + // Initialise these with the config service values... + this.sectionsByArea.set(new HashMap>(xmlConfigService.getSectionsByArea())); + this.sections.set(new ArrayList(xmlConfigService.getSections())); + + // Check to see if there are any modules that we need to apply... + List evaluatedModules = this.getEvaluatedModules(); + if (evaluatedModules != null && !evaluatedModules.isEmpty()) + { + for (BasicExtensionModule currModule: evaluatedModules) + { + for (Element currentConfigElement: currModule.getConfigurations()) + { + // Set up containers for our request specific configuration - this will contain data taken from the evaluated modules... + Map parsedElementReaders = new HashMap(); + Map parsedEvaluators = new HashMap(); + List parsedConfigSections = new ArrayList(); + + // Parse and process the parses configuration... + String currentArea = xmlConfigService.parseFragment(currentConfigElement, parsedElementReaders, parsedEvaluators, parsedConfigSections); + for (Map.Entry entry : parsedEvaluators.entrySet()) + { + // add the evaluators to the config service + parsedEvaluators.put(entry.getKey(), entry.getValue()); + } + for (Map.Entry entry : parsedElementReaders.entrySet()) + { + // add the element readers to the config service + parsedElementReaders.put(entry.getKey(), entry.getValue()); + } + for (ConfigSection section : parsedConfigSections) + { + // Update local configuration with our updated data... + xmlConfigService.addConfigSection(section, currentArea, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get()); + } + } + } + } + } + } + + /** + *

Adds the <{@code}@markup> directive to the container which allows FreeMarker templates to be extended.

+ */ + public void addExtensibilityDirectives(Map freeMarkerModel, ExtensibilityModel extModel) + { + MarkupDirective mud = new MarkupDirective("markup", extModel); + freeMarkerModel.put("markup", mud); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepoClassPathStore.java b/source/java/org/alfresco/repo/web/scripts/RepoClassPathStore.java index 09f576c58e..22e7f9e7e6 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepoClassPathStore.java +++ b/source/java/org/alfresco/repo/web/scripts/RepoClassPathStore.java @@ -1,57 +1,57 @@ -package org.alfresco.repo.web.scripts; - -import java.io.IOException; - -import org.springframework.extensions.webscripts.ClassPathStore; - -import freemarker.cache.TemplateLoader; - -/** - * Extension of the SpringSurf ClassPathStore to ensure that the examination of - * last modified dates on classpath bound resources does not cause a performance - * degredation in REST heavy client applications. - *

- * In the repository, due to the possibility of Repository bound resources, all - * WebScript search path lists have the "delay" set to either zero seconds (no delay) - * or something close to that. This means that the FreeMarker template cache is - * always or often requesting the last modified date of a classpath resource - and - * the resources do not change. Note that the /extension classpath store still uses - * the original ClassPathStore. Otherwise all stores can be refreshed as usual via - * the Refresh WebScripts command. - * - * @author Kevin Roast - */ -public class RepoClassPathStore extends ClassPathStore -{ - @Override - public TemplateLoader getTemplateLoader() - { - return new ClassPathTemplateLoader(); - } - - @Override - public long lastModified(String documentPath) - throws IOException - { - return -1L; - } - - /** - * Class Path Store implementation of a Template Loader - *

- * Retrieves templates either from classes in the class path or classes inside of JAR files - * within the class path - *

- * This implementation always returns a fixed last modified date of -1. - */ - private class ClassPathTemplateLoader extends ClassPathStore.ClassPathTemplateLoader - { - /** - * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object) - */ - public long getLastModified(Object templateSource) - { - return -1L; - } - } -} +package org.alfresco.repo.web.scripts; + +import java.io.IOException; + +import org.springframework.extensions.webscripts.ClassPathStore; + +import freemarker.cache.TemplateLoader; + +/** + * Extension of the SpringSurf ClassPathStore to ensure that the examination of + * last modified dates on classpath bound resources does not cause a performance + * degredation in REST heavy client applications. + *

+ * In the repository, due to the possibility of Repository bound resources, all + * WebScript search path lists have the "delay" set to either zero seconds (no delay) + * or something close to that. This means that the FreeMarker template cache is + * always or often requesting the last modified date of a classpath resource - and + * the resources do not change. Note that the /extension classpath store still uses + * the original ClassPathStore. Otherwise all stores can be refreshed as usual via + * the Refresh WebScripts command. + * + * @author Kevin Roast + */ +public class RepoClassPathStore extends ClassPathStore +{ + @Override + public TemplateLoader getTemplateLoader() + { + return new ClassPathTemplateLoader(); + } + + @Override + public long lastModified(String documentPath) + throws IOException + { + return -1L; + } + + /** + * Class Path Store implementation of a Template Loader + *

+ * Retrieves templates either from classes in the class path or classes inside of JAR files + * within the class path + *

+ * This implementation always returns a fixed last modified date of -1. + */ + private class ClassPathTemplateLoader extends ClassPathStore.ClassPathTemplateLoader + { + /** + * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object) + */ + public long getLastModified(Object templateSource) + { + return -1L; + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java index 7ffcb1127e..8b326b1c14 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java @@ -1,722 +1,722 @@ -package org.alfresco.repo.web.scripts; - -import java.io.File; -import java.io.IOException; -import java.net.SocketException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; -import javax.transaction.Status; -import javax.transaction.UserTransaction; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.error.ExceptionStackUtil; -import org.alfresco.repo.model.Repository; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.transaction.TooBusyException; -import org.alfresco.repo.web.scripts.bean.LoginPost; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.TemplateService; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.descriptor.DescriptorService; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.TempFileProvider; -import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.extensions.webscripts.AbstractRuntimeContainer; -import org.springframework.extensions.webscripts.Authenticator; -import org.springframework.extensions.webscripts.Description; -import org.springframework.extensions.webscripts.Description.RequiredAuthentication; -import org.springframework.extensions.webscripts.Description.RequiredTransaction; -import org.springframework.extensions.webscripts.Description.RequiredTransactionParameters; -import org.springframework.extensions.webscripts.Description.TransactionCapability; -import org.springframework.extensions.webscripts.ServerModel; -import org.springframework.extensions.webscripts.WebScript; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - - -/** - * Repository (server-tier) container for Web Scripts - * - * @author steveglover - * @author davidc - */ -public class RepositoryContainer extends AbstractRuntimeContainer -{ - // Logger - protected static final Log logger = LogFactory.getLog(RepositoryContainer.class); - - /** Component Dependencies */ - private Repository repository; - private RepositoryImageResolver imageResolver; - private TransactionService transactionService; - private RetryingTransactionHelper fallbackTransactionHelper; - private AuthorityService authorityService; - private DescriptorService descriptorService; - - private boolean encryptTempFiles = false; - private String tempDirectoryName = null; - private int memoryThreshold = 4 * 1024 * 1024; // 4mb - private long maxContentSize = (long) 4 * 1024 * 1024 * 1024; // 4gb - private ThresholdOutputStreamFactory streamFactory = null; - - private Class[] notPublicExceptions = new Class[] {}; - private Class[] publicExceptions = new Class[] {}; - - /* - * Shame init is already used (by TenantRepositoryContainer). - */ - public void setup() - { - File tempDirectory = TempFileProvider.getTempDir(tempDirectoryName); - this.streamFactory = ThresholdOutputStreamFactory.newInstance(tempDirectory, memoryThreshold, maxContentSize, encryptTempFiles); - } - - public void setEncryptTempFiles(Boolean encryptTempFiles) - { - if(encryptTempFiles != null) - { - this.encryptTempFiles = encryptTempFiles.booleanValue(); - } - } - - public void setTempDirectoryName(String tempDirectoryName) - { - this.tempDirectoryName = tempDirectoryName; - } - - public void setMemoryThreshold(Integer memoryThreshold) - { - if(memoryThreshold != null) - { - this.memoryThreshold = memoryThreshold.intValue(); - } - } - - public void setMaxContentSize(Long maxContentSize) - { - if(maxContentSize != null) - { - this.maxContentSize = maxContentSize.longValue(); - } - } - - /** - * @param repository Repository - */ - public void setRepository(Repository repository) - { - this.repository = repository; - } - - /** - * @param imageResolver RepositoryImageResolver - */ - public void setRepositoryImageResolver(RepositoryImageResolver imageResolver) - { - this.imageResolver = imageResolver; - } - - /** - * @param transactionService TransactionService - */ - public void setTransactionService(TransactionService transactionService) - { - this.transactionService = transactionService; - } - - /** - * @param fallbackTransactionHelper an unlimited transaction helper used to generate error responses - */ - public void setFallbackTransactionHelper(RetryingTransactionHelper fallbackTransactionHelper) - { - this.fallbackTransactionHelper = fallbackTransactionHelper; - } - - /** - * @param descriptorService DescriptorService - */ - public void setDescriptorService(DescriptorService descriptorService) - { - this.descriptorService = descriptorService; - } - - /** - * @param authorityService AuthorityService - */ - public void setAuthorityService(AuthorityService authorityService) - { - this.authorityService = authorityService; - } - - /** - * Exceptions which may contain information that cannot be displayed in UI - * - * @param notPublicExceptions - {@link Class}<?>[] instance which contains list of not public exceptions - */ - public void setNotPublicExceptions(List> notPublicExceptions) - { - this.notPublicExceptions = new Class[] {}; - if((null != notPublicExceptions) && !notPublicExceptions.isEmpty()) - { - this.notPublicExceptions = notPublicExceptions.toArray(this.notPublicExceptions); - } - } - - public Class[] getNotPublicExceptions() - { - return notPublicExceptions; - } - - /** - * Exceptions which may contain information that need to display in UI - * - * @param publicExceptions - {@link Class}<?>[] instance which contains list of public exceptions - */ - public void setPublicExceptions(List> publicExceptions) - { - this.publicExceptions = new Class[] {}; - if((null != publicExceptions) && !publicExceptions.isEmpty()) - { - this.publicExceptions = publicExceptions.toArray(this.publicExceptions); - } - } - - public Class[] getPublicExceptions() - { - return publicExceptions; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.Container#getDescription() - */ - public ServerModel getDescription() - { - return new RepositoryServerModel(descriptorService.getCurrentRepositoryDescriptor(), descriptorService.getServerDescriptor()); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getScriptParameters() - */ - public Map getScriptParameters() - { - Map params = new HashMap(); - params.putAll(super.getScriptParameters()); - addRepoParameters(params); - return params; - } - - /* - * (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getTemplateParameters() - */ - public Map getTemplateParameters() - { - // Ensure we have a transaction - we might be generating the status template after the main transaction failed - return fallbackTransactionHelper.doInTransaction(new RetryingTransactionCallback>() - { - public Map execute() throws Throwable - { - Map params = new HashMap(); - params.putAll(RepositoryContainer.super.getTemplateParameters()); - params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver()); - addRepoParameters(params); - return params; - } - }, true); - } - - /** - * Add Repository specific parameters - * - * @param params Map - */ - private void addRepoParameters(Map params) - { - if (AlfrescoTransactionSupport.getTransactionId() != null && - AuthenticationUtil.getFullAuthentication() != null) - { - NodeRef rootHome = repository.getRootHome(); - if (rootHome != null) - { - params.put("roothome", rootHome); - } - NodeRef companyHome = repository.getCompanyHome(); - if (companyHome != null) - { - params.put("companyhome", companyHome); - } - NodeRef person = repository.getFullyAuthenticatedPerson(); - if (person != null) - { - params.put("person", person); - NodeRef userHome = repository.getUserHome(person); - if (userHome != null) - { - params.put("userhome", userHome); - } - } - } - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.RuntimeContainer#executeScript(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse, org.alfresco.web.scripts.Authenticator) - */ - public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, final Authenticator auth) - throws IOException - { - try - { - executeScriptInternal(scriptReq, scriptRes, auth); - } - catch (RuntimeException e) - { - Throwable hideCause = ExceptionStackUtil.getCause(e, notPublicExceptions); - Throwable displayCause = ExceptionStackUtil.getCause(e, publicExceptions); - if (displayCause == null && hideCause != null) - { - AlfrescoRuntimeException alf = null; - if (e instanceof AlfrescoRuntimeException) - { - alf = (AlfrescoRuntimeException) e; - } - else - { - // The message will not have a numerical identifier - alf = new AlfrescoRuntimeException("WebScript execution failed", e); - } - String num = alf.getNumericalId(); - logger.error("Server error (" + num + ")", e); - throw new RuntimeException("Server error (" + num + "). Details can be found in the server logs."); - } - else - { - throw e; - } - } - } - - protected void executeScriptInternal(WebScriptRequest scriptReq, WebScriptResponse scriptRes, final Authenticator auth) - throws IOException - { - final WebScript script = scriptReq.getServiceMatch().getWebScript(); - final Description desc = script.getDescription(); - final boolean debug = logger.isDebugEnabled(); - - // Escalate the webscript declared level of authentication to the container required authentication - // eg. must be guest if MT is enabled unless credentials are empty - RequiredAuthentication containerRequiredAuthentication = getRequiredAuthentication(); - final RequiredAuthentication required = (desc.getRequiredAuthentication().compareTo(containerRequiredAuthentication) < 0 && !auth.emptyCredentials() ? containerRequiredAuthentication : desc.getRequiredAuthentication()); - final boolean isGuest = scriptReq.isGuest(); - - if (required == RequiredAuthentication.none) - { - // TODO revisit - cleared here, in-lieu of WebClient clear - //AuthenticationUtil.clearCurrentSecurityContext(); - - transactionedExecuteAs(script, scriptReq, scriptRes); - } - else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest) - { - throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access."); - } - else - { - try - { - AuthenticationUtil.pushAuthentication(); - - // - // Determine if user already authenticated - // - if (debug) - { - String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); - logger.debug("Authentication required: " + required); - logger.debug("Guest login requested: " + isGuest); - } - - // - // Apply appropriate authentication to Web Script invocation - // - RetryingTransactionCallback authWork = new RetryingTransactionCallback() - { - public Boolean execute() throws Exception - { - if (auth == null || auth.authenticate(required, isGuest)) - { - // The user will now have been authenticated, based on HTTP Auth, Ticket etc - // Check that the user they authenticated as has appropriate access to the script - - // Check to see if they supplied HTTP Auth or Ticket as guest, on a script that needs more - if (required == RequiredAuthentication.user || required == RequiredAuthentication.admin) - { - String authenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser(); - String runAsUser = AuthenticationUtil.getRunAsUser(); - - if ( (authenticatedUser == null) || - (authenticatedUser.equals(runAsUser) && authorityService.hasGuestAuthority()) || - (!authenticatedUser.equals(runAsUser) && authorityService.isGuestAuthority(authenticatedUser)) ) - { - throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access."); - } - } - - // Check to see if they're admin or system on an Admin only script - if (required == RequiredAuthentication.admin && !(authorityService.hasAdminAuthority() || AuthenticationUtil.getFullyAuthenticatedUser().equals(AuthenticationUtil.getSystemUserName()))) - { - throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access."); - } - - if (debug) - { - String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - logger.debug("Authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); - } - - return true; - } - return false; - } - }; - - boolean readOnly = transactionService.isReadOnly(); - boolean requiresNew = !readOnly && AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY; - if (transactionService.getRetryingTransactionHelper().doInTransaction(authWork, readOnly, requiresNew)) - { - // Execute Web Script if authentication passed - // The Web Script has its own txn management with potential runAs() user - transactionedExecuteAs(script, scriptReq, scriptRes); - } - else - { - throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed for Web Script " + desc.getId()); - } - } - finally - { - // - // Reset authentication for current thread - // - AuthenticationUtil.popAuthentication(); - - if (debug) - { - String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); - } - } - } - } - - /** - * Execute script within required level of transaction - * - * @param script WebScript - * @param scriptReq WebScriptRequest - * @param scriptRes WebScriptResponse - * @throws IOException - */ - protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes) - throws IOException - { - try - { - final Description description = script.getDescription(); - if (description.getRequiredTransaction() == RequiredTransaction.none) - { - script.execute(scriptReq, scriptRes); - } - else - { - final BufferedRequest bufferedReq; - final BufferedResponse bufferedRes; - RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters(); - if (trxParams.getCapability() == TransactionCapability.readwrite) - { - if (trxParams.getBufferSize() > 0) - { - if (logger.isDebugEnabled()) - logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize()); - - // create buffered request and response that allow transaction retrying - bufferedReq = new BufferedRequest(scriptReq, streamFactory); - bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize()); - } - else - { - if (logger.isDebugEnabled()) - logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0"); - bufferedReq = null; - bufferedRes = null; - } - } - else - { - bufferedReq = null; - bufferedRes = null; - } - - // encapsulate script within transaction - RetryingTransactionCallback work = new RetryingTransactionCallback() - { - public Object execute() throws Exception - { - try - { - if (logger.isDebugEnabled()) - logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + "," - + description.getRequiredTransactionParameters().getCapability()); - - if (bufferedRes == null) - { - script.execute(scriptReq, scriptRes); - } - else - { - // Reset the request and response in case of a transaction retry - bufferedReq.reset(); - bufferedRes.reset(); - script.execute(bufferedReq, bufferedRes); - } - } - catch(Exception e) - { - if (logger.isDebugEnabled()) - { - logger.debug("Transaction exception: " + description.getRequiredTransaction() + ": " + e.getMessage()); - // Note: user transaction shouldn't be null, but just in case inside this exception handler - UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction(); - if (userTrx != null) - { - logger.debug("Transaction status: " + userTrx.getStatus()); - } - } - - UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction(); - if (userTrx != null) - { - if (userTrx.getStatus() != Status.STATUS_MARKED_ROLLBACK) - { - if (logger.isDebugEnabled()) - logger.debug("Marking web script transaction for rollback"); - try - { - userTrx.setRollbackOnly(); - } - catch(Throwable re) - { - if (logger.isDebugEnabled()) - logger.debug("Caught and ignoring exception during marking for rollback: " + re.getMessage()); - } - } - } - - // re-throw original exception for retry - throw e; - } - finally - { - if (logger.isDebugEnabled()) - logger.debug("End retry transaction block: " + description.getRequiredTransaction() + "," - + description.getRequiredTransactionParameters().getCapability()); - } - - return null; - } - }; - - boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly; - boolean requiresNew = description.getRequiredTransaction() == RequiredTransaction.requiresnew; - - // log a warning if we detect a GET webscript being run in a readwrite transaction, GET calls should - // NOT have any side effects so this scenario as a warning sign something maybe amiss, see ALF-10179. - if (logger.isDebugEnabled() && !readonly && "GET".equalsIgnoreCase(description.getMethod())) - { - logger.debug("Webscript with URL '" + scriptReq.getURL() + - "' is a GET request but it's descriptor has declared a readwrite transaction is required"); - } - - try - { - RetryingTransactionHelper transactionHelper = transactionService.getRetryingTransactionHelper(); - if(script instanceof LoginPost) - { - //login script requires read-write transaction because of authorization intercepter - transactionHelper.setForceWritable(true); - } - transactionHelper.doInTransaction(work, readonly, requiresNew); - } - catch (TooBusyException e) - { - // Map TooBusyException to a 503 status code - throw new WebScriptException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, e.getMessage(), e); - } - finally - { - // Get rid of any temporary files - if (bufferedReq != null) - { - bufferedReq.close(); - } - } - - // Ensure a response is always flushed after successful execution - if (bufferedRes != null) - { - bufferedRes.writeResponse(); - } - - } - } - catch (IOException ioe) - { - Throwable socketException = ExceptionStackUtil.getCause(ioe, SocketException.class); - Class clientAbortException = null; - try - { - clientAbortException = Class.forName("org.apache.catalina.connector.ClientAbortException"); - } - catch (ClassNotFoundException e) - { - // do nothing - } - // Note: if you need to look for more exceptions in the stack, then create a static array and pass it in - if ((socketException != null && socketException.getMessage().contains("Broken pipe")) || (clientAbortException != null && ExceptionStackUtil.getCause(ioe, clientAbortException) != null)) - { - if (logger.isDebugEnabled()) - { - logger.warn("Client has cut off communication", ioe); - } - else - { - logger.info("Client has cut off communication"); - } - } - else - { - throw ioe; - } - } - } - - /** - * Execute script within required level of transaction as required effective user. - * - * @param script WebScript - * @param scriptReq WebScriptRequest - * @param scriptRes WebScriptResponse - * @throws IOException - */ - private void transactionedExecuteAs(final WebScript script, final WebScriptRequest scriptReq, - final WebScriptResponse scriptRes) throws IOException - { - String runAs = script.getDescription().getRunAs(); - if (runAs == null) - { - transactionedExecute(script, scriptReq, scriptRes); - } - else - { - RunAsWork work = new RunAsWork() - { - public Object doWork() throws Exception - { - transactionedExecute(script, scriptReq, scriptRes); - return null; - } - }; - AuthenticationUtil.runAs(work, runAs); - } - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#onApplicationEvent(org.springframework.context.ApplicationEvent) - */ - @Override - public void onApplicationEvent(ApplicationEvent event) - { - if (event instanceof ContextRefreshedEvent) - { - ContextRefreshedEvent refreshEvent = (ContextRefreshedEvent)event; - ApplicationContext refreshContext = refreshEvent.getApplicationContext(); - if (refreshContext != null && refreshContext.equals(applicationContext)) - { - RunAsWork work = new RunAsWork() - { - public Object doWork() throws Exception - { - reset(); - return null; - } - }; - AuthenticationUtil.runAs(work, AuthenticationUtil.getSystemUserName()); - } - } - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRequiredAuthentication() - */ - @Override - public RequiredAuthentication getRequiredAuthentication() - { - if (AuthenticationUtil.isMtEnabled()) - { - return RequiredAuthentication.guest; // user or guest (ie. at least guest) - } - - return RequiredAuthentication.none; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.RuntimeContainer#authenticate(org.alfresco.web.scripts.Authenticator, org.alfresco.web.scripts.Description.RequiredAuthentication) - */ - @Override - public boolean authenticate(Authenticator auth, RequiredAuthentication required) - { - if (auth != null) - { - AuthenticationUtil.clearCurrentSecurityContext(); - - return auth.authenticate(required, false); - } - - return false; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#reset() - */ - @Override - public void reset() - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Object execute() throws Exception - { - internalReset(); - return null; - } - }, true, false); - } - - private void internalReset() - { - super.reset(); - } -} +package org.alfresco.repo.web.scripts; + +import java.io.File; +import java.io.IOException; +import java.net.SocketException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.error.ExceptionStackUtil; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.transaction.TooBusyException; +import org.alfresco.repo.web.scripts.bean.LoginPost; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.descriptor.DescriptorService; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.TempFileProvider; +import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.extensions.webscripts.AbstractRuntimeContainer; +import org.springframework.extensions.webscripts.Authenticator; +import org.springframework.extensions.webscripts.Description; +import org.springframework.extensions.webscripts.Description.RequiredAuthentication; +import org.springframework.extensions.webscripts.Description.RequiredTransaction; +import org.springframework.extensions.webscripts.Description.RequiredTransactionParameters; +import org.springframework.extensions.webscripts.Description.TransactionCapability; +import org.springframework.extensions.webscripts.ServerModel; +import org.springframework.extensions.webscripts.WebScript; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + + +/** + * Repository (server-tier) container for Web Scripts + * + * @author steveglover + * @author davidc + */ +public class RepositoryContainer extends AbstractRuntimeContainer +{ + // Logger + protected static final Log logger = LogFactory.getLog(RepositoryContainer.class); + + /** Component Dependencies */ + private Repository repository; + private RepositoryImageResolver imageResolver; + private TransactionService transactionService; + private RetryingTransactionHelper fallbackTransactionHelper; + private AuthorityService authorityService; + private DescriptorService descriptorService; + + private boolean encryptTempFiles = false; + private String tempDirectoryName = null; + private int memoryThreshold = 4 * 1024 * 1024; // 4mb + private long maxContentSize = (long) 4 * 1024 * 1024 * 1024; // 4gb + private ThresholdOutputStreamFactory streamFactory = null; + + private Class[] notPublicExceptions = new Class[] {}; + private Class[] publicExceptions = new Class[] {}; + + /* + * Shame init is already used (by TenantRepositoryContainer). + */ + public void setup() + { + File tempDirectory = TempFileProvider.getTempDir(tempDirectoryName); + this.streamFactory = ThresholdOutputStreamFactory.newInstance(tempDirectory, memoryThreshold, maxContentSize, encryptTempFiles); + } + + public void setEncryptTempFiles(Boolean encryptTempFiles) + { + if(encryptTempFiles != null) + { + this.encryptTempFiles = encryptTempFiles.booleanValue(); + } + } + + public void setTempDirectoryName(String tempDirectoryName) + { + this.tempDirectoryName = tempDirectoryName; + } + + public void setMemoryThreshold(Integer memoryThreshold) + { + if(memoryThreshold != null) + { + this.memoryThreshold = memoryThreshold.intValue(); + } + } + + public void setMaxContentSize(Long maxContentSize) + { + if(maxContentSize != null) + { + this.maxContentSize = maxContentSize.longValue(); + } + } + + /** + * @param repository Repository + */ + public void setRepository(Repository repository) + { + this.repository = repository; + } + + /** + * @param imageResolver RepositoryImageResolver + */ + public void setRepositoryImageResolver(RepositoryImageResolver imageResolver) + { + this.imageResolver = imageResolver; + } + + /** + * @param transactionService TransactionService + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + /** + * @param fallbackTransactionHelper an unlimited transaction helper used to generate error responses + */ + public void setFallbackTransactionHelper(RetryingTransactionHelper fallbackTransactionHelper) + { + this.fallbackTransactionHelper = fallbackTransactionHelper; + } + + /** + * @param descriptorService DescriptorService + */ + public void setDescriptorService(DescriptorService descriptorService) + { + this.descriptorService = descriptorService; + } + + /** + * @param authorityService AuthorityService + */ + public void setAuthorityService(AuthorityService authorityService) + { + this.authorityService = authorityService; + } + + /** + * Exceptions which may contain information that cannot be displayed in UI + * + * @param notPublicExceptions - {@link Class}<?>[] instance which contains list of not public exceptions + */ + public void setNotPublicExceptions(List> notPublicExceptions) + { + this.notPublicExceptions = new Class[] {}; + if((null != notPublicExceptions) && !notPublicExceptions.isEmpty()) + { + this.notPublicExceptions = notPublicExceptions.toArray(this.notPublicExceptions); + } + } + + public Class[] getNotPublicExceptions() + { + return notPublicExceptions; + } + + /** + * Exceptions which may contain information that need to display in UI + * + * @param publicExceptions - {@link Class}<?>[] instance which contains list of public exceptions + */ + public void setPublicExceptions(List> publicExceptions) + { + this.publicExceptions = new Class[] {}; + if((null != publicExceptions) && !publicExceptions.isEmpty()) + { + this.publicExceptions = publicExceptions.toArray(this.publicExceptions); + } + } + + public Class[] getPublicExceptions() + { + return publicExceptions; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.Container#getDescription() + */ + public ServerModel getDescription() + { + return new RepositoryServerModel(descriptorService.getCurrentRepositoryDescriptor(), descriptorService.getServerDescriptor()); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getScriptParameters() + */ + public Map getScriptParameters() + { + Map params = new HashMap(); + params.putAll(super.getScriptParameters()); + addRepoParameters(params); + return params; + } + + /* + * (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getTemplateParameters() + */ + public Map getTemplateParameters() + { + // Ensure we have a transaction - we might be generating the status template after the main transaction failed + return fallbackTransactionHelper.doInTransaction(new RetryingTransactionCallback>() + { + public Map execute() throws Throwable + { + Map params = new HashMap(); + params.putAll(RepositoryContainer.super.getTemplateParameters()); + params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver()); + addRepoParameters(params); + return params; + } + }, true); + } + + /** + * Add Repository specific parameters + * + * @param params Map + */ + private void addRepoParameters(Map params) + { + if (AlfrescoTransactionSupport.getTransactionId() != null && + AuthenticationUtil.getFullAuthentication() != null) + { + NodeRef rootHome = repository.getRootHome(); + if (rootHome != null) + { + params.put("roothome", rootHome); + } + NodeRef companyHome = repository.getCompanyHome(); + if (companyHome != null) + { + params.put("companyhome", companyHome); + } + NodeRef person = repository.getFullyAuthenticatedPerson(); + if (person != null) + { + params.put("person", person); + NodeRef userHome = repository.getUserHome(person); + if (userHome != null) + { + params.put("userhome", userHome); + } + } + } + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.RuntimeContainer#executeScript(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse, org.alfresco.web.scripts.Authenticator) + */ + public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, final Authenticator auth) + throws IOException + { + try + { + executeScriptInternal(scriptReq, scriptRes, auth); + } + catch (RuntimeException e) + { + Throwable hideCause = ExceptionStackUtil.getCause(e, notPublicExceptions); + Throwable displayCause = ExceptionStackUtil.getCause(e, publicExceptions); + if (displayCause == null && hideCause != null) + { + AlfrescoRuntimeException alf = null; + if (e instanceof AlfrescoRuntimeException) + { + alf = (AlfrescoRuntimeException) e; + } + else + { + // The message will not have a numerical identifier + alf = new AlfrescoRuntimeException("WebScript execution failed", e); + } + String num = alf.getNumericalId(); + logger.error("Server error (" + num + ")", e); + throw new RuntimeException("Server error (" + num + "). Details can be found in the server logs."); + } + else + { + throw e; + } + } + } + + protected void executeScriptInternal(WebScriptRequest scriptReq, WebScriptResponse scriptRes, final Authenticator auth) + throws IOException + { + final WebScript script = scriptReq.getServiceMatch().getWebScript(); + final Description desc = script.getDescription(); + final boolean debug = logger.isDebugEnabled(); + + // Escalate the webscript declared level of authentication to the container required authentication + // eg. must be guest if MT is enabled unless credentials are empty + RequiredAuthentication containerRequiredAuthentication = getRequiredAuthentication(); + final RequiredAuthentication required = (desc.getRequiredAuthentication().compareTo(containerRequiredAuthentication) < 0 && !auth.emptyCredentials() ? containerRequiredAuthentication : desc.getRequiredAuthentication()); + final boolean isGuest = scriptReq.isGuest(); + + if (required == RequiredAuthentication.none) + { + // TODO revisit - cleared here, in-lieu of WebClient clear + //AuthenticationUtil.clearCurrentSecurityContext(); + + transactionedExecuteAs(script, scriptReq, scriptRes); + } + else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest) + { + throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access."); + } + else + { + try + { + AuthenticationUtil.pushAuthentication(); + + // + // Determine if user already authenticated + // + if (debug) + { + String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); + logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); + logger.debug("Authentication required: " + required); + logger.debug("Guest login requested: " + isGuest); + } + + // + // Apply appropriate authentication to Web Script invocation + // + RetryingTransactionCallback authWork = new RetryingTransactionCallback() + { + public Boolean execute() throws Exception + { + if (auth == null || auth.authenticate(required, isGuest)) + { + // The user will now have been authenticated, based on HTTP Auth, Ticket etc + // Check that the user they authenticated as has appropriate access to the script + + // Check to see if they supplied HTTP Auth or Ticket as guest, on a script that needs more + if (required == RequiredAuthentication.user || required == RequiredAuthentication.admin) + { + String authenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser(); + String runAsUser = AuthenticationUtil.getRunAsUser(); + + if ( (authenticatedUser == null) || + (authenticatedUser.equals(runAsUser) && authorityService.hasGuestAuthority()) || + (!authenticatedUser.equals(runAsUser) && authorityService.isGuestAuthority(authenticatedUser)) ) + { + throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access."); + } + } + + // Check to see if they're admin or system on an Admin only script + if (required == RequiredAuthentication.admin && !(authorityService.hasAdminAuthority() || AuthenticationUtil.getFullyAuthenticatedUser().equals(AuthenticationUtil.getSystemUserName()))) + { + throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access."); + } + + if (debug) + { + String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); + logger.debug("Authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); + } + + return true; + } + return false; + } + }; + + boolean readOnly = transactionService.isReadOnly(); + boolean requiresNew = !readOnly && AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY; + if (transactionService.getRetryingTransactionHelper().doInTransaction(authWork, readOnly, requiresNew)) + { + // Execute Web Script if authentication passed + // The Web Script has its own txn management with potential runAs() user + transactionedExecuteAs(script, scriptReq, scriptRes); + } + else + { + throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed for Web Script " + desc.getId()); + } + } + finally + { + // + // Reset authentication for current thread + // + AuthenticationUtil.popAuthentication(); + + if (debug) + { + String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); + logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); + } + } + } + } + + /** + * Execute script within required level of transaction + * + * @param script WebScript + * @param scriptReq WebScriptRequest + * @param scriptRes WebScriptResponse + * @throws IOException + */ + protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes) + throws IOException + { + try + { + final Description description = script.getDescription(); + if (description.getRequiredTransaction() == RequiredTransaction.none) + { + script.execute(scriptReq, scriptRes); + } + else + { + final BufferedRequest bufferedReq; + final BufferedResponse bufferedRes; + RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters(); + if (trxParams.getCapability() == TransactionCapability.readwrite) + { + if (trxParams.getBufferSize() > 0) + { + if (logger.isDebugEnabled()) + logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize()); + + // create buffered request and response that allow transaction retrying + bufferedReq = new BufferedRequest(scriptReq, streamFactory); + bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize()); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0"); + bufferedReq = null; + bufferedRes = null; + } + } + else + { + bufferedReq = null; + bufferedRes = null; + } + + // encapsulate script within transaction + RetryingTransactionCallback work = new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + try + { + if (logger.isDebugEnabled()) + logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + "," + + description.getRequiredTransactionParameters().getCapability()); + + if (bufferedRes == null) + { + script.execute(scriptReq, scriptRes); + } + else + { + // Reset the request and response in case of a transaction retry + bufferedReq.reset(); + bufferedRes.reset(); + script.execute(bufferedReq, bufferedRes); + } + } + catch(Exception e) + { + if (logger.isDebugEnabled()) + { + logger.debug("Transaction exception: " + description.getRequiredTransaction() + ": " + e.getMessage()); + // Note: user transaction shouldn't be null, but just in case inside this exception handler + UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction(); + if (userTrx != null) + { + logger.debug("Transaction status: " + userTrx.getStatus()); + } + } + + UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction(); + if (userTrx != null) + { + if (userTrx.getStatus() != Status.STATUS_MARKED_ROLLBACK) + { + if (logger.isDebugEnabled()) + logger.debug("Marking web script transaction for rollback"); + try + { + userTrx.setRollbackOnly(); + } + catch(Throwable re) + { + if (logger.isDebugEnabled()) + logger.debug("Caught and ignoring exception during marking for rollback: " + re.getMessage()); + } + } + } + + // re-throw original exception for retry + throw e; + } + finally + { + if (logger.isDebugEnabled()) + logger.debug("End retry transaction block: " + description.getRequiredTransaction() + "," + + description.getRequiredTransactionParameters().getCapability()); + } + + return null; + } + }; + + boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly; + boolean requiresNew = description.getRequiredTransaction() == RequiredTransaction.requiresnew; + + // log a warning if we detect a GET webscript being run in a readwrite transaction, GET calls should + // NOT have any side effects so this scenario as a warning sign something maybe amiss, see ALF-10179. + if (logger.isDebugEnabled() && !readonly && "GET".equalsIgnoreCase(description.getMethod())) + { + logger.debug("Webscript with URL '" + scriptReq.getURL() + + "' is a GET request but it's descriptor has declared a readwrite transaction is required"); + } + + try + { + RetryingTransactionHelper transactionHelper = transactionService.getRetryingTransactionHelper(); + if(script instanceof LoginPost) + { + //login script requires read-write transaction because of authorization intercepter + transactionHelper.setForceWritable(true); + } + transactionHelper.doInTransaction(work, readonly, requiresNew); + } + catch (TooBusyException e) + { + // Map TooBusyException to a 503 status code + throw new WebScriptException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, e.getMessage(), e); + } + finally + { + // Get rid of any temporary files + if (bufferedReq != null) + { + bufferedReq.close(); + } + } + + // Ensure a response is always flushed after successful execution + if (bufferedRes != null) + { + bufferedRes.writeResponse(); + } + + } + } + catch (IOException ioe) + { + Throwable socketException = ExceptionStackUtil.getCause(ioe, SocketException.class); + Class clientAbortException = null; + try + { + clientAbortException = Class.forName("org.apache.catalina.connector.ClientAbortException"); + } + catch (ClassNotFoundException e) + { + // do nothing + } + // Note: if you need to look for more exceptions in the stack, then create a static array and pass it in + if ((socketException != null && socketException.getMessage().contains("Broken pipe")) || (clientAbortException != null && ExceptionStackUtil.getCause(ioe, clientAbortException) != null)) + { + if (logger.isDebugEnabled()) + { + logger.warn("Client has cut off communication", ioe); + } + else + { + logger.info("Client has cut off communication"); + } + } + else + { + throw ioe; + } + } + } + + /** + * Execute script within required level of transaction as required effective user. + * + * @param script WebScript + * @param scriptReq WebScriptRequest + * @param scriptRes WebScriptResponse + * @throws IOException + */ + private void transactionedExecuteAs(final WebScript script, final WebScriptRequest scriptReq, + final WebScriptResponse scriptRes) throws IOException + { + String runAs = script.getDescription().getRunAs(); + if (runAs == null) + { + transactionedExecute(script, scriptReq, scriptRes); + } + else + { + RunAsWork work = new RunAsWork() + { + public Object doWork() throws Exception + { + transactionedExecute(script, scriptReq, scriptRes); + return null; + } + }; + AuthenticationUtil.runAs(work, runAs); + } + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#onApplicationEvent(org.springframework.context.ApplicationEvent) + */ + @Override + public void onApplicationEvent(ApplicationEvent event) + { + if (event instanceof ContextRefreshedEvent) + { + ContextRefreshedEvent refreshEvent = (ContextRefreshedEvent)event; + ApplicationContext refreshContext = refreshEvent.getApplicationContext(); + if (refreshContext != null && refreshContext.equals(applicationContext)) + { + RunAsWork work = new RunAsWork() + { + public Object doWork() throws Exception + { + reset(); + return null; + } + }; + AuthenticationUtil.runAs(work, AuthenticationUtil.getSystemUserName()); + } + } + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRequiredAuthentication() + */ + @Override + public RequiredAuthentication getRequiredAuthentication() + { + if (AuthenticationUtil.isMtEnabled()) + { + return RequiredAuthentication.guest; // user or guest (ie. at least guest) + } + + return RequiredAuthentication.none; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.RuntimeContainer#authenticate(org.alfresco.web.scripts.Authenticator, org.alfresco.web.scripts.Description.RequiredAuthentication) + */ + @Override + public boolean authenticate(Authenticator auth, RequiredAuthentication required) + { + if (auth != null) + { + AuthenticationUtil.clearCurrentSecurityContext(); + + return auth.authenticate(required, false); + } + + return false; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#reset() + */ + @Override + public void reset() + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + internalReset(); + return null; + } + }, true, false); + } + + private void internalReset() + { + super.reset(); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryImageResolver.java b/source/java/org/alfresco/repo/web/scripts/RepositoryImageResolver.java index 96049b39b4..f6b14a38af 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryImageResolver.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryImageResolver.java @@ -1,55 +1,55 @@ -package org.alfresco.repo.web.scripts; - -import javax.servlet.ServletContext; - -import org.alfresco.service.cmr.repository.FileTypeImageSize; -import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.web.context.ServletContextAware; - - -/** - * Web Scripts Image Resolver - * - * @author davidc - */ -public class RepositoryImageResolver - implements ServletContextAware, InitializingBean -{ - private ServletContext servletContext; - private TemplateImageResolver imageResolver; - - - /* (non-Javadoc) - * @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext) - */ - public void setServletContext(ServletContext context) - { - this.servletContext = context; - } - - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @SuppressWarnings("serial") - public void afterPropertiesSet() - throws Exception - { - this.imageResolver = new TemplateImageResolver() - { - public String resolveImagePathForName(String filename, FileTypeImageSize size) - { - return FileTypeImageUtils.getFileTypeImage(servletContext, filename, size); - } - }; - } - - /** - * @return image resolver - */ - public TemplateImageResolver getImageResolver() - { - return this.imageResolver; - } - -} +package org.alfresco.repo.web.scripts; + +import javax.servlet.ServletContext; + +import org.alfresco.service.cmr.repository.FileTypeImageSize; +import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.web.context.ServletContextAware; + + +/** + * Web Scripts Image Resolver + * + * @author davidc + */ +public class RepositoryImageResolver + implements ServletContextAware, InitializingBean +{ + private ServletContext servletContext; + private TemplateImageResolver imageResolver; + + + /* (non-Javadoc) + * @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext) + */ + public void setServletContext(ServletContext context) + { + this.servletContext = context; + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @SuppressWarnings("serial") + public void afterPropertiesSet() + throws Exception + { + this.imageResolver = new TemplateImageResolver() + { + public String resolveImagePathForName(String filename, FileTypeImageSize size) + { + return FileTypeImageUtils.getFileTypeImage(servletContext, filename, size); + } + }; + } + + /** + * @return image resolver + */ + public TemplateImageResolver getImageResolver() + { + return this.imageResolver; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessor.java b/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessor.java index ccfbc663bc..5c5e0b85f0 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessor.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessor.java @@ -1,181 +1,181 @@ -package org.alfresco.repo.web.scripts; - -import java.io.InputStream; -import java.io.Reader; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.jscript.ValueConverter; -import org.alfresco.scripts.ScriptException; -import org.alfresco.service.cmr.repository.ScriptLocation; -import org.alfresco.service.cmr.repository.ScriptService; -import org.springframework.extensions.webscripts.MultiScriptLoader; -import org.springframework.extensions.webscripts.ScriptContent; -import org.springframework.extensions.webscripts.ScriptLoader; -import org.springframework.extensions.webscripts.ScriptProcessor; -import org.springframework.extensions.webscripts.SearchPath; -import org.springframework.extensions.webscripts.Store; -import org.springframework.extensions.webscripts.WebScriptException; - - -/** - * Repository (server-tier) Web Script Processor - * - * @author davidc - */ -public class RepositoryScriptProcessor implements ScriptProcessor -{ - // dependencies - protected ScriptService scriptService; - protected ScriptLoader scriptLoader; - protected SearchPath searchPath; - - // Javascript Converter - private final ValueConverter valueConverter = new ValueConverter(); - - - /** - * @param scriptService ScriptService - */ - public void setScriptService(ScriptService scriptService) - { - this.scriptService = scriptService; - } - - /** - * @param searchPath SearchPath - */ - public void setSearchPath(SearchPath searchPath) - { - this.searchPath = searchPath; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ScriptProcessor#findScript(java.lang.String) - */ - public ScriptContent findScript(String path) - { - return scriptLoader.getScript(path); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ScriptProcessor#executeScript(java.lang.String, java.util.Map) - */ - public Object executeScript(String path, Map model) - throws ScriptException - { - // locate script within web script stores - ScriptContent scriptContent = findScript(path); - if (scriptContent == null) - { - throw new WebScriptException("Unable to locate script " + path); - } - // execute script - return executeScript(scriptContent, model); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ScriptProcessor#executeScript(org.alfresco.web.scripts.ScriptContent, java.util.Map) - */ - public Object executeScript(ScriptContent content, Map model) - { - return scriptService.executeScript("javascript", new RepositoryScriptLocation(content), model); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ScriptProcessor#unwrapValue(java.lang.Object) - */ - public Object unwrapValue(Object value) - { - return valueConverter.convertValueForJava(value); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ScriptProcessor#reset() - */ - public void reset() - { - init(); - this.scriptService.resetScriptProcessors(); - } - - /** - * Register script loader from each Web Script Store with Script Processor - */ - private void init() - { - List loaders = new ArrayList(); - for (Store apiStore : searchPath.getStores()) - { - ScriptLoader loader = apiStore.getScriptLoader(); - if (loader == null) - { - throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath()); - } - loaders.add(loader); - } - scriptLoader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()])); - } - - - /** - * Script Location Facade - */ - private static class RepositoryScriptLocation implements ScriptLocation - { - private ScriptContent content; - - private RepositoryScriptLocation(ScriptContent content) - { - this.content = content; - } - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream() - */ - public InputStream getInputStream() - { - return content.getInputStream(); - } - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.ScriptLocation#getReader() - */ - public Reader getReader() - { - return content.getReader(); - } - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.ScriptLocation#isCachable() - */ - public boolean isCachable() - { - return content.isCachable(); - } - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.ScriptLocation#isSecure() - */ - public boolean isSecure() - { - return content.isSecure(); - } - - /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.ScriptLocation#getPath() - */ - public String getPath() - { - return content.getPath(); - } - - @Override - public String toString() - { - return content.getPathDescription(); - } - } +package org.alfresco.repo.web.scripts; + +import java.io.InputStream; +import java.io.Reader; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.jscript.ValueConverter; +import org.alfresco.scripts.ScriptException; +import org.alfresco.service.cmr.repository.ScriptLocation; +import org.alfresco.service.cmr.repository.ScriptService; +import org.springframework.extensions.webscripts.MultiScriptLoader; +import org.springframework.extensions.webscripts.ScriptContent; +import org.springframework.extensions.webscripts.ScriptLoader; +import org.springframework.extensions.webscripts.ScriptProcessor; +import org.springframework.extensions.webscripts.SearchPath; +import org.springframework.extensions.webscripts.Store; +import org.springframework.extensions.webscripts.WebScriptException; + + +/** + * Repository (server-tier) Web Script Processor + * + * @author davidc + */ +public class RepositoryScriptProcessor implements ScriptProcessor +{ + // dependencies + protected ScriptService scriptService; + protected ScriptLoader scriptLoader; + protected SearchPath searchPath; + + // Javascript Converter + private final ValueConverter valueConverter = new ValueConverter(); + + + /** + * @param scriptService ScriptService + */ + public void setScriptService(ScriptService scriptService) + { + this.scriptService = scriptService; + } + + /** + * @param searchPath SearchPath + */ + public void setSearchPath(SearchPath searchPath) + { + this.searchPath = searchPath; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ScriptProcessor#findScript(java.lang.String) + */ + public ScriptContent findScript(String path) + { + return scriptLoader.getScript(path); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ScriptProcessor#executeScript(java.lang.String, java.util.Map) + */ + public Object executeScript(String path, Map model) + throws ScriptException + { + // locate script within web script stores + ScriptContent scriptContent = findScript(path); + if (scriptContent == null) + { + throw new WebScriptException("Unable to locate script " + path); + } + // execute script + return executeScript(scriptContent, model); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ScriptProcessor#executeScript(org.alfresco.web.scripts.ScriptContent, java.util.Map) + */ + public Object executeScript(ScriptContent content, Map model) + { + return scriptService.executeScript("javascript", new RepositoryScriptLocation(content), model); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ScriptProcessor#unwrapValue(java.lang.Object) + */ + public Object unwrapValue(Object value) + { + return valueConverter.convertValueForJava(value); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ScriptProcessor#reset() + */ + public void reset() + { + init(); + this.scriptService.resetScriptProcessors(); + } + + /** + * Register script loader from each Web Script Store with Script Processor + */ + private void init() + { + List loaders = new ArrayList(); + for (Store apiStore : searchPath.getStores()) + { + ScriptLoader loader = apiStore.getScriptLoader(); + if (loader == null) + { + throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath()); + } + loaders.add(loader); + } + scriptLoader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()])); + } + + + /** + * Script Location Facade + */ + private static class RepositoryScriptLocation implements ScriptLocation + { + private ScriptContent content; + + private RepositoryScriptLocation(ScriptContent content) + { + this.content = content; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream() + */ + public InputStream getInputStream() + { + return content.getInputStream(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.ScriptLocation#getReader() + */ + public Reader getReader() + { + return content.getReader(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.ScriptLocation#isCachable() + */ + public boolean isCachable() + { + return content.isCachable(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.ScriptLocation#isSecure() + */ + public boolean isSecure() + { + return content.isSecure(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.ScriptLocation#getPath() + */ + public String getPath() + { + return content.getPath(); + } + + @Override + public String toString() + { + return content.getPathDescription(); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessorFactory.java b/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessorFactory.java index 19628fbf86..b548601e74 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessorFactory.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryScriptProcessorFactory.java @@ -1,29 +1,29 @@ -package org.alfresco.repo.web.scripts; - -import org.springframework.extensions.webscripts.ScriptProcessor; -import org.springframework.extensions.webscripts.ScriptProcessorFactory; - -/** - * @author Kevin Roast - */ -public class RepositoryScriptProcessorFactory implements ScriptProcessorFactory -{ - private ScriptProcessor scriptProcessor; - - - /** - * @param scriptProcessor the ScriptProcessor to set - */ - public void setScriptProcessor(ScriptProcessor scriptProcessor) - { - this.scriptProcessor = scriptProcessor; - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.ScriptProcessorFactory#newInstance() - */ - public ScriptProcessor newInstance() - { - return scriptProcessor; - } +package org.alfresco.repo.web.scripts; + +import org.springframework.extensions.webscripts.ScriptProcessor; +import org.springframework.extensions.webscripts.ScriptProcessorFactory; + +/** + * @author Kevin Roast + */ +public class RepositoryScriptProcessorFactory implements ScriptProcessorFactory +{ + private ScriptProcessor scriptProcessor; + + + /** + * @param scriptProcessor the ScriptProcessor to set + */ + public void setScriptProcessor(ScriptProcessor scriptProcessor) + { + this.scriptProcessor = scriptProcessor; + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.ScriptProcessorFactory#newInstance() + */ + public ScriptProcessor newInstance() + { + return scriptProcessor; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryServerModel.java b/source/java/org/alfresco/repo/web/scripts/RepositoryServerModel.java index 04b6201319..42d9e62e50 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryServerModel.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryServerModel.java @@ -1,117 +1,117 @@ -package org.alfresco.repo.web.scripts; - -import org.alfresco.service.descriptor.Descriptor; -import org.springframework.extensions.webscripts.ServerModel; - - -/** - * Script / Template Model representing Repository Server meta-data - * - * @author davidc - */ -public class RepositoryServerModel implements ServerModel -{ - private Descriptor currentDescriptor; - private Descriptor serverDescriptor; - - /** - * Construct - * - * @param currentDescriptor Descriptor - * @param serverDescriptor Descriptor - */ - /*package*/ RepositoryServerModel(Descriptor currentDescriptor, Descriptor serverDescriptor) - { - this.currentDescriptor = currentDescriptor; - this.serverDescriptor = serverDescriptor; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getContainerName() - */ - public String getContainerName() - { - return "Repository"; - } - - /*(non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getId() - */ - public String getId() - { - return currentDescriptor.getId(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getName() - */ - public String getName() - { - return currentDescriptor.getName(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersionMajor() - */ - public String getVersionMajor() - { - return currentDescriptor.getVersionMajor(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersionMinor() - */ - public String getVersionMinor() - { - return currentDescriptor.getVersionMinor(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersionRevision() - */ - public String getVersionRevision() - { - return currentDescriptor.getVersionRevision(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersionLabel() - */ - public String getVersionLabel() - { - return currentDescriptor.getVersionLabel(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersionBuild() - */ - public String getVersionBuild() - { - return currentDescriptor.getVersionBuild(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getVersion() - */ - public String getVersion() - { - return currentDescriptor.getVersion(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getEdition() - */ - public String getEdition() - { - return serverDescriptor.getEdition(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.ServerModel#getSchema() - */ - public int getSchema() - { - return currentDescriptor.getSchema(); - } - -} +package org.alfresco.repo.web.scripts; + +import org.alfresco.service.descriptor.Descriptor; +import org.springframework.extensions.webscripts.ServerModel; + + +/** + * Script / Template Model representing Repository Server meta-data + * + * @author davidc + */ +public class RepositoryServerModel implements ServerModel +{ + private Descriptor currentDescriptor; + private Descriptor serverDescriptor; + + /** + * Construct + * + * @param currentDescriptor Descriptor + * @param serverDescriptor Descriptor + */ + /*package*/ RepositoryServerModel(Descriptor currentDescriptor, Descriptor serverDescriptor) + { + this.currentDescriptor = currentDescriptor; + this.serverDescriptor = serverDescriptor; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getContainerName() + */ + public String getContainerName() + { + return "Repository"; + } + + /*(non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getId() + */ + public String getId() + { + return currentDescriptor.getId(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getName() + */ + public String getName() + { + return currentDescriptor.getName(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersionMajor() + */ + public String getVersionMajor() + { + return currentDescriptor.getVersionMajor(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersionMinor() + */ + public String getVersionMinor() + { + return currentDescriptor.getVersionMinor(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersionRevision() + */ + public String getVersionRevision() + { + return currentDescriptor.getVersionRevision(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersionLabel() + */ + public String getVersionLabel() + { + return currentDescriptor.getVersionLabel(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersionBuild() + */ + public String getVersionBuild() + { + return currentDescriptor.getVersionBuild(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getVersion() + */ + public String getVersion() + { + return currentDescriptor.getVersion(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getEdition() + */ + public String getEdition() + { + return serverDescriptor.getEdition(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.ServerModel#getSchema() + */ + public int getSchema() + { + return currentDescriptor.getSchema(); + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessor.java b/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessor.java index c78d623ee2..029287f18e 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessor.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessor.java @@ -1,236 +1,236 @@ -package org.alfresco.repo.web.scripts; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.processor.ProcessorExtension; -import org.alfresco.repo.template.FreeMarkerProcessor; -import org.alfresco.repo.template.QNameAwareObjectWrapper; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.extensions.surf.util.AbstractLifecycleBean; -import org.springframework.extensions.webscripts.SearchPath; -import org.springframework.extensions.webscripts.Store; -import org.springframework.extensions.webscripts.TemplateProcessor; -import org.springframework.extensions.webscripts.WebScriptException; - -import freemarker.cache.MultiTemplateLoader; -import freemarker.cache.StrongCacheStorage; -import freemarker.cache.TemplateLoader; -import freemarker.core.TemplateClassResolver; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateExceptionHandler; -import freemarker.template.Version; - - -/** - * Repository (server-tier) Web Script Template Processor - * - * @author davidc - */ -public class RepositoryTemplateProcessor extends FreeMarkerProcessor - implements TemplateProcessor, ApplicationContextAware, ApplicationListener -{ - private ProcessorLifecycle lifecycle = new ProcessorLifecycle(); - protected SearchPath searchPath; - protected String defaultEncoding; - protected Configuration templateConfig; - protected FreeMarkerProcessor freeMarkerProcessor; - private int updateDelay = 1; - - - /* (non-Javadoc) - * @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String) - */ - @Override - public void setDefaultEncoding(String defaultEncoding) - { - this.defaultEncoding = defaultEncoding; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding() - */ - public String getDefaultEncoding() - { - return this.defaultEncoding; - } - - /** - * @param updateDelay the time in seconds between checks on the modified date for cached templates - */ - public void setUpdateDelay(int updateDelay) - { - this.updateDelay = updateDelay; - } - - /** - * @deprecated - * @param cacheSize not used anymore - */ - @Deprecated - public void setCacheSize(int cacheSize) - { - } - - /** - * @param searchPath SearchPath - */ - public void setSearchPath(SearchPath searchPath) - { - this.searchPath = searchPath; - } - - /** - * Set the freemarker processor - * - * @param freeMarkerProcessor the free marker processor - */ - public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor) - { - this.freeMarkerProcessor = freeMarkerProcessor; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig() - */ - @Override - protected Configuration getConfig() - { - return templateConfig; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.TemplateProcessor#reset() - */ - public void reset() - { - if (templateConfig != null) - { - templateConfig.clearTemplateCache(); - } - initConfig(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.TemplateProcessor#hasTemplate(java.lang.String) - */ - public boolean hasTemplate(String templatePath) - { - boolean hasTemplate = false; - try - { - Template template = templateConfig.getTemplate(templatePath); - hasTemplate = (template != null); - } - catch(FileNotFoundException e) - { - // NOTE: return false as template is not found - } - catch(IOException e) - { - throw new WebScriptException("Failed to retrieve template " + templatePath, e); - } - return hasTemplate; - } - - /** - * Initialise FreeMarker Configuration - */ - protected void initConfig() - { - Configuration config = new Configuration(); - - // setup template cache - config.setCacheStorage(new StrongCacheStorage()); - config.setTemplateUpdateDelay(updateDelay); - - // setup template loaders - List loaders = new ArrayList(); - for (Store apiStore : searchPath.getStores()) - { - TemplateLoader loader = apiStore.getTemplateLoader(); - if (loader == null) - { - throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath()); - } - loaders.add(loader); - } - MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()])); - config.setTemplateLoader(loader); - - // use our custom object wrapper that can deal with QNameMap objects directly - config.setObjectWrapper(new QNameAwareObjectWrapper()); - - // rethrow any exception so we can deal with them - config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - - // turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists() - config.setLocalizedLookup(false); - - // set template encoding - if (defaultEncoding != null) - { - config.setDefaultEncoding(defaultEncoding); - } - - // set output encoding - config.setOutputEncoding("UTF-8"); - config.setIncompatibleImprovements(new Version(2, 3, 20)); - config.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER); - - templateConfig = config; - } - - /** - * Tempory fix to initialise this template processor with the freeMarker extensions expected by - * the templates. - */ - private void initProcessorExtensions() - { - for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions()) - { - this.registerProcessorExtension(processorExtension); - } - } - - /* (non-Javadoc) - * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) - */ - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException - { - lifecycle.setApplicationContext(applicationContext); - } - - /* (non-Javadoc) - * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) - */ - public void onApplicationEvent(ApplicationEvent event) - { - lifecycle.onApplicationEvent(event); - } - - /** - * Hooks into Spring Application Lifecycle - */ - private class ProcessorLifecycle extends AbstractLifecycleBean - { - @Override - protected void onBootstrap(ApplicationEvent event) - { - initProcessorExtensions(); - } - - @Override - protected void onShutdown(ApplicationEvent event) - { - } - } - -} +package org.alfresco.repo.web.scripts; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.processor.ProcessorExtension; +import org.alfresco.repo.template.FreeMarkerProcessor; +import org.alfresco.repo.template.QNameAwareObjectWrapper; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; +import org.springframework.extensions.webscripts.SearchPath; +import org.springframework.extensions.webscripts.Store; +import org.springframework.extensions.webscripts.TemplateProcessor; +import org.springframework.extensions.webscripts.WebScriptException; + +import freemarker.cache.MultiTemplateLoader; +import freemarker.cache.StrongCacheStorage; +import freemarker.cache.TemplateLoader; +import freemarker.core.TemplateClassResolver; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.Version; + + +/** + * Repository (server-tier) Web Script Template Processor + * + * @author davidc + */ +public class RepositoryTemplateProcessor extends FreeMarkerProcessor + implements TemplateProcessor, ApplicationContextAware, ApplicationListener +{ + private ProcessorLifecycle lifecycle = new ProcessorLifecycle(); + protected SearchPath searchPath; + protected String defaultEncoding; + protected Configuration templateConfig; + protected FreeMarkerProcessor freeMarkerProcessor; + private int updateDelay = 1; + + + /* (non-Javadoc) + * @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String) + */ + @Override + public void setDefaultEncoding(String defaultEncoding) + { + this.defaultEncoding = defaultEncoding; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding() + */ + public String getDefaultEncoding() + { + return this.defaultEncoding; + } + + /** + * @param updateDelay the time in seconds between checks on the modified date for cached templates + */ + public void setUpdateDelay(int updateDelay) + { + this.updateDelay = updateDelay; + } + + /** + * @deprecated + * @param cacheSize not used anymore + */ + @Deprecated + public void setCacheSize(int cacheSize) + { + } + + /** + * @param searchPath SearchPath + */ + public void setSearchPath(SearchPath searchPath) + { + this.searchPath = searchPath; + } + + /** + * Set the freemarker processor + * + * @param freeMarkerProcessor the free marker processor + */ + public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor) + { + this.freeMarkerProcessor = freeMarkerProcessor; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig() + */ + @Override + protected Configuration getConfig() + { + return templateConfig; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.TemplateProcessor#reset() + */ + public void reset() + { + if (templateConfig != null) + { + templateConfig.clearTemplateCache(); + } + initConfig(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.TemplateProcessor#hasTemplate(java.lang.String) + */ + public boolean hasTemplate(String templatePath) + { + boolean hasTemplate = false; + try + { + Template template = templateConfig.getTemplate(templatePath); + hasTemplate = (template != null); + } + catch(FileNotFoundException e) + { + // NOTE: return false as template is not found + } + catch(IOException e) + { + throw new WebScriptException("Failed to retrieve template " + templatePath, e); + } + return hasTemplate; + } + + /** + * Initialise FreeMarker Configuration + */ + protected void initConfig() + { + Configuration config = new Configuration(); + + // setup template cache + config.setCacheStorage(new StrongCacheStorage()); + config.setTemplateUpdateDelay(updateDelay); + + // setup template loaders + List loaders = new ArrayList(); + for (Store apiStore : searchPath.getStores()) + { + TemplateLoader loader = apiStore.getTemplateLoader(); + if (loader == null) + { + throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath()); + } + loaders.add(loader); + } + MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()])); + config.setTemplateLoader(loader); + + // use our custom object wrapper that can deal with QNameMap objects directly + config.setObjectWrapper(new QNameAwareObjectWrapper()); + + // rethrow any exception so we can deal with them + config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + // turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists() + config.setLocalizedLookup(false); + + // set template encoding + if (defaultEncoding != null) + { + config.setDefaultEncoding(defaultEncoding); + } + + // set output encoding + config.setOutputEncoding("UTF-8"); + config.setIncompatibleImprovements(new Version(2, 3, 20)); + config.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER); + + templateConfig = config; + } + + /** + * Tempory fix to initialise this template processor with the freeMarker extensions expected by + * the templates. + */ + private void initProcessorExtensions() + { + for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions()) + { + this.registerProcessorExtension(processorExtension); + } + } + + /* (non-Javadoc) + * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) + */ + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + lifecycle.setApplicationContext(applicationContext); + } + + /* (non-Javadoc) + * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) + */ + public void onApplicationEvent(ApplicationEvent event) + { + lifecycle.onApplicationEvent(event); + } + + /** + * Hooks into Spring Application Lifecycle + */ + private class ProcessorLifecycle extends AbstractLifecycleBean + { + @Override + protected void onBootstrap(ApplicationEvent event) + { + initProcessorExtensions(); + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + } + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessorFactory.java b/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessorFactory.java index 53f7939725..f47f6fbcdd 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessorFactory.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryTemplateProcessorFactory.java @@ -1,29 +1,29 @@ -package org.alfresco.repo.web.scripts; - -import org.springframework.extensions.webscripts.TemplateProcessor; -import org.springframework.extensions.webscripts.TemplateProcessorFactory; - -/** - * @author Kevin Roast - */ -public class RepositoryTemplateProcessorFactory implements TemplateProcessorFactory -{ - private TemplateProcessor templateProcessor; - - - /** - * @param templateProcessor the TemplateProcessor to set - */ - public void setTemplateProcessor(TemplateProcessor templateProcessor) - { - this.templateProcessor = templateProcessor; - } - - /* (non-Javadoc) - * @see org.springframework.extensions.webscripts.TemplateProcessorFactory#newInstance() - */ - public TemplateProcessor newInstance() - { - return templateProcessor; - } +package org.alfresco.repo.web.scripts; + +import org.springframework.extensions.webscripts.TemplateProcessor; +import org.springframework.extensions.webscripts.TemplateProcessorFactory; + +/** + * @author Kevin Roast + */ +public class RepositoryTemplateProcessorFactory implements TemplateProcessorFactory +{ + private TemplateProcessor templateProcessor; + + + /** + * @param templateProcessor the TemplateProcessor to set + */ + public void setTemplateProcessor(TemplateProcessor templateProcessor) + { + this.templateProcessor = templateProcessor; + } + + /* (non-Javadoc) + * @see org.springframework.extensions.webscripts.TemplateProcessorFactory#newInstance() + */ + public TemplateProcessor newInstance() + { + return templateProcessor; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/admin/NodeBrowserPost.java b/source/java/org/alfresco/repo/web/scripts/admin/NodeBrowserPost.java index cbcb2a7fe6..8137a5a688 100644 --- a/source/java/org/alfresco/repo/web/scripts/admin/NodeBrowserPost.java +++ b/source/java/org/alfresco/repo/web/scripts/admin/NodeBrowserPost.java @@ -1,1354 +1,1354 @@ -package org.alfresco.repo.web.scripts.admin; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AccessPermission; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.OwnableService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.NamespaceException; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.GUID; -import org.alfresco.util.ISO9075; -import org.springframework.extensions.surf.util.URLEncoder; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; - -/** - * Admin Console NodeBrowser WebScript POST controller. - *

- * Implements a low-level node browser client for the Admin Console tool. - * - * @author Kevin Roast - * @since 5.1 - */ -public class NodeBrowserPost extends DeclarativeWebScript implements Serializable -{ - private static final long serialVersionUID = 8464392337270665212L; - - // stores and node - transient private List stores = null; - - // supporting repository services - transient private TransactionService transactionService; - transient private NodeService nodeService; - transient private DictionaryService dictionaryService; - transient private SearchService searchService; - transient private NamespaceService namespaceService; - transient private PermissionService permissionService; - transient private OwnableService ownableService; - transient private LockService lockService; - transient private CheckOutCheckInService cociService; - - /** - * @param transactionService transaction service - */ - public void setTransactionService(TransactionService transactionService) - { - this.transactionService = transactionService; - } - - protected TransactionService getTransactionService() - { - return transactionService; - } - - /** - * @param nodeService node service - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - protected NodeService getNodeService() - { - return nodeService; - } - - /** - * @param searchService search service - */ - public void setSearchService(SearchService searchService) - { - this.searchService = searchService; - } - - protected SearchService getSearchService() - { - return searchService; - } - - /** - * @param dictionaryService dictionary service - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - protected DictionaryService getDictionaryService() - { - return dictionaryService; - } - - /** - * @param namespaceService namespace service - */ - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - - protected NamespaceService getNamespaceService() - { - return this.namespaceService; - } - - /** - * @param permissionService permission service - */ - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - protected PermissionService getPermissionService() - { - return permissionService; - } - - public void setOwnableService(OwnableService ownableService) - { - this.ownableService = ownableService; - } - - protected OwnableService getOwnableService() - { - return ownableService; - } - - public void setLockService(LockService lockService) - { - this.lockService = lockService; - } - - protected LockService getLockService() - { - return this.lockService; - } - - public void setCheckOutCheckInService(CheckOutCheckInService cociService) - { - this.cociService = cociService; - } - - protected CheckOutCheckInService getCheckOutCheckInService() - { - return this.cociService; - } - - /** - * Gets the list of repository stores - * - * @return stores - */ - public List getStores() - { - if (stores == null) - { - stores = getNodeService().getStores(); - } - return stores; - } - - /** - * Gets the current node type - * - * @return node type - */ - public QName getNodeType(NodeRef nodeRef) - { - return getNodeService().getType(nodeRef); - } - - /** - * Gets the current node primary path - * - * @return primary path - */ - public String getPrimaryPath(NodeRef nodeRef) - { - Path primaryPath = getNodeService().getPath(nodeRef); - return ISO9075.decode(primaryPath.toString()); - } - - /** - * Gets the current node primary path - * - * @return primary path - */ - public String getPrimaryPrefixedPath(NodeRef nodeRef) - { - Path primaryPath = getNodeService().getPath(nodeRef); - return ISO9075.decode(primaryPath.toPrefixString(getNamespaceService())); - } - - /** - * Gets the current node primary parent reference - * - * @return primary parent ref - */ - public NodeRef getPrimaryParent(NodeRef nodeRef) - { - Path primaryPath = getNodeService().getPath(nodeRef); - Path.Element element = primaryPath.last(); - NodeRef parentRef = ((Path.ChildAssocElement) element).getRef().getParentRef(); - return parentRef; - } - - /** - * Gets the current node aspects - * - * @return node aspects - */ - public List getAspects(NodeRef nodeRef) - { - Set qnames = getNodeService().getAspects(nodeRef); - List aspects = new ArrayList(qnames.size()); - for (QName qname : qnames) - { - aspects.add(new Aspect(qname)); - } - return aspects; - } - - /** - * Gets the current node parents - * - * @return node parents - */ - public List getParents(NodeRef nodeRef) - { - List parents = getNodeService().getParentAssocs(nodeRef); - List assocs = new ArrayList(parents.size()); - for (ChildAssociationRef ref : parents) - { - assocs.add(new ChildAssociation(ref)); - } - return assocs; - } - - /** - * Gets the current node properties - * - * @return properties - */ - public List getProperties(NodeRef nodeRef) - { - Map propertyValues = getNodeService().getProperties(nodeRef); - List properties = new ArrayList(propertyValues.size()); - for (Map.Entry property : propertyValues.entrySet()) - { - properties.add(new Property(property.getKey(), property.getValue())); - } - return properties; - } - - /** - * Gets whether the current node inherits its permissions from a parent node - * - * @return true => inherits permissions - */ - public boolean getInheritPermissions(NodeRef nodeRef) - { - Boolean inheritPermissions = this.getPermissionService().getInheritParentPermissions(nodeRef); - return inheritPermissions.booleanValue(); - } - - /** - * Gets the current node permissions - * - * @return the permissions - */ - public List getPermissions(NodeRef nodeRef) - { - List permissions = null; - AccessStatus readPermissions = this.getPermissionService().hasPermission(nodeRef, PermissionService.READ_PERMISSIONS); - if (readPermissions.equals(AccessStatus.ALLOWED)) - { - List nodePermissions = new ArrayList(); - for (Iterator iterator = getPermissionService().getAllSetPermissions(nodeRef).iterator(); iterator - .hasNext();) - { - AccessPermission ap = iterator.next(); - nodePermissions.add(new Permission(ap.getPermission(), ap.getAuthority(), ap.getAccessStatus().toString())); - } - permissions = nodePermissions; - } - else - { - List noReadPermissions = new ArrayList(1); - noReadPermissions.add(new NoReadPermissionGranted()); - permissions = noReadPermissions; - } - return permissions; - } - - /** - * Gets the current node permissions - * - * @return the permissions - */ - public List getStorePermissionMasks(NodeRef nodeRef) - { - List permissionMasks = new ArrayList(1); - permissionMasks.add(new NoStoreMask()); - return permissionMasks; - } - - /** - * Gets the current node children - * - * @return node children - */ - public List getChildren(NodeRef nodeRef) - { - List refs = getNodeService().getChildAssocs(nodeRef); - List assocs = new ArrayList(refs.size()); - for (ChildAssociationRef ref : refs) - { - assocs.add(new ChildAssociation(ref)); - } - return assocs; - } - - /** - * Gets the current node associations - * - * @return associations - */ - public List getAssocs(NodeRef nodeRef) - { - List refs = null; - try - { - refs = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); - } - catch (UnsupportedOperationException err) - { - // some stores do not support associations - // but we doesn't want NPE in code below - refs = new ArrayList(); - } - List assocs = new ArrayList(refs.size()); - for (AssociationRef ref : refs) - { - assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef())); - } - return assocs; - } - - /** - * Gets the current source associations - * - * @return associations - */ - public List getSourceAssocs(NodeRef nodeRef) - { - List refs = null; - try - { - refs = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); - } - catch (UnsupportedOperationException err) - { - // some stores do not support associations - // but we doesn't want NPE in code below - refs = new ArrayList(); - } - List assocs = new ArrayList(refs.size()); - for (AssociationRef ref : refs) - { - assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef())); - } - return assocs; - } - - @Override - protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) - { - Map result = new HashMap<>(16); - - // gather inputs - Map returnParams = new HashMap<>(16); - String store = req.getParameter("nodebrowser-store"); - String searcher = req.getParameter("nodebrowser-search"); - String query = req.getParameter("nodebrowser-query"); - String maxResults = req.getParameter("nodebrowser-query-maxresults"); - String skipCount = req.getParameter("nodebrowser-query-skipcount"); - String error = null; - - StoreRef storeRef = new StoreRef(store); - - // always a list of assoc refs from some result - List assocRefs = Collections.emptyList(); - NodeRef currentNode = null; - - // what action should be processed? - long timeStart = System.currentTimeMillis(); - String actionValue = req.getParameter("nodebrowser-action-value"); - String action = req.getParameter("nodebrowser-action"); - final String execute = req.getParameter("nodebrowser-execute"); - final String executeValue = req.getParameter("nodebrowser-execute-value"); - String message = null; - try - { - // 'execute' is an action that performs an operation on a node e.g. delete - // the 'executeValue' param provides context - // this is done before the view action to ensure node state is correct - if (execute != null) - { - switch (execute) - { - case "delete": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - // delete the node using the standard NodeService - nodeService.deleteNode(new NodeRef(executeValue)); - return null; - } - }, false, true); - message = "nodebrowser.message.delete"; - break; - } - case "fdelete": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - // delete the node - but ensure that it is not archived - NodeRef ref = new NodeRef(executeValue); - nodeService.addAspect(ref, ContentModel.ASPECT_TEMPORARY, null); - nodeService.deleteNode(ref); - return null; - } - }, false, true); - message = "nodebrowser.message.delete"; - break; - } - case "restore": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - nodeService.restoreNode(new NodeRef(executeValue), null, null, null); - return null; - } - }, false, true); - message = "nodebrowser.message.restore"; - break; - } - case "take-ownership": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - ownableService.takeOwnership(new NodeRef(executeValue)); - return null; - } - }, false, true); - message = "nodebrowser.message.take-ownership"; - break; - } - case "delete-permissions": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - NodeRef ref = new NodeRef(executeValue); - permissionService.deletePermissions(ref); - permissionService.setInheritParentPermissions(ref, true); - return null; - } - }, false, true); - message = "nodebrowser.message.delete-permissions"; - break; - } - case "delete-property": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - // argument value contains "NodeRef|QName" packed string - String[] parts = executeValue.split("\\|"); - nodeService.removeProperty(new NodeRef(parts[0]), QName.createQName(parts[1])); - return null; - } - }, false, true); - message = "nodebrowser.message.delete-property"; - break; - } - case "unlock": - { - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - NodeRef ref = new NodeRef(executeValue); - if (cociService.isCheckedOut(ref)) - { - NodeRef wcRef = cociService.getWorkingCopy(ref); - if (wcRef != null) - { - cociService.cancelCheckout(wcRef); - } - } - else - { - lockService.unlock(ref); - } - return null; - } - }, false, true); - message = "nodebrowser.message.unlock"; - break; - } - } - } - - // 'action' is a view action that request an update of the admin console view state e.g. 'search' or 'children' - // the 'actionValue' param provides context as may other parameters such as 'query' - switch (action) - { - // on Execute btn press and query present, perform search - case "search": - { - if (query != null && query.trim().length() != 0) - { - switch (searcher) - { - case "noderef": - { - // ensure node exists - or throw error - NodeRef nodeRef = new NodeRef(query); - boolean exists = getNodeService().exists(nodeRef); - if (!exists) - { - throw new AlfrescoRuntimeException("Node " + nodeRef + " does not exist."); - } - currentNode = nodeRef; - // this is not really a search for results, it is a direct node reference - // so gather the child assocs as usual and update the action value for the UI location - assocRefs = getNodeService().getChildAssocs(currentNode); - actionValue = query; - action = "parent"; - break; - } - case "selectnodes": - { - List nodes = getSearchService().selectNodes( - getNodeService().getRootNode(storeRef), query, null, getNamespaceService(), false); - assocRefs = new ArrayList<>(nodes.size()); - for (NodeRef node: nodes) - { - assocRefs.add(getNodeService().getPrimaryParent(node)); - } - break; - } - default: - { - // perform search - SearchParameters params = new SearchParameters(); - params.setQuery(query); - params.addStore(storeRef); - params.setLanguage(searcher); - if (maxResults != null && maxResults.length() != 0) - { - params.setMaxItems(Integer.parseInt(maxResults)); - params.setLimit(Integer.parseInt(maxResults)); - } - if (skipCount != null && skipCount.length() != 0) - { - params.setSkipCount(Integer.parseInt(skipCount)); - } - ResultSet rs = getSearchService().query(params); - assocRefs = rs.getChildAssocRefs(); - break; - } - } - } - break; - } - case "root": - { - // iterate the properties and children of a store root node - currentNode = getNodeService().getRootNode(storeRef); - assocRefs = getNodeService().getChildAssocs(currentNode); - break; - } - case "parent": - case "children": - { - currentNode = new NodeRef(actionValue); - assocRefs = getNodeService().getChildAssocs(currentNode); - break; - } - } - - // get the required information from the assocRefs list and wrap objects - List wrappers = new ArrayList<>(assocRefs.size()); - for (ChildAssociationRef ref : assocRefs) - { - wrappers.add(new ChildAssocRefWrapper(ref)); - } - result.put("children", wrappers); - } - catch (Throwable e) - { - // empty child list on error - current node will still be null - result.put("children", new ArrayList<>(0)); - error = e.getMessage(); - } - - // current node info if any - if (currentNode != null) - { - // node info - Map info = new HashMap<>(8); - info.put("nodeRef", currentNode.toString()); - info.put("path", getNodeService().getPath(currentNode).toPrefixString(getNamespaceService())); - info.put("type", getNodeService().getType(currentNode).toPrefixString(getNamespaceService())); - ChildAssociationRef parent = getNodeService().getPrimaryParent(currentNode); - info.put("parent", parent.getParentRef() != null ? parent.getParentRef().toString() : ""); - result.put("info", info); - - // node properties - result.put("properties", getProperties(currentNode)); - - // parents - List parents = getNodeService().getParentAssocs(currentNode); - List assocs = new ArrayList(parents.size()); - for (ChildAssociationRef ref : parents) - { - assocs.add(new ChildAssociation(ref)); - } - result.put("parents", assocs); - - // aspects - List aspects = getAspects(currentNode); - result.put("aspects", aspects); - - // target assocs - List targetAssocs = getAssocs(currentNode); - result.put("assocs", targetAssocs); - - // source assocs - List sourceAssocs = getSourceAssocs(currentNode); - result.put("sourceAssocs", sourceAssocs); - - // permissions - Map permissionInfo = new HashMap(); - permissionInfo.put("entries", getPermissions(currentNode)); - permissionInfo.put("owner", getOwnableService().getOwner(currentNode)); - permissionInfo.put("inherit", getInheritPermissions(currentNode)); - result.put("permissions", permissionInfo); - } - - // store result in session for the resulting GET request webscript - final String resultId = GUID.generate(); - HttpServletRequest request = ((WebScriptServletRequest)req).getHttpServletRequest(); - HttpSession session = request.getSession(); - session.putValue(resultId, result); - - // return params - returnParams.put("resultId", resultId); - returnParams.put("action", action); - returnParams.put("actionValue", actionValue); - returnParams.put("query", query); - returnParams.put("store", store); - returnParams.put("searcher", searcher); - returnParams.put("maxResults", maxResults); - returnParams.put("skipCount", skipCount); - returnParams.put("in", Long.toString(System.currentTimeMillis()-timeStart)); - returnParams.put("e", error); - returnParams.put("m", message); - - // redirect as all admin console pages do (follow standard pattern) - // The logic to generate the navigation section and server meta-data is all tied into alfresco-common.lib.js - // which is great for writing JS based JMX surfaced pages, but not so great for Java backed WebScripts. - status.setCode(301); - status.setRedirect(true); - status.setLocation(buildUrl(req, returnParams, execute != null && execute.length() != 0 ? execute : action)); - - return null; - } - - private static String buildUrl(WebScriptRequest req, Map params, String hash) - { - StringBuilder url = new StringBuilder(256); - - url.append(req.getServicePath()); - if (!params.isEmpty()) - { - boolean first = true; - for (String key: params.keySet()) - { - String val = params.get(key); - if (val != null && val.length() != 0) - { - url.append(first ? '?' : '&'); - url.append(key); - url.append('='); - url.append(URLEncoder.encode(val)); - first = false; - } - } - } - if (hash != null && hash.length() != 0) - { - url.append('#').append(hash); - } - - return url.toString(); - } - - /** - * Node wrapper class - */ - public class Node implements Serializable - { - private static final long serialVersionUID = 12608347204513848L; - - private String qnamePath; - - private String prefixedQNamePath; - - private NodeRef nodeRef; - - private NodeRef parentNodeRef; - - private QNameBean childAssoc; - - private QNameBean type; - - public Node(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - Path path = getNodeService().getPath(nodeRef); - this.qnamePath = path.toString(); - this.prefixedQNamePath = path.toPrefixString(getNamespaceService()); - this.parentNodeRef = getPrimaryParent(nodeRef); - ChildAssociationRef ref = getNodeService().getPrimaryParent(nodeRef); - this.childAssoc = ref.getQName() != null ? new QNameBean(ref.getQName()) : null; - this.type = new QNameBean(getNodeService().getType(nodeRef)); - } - - public String getQnamePath() - { - return qnamePath; - } - - public String getPrefixedQNamePath() - { - return prefixedQNamePath; - } - - public NodeRef getNodeRef() - { - return nodeRef; - } - - public String getId() - { - return nodeRef.getId(); - } - - public String getName() - { - return childAssoc != null ? childAssoc.getName() : ""; - } - - public String getPrefixedName() - { - return childAssoc != null ? childAssoc.getPrefixedName() : ""; - } - - public QNameBean getType() - { - return type; - } - - public void setNodeRef(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - } - - public NodeRef getParentNodeRef() - { - return parentNodeRef; - } - - public void setParentNodeRef(NodeRef parentNodeRef) - { - this.parentNodeRef = parentNodeRef; - } - } - - /** - * Qname wrapper class - */ - public class QNameBean implements Serializable - { - private static final long serialVersionUID = 6982292337846270774L; - - protected QName name; - private String prefixString = null; - - public QNameBean(QName name) - { - this.name = name; - } - - public String getName() - { - return name.toString(); - } - - public String getPrefixedName() - { - try - { - return prefixString != null ? prefixString : (prefixString = name.toPrefixString(getNamespaceService())); - } - catch(NamespaceException e) - { - return name.getLocalName(); - } - } - - public String toString() - { - return getName(); - } - } - - /** - * Aspect wrapper class - */ - public class Aspect extends QNameBean implements Serializable - { - private static final long serialVersionUID = -6448182941386934326L; - - public Aspect(QName name) - { - super(name); - } - } - - /** - * Association wrapper class - */ - public class Association implements Serializable - { - private static final long serialVersionUID = 1078430803027004L; - - protected QNameBean name; - protected QNameBean typeName; - - public Association(QName name, QName typeName) - { - this.name = name != null ? new QNameBean(name) : null; - this.typeName = new QNameBean(typeName); - } - - public QNameBean getName() - { - return name; - } - - public QNameBean getTypeName() - { - return typeName; - } - } - - /** - * Child assoc wrapper class - */ - public class ChildAssociation extends Association implements Serializable - { - private static final long serialVersionUID = -52439282250891063L; - - protected NodeRef childRef; - protected NodeRef parentRef; - protected QNameBean childType; - protected QNameBean parentType; - protected boolean primary; - - // from Association - protected QNameBean name; - protected QNameBean typeName; - - public ChildAssociation(ChildAssociationRef ref) - { - super(ref.getQName() != null ? ref.getQName() : null, - ref.getTypeQName() != null ? ref.getTypeQName() : null); - - this.childRef = ref.getChildRef(); - this.parentRef = ref.getParentRef(); // could be null - if (childRef != null) - this.childType = new QNameBean(getNodeType(childRef)); - if (parentRef != null) - this.parentType = new QNameBean(getNodeType(parentRef)); - this.primary = ref.isPrimary(); - } - - public NodeRef getChildRef() - { - return childRef; - } - - public QNameBean getChildTypeName() - { - return childType; - } - - public NodeRef getParentRef() - { - return parentRef; - } - - public QNameBean getParentTypeName() - { - return parentType; - } - - public boolean isPrimary() - { - return primary; - } - - public boolean getPrimary() - { - return this.isPrimary(); - } - } - - /** - * Wrapper to resolve Assoc Type and QName to short form with resolved prefix - */ - public class ChildAssocRefWrapper implements Serializable - { - private static final long serialVersionUID = 4321292337846270665L; - - final private ChildAssociationRef ref; - private String qname = null; - private String typeqname = null; - - public ChildAssocRefWrapper(ChildAssociationRef r) - { - ref = r; - } - - public String getTypeQName() - { - return typeqname != null ? typeqname : ( - typeqname = ref.getTypeQName() != null ? ref.getTypeQName().toPrefixString(getNamespaceService()) : ""); - } - - public String getQName() - { - return qname != null ? qname : ( - qname = ref.getQName() != null ? ref.getQName().toPrefixString(getNamespaceService()) : ""); - } - - public NodeRef getChildRef() - { - return ref.getChildRef(); - } - - public NodeRef getParentRef() - { - return ref.getParentRef(); - } - - public boolean isPrimary() - { - return ref.isPrimary(); - } - - public boolean isChildLocked() - { - return lockService != null && lockService.getLockType(ref.getChildRef()) != null; - } - } - - /** - * Peer assoc wrapper class - */ - public class PeerAssociation extends Association implements Serializable - { - private static final long serialVersionUID = 4833278311416507L; - - protected NodeRef sourceRef; - protected NodeRef targetRef; - protected QNameBean sourceType; - protected QNameBean targetType; - - // from Association - protected QNameBean name; - protected QNameBean typeName; - - public PeerAssociation(QName typeName, NodeRef sourceRef, NodeRef targetRef) - { - super(null, typeName); - - this.sourceRef = sourceRef; - this.targetRef = targetRef; - if (sourceRef != null) - this.sourceType = new QNameBean(getNodeType(sourceRef)); - if (targetRef != null) - this.targetType = new QNameBean(getNodeType(targetRef)); - } - - public NodeRef getSourceRef() - { - return sourceRef; - } - - public QNameBean getSourceTypeName() - { - return sourceType; - } - - public NodeRef getTargetRef() - { - return targetRef; - } - - public QNameBean getTargetTypeName() - { - return targetType; - } - } - - /** - * Property wrapper class - */ - public class Property implements Serializable - { - private static final long serialVersionUID = 7755924782250077L; - - private QNameBean name; - - private boolean isCollection = false; - - private List values; - - private boolean residual; - - private QNameBean typeName; - - /** - * Construct - * - * @param name property name - * @param value property values - */ - @SuppressWarnings("unchecked") - public Property(QName qname, Serializable value) - { - this.name = new QNameBean(qname); - - PropertyDefinition propDef = getDictionaryService().getProperty(qname); - if (propDef != null) - { - QName qn = propDef.getDataType().getName(); - typeName = qn != null ? new QNameBean(propDef.getDataType().getName()) : null; - residual = false; - } - else - { - residual = true; - } - - // handle multi/single values - final List values; - if (value instanceof Collection) - { - Collection oldValues = (Collection) value; - values = new ArrayList(oldValues.size()); - isCollection = true; - for (Serializable multiValue : oldValues) - { - values.add(new Value(multiValue instanceof QName ? new QNameBean((QName) multiValue) : multiValue)); - } - } - else - { - values = Collections.singletonList(new Value(value instanceof QName ? new QNameBean((QName) value) : value)); - } - this.values = values; - } - - /** - * Gets the property name - * - * @return name - */ - public QNameBean getName() - { - return name; - } - - public QNameBean getTypeName() - { - return typeName; - } - - /** - * Gets the prefixed property name - * - * @return prefixed name - */ - public String getPrefixedName() - { - return name.getPrefixedName(); - } - - /** - * Gets the property value - * - * @return value - */ - public List getValues() - { - return values; - } - - /** - * Determines whether the property is residual - * - * @return true => property is not defined in dictionary - */ - public boolean getResidual() - { - return residual; - } - - /** - * Determines whether the property is of ANY type - * - * @return true => is any - */ - public boolean isAny() - { - return (getTypeName() == null) ? false : getTypeName().getName().equals(DataTypeDefinition.ANY.toString()); - } - - /** - * Determines whether the property is a collection - * - * @return true => is collection - */ - public boolean isCollection() - { - return isCollection; - } - - /** - * Value wrapper - */ - public class Value implements Serializable - { - private static final long serialVersionUID = 47235536691732705L; - - private Serializable value; - - /** - * Construct - * - * @param value value - */ - public Value(Serializable value) - { - this.value = value; - } - - /** - * Gets the value - * - * @return the value - */ - public Serializable getValue() - { - return value; - } - - /** - * Gets the value datatype - * - * @return the value datatype - */ - public String getDataType() - { - String datatype = null; - if (Property.this.getTypeName() != null) - { - datatype = Property.this.getTypeName().getName(); - } - if (datatype == null || datatype.equals(DataTypeDefinition.ANY.toString())) - { - if (value != null) - { - DataTypeDefinition dataTypeDefinition = getDictionaryService().getDataType(value.getClass()); - if (dataTypeDefinition != null) - { - datatype = getDictionaryService().getDataType(value.getClass()).getName().toString(); - } - } - } - return datatype; - } - - /** - * Determines whether the value is content - * - * @return true => is content - */ - public boolean isContent() - { - String datatype = getDataType(); - return (datatype == null) ? false : datatype.equals(DataTypeDefinition.CONTENT.toString()); - } - - /** - * Determines whether the value is a node ref - * - * @return true => is node ref - */ - public boolean isNodeRef() - { - String datatype = getDataType(); - return (datatype == null) ? false : datatype.equals(DataTypeDefinition.NODE_REF.toString()) || datatype.equals(DataTypeDefinition.CATEGORY.toString()); - } - - /** - * Determines whether the value is null - * - * @return true => value is null - */ - public boolean isNullValue() - { - return value == null; - } - } - } - - /** - * Permission bean - */ - public static class Permission implements Serializable - { - private static final long serialVersionUID = 1235536691732705L; - - private final String permission; - private final String authority; - private final String accessStatus; - - public Permission(String permission, String authority, String accessStatus) - { - this.permission = permission; - this.authority = authority; - this.accessStatus = accessStatus; - } - - public String getPermission() - { - return permission; - } - - public String getAuthority() - { - return authority; - } - - public String getAccessStatus() - { - return accessStatus; - } - } - - /** - * Permission representing the fact that "Read Permissions" has not been granted - */ - public static class NoReadPermissionGranted extends Permission implements Serializable - { - private static final long serialVersionUID = 1236786691732705L; - - public NoReadPermissionGranted() - { - super(PermissionService.READ_PERMISSIONS, "[Current Authority]", "Not Granted"); - } - } - - public static class NoStoreMask extends Permission implements Serializable - { - private static final long serialVersionUID = 3125536691732705L; - - public NoStoreMask() - { - super("All ", "All", "Allowed"); - } - } -} +package org.alfresco.repo.web.scripts.admin; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.GUID; +import org.alfresco.util.ISO9075; +import org.springframework.extensions.surf.util.URLEncoder; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; + +/** + * Admin Console NodeBrowser WebScript POST controller. + *

+ * Implements a low-level node browser client for the Admin Console tool. + * + * @author Kevin Roast + * @since 5.1 + */ +public class NodeBrowserPost extends DeclarativeWebScript implements Serializable +{ + private static final long serialVersionUID = 8464392337270665212L; + + // stores and node + transient private List stores = null; + + // supporting repository services + transient private TransactionService transactionService; + transient private NodeService nodeService; + transient private DictionaryService dictionaryService; + transient private SearchService searchService; + transient private NamespaceService namespaceService; + transient private PermissionService permissionService; + transient private OwnableService ownableService; + transient private LockService lockService; + transient private CheckOutCheckInService cociService; + + /** + * @param transactionService transaction service + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + protected TransactionService getTransactionService() + { + return transactionService; + } + + /** + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + protected NodeService getNodeService() + { + return nodeService; + } + + /** + * @param searchService search service + */ + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + protected SearchService getSearchService() + { + return searchService; + } + + /** + * @param dictionaryService dictionary service + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + protected DictionaryService getDictionaryService() + { + return dictionaryService; + } + + /** + * @param namespaceService namespace service + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + protected NamespaceService getNamespaceService() + { + return this.namespaceService; + } + + /** + * @param permissionService permission service + */ + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + protected PermissionService getPermissionService() + { + return permissionService; + } + + public void setOwnableService(OwnableService ownableService) + { + this.ownableService = ownableService; + } + + protected OwnableService getOwnableService() + { + return ownableService; + } + + public void setLockService(LockService lockService) + { + this.lockService = lockService; + } + + protected LockService getLockService() + { + return this.lockService; + } + + public void setCheckOutCheckInService(CheckOutCheckInService cociService) + { + this.cociService = cociService; + } + + protected CheckOutCheckInService getCheckOutCheckInService() + { + return this.cociService; + } + + /** + * Gets the list of repository stores + * + * @return stores + */ + public List getStores() + { + if (stores == null) + { + stores = getNodeService().getStores(); + } + return stores; + } + + /** + * Gets the current node type + * + * @return node type + */ + public QName getNodeType(NodeRef nodeRef) + { + return getNodeService().getType(nodeRef); + } + + /** + * Gets the current node primary path + * + * @return primary path + */ + public String getPrimaryPath(NodeRef nodeRef) + { + Path primaryPath = getNodeService().getPath(nodeRef); + return ISO9075.decode(primaryPath.toString()); + } + + /** + * Gets the current node primary path + * + * @return primary path + */ + public String getPrimaryPrefixedPath(NodeRef nodeRef) + { + Path primaryPath = getNodeService().getPath(nodeRef); + return ISO9075.decode(primaryPath.toPrefixString(getNamespaceService())); + } + + /** + * Gets the current node primary parent reference + * + * @return primary parent ref + */ + public NodeRef getPrimaryParent(NodeRef nodeRef) + { + Path primaryPath = getNodeService().getPath(nodeRef); + Path.Element element = primaryPath.last(); + NodeRef parentRef = ((Path.ChildAssocElement) element).getRef().getParentRef(); + return parentRef; + } + + /** + * Gets the current node aspects + * + * @return node aspects + */ + public List getAspects(NodeRef nodeRef) + { + Set qnames = getNodeService().getAspects(nodeRef); + List aspects = new ArrayList(qnames.size()); + for (QName qname : qnames) + { + aspects.add(new Aspect(qname)); + } + return aspects; + } + + /** + * Gets the current node parents + * + * @return node parents + */ + public List getParents(NodeRef nodeRef) + { + List parents = getNodeService().getParentAssocs(nodeRef); + List assocs = new ArrayList(parents.size()); + for (ChildAssociationRef ref : parents) + { + assocs.add(new ChildAssociation(ref)); + } + return assocs; + } + + /** + * Gets the current node properties + * + * @return properties + */ + public List getProperties(NodeRef nodeRef) + { + Map propertyValues = getNodeService().getProperties(nodeRef); + List properties = new ArrayList(propertyValues.size()); + for (Map.Entry property : propertyValues.entrySet()) + { + properties.add(new Property(property.getKey(), property.getValue())); + } + return properties; + } + + /** + * Gets whether the current node inherits its permissions from a parent node + * + * @return true => inherits permissions + */ + public boolean getInheritPermissions(NodeRef nodeRef) + { + Boolean inheritPermissions = this.getPermissionService().getInheritParentPermissions(nodeRef); + return inheritPermissions.booleanValue(); + } + + /** + * Gets the current node permissions + * + * @return the permissions + */ + public List getPermissions(NodeRef nodeRef) + { + List permissions = null; + AccessStatus readPermissions = this.getPermissionService().hasPermission(nodeRef, PermissionService.READ_PERMISSIONS); + if (readPermissions.equals(AccessStatus.ALLOWED)) + { + List nodePermissions = new ArrayList(); + for (Iterator iterator = getPermissionService().getAllSetPermissions(nodeRef).iterator(); iterator + .hasNext();) + { + AccessPermission ap = iterator.next(); + nodePermissions.add(new Permission(ap.getPermission(), ap.getAuthority(), ap.getAccessStatus().toString())); + } + permissions = nodePermissions; + } + else + { + List noReadPermissions = new ArrayList(1); + noReadPermissions.add(new NoReadPermissionGranted()); + permissions = noReadPermissions; + } + return permissions; + } + + /** + * Gets the current node permissions + * + * @return the permissions + */ + public List getStorePermissionMasks(NodeRef nodeRef) + { + List permissionMasks = new ArrayList(1); + permissionMasks.add(new NoStoreMask()); + return permissionMasks; + } + + /** + * Gets the current node children + * + * @return node children + */ + public List getChildren(NodeRef nodeRef) + { + List refs = getNodeService().getChildAssocs(nodeRef); + List assocs = new ArrayList(refs.size()); + for (ChildAssociationRef ref : refs) + { + assocs.add(new ChildAssociation(ref)); + } + return assocs; + } + + /** + * Gets the current node associations + * + * @return associations + */ + public List getAssocs(NodeRef nodeRef) + { + List refs = null; + try + { + refs = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); + } + catch (UnsupportedOperationException err) + { + // some stores do not support associations + // but we doesn't want NPE in code below + refs = new ArrayList(); + } + List assocs = new ArrayList(refs.size()); + for (AssociationRef ref : refs) + { + assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef())); + } + return assocs; + } + + /** + * Gets the current source associations + * + * @return associations + */ + public List getSourceAssocs(NodeRef nodeRef) + { + List refs = null; + try + { + refs = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); + } + catch (UnsupportedOperationException err) + { + // some stores do not support associations + // but we doesn't want NPE in code below + refs = new ArrayList(); + } + List assocs = new ArrayList(refs.size()); + for (AssociationRef ref : refs) + { + assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef())); + } + return assocs; + } + + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + Map result = new HashMap<>(16); + + // gather inputs + Map returnParams = new HashMap<>(16); + String store = req.getParameter("nodebrowser-store"); + String searcher = req.getParameter("nodebrowser-search"); + String query = req.getParameter("nodebrowser-query"); + String maxResults = req.getParameter("nodebrowser-query-maxresults"); + String skipCount = req.getParameter("nodebrowser-query-skipcount"); + String error = null; + + StoreRef storeRef = new StoreRef(store); + + // always a list of assoc refs from some result + List assocRefs = Collections.emptyList(); + NodeRef currentNode = null; + + // what action should be processed? + long timeStart = System.currentTimeMillis(); + String actionValue = req.getParameter("nodebrowser-action-value"); + String action = req.getParameter("nodebrowser-action"); + final String execute = req.getParameter("nodebrowser-execute"); + final String executeValue = req.getParameter("nodebrowser-execute-value"); + String message = null; + try + { + // 'execute' is an action that performs an operation on a node e.g. delete + // the 'executeValue' param provides context + // this is done before the view action to ensure node state is correct + if (execute != null) + { + switch (execute) + { + case "delete": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // delete the node using the standard NodeService + nodeService.deleteNode(new NodeRef(executeValue)); + return null; + } + }, false, true); + message = "nodebrowser.message.delete"; + break; + } + case "fdelete": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // delete the node - but ensure that it is not archived + NodeRef ref = new NodeRef(executeValue); + nodeService.addAspect(ref, ContentModel.ASPECT_TEMPORARY, null); + nodeService.deleteNode(ref); + return null; + } + }, false, true); + message = "nodebrowser.message.delete"; + break; + } + case "restore": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + nodeService.restoreNode(new NodeRef(executeValue), null, null, null); + return null; + } + }, false, true); + message = "nodebrowser.message.restore"; + break; + } + case "take-ownership": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + ownableService.takeOwnership(new NodeRef(executeValue)); + return null; + } + }, false, true); + message = "nodebrowser.message.take-ownership"; + break; + } + case "delete-permissions": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + NodeRef ref = new NodeRef(executeValue); + permissionService.deletePermissions(ref); + permissionService.setInheritParentPermissions(ref, true); + return null; + } + }, false, true); + message = "nodebrowser.message.delete-permissions"; + break; + } + case "delete-property": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // argument value contains "NodeRef|QName" packed string + String[] parts = executeValue.split("\\|"); + nodeService.removeProperty(new NodeRef(parts[0]), QName.createQName(parts[1])); + return null; + } + }, false, true); + message = "nodebrowser.message.delete-property"; + break; + } + case "unlock": + { + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + NodeRef ref = new NodeRef(executeValue); + if (cociService.isCheckedOut(ref)) + { + NodeRef wcRef = cociService.getWorkingCopy(ref); + if (wcRef != null) + { + cociService.cancelCheckout(wcRef); + } + } + else + { + lockService.unlock(ref); + } + return null; + } + }, false, true); + message = "nodebrowser.message.unlock"; + break; + } + } + } + + // 'action' is a view action that request an update of the admin console view state e.g. 'search' or 'children' + // the 'actionValue' param provides context as may other parameters such as 'query' + switch (action) + { + // on Execute btn press and query present, perform search + case "search": + { + if (query != null && query.trim().length() != 0) + { + switch (searcher) + { + case "noderef": + { + // ensure node exists - or throw error + NodeRef nodeRef = new NodeRef(query); + boolean exists = getNodeService().exists(nodeRef); + if (!exists) + { + throw new AlfrescoRuntimeException("Node " + nodeRef + " does not exist."); + } + currentNode = nodeRef; + // this is not really a search for results, it is a direct node reference + // so gather the child assocs as usual and update the action value for the UI location + assocRefs = getNodeService().getChildAssocs(currentNode); + actionValue = query; + action = "parent"; + break; + } + case "selectnodes": + { + List nodes = getSearchService().selectNodes( + getNodeService().getRootNode(storeRef), query, null, getNamespaceService(), false); + assocRefs = new ArrayList<>(nodes.size()); + for (NodeRef node: nodes) + { + assocRefs.add(getNodeService().getPrimaryParent(node)); + } + break; + } + default: + { + // perform search + SearchParameters params = new SearchParameters(); + params.setQuery(query); + params.addStore(storeRef); + params.setLanguage(searcher); + if (maxResults != null && maxResults.length() != 0) + { + params.setMaxItems(Integer.parseInt(maxResults)); + params.setLimit(Integer.parseInt(maxResults)); + } + if (skipCount != null && skipCount.length() != 0) + { + params.setSkipCount(Integer.parseInt(skipCount)); + } + ResultSet rs = getSearchService().query(params); + assocRefs = rs.getChildAssocRefs(); + break; + } + } + } + break; + } + case "root": + { + // iterate the properties and children of a store root node + currentNode = getNodeService().getRootNode(storeRef); + assocRefs = getNodeService().getChildAssocs(currentNode); + break; + } + case "parent": + case "children": + { + currentNode = new NodeRef(actionValue); + assocRefs = getNodeService().getChildAssocs(currentNode); + break; + } + } + + // get the required information from the assocRefs list and wrap objects + List wrappers = new ArrayList<>(assocRefs.size()); + for (ChildAssociationRef ref : assocRefs) + { + wrappers.add(new ChildAssocRefWrapper(ref)); + } + result.put("children", wrappers); + } + catch (Throwable e) + { + // empty child list on error - current node will still be null + result.put("children", new ArrayList<>(0)); + error = e.getMessage(); + } + + // current node info if any + if (currentNode != null) + { + // node info + Map info = new HashMap<>(8); + info.put("nodeRef", currentNode.toString()); + info.put("path", getNodeService().getPath(currentNode).toPrefixString(getNamespaceService())); + info.put("type", getNodeService().getType(currentNode).toPrefixString(getNamespaceService())); + ChildAssociationRef parent = getNodeService().getPrimaryParent(currentNode); + info.put("parent", parent.getParentRef() != null ? parent.getParentRef().toString() : ""); + result.put("info", info); + + // node properties + result.put("properties", getProperties(currentNode)); + + // parents + List parents = getNodeService().getParentAssocs(currentNode); + List assocs = new ArrayList(parents.size()); + for (ChildAssociationRef ref : parents) + { + assocs.add(new ChildAssociation(ref)); + } + result.put("parents", assocs); + + // aspects + List aspects = getAspects(currentNode); + result.put("aspects", aspects); + + // target assocs + List targetAssocs = getAssocs(currentNode); + result.put("assocs", targetAssocs); + + // source assocs + List sourceAssocs = getSourceAssocs(currentNode); + result.put("sourceAssocs", sourceAssocs); + + // permissions + Map permissionInfo = new HashMap(); + permissionInfo.put("entries", getPermissions(currentNode)); + permissionInfo.put("owner", getOwnableService().getOwner(currentNode)); + permissionInfo.put("inherit", getInheritPermissions(currentNode)); + result.put("permissions", permissionInfo); + } + + // store result in session for the resulting GET request webscript + final String resultId = GUID.generate(); + HttpServletRequest request = ((WebScriptServletRequest)req).getHttpServletRequest(); + HttpSession session = request.getSession(); + session.putValue(resultId, result); + + // return params + returnParams.put("resultId", resultId); + returnParams.put("action", action); + returnParams.put("actionValue", actionValue); + returnParams.put("query", query); + returnParams.put("store", store); + returnParams.put("searcher", searcher); + returnParams.put("maxResults", maxResults); + returnParams.put("skipCount", skipCount); + returnParams.put("in", Long.toString(System.currentTimeMillis()-timeStart)); + returnParams.put("e", error); + returnParams.put("m", message); + + // redirect as all admin console pages do (follow standard pattern) + // The logic to generate the navigation section and server meta-data is all tied into alfresco-common.lib.js + // which is great for writing JS based JMX surfaced pages, but not so great for Java backed WebScripts. + status.setCode(301); + status.setRedirect(true); + status.setLocation(buildUrl(req, returnParams, execute != null && execute.length() != 0 ? execute : action)); + + return null; + } + + private static String buildUrl(WebScriptRequest req, Map params, String hash) + { + StringBuilder url = new StringBuilder(256); + + url.append(req.getServicePath()); + if (!params.isEmpty()) + { + boolean first = true; + for (String key: params.keySet()) + { + String val = params.get(key); + if (val != null && val.length() != 0) + { + url.append(first ? '?' : '&'); + url.append(key); + url.append('='); + url.append(URLEncoder.encode(val)); + first = false; + } + } + } + if (hash != null && hash.length() != 0) + { + url.append('#').append(hash); + } + + return url.toString(); + } + + /** + * Node wrapper class + */ + public class Node implements Serializable + { + private static final long serialVersionUID = 12608347204513848L; + + private String qnamePath; + + private String prefixedQNamePath; + + private NodeRef nodeRef; + + private NodeRef parentNodeRef; + + private QNameBean childAssoc; + + private QNameBean type; + + public Node(NodeRef nodeRef) + { + this.nodeRef = nodeRef; + Path path = getNodeService().getPath(nodeRef); + this.qnamePath = path.toString(); + this.prefixedQNamePath = path.toPrefixString(getNamespaceService()); + this.parentNodeRef = getPrimaryParent(nodeRef); + ChildAssociationRef ref = getNodeService().getPrimaryParent(nodeRef); + this.childAssoc = ref.getQName() != null ? new QNameBean(ref.getQName()) : null; + this.type = new QNameBean(getNodeService().getType(nodeRef)); + } + + public String getQnamePath() + { + return qnamePath; + } + + public String getPrefixedQNamePath() + { + return prefixedQNamePath; + } + + public NodeRef getNodeRef() + { + return nodeRef; + } + + public String getId() + { + return nodeRef.getId(); + } + + public String getName() + { + return childAssoc != null ? childAssoc.getName() : ""; + } + + public String getPrefixedName() + { + return childAssoc != null ? childAssoc.getPrefixedName() : ""; + } + + public QNameBean getType() + { + return type; + } + + public void setNodeRef(NodeRef nodeRef) + { + this.nodeRef = nodeRef; + } + + public NodeRef getParentNodeRef() + { + return parentNodeRef; + } + + public void setParentNodeRef(NodeRef parentNodeRef) + { + this.parentNodeRef = parentNodeRef; + } + } + + /** + * Qname wrapper class + */ + public class QNameBean implements Serializable + { + private static final long serialVersionUID = 6982292337846270774L; + + protected QName name; + private String prefixString = null; + + public QNameBean(QName name) + { + this.name = name; + } + + public String getName() + { + return name.toString(); + } + + public String getPrefixedName() + { + try + { + return prefixString != null ? prefixString : (prefixString = name.toPrefixString(getNamespaceService())); + } + catch(NamespaceException e) + { + return name.getLocalName(); + } + } + + public String toString() + { + return getName(); + } + } + + /** + * Aspect wrapper class + */ + public class Aspect extends QNameBean implements Serializable + { + private static final long serialVersionUID = -6448182941386934326L; + + public Aspect(QName name) + { + super(name); + } + } + + /** + * Association wrapper class + */ + public class Association implements Serializable + { + private static final long serialVersionUID = 1078430803027004L; + + protected QNameBean name; + protected QNameBean typeName; + + public Association(QName name, QName typeName) + { + this.name = name != null ? new QNameBean(name) : null; + this.typeName = new QNameBean(typeName); + } + + public QNameBean getName() + { + return name; + } + + public QNameBean getTypeName() + { + return typeName; + } + } + + /** + * Child assoc wrapper class + */ + public class ChildAssociation extends Association implements Serializable + { + private static final long serialVersionUID = -52439282250891063L; + + protected NodeRef childRef; + protected NodeRef parentRef; + protected QNameBean childType; + protected QNameBean parentType; + protected boolean primary; + + // from Association + protected QNameBean name; + protected QNameBean typeName; + + public ChildAssociation(ChildAssociationRef ref) + { + super(ref.getQName() != null ? ref.getQName() : null, + ref.getTypeQName() != null ? ref.getTypeQName() : null); + + this.childRef = ref.getChildRef(); + this.parentRef = ref.getParentRef(); // could be null + if (childRef != null) + this.childType = new QNameBean(getNodeType(childRef)); + if (parentRef != null) + this.parentType = new QNameBean(getNodeType(parentRef)); + this.primary = ref.isPrimary(); + } + + public NodeRef getChildRef() + { + return childRef; + } + + public QNameBean getChildTypeName() + { + return childType; + } + + public NodeRef getParentRef() + { + return parentRef; + } + + public QNameBean getParentTypeName() + { + return parentType; + } + + public boolean isPrimary() + { + return primary; + } + + public boolean getPrimary() + { + return this.isPrimary(); + } + } + + /** + * Wrapper to resolve Assoc Type and QName to short form with resolved prefix + */ + public class ChildAssocRefWrapper implements Serializable + { + private static final long serialVersionUID = 4321292337846270665L; + + final private ChildAssociationRef ref; + private String qname = null; + private String typeqname = null; + + public ChildAssocRefWrapper(ChildAssociationRef r) + { + ref = r; + } + + public String getTypeQName() + { + return typeqname != null ? typeqname : ( + typeqname = ref.getTypeQName() != null ? ref.getTypeQName().toPrefixString(getNamespaceService()) : ""); + } + + public String getQName() + { + return qname != null ? qname : ( + qname = ref.getQName() != null ? ref.getQName().toPrefixString(getNamespaceService()) : ""); + } + + public NodeRef getChildRef() + { + return ref.getChildRef(); + } + + public NodeRef getParentRef() + { + return ref.getParentRef(); + } + + public boolean isPrimary() + { + return ref.isPrimary(); + } + + public boolean isChildLocked() + { + return lockService != null && lockService.getLockType(ref.getChildRef()) != null; + } + } + + /** + * Peer assoc wrapper class + */ + public class PeerAssociation extends Association implements Serializable + { + private static final long serialVersionUID = 4833278311416507L; + + protected NodeRef sourceRef; + protected NodeRef targetRef; + protected QNameBean sourceType; + protected QNameBean targetType; + + // from Association + protected QNameBean name; + protected QNameBean typeName; + + public PeerAssociation(QName typeName, NodeRef sourceRef, NodeRef targetRef) + { + super(null, typeName); + + this.sourceRef = sourceRef; + this.targetRef = targetRef; + if (sourceRef != null) + this.sourceType = new QNameBean(getNodeType(sourceRef)); + if (targetRef != null) + this.targetType = new QNameBean(getNodeType(targetRef)); + } + + public NodeRef getSourceRef() + { + return sourceRef; + } + + public QNameBean getSourceTypeName() + { + return sourceType; + } + + public NodeRef getTargetRef() + { + return targetRef; + } + + public QNameBean getTargetTypeName() + { + return targetType; + } + } + + /** + * Property wrapper class + */ + public class Property implements Serializable + { + private static final long serialVersionUID = 7755924782250077L; + + private QNameBean name; + + private boolean isCollection = false; + + private List values; + + private boolean residual; + + private QNameBean typeName; + + /** + * Construct + * + * @param name property name + * @param value property values + */ + @SuppressWarnings("unchecked") + public Property(QName qname, Serializable value) + { + this.name = new QNameBean(qname); + + PropertyDefinition propDef = getDictionaryService().getProperty(qname); + if (propDef != null) + { + QName qn = propDef.getDataType().getName(); + typeName = qn != null ? new QNameBean(propDef.getDataType().getName()) : null; + residual = false; + } + else + { + residual = true; + } + + // handle multi/single values + final List values; + if (value instanceof Collection) + { + Collection oldValues = (Collection) value; + values = new ArrayList(oldValues.size()); + isCollection = true; + for (Serializable multiValue : oldValues) + { + values.add(new Value(multiValue instanceof QName ? new QNameBean((QName) multiValue) : multiValue)); + } + } + else + { + values = Collections.singletonList(new Value(value instanceof QName ? new QNameBean((QName) value) : value)); + } + this.values = values; + } + + /** + * Gets the property name + * + * @return name + */ + public QNameBean getName() + { + return name; + } + + public QNameBean getTypeName() + { + return typeName; + } + + /** + * Gets the prefixed property name + * + * @return prefixed name + */ + public String getPrefixedName() + { + return name.getPrefixedName(); + } + + /** + * Gets the property value + * + * @return value + */ + public List getValues() + { + return values; + } + + /** + * Determines whether the property is residual + * + * @return true => property is not defined in dictionary + */ + public boolean getResidual() + { + return residual; + } + + /** + * Determines whether the property is of ANY type + * + * @return true => is any + */ + public boolean isAny() + { + return (getTypeName() == null) ? false : getTypeName().getName().equals(DataTypeDefinition.ANY.toString()); + } + + /** + * Determines whether the property is a collection + * + * @return true => is collection + */ + public boolean isCollection() + { + return isCollection; + } + + /** + * Value wrapper + */ + public class Value implements Serializable + { + private static final long serialVersionUID = 47235536691732705L; + + private Serializable value; + + /** + * Construct + * + * @param value value + */ + public Value(Serializable value) + { + this.value = value; + } + + /** + * Gets the value + * + * @return the value + */ + public Serializable getValue() + { + return value; + } + + /** + * Gets the value datatype + * + * @return the value datatype + */ + public String getDataType() + { + String datatype = null; + if (Property.this.getTypeName() != null) + { + datatype = Property.this.getTypeName().getName(); + } + if (datatype == null || datatype.equals(DataTypeDefinition.ANY.toString())) + { + if (value != null) + { + DataTypeDefinition dataTypeDefinition = getDictionaryService().getDataType(value.getClass()); + if (dataTypeDefinition != null) + { + datatype = getDictionaryService().getDataType(value.getClass()).getName().toString(); + } + } + } + return datatype; + } + + /** + * Determines whether the value is content + * + * @return true => is content + */ + public boolean isContent() + { + String datatype = getDataType(); + return (datatype == null) ? false : datatype.equals(DataTypeDefinition.CONTENT.toString()); + } + + /** + * Determines whether the value is a node ref + * + * @return true => is node ref + */ + public boolean isNodeRef() + { + String datatype = getDataType(); + return (datatype == null) ? false : datatype.equals(DataTypeDefinition.NODE_REF.toString()) || datatype.equals(DataTypeDefinition.CATEGORY.toString()); + } + + /** + * Determines whether the value is null + * + * @return true => value is null + */ + public boolean isNullValue() + { + return value == null; + } + } + } + + /** + * Permission bean + */ + public static class Permission implements Serializable + { + private static final long serialVersionUID = 1235536691732705L; + + private final String permission; + private final String authority; + private final String accessStatus; + + public Permission(String permission, String authority, String accessStatus) + { + this.permission = permission; + this.authority = authority; + this.accessStatus = accessStatus; + } + + public String getPermission() + { + return permission; + } + + public String getAuthority() + { + return authority; + } + + public String getAccessStatus() + { + return accessStatus; + } + } + + /** + * Permission representing the fact that "Read Permissions" has not been granted + */ + public static class NoReadPermissionGranted extends Permission implements Serializable + { + private static final long serialVersionUID = 1236786691732705L; + + public NoReadPermissionGranted() + { + super(PermissionService.READ_PERMISSIONS, "[Current Authority]", "Not Granted"); + } + } + + public static class NoStoreMask extends Permission implements Serializable + { + private static final long serialVersionUID = 3125536691732705L; + + public NoStoreMask() + { + super("All ", "All", "Allowed"); + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/audit/AuditEntryDelete.java b/source/java/org/alfresco/repo/web/scripts/audit/AuditEntryDelete.java index 7c57677f2b..ee54a9c783 100644 --- a/source/java/org/alfresco/repo/web/scripts/audit/AuditEntryDelete.java +++ b/source/java/org/alfresco/repo/web/scripts/audit/AuditEntryDelete.java @@ -1,86 +1,86 @@ -package org.alfresco.repo.web.scripts.audit; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.service.cmr.audit.AuditQueryParameters; -import org.alfresco.service.cmr.audit.AuditService.AuditApplication; -import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * @author Mark Rogers - * @since 4.2 - */ -public class AuditEntryDelete extends AbstractAuditWebScript -{ - @Override - protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) - { - Map model = new HashMap(7); - - Long id = getId(req); - if (id == null) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.entry.id.notProvided"); - } - final List auditEntryIds = new ArrayList(); - - // Need to check that the audit entry actually exists - otherwise we get into a concurrency retry loop - AuditQueryParameters params = new AuditQueryParameters(); - AuditQueryCallback callback = new AuditQueryCallback(){ - - @Override - public boolean valuesRequired() { - return false; - } - - @Override - public boolean handleAuditEntry(Long entryId, - String applicationName, - String user, long time, - Map values) { - auditEntryIds.add(entryId); - return false; - } - - @Override - public boolean handleAuditEntryError(Long entryId, String errorMsg, - Throwable error) - { - return true; - } - - }; - - params.setToId(id); - params.setFromId(id); - auditService.auditQuery(callback, params, 1); - - if(auditEntryIds.size() > 0) - { - // - int deleted = auditService.clearAudit(auditEntryIds); - - model.put(JSON_KEY_DELETED, deleted); - - // Done - if (logger.isDebugEnabled()) - { - logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); - } - return model; - } - else - { - // Not found - throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.entry.id.notfound", id); - } - } +package org.alfresco.repo.web.scripts.audit; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.audit.AuditQueryParameters; +import org.alfresco.service.cmr.audit.AuditService.AuditApplication; +import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author Mark Rogers + * @since 4.2 + */ +public class AuditEntryDelete extends AbstractAuditWebScript +{ + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + Map model = new HashMap(7); + + Long id = getId(req); + if (id == null) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.entry.id.notProvided"); + } + final List auditEntryIds = new ArrayList(); + + // Need to check that the audit entry actually exists - otherwise we get into a concurrency retry loop + AuditQueryParameters params = new AuditQueryParameters(); + AuditQueryCallback callback = new AuditQueryCallback(){ + + @Override + public boolean valuesRequired() { + return false; + } + + @Override + public boolean handleAuditEntry(Long entryId, + String applicationName, + String user, long time, + Map values) { + auditEntryIds.add(entryId); + return false; + } + + @Override + public boolean handleAuditEntryError(Long entryId, String errorMsg, + Throwable error) + { + return true; + } + + }; + + params.setToId(id); + params.setFromId(id); + auditService.auditQuery(callback, params, 1); + + if(auditEntryIds.size() > 0) + { + // + int deleted = auditService.clearAudit(auditEntryIds); + + model.put(JSON_KEY_DELETED, deleted); + + // Done + if (logger.isDebugEnabled()) + { + logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); + } + return model; + } + else + { + // Not found + throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.entry.id.notfound", id); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/ADMRemoteStore.java b/source/java/org/alfresco/repo/web/scripts/bean/ADMRemoteStore.java index 8b2520cd77..f3256071dd 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/ADMRemoteStore.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/ADMRemoteStore.java @@ -1,1086 +1,1086 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.io.Writer; -import java.net.SocketException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.query.CannedQueryPageDetails; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.model.filefolder.HiddenAspect; -import org.alfresco.repo.policy.BehaviourFilter; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.service.cmr.model.FileExistsException; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileFolderUtil; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.model.FileNotFoundException; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentIOException; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.surf.util.URLDecoder; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * ADM Remote Store service. - *

- * This implementation of the RemoteStore is tied to the current SiteService implementation. - *

- * It remaps incoming generic document path requests to the appropriate folder structure - * in the Sites folder. Dashboard pages and component bindings are remapped to take advantage - * of inherited permissions in the appropriate root site folder, ensuring that only valid - * users can write to the appropriate configuration objects. - * - * @see BaseRemoteStore for the available API methods. - * - * @author Kevin Roast - */ -public class ADMRemoteStore extends BaseRemoteStore -{ - private static final Log logger = LogFactory.getLog(ADMRemoteStore.class); - - // name of the surf config folder - private static final String SURF_CONFIG = "surf-config"; - - // patterns used to match site and user specific configuration locations - private static final String PATH_COMPONENTS = "components"; - private static final String PATH_PAGES = "pages"; - private static final String PATH_USER = "user"; - private static final String PATH_SITE = "site"; - private static final String USER_CONFIG = ".*\\." + PATH_USER + "~(.*)~.*"; - private static final String USER_CONFIG_PATTERN = USER_CONFIG.replaceAll("\\.\\*", "*").replace("\\", ""); - private static final Pattern USER_PATTERN_1 = Pattern.compile(".*/" + PATH_COMPONENTS + "/" + USER_CONFIG); - private static final Pattern USER_PATTERN_2 = Pattern.compile(".*/" + PATH_PAGES + "/" + PATH_USER + "/(.*?)(/.*)?$"); - private static final Pattern SITE_PATTERN_1 = Pattern.compile(".*/" + PATH_COMPONENTS + "/.*\\." + PATH_SITE + "~(.*)~.*"); - private static final Pattern SITE_PATTERN_2 = Pattern.compile(".*/" + PATH_PAGES + "/" + PATH_SITE + "/(.*?)(/.*)?$"); - - - // service beans - protected NodeService nodeService; - protected NodeService unprotNodeService; - protected FileFolderService fileFolderService; - protected NamespaceService namespaceService; - protected SiteService siteService; - protected ContentService contentService; - protected HiddenAspect hiddenAspect; - private BehaviourFilter behaviourFilter; - - /** - * Date format pattern used to parse HTTP date headers in RFC 1123 format. - */ - private static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; - private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); - - - /** - * @param nodeService the NodeService to set - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - /** - * @param nodeService the NodeService to set - */ - public void setUnprotectedNodeService(NodeService nodeService) - { - this.unprotNodeService = nodeService; - } - - /** - * @param fileFolderService the FileFolderService to set - */ - public void setFileFolderService(FileFolderService fileFolderService) - { - this.fileFolderService = fileFolderService; - } - - /** - * @param namespaceService the NamespaceService to set - */ - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - - /** - * @param siteService the SiteService to set - */ - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - /** - * @param contentService the ContentService to set - */ - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - - public void setHiddenAspect(HiddenAspect hiddenAspect) - { - this.hiddenAspect = hiddenAspect; - } - - public void setBehaviourFilter(BehaviourFilter behaviourFilter) - { - this.behaviourFilter = behaviourFilter; - } - - /** - * Gets the last modified timestamp for the document. - *

- * The output will be the last modified date as a long toString(). - * - * @param path document path to an existing document - */ - @Override - protected void lastModified(final WebScriptResponse res, final String store, final String path) - throws IOException - { - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveFilePath(encpath); - if (fileInfo == null) - { - throw new WebScriptException("Unable to locate file: " + encpath); - } - - Writer out = res.getWriter(); - out.write(Long.toString(fileInfo.getModifiedDate().getTime())); - out.close(); - if (logger.isDebugEnabled()) - logger.debug("lastModified: " + Long.toString(fileInfo.getModifiedDate().getTime())); - return null; - } - }, AuthenticationUtil.getSystemUserName()); - } - - /** - * Gets a document. - *

- * The output will be the document content stream. - * - * @param path document path - */ - @Override - protected void getDocument(final WebScriptResponse res, final String store, final String path) - { - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveFilePath(encpath); - if (fileInfo == null || fileInfo.isFolder()) - { - res.setStatus(Status.STATUS_NOT_FOUND); - return null; - } - - final ContentReader reader; - try - { - reader = contentService.getReader(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT); - if (reader == null || !reader.exists()) - { - throw new WebScriptException("No content found for file: " + encpath); - } - - // establish mimetype - String mimetype = reader.getMimetype(); - if (mimetype == null || mimetype.length() == 0) - { - mimetype = MimetypeMap.MIMETYPE_BINARY; - int extIndex = encpath.lastIndexOf('.'); - if (extIndex != -1) - { - String ext = encpath.substring(extIndex + 1); - String mt = mimetypeService.getMimetypesByExtension().get(ext); - if (mt != null) - { - mimetype = mt; - } - } - } - - // set mimetype for the content and the character encoding + length for the stream - res.setContentType(mimetype); - res.setContentEncoding(reader.getEncoding()); - SimpleDateFormat formatter = new SimpleDateFormat(PATTERN_RFC1123, Locale.US); - formatter.setTimeZone(GMT); - res.setHeader("Last-Modified", formatter.format(fileInfo.getModifiedDate())); - res.setHeader("Content-Length", Long.toString(reader.getSize())); - - if (logger.isDebugEnabled()) - logger.debug("getDocument: " + fileInfo.toString()); - - // get the content and stream directly to the response output stream - // assuming the repository is capable of streaming in chunks, this should allow large files - // to be streamed directly to the browser response stream. - try - { - reader.getContent(res.getOutputStream()); - } - catch (SocketException e1) - { - // the client cut the connection - our mission was accomplished apart from a little error message - if (logger.isDebugEnabled()) - logger.debug("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); - } - catch (ContentIOException e2) - { - if (logger.isInfoEnabled()) - logger.info("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); - } - catch (Throwable err) - { - if (err.getCause() instanceof SocketException) - { - if (logger.isDebugEnabled()) - logger.debug("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); - } - else - { - if (logger.isInfoEnabled()) - logger.info(err.getMessage()); - res.setStatus(Status.STATUS_INTERNAL_SERVER_ERROR); - } - } - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - } - return null; - } - }, AuthenticationUtil.getSystemUserName()); - } - - /** - * Determines if the document exists. - * - * The output will be either the string "true" or the string "false". - * - * @param path document path - */ - @Override - protected void hasDocument(final WebScriptResponse res, final String store, final String path) throws IOException - { - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveFilePath(encpath); - - Writer out = res.getWriter(); - out.write(Boolean.toString(fileInfo != null && !fileInfo.isFolder())); - out.close(); - if (logger.isDebugEnabled()) - logger.debug("hasDocument: " + Boolean.toString(fileInfo != null && !fileInfo.isFolder())); - return null; - } - }, AuthenticationUtil.getSystemUserName()); - } - - /** - * Creates a document. - *

- * Create methods are user authenticated, so the creation of site config must be - * allowed for the current user. - * - * @param path document path - * @param content content of the document to write - */ - @Override - protected void createDocument(final WebScriptResponse res, final String store, final String path, final InputStream content) - { - try - { - writeDocument(path, content); - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - throw ae; - } - catch (FileExistsException feeErr) - { - res.setStatus(Status.STATUS_CONFLICT); - throw feeErr; - } - } - - /** - * Creates multiple XML documents encapsulated in a single one. - * - * @param res WebScriptResponse - * @param store String - * @param in XML document containing multiple document contents to write - */ - @Override - protected void createDocuments(WebScriptResponse res, String store, InputStream in) - { - try - { - DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document document; - document = documentBuilder.parse(in); - Element docEl = document.getDocumentElement(); - Transformer transformer = ADMRemoteStore.this.transformer.get(); - for (Node n = docEl.getFirstChild(); n != null; n = n.getNextSibling()) - { - if (!(n instanceof Element)) - { - continue; - } - final String path = ((Element) n).getAttribute("path"); - - // Turn the first element child into a document - Document doc = documentBuilder.newDocument(); - Node child; - for (child = n.getFirstChild(); child != null ; child=child.getNextSibling()) - { - if (child instanceof Element) - { - doc.appendChild(doc.importNode(child, true)); - break; - } - } - ByteArrayOutputStream out = new ByteArrayOutputStream(512); - transformer.transform(new DOMSource(doc), new StreamResult(out)); - out.close(); - - writeDocument(path, new ByteArrayInputStream(out.toByteArray())); - } - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - throw ae; - } - catch (FileExistsException feeErr) - { - res.setStatus(Status.STATUS_CONFLICT); - throw feeErr; - } - catch (Exception e) - { - // various annoying checked SAX/IO exceptions related to XML processing can be thrown - // none of them should occur if the XML document is well formed - logger.error(e); - res.setStatus(Status.STATUS_INTERNAL_SERVER_ERROR); - throw new AlfrescoRuntimeException(e.getMessage(), e); - } - } - - protected void writeDocument(final String path, final InputStream content) - { - final String encpath = encodePath(path); - final int off = encpath.lastIndexOf('/'); - if (off != -1) - { - // check we actually are the user we are creating a user specific path for - final String runAsUser = getPathRunAsUser(path); - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - final FileInfo parentFolder = resolveNodePath(encpath, true, false); - if (parentFolder == null) - { - throw new IllegalStateException("Unable to aquire parent folder reference for path: " + path); - } - - // ALF-17729 / ALF-17796 - disable auditable on parent folder - NodeRef parentFolderRef = parentFolder.getNodeRef(); - behaviourFilter.disableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); - - try - { - final String name = encpath.substring(off + 1); - // existence check - convert to an UPDATE - could occur if multiple threads request - // a write to the same document - a valid possibility but rare - if (nodeService.getChildByName(parentFolderRef, ContentModel.ASSOC_CONTAINS, name) == null) - { - FileInfo fileInfo = fileFolderService.create( - parentFolderRef, name, ContentModel.TYPE_CONTENT); - Map aspectProperties = new HashMap(1, 1.0f); - aspectProperties.put(ContentModel.PROP_IS_INDEXED, false); - unprotNodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_INDEX_CONTROL, aspectProperties); - ContentWriter writer = contentService.getWriter( - fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true); - writer.guessMimetype(fileInfo.getName()); - writer.putContent(content); - if (logger.isDebugEnabled()) - logger.debug("createDocument: " + fileInfo.toString()); - } - else - { - ContentWriter writer = contentService.getWriter( - nodeService.getChildByName(parentFolderRef, ContentModel.ASSOC_CONTAINS, name), - ContentModel.PROP_CONTENT, - true); - writer.guessMimetype(name); - writer.putContent(content); - if (logger.isDebugEnabled()) - logger.debug("createDocument (updated): " + name); - } - } - finally - { - behaviourFilter.enableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); - } - - return null; - } - }, runAsUser); - } - } - - /** - * Get the RunAs user need to execute a Write operation on the given path. - * - * @param path Document path - * @return runas user - will be the Full Authenticated User or System as required - */ - protected String getPathRunAsUser(final String path) - { - // check we actually are the user we are creating a user specific path for - String runAsUser = AuthenticationUtil.getFullyAuthenticatedUser(); - String userId = null; - Matcher matcher; - if ((matcher = USER_PATTERN_1.matcher(path)).matches()) - { - userId = matcher.group(1); - } - else if ((matcher = USER_PATTERN_2.matcher(path)).matches()) - { - userId = matcher.group(1); - } - if (userId != null && userId.equals(runAsUser)) - { - runAsUser = AuthenticationUtil.getSystemUserName(); - } - return runAsUser; - } - - /** - * Updates an existing document. - *

- * Update methods are user authenticated, so the modification of site config must be - * allowed for the current user. - * - * @param path document path to update - * @param content content to update the document with - */ - @Override - protected void updateDocument(final WebScriptResponse res, String store, final String path, final InputStream content) - { - final String runAsUser = getPathRunAsUser(path); - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveFilePath(encpath); - if (fileInfo == null || fileInfo.isFolder()) - { - res.setStatus(Status.STATUS_NOT_FOUND); - return null; - } - - try - { - ContentWriter writer = contentService.getWriter(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true); - writer.putContent(content); - if (logger.isDebugEnabled()) - logger.debug("updateDocument: " + fileInfo.toString()); - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - throw ae; - } - return null; - } - }, runAsUser); - } - - /** - * Deletes an existing document. - *

- * Delete methods are user authenticated, so the deletion of the document must be - * allowed for the current user. - * - * @param path document path - */ - @Override - protected void deleteDocument(final WebScriptResponse res, final String store, final String path) - { - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveFilePath(encpath); - if (fileInfo == null || fileInfo.isFolder()) - { - res.setStatus(Status.STATUS_NOT_FOUND); - return; - } - - try - { - final NodeRef fileRef = fileInfo.getNodeRef(); - this.nodeService.addAspect(fileRef, ContentModel.ASPECT_TEMPORARY, null); - - // ALF-17729 - NodeRef parentFolderRef = unprotNodeService.getPrimaryParent(fileRef).getParentRef(); - behaviourFilter.disableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); - - try - { - this.nodeService.deleteNode(fileRef); - } - finally - { - behaviourFilter.enableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); - } - - if (logger.isDebugEnabled()) - logger.debug("deleteDocument: " + fileInfo.toString()); - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - throw ae; - } - } - - /** - * Lists the document paths under a given path. - *

- * The output will be the list of relative document paths found under the path. - * Separated by newline characters. - * - * @param path document path - * @param recurse true to peform a recursive list, false for direct children only. - * - * @throws IOException if an error occurs listing the documents - */ - @Override - protected void listDocuments(final WebScriptResponse res, final String store, final String path, final boolean recurse) - throws IOException - { - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - res.setContentType("text/plain;charset=UTF-8"); - - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveNodePath(encpath, false, true); - if (fileInfo == null || !fileInfo.isFolder()) - { - res.setStatus(Status.STATUS_NOT_FOUND); - return null; - } - - try - { - outputFileNodes(res.getWriter(), fileInfo, aquireSurfConfigRef(encpath, false), "*", recurse); - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - } - finally - { - res.getWriter().close(); - } - return null; - } - }, AuthenticationUtil.getSystemUserName()); - } - - /** - * Lists the document paths matching a file pattern under a given path. - * - * The output will be the list of relative document paths found under the path that - * match the given file pattern. Separated by newline characters. - * - * @param path document path - * @param pattern file pattern to match - allows wildcards e.g. page.*.site.xml - * - * @throws IOException if an error occurs listing the documents - */ - @Override - protected void listDocuments(final WebScriptResponse res, final String store, final String path, final String pattern) - throws IOException - { - AuthenticationUtil.runAs(new RunAsWork() - { - @SuppressWarnings("synthetic-access") - public Void doWork() throws Exception - { - res.setContentType("text/plain;charset=UTF-8"); - - String filePattern; - if (pattern == null || pattern.length() == 0) - { - filePattern = "*"; - } - else - { - // need to ensure match pattern is path encoded - but don't encode * character! - StringBuilder buf = new StringBuilder(pattern.length()); - for (StringTokenizer t = new StringTokenizer(pattern, "*"); t.hasMoreTokens(); /**/) - { - buf.append(encodePath(t.nextToken())); - if (t.hasMoreTokens()) - { - buf.append('*'); - } - } - // ensure the escape character is itself escaped - filePattern = buf.toString().replace("\\", "\\\\"); - } - - // ensure we pass in the file pattern as it is used as part of the folder match - i.e. - // for a site component set e.g. /alfresco/site-data/components/page.*.site~xyz~dashboard.xml - final String encpath = encodePath(path); - final FileInfo fileInfo = resolveNodePath(encpath, filePattern, false, true); - if (fileInfo == null || !fileInfo.isFolder()) - { - res.setStatus(Status.STATUS_NOT_FOUND); - return null; - } - - if (logger.isDebugEnabled()) - logger.debug("listDocuments() pattern: " + filePattern); - - try - { - outputFileNodes( - res.getWriter(), fileInfo, - aquireSurfConfigRef(encpath + "/" + filePattern, false), - filePattern, false); - } - catch (AccessDeniedException ae) - { - res.setStatus(Status.STATUS_UNAUTHORIZED); - } - finally - { - res.getWriter().close(); - } - return null; - } - }, AuthenticationUtil.getSystemUserName()); - } - - /** - * @param path cm:name based root relative path - * example: /alfresco/site-data/pages/customise-user-dashboard.xml - * - * @return FileInfo representing the file/folder at the specified path location - * or null if the supplied path does not exist in the store - */ - private FileInfo resolveFilePath(final String path) - { - return resolveNodePath(path, false, false); - } - - /** - * @param path cm:name based root relative path - * example: /alfresco/site-data/pages/customise-user-dashboard.xml - * /alfresco/site-data/components - * @param create if true create the config and folder dirs for the given path returning - * the FileInfo for the last parent in the path, if false only attempt to - * resolve the folder path if it exists returning the last element. - * @param isFolder True if the path is for a folder, false if it ends in a filename - * - * @return FileInfo representing the file/folder at the specified path location (see create - * parameter above) or null if the supplied path does not exist in the store. - */ - private FileInfo resolveNodePath(final String path, final boolean create, final boolean isFolder) - { - return resolveNodePath(path, null, create, isFolder); - } - - /** - * @param path cm:name based root relative path - * example: /alfresco/site-data/pages/customise-user-dashboard.xml - * /alfresco/site-data/components - * @param pattern optional pattern that is used as part of the match to aquire the surf-config - * folder under the appropriate sites or user location. - * @param create if true create the config and folder dirs for the given path returning - * the FileInfo for the last parent in the path, if false only attempt to - * resolve the folder path if it exists returning the last element. - * @param isFolder True if the path is for a folder, false if it ends in a filename - * - * @return FileInfo representing the file/folder at the specified path location (see create - * parameter above) or null if the supplied path does not exist in the store. - */ - private FileInfo resolveNodePath(final String path, final String pattern, final boolean create, final boolean isFolder) - { - if (logger.isDebugEnabled()) - logger.debug("Resolving path: " + path); - - FileInfo result = null; - if (path != null) - { - // break down the path into its component elements - List pathElements = new ArrayList(4); - final StringTokenizer t = new StringTokenizer(path, "/"); - // the store requires paths of the form /alfresco/site-data/[/]/.xml - if (t.countTokens() >= 3) - { - t.nextToken(); // skip /alfresco - t.nextToken(); // skip /site-data - // collect remaining folder path (and file) - while (t.hasMoreTokens()) - { - pathElements.add(t.nextToken()); - } - - NodeRef surfConfigRef = aquireSurfConfigRef(path + (pattern != null ? ("/" + pattern) : ""), create); - try - { - if (surfConfigRef != null) - { - if (create) - { - List folders = isFolder ? pathElements : pathElements.subList(0, pathElements.size() - 1); - - List folderDetails = new ArrayList<>(pathElements.size()); - Map prop = new HashMap<>(2); - prop.put(ContentModel.PROP_IS_INDEXED, false); - prop.put(ContentModel.PROP_IS_CONTENT_INDEXED, false); - for (String element : folders) - { - Map> aspects = Collections.singletonMap(ContentModel.ASPECT_INDEX_CONTROL, prop); - folderDetails.add(new FileFolderUtil.PathElementDetails(element, aspects)); - } - // ensure folders exist down to the specified parent - // ALF-17729 / ALF-17796 - disable auditable on parent folders - result = FileFolderUtil.makeFolders( - this.fileFolderService,nodeService, - surfConfigRef, - folderDetails, - ContentModel.TYPE_FOLDER, - behaviourFilter, - new HashSet(Arrays.asList(new QName[]{ContentModel.ASPECT_AUDITABLE}))); - } - else - { - // perform the cm:name path lookup against our config root node - result = this.fileFolderService.resolveNamePath(surfConfigRef, pathElements); - } - } - } - catch (FileNotFoundException fnfErr) - { - // this is a valid condition - we return null to indicate failed lookup - } - } - } - return result; - } - - /** - * Aquire (optionally create) the NodeRef to the "surf-config" folder as appropriate - * for the given path. - *

- * Disassmbles the path to correct match either user, site or generic folder path. - * - * @param path String - * @param create boolean - * - * @return NodeRef to the "surf-config" folder, or null if it does not exist yet. - */ - private NodeRef aquireSurfConfigRef(final String path, final boolean create) - { - // remap the path into the appropriate Sites or site relative folder location - // by first matching the path to appropriate user or site regex - final boolean debug = logger.isDebugEnabled(); - String userId = null; - String siteName = null; - Matcher matcher; - if (debug) - { - // user data is stored directly under the Sites folder along with - // other generic config files - there is actually no need to match - // anything other than site specific config other than for debug - if ((matcher = USER_PATTERN_1.matcher(path)).matches()) - { - userId = matcher.group(1); - } - else if ((matcher = USER_PATTERN_2.matcher(path)).matches()) - { - userId = matcher.group(1); - } - else if ((matcher = SITE_PATTERN_1.matcher(path)).matches()) - { - siteName = matcher.group(1); - } - else if ((matcher = SITE_PATTERN_2.matcher(path)).matches()) - { - siteName = matcher.group(1); - } - } - else if ((matcher = SITE_PATTERN_1.matcher(path)).matches()) - { - siteName = matcher.group(1); - } - else if ((matcher = SITE_PATTERN_2.matcher(path)).matches()) - { - siteName = matcher.group(1); - } - - NodeRef surfConfigRef = null; - if (siteName != null) - { - if (debug) logger.debug("...resolved site path id: " + siteName); - NodeRef siteRef = getSiteNodeRef(siteName); - if (siteRef != null) - { - surfConfigRef = getSurfConfigNodeRef(siteRef, create); - } - } - else - { - if (debug) - { - if (userId != null) - { - logger.debug("...resolved user path id: " + userId); - } - else - { - logger.debug("...resolved to generic path."); - } - } - surfConfigRef = getSurfConfigNodeRef(getRootNodeRef(), create); - } - return surfConfigRef; - } - - /** - * Return the "surf-config" noderef under the given root. No attempt will be made - * to create the node if it does not exist yet. - * - * @param rootRef Root node reference where the "surf-config" folder should live - * - * @return surf-config folder ref if found, null otherwise - */ - private NodeRef getSurfConfigNodeRef(final NodeRef rootRef) - { - return getSurfConfigNodeRef(rootRef, false); - } - - /** - * Return the "surf-config" noderef under the given root. Optionally create the - * folder if it does not exist yet. NOTE: must only be set to create if within a - * WRITE transaction context. - *

- * Adds the "isIndexed = false" property to the surf-config folder node. - * - * @param rootRef Root node reference where the "surf-config" folder should live - * @param create True to create the folder if missing, false otherwise - * - * @return surf-config folder ref if found, null otherwise if not creating - */ - protected NodeRef getSurfConfigNodeRef(final NodeRef rootRef, final boolean create) - { - NodeRef surfConfigRef = this.unprotNodeService.getChildByName( - rootRef, ContentModel.ASSOC_CONTAINS, SURF_CONFIG); - if (create && surfConfigRef == null) - { - if (logger.isDebugEnabled()) - logger.debug("'surf-config' folder not found under path, creating..."); - QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, SURF_CONFIG); - Map properties = new HashMap(1, 1.0f); - properties.put(ContentModel.PROP_NAME, (Serializable) SURF_CONFIG); - ChildAssociationRef ref = this.unprotNodeService.createNode( - rootRef, ContentModel.ASSOC_CONTAINS, assocQName, ContentModel.TYPE_FOLDER, properties); - surfConfigRef = ref.getChildRef(); - // surf-config needs to be hidden - applies index control aspect as part of the hidden aspect - hiddenAspect.hideNode(ref.getChildRef(), false, false, false); - } - return surfConfigRef; - } - - /** - * @return NodeRef to the shared components config folder - */ - protected NodeRef getGlobalComponentsNodeRef() - { - NodeRef result = null; - - NodeRef surfRef = getSurfConfigNodeRef(siteService.getSiteRoot()); - if (surfRef != null) - { - result = nodeService.getChildByName(surfRef, ContentModel.ASSOC_CONTAINS, PATH_COMPONENTS); - } - - return result; - } - - /** - * @return NodeRef to the shared user config folder - */ - protected NodeRef getGlobalUserFolderNodeRef() - { - NodeRef result = null; - - NodeRef surfRef = getSurfConfigNodeRef(siteService.getSiteRoot()); - if (surfRef != null) - { - NodeRef pagesRef = nodeService.getChildByName(surfRef, ContentModel.ASSOC_CONTAINS, PATH_PAGES); - if (pagesRef != null) - { - result = nodeService.getChildByName(pagesRef, ContentModel.ASSOC_CONTAINS, PATH_USER); - } - } - - return result; - } - - /** - * Generate the search pattern for a Surf config location for a user name. - * - * @param userName to build pattern for - * @return the search pattern - */ - protected String buildUserConfigSearchPattern(String userName) - { - return USER_CONFIG_PATTERN.replace("(*)", encodePath(userName)); - } - - /** - * @return the Sites folder root node reference - */ - private NodeRef getRootNodeRef() - { - return this.siteService.getSiteRoot(); - } - - /** - * @param shortName Site shortname - * - * @return the given Site folder node reference - */ - private NodeRef getSiteNodeRef(String shortName) - { - SiteInfo siteInfo = this.siteService.getSite(shortName); - return siteInfo != null ? siteInfo.getNodeRef() : null; - } - - /** - * Output the matching file paths a node contains based on a pattern search. - * - * @param out Writer for output - relative paths separated by newline characters - * @param surfConfigRef Surf-Config folder - * @param fileInfo The FileInfo node to use as the parent - * @param pattern Optional pattern to match filenames against ("*" is match all) - * @param recurse True to recurse sub-directories - * @throws IOException - */ - private void outputFileNodes(Writer out, FileInfo fileInfo, NodeRef surfConfigRef, String pattern, boolean recurse) throws IOException - { - if (surfConfigRef != null) - { - final boolean debug = logger.isDebugEnabled(); - PagingResults files = getFileNodes(fileInfo, pattern, recurse); - - final Map nameCache = new HashMap(); - for (final FileInfo file : files.getPage()) - { - // walking up the parent tree manually until the "surf-config" parent is hit - // and manually appending the rest of the cm:name path down to the node. - final StringBuilder displayPath = new StringBuilder(64); - NodeRef ref = unprotNodeService.getPrimaryParent(file.getNodeRef()).getParentRef(); - while (!ref.equals(surfConfigRef)) - { - String name = nameCache.get(ref); - if (name == null) - { - name = (String) unprotNodeService.getProperty(ref, ContentModel.PROP_NAME); - nameCache.put(ref, name); - } - displayPath.insert(0, '/'); - displayPath.insert(0, name); - ref = unprotNodeService.getPrimaryParent(ref).getParentRef(); - } - - out.write("/alfresco/site-data/"); - out.write(URLDecoder.decode(displayPath.toString())); - out.write(URLDecoder.decode(file.getName())); - out.write('\n'); - if (debug) logger.debug(" /alfresco/site-data/" + displayPath.toString() + file.getName()); - } - } - } - - protected PagingResults getFileNodes(FileInfo fileInfo, String pattern, boolean recurse) - { - return fileFolderService.list( - fileInfo.getNodeRef(), true, false, - pattern, null, null, - new PagingRequest(CannedQueryPageDetails.DEFAULT_PAGE_SIZE)); - } -} +package org.alfresco.repo.web.scripts.bean; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.io.Writer; +import java.net.SocketException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.query.CannedQueryPageDetails; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.model.filefolder.HiddenAspect; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileFolderUtil; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.URLDecoder; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * ADM Remote Store service. + *

+ * This implementation of the RemoteStore is tied to the current SiteService implementation. + *

+ * It remaps incoming generic document path requests to the appropriate folder structure + * in the Sites folder. Dashboard pages and component bindings are remapped to take advantage + * of inherited permissions in the appropriate root site folder, ensuring that only valid + * users can write to the appropriate configuration objects. + * + * @see BaseRemoteStore for the available API methods. + * + * @author Kevin Roast + */ +public class ADMRemoteStore extends BaseRemoteStore +{ + private static final Log logger = LogFactory.getLog(ADMRemoteStore.class); + + // name of the surf config folder + private static final String SURF_CONFIG = "surf-config"; + + // patterns used to match site and user specific configuration locations + private static final String PATH_COMPONENTS = "components"; + private static final String PATH_PAGES = "pages"; + private static final String PATH_USER = "user"; + private static final String PATH_SITE = "site"; + private static final String USER_CONFIG = ".*\\." + PATH_USER + "~(.*)~.*"; + private static final String USER_CONFIG_PATTERN = USER_CONFIG.replaceAll("\\.\\*", "*").replace("\\", ""); + private static final Pattern USER_PATTERN_1 = Pattern.compile(".*/" + PATH_COMPONENTS + "/" + USER_CONFIG); + private static final Pattern USER_PATTERN_2 = Pattern.compile(".*/" + PATH_PAGES + "/" + PATH_USER + "/(.*?)(/.*)?$"); + private static final Pattern SITE_PATTERN_1 = Pattern.compile(".*/" + PATH_COMPONENTS + "/.*\\." + PATH_SITE + "~(.*)~.*"); + private static final Pattern SITE_PATTERN_2 = Pattern.compile(".*/" + PATH_PAGES + "/" + PATH_SITE + "/(.*?)(/.*)?$"); + + + // service beans + protected NodeService nodeService; + protected NodeService unprotNodeService; + protected FileFolderService fileFolderService; + protected NamespaceService namespaceService; + protected SiteService siteService; + protected ContentService contentService; + protected HiddenAspect hiddenAspect; + private BehaviourFilter behaviourFilter; + + /** + * Date format pattern used to parse HTTP date headers in RFC 1123 format. + */ + private static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; + private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); + + + /** + * @param nodeService the NodeService to set + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param nodeService the NodeService to set + */ + public void setUnprotectedNodeService(NodeService nodeService) + { + this.unprotNodeService = nodeService; + } + + /** + * @param fileFolderService the FileFolderService to set + */ + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + /** + * @param namespaceService the NamespaceService to set + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param siteService the SiteService to set + */ + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + /** + * @param contentService the ContentService to set + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + public void setHiddenAspect(HiddenAspect hiddenAspect) + { + this.hiddenAspect = hiddenAspect; + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + /** + * Gets the last modified timestamp for the document. + *

+ * The output will be the last modified date as a long toString(). + * + * @param path document path to an existing document + */ + @Override + protected void lastModified(final WebScriptResponse res, final String store, final String path) + throws IOException + { + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveFilePath(encpath); + if (fileInfo == null) + { + throw new WebScriptException("Unable to locate file: " + encpath); + } + + Writer out = res.getWriter(); + out.write(Long.toString(fileInfo.getModifiedDate().getTime())); + out.close(); + if (logger.isDebugEnabled()) + logger.debug("lastModified: " + Long.toString(fileInfo.getModifiedDate().getTime())); + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } + + /** + * Gets a document. + *

+ * The output will be the document content stream. + * + * @param path document path + */ + @Override + protected void getDocument(final WebScriptResponse res, final String store, final String path) + { + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveFilePath(encpath); + if (fileInfo == null || fileInfo.isFolder()) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return null; + } + + final ContentReader reader; + try + { + reader = contentService.getReader(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT); + if (reader == null || !reader.exists()) + { + throw new WebScriptException("No content found for file: " + encpath); + } + + // establish mimetype + String mimetype = reader.getMimetype(); + if (mimetype == null || mimetype.length() == 0) + { + mimetype = MimetypeMap.MIMETYPE_BINARY; + int extIndex = encpath.lastIndexOf('.'); + if (extIndex != -1) + { + String ext = encpath.substring(extIndex + 1); + String mt = mimetypeService.getMimetypesByExtension().get(ext); + if (mt != null) + { + mimetype = mt; + } + } + } + + // set mimetype for the content and the character encoding + length for the stream + res.setContentType(mimetype); + res.setContentEncoding(reader.getEncoding()); + SimpleDateFormat formatter = new SimpleDateFormat(PATTERN_RFC1123, Locale.US); + formatter.setTimeZone(GMT); + res.setHeader("Last-Modified", formatter.format(fileInfo.getModifiedDate())); + res.setHeader("Content-Length", Long.toString(reader.getSize())); + + if (logger.isDebugEnabled()) + logger.debug("getDocument: " + fileInfo.toString()); + + // get the content and stream directly to the response output stream + // assuming the repository is capable of streaming in chunks, this should allow large files + // to be streamed directly to the browser response stream. + try + { + reader.getContent(res.getOutputStream()); + } + catch (SocketException e1) + { + // the client cut the connection - our mission was accomplished apart from a little error message + if (logger.isDebugEnabled()) + logger.debug("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); + } + catch (ContentIOException e2) + { + if (logger.isInfoEnabled()) + logger.info("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); + } + catch (Throwable err) + { + if (err.getCause() instanceof SocketException) + { + if (logger.isDebugEnabled()) + logger.debug("Client aborted stream read:\n\tnode: " + encpath + "\n\tcontent: " + reader); + } + else + { + if (logger.isInfoEnabled()) + logger.info(err.getMessage()); + res.setStatus(Status.STATUS_INTERNAL_SERVER_ERROR); + } + } + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + } + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } + + /** + * Determines if the document exists. + * + * The output will be either the string "true" or the string "false". + * + * @param path document path + */ + @Override + protected void hasDocument(final WebScriptResponse res, final String store, final String path) throws IOException + { + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveFilePath(encpath); + + Writer out = res.getWriter(); + out.write(Boolean.toString(fileInfo != null && !fileInfo.isFolder())); + out.close(); + if (logger.isDebugEnabled()) + logger.debug("hasDocument: " + Boolean.toString(fileInfo != null && !fileInfo.isFolder())); + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } + + /** + * Creates a document. + *

+ * Create methods are user authenticated, so the creation of site config must be + * allowed for the current user. + * + * @param path document path + * @param content content of the document to write + */ + @Override + protected void createDocument(final WebScriptResponse res, final String store, final String path, final InputStream content) + { + try + { + writeDocument(path, content); + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + throw ae; + } + catch (FileExistsException feeErr) + { + res.setStatus(Status.STATUS_CONFLICT); + throw feeErr; + } + } + + /** + * Creates multiple XML documents encapsulated in a single one. + * + * @param res WebScriptResponse + * @param store String + * @param in XML document containing multiple document contents to write + */ + @Override + protected void createDocuments(WebScriptResponse res, String store, InputStream in) + { + try + { + DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document; + document = documentBuilder.parse(in); + Element docEl = document.getDocumentElement(); + Transformer transformer = ADMRemoteStore.this.transformer.get(); + for (Node n = docEl.getFirstChild(); n != null; n = n.getNextSibling()) + { + if (!(n instanceof Element)) + { + continue; + } + final String path = ((Element) n).getAttribute("path"); + + // Turn the first element child into a document + Document doc = documentBuilder.newDocument(); + Node child; + for (child = n.getFirstChild(); child != null ; child=child.getNextSibling()) + { + if (child instanceof Element) + { + doc.appendChild(doc.importNode(child, true)); + break; + } + } + ByteArrayOutputStream out = new ByteArrayOutputStream(512); + transformer.transform(new DOMSource(doc), new StreamResult(out)); + out.close(); + + writeDocument(path, new ByteArrayInputStream(out.toByteArray())); + } + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + throw ae; + } + catch (FileExistsException feeErr) + { + res.setStatus(Status.STATUS_CONFLICT); + throw feeErr; + } + catch (Exception e) + { + // various annoying checked SAX/IO exceptions related to XML processing can be thrown + // none of them should occur if the XML document is well formed + logger.error(e); + res.setStatus(Status.STATUS_INTERNAL_SERVER_ERROR); + throw new AlfrescoRuntimeException(e.getMessage(), e); + } + } + + protected void writeDocument(final String path, final InputStream content) + { + final String encpath = encodePath(path); + final int off = encpath.lastIndexOf('/'); + if (off != -1) + { + // check we actually are the user we are creating a user specific path for + final String runAsUser = getPathRunAsUser(path); + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + final FileInfo parentFolder = resolveNodePath(encpath, true, false); + if (parentFolder == null) + { + throw new IllegalStateException("Unable to aquire parent folder reference for path: " + path); + } + + // ALF-17729 / ALF-17796 - disable auditable on parent folder + NodeRef parentFolderRef = parentFolder.getNodeRef(); + behaviourFilter.disableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); + + try + { + final String name = encpath.substring(off + 1); + // existence check - convert to an UPDATE - could occur if multiple threads request + // a write to the same document - a valid possibility but rare + if (nodeService.getChildByName(parentFolderRef, ContentModel.ASSOC_CONTAINS, name) == null) + { + FileInfo fileInfo = fileFolderService.create( + parentFolderRef, name, ContentModel.TYPE_CONTENT); + Map aspectProperties = new HashMap(1, 1.0f); + aspectProperties.put(ContentModel.PROP_IS_INDEXED, false); + unprotNodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_INDEX_CONTROL, aspectProperties); + ContentWriter writer = contentService.getWriter( + fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true); + writer.guessMimetype(fileInfo.getName()); + writer.putContent(content); + if (logger.isDebugEnabled()) + logger.debug("createDocument: " + fileInfo.toString()); + } + else + { + ContentWriter writer = contentService.getWriter( + nodeService.getChildByName(parentFolderRef, ContentModel.ASSOC_CONTAINS, name), + ContentModel.PROP_CONTENT, + true); + writer.guessMimetype(name); + writer.putContent(content); + if (logger.isDebugEnabled()) + logger.debug("createDocument (updated): " + name); + } + } + finally + { + behaviourFilter.enableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); + } + + return null; + } + }, runAsUser); + } + } + + /** + * Get the RunAs user need to execute a Write operation on the given path. + * + * @param path Document path + * @return runas user - will be the Full Authenticated User or System as required + */ + protected String getPathRunAsUser(final String path) + { + // check we actually are the user we are creating a user specific path for + String runAsUser = AuthenticationUtil.getFullyAuthenticatedUser(); + String userId = null; + Matcher matcher; + if ((matcher = USER_PATTERN_1.matcher(path)).matches()) + { + userId = matcher.group(1); + } + else if ((matcher = USER_PATTERN_2.matcher(path)).matches()) + { + userId = matcher.group(1); + } + if (userId != null && userId.equals(runAsUser)) + { + runAsUser = AuthenticationUtil.getSystemUserName(); + } + return runAsUser; + } + + /** + * Updates an existing document. + *

+ * Update methods are user authenticated, so the modification of site config must be + * allowed for the current user. + * + * @param path document path to update + * @param content content to update the document with + */ + @Override + protected void updateDocument(final WebScriptResponse res, String store, final String path, final InputStream content) + { + final String runAsUser = getPathRunAsUser(path); + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveFilePath(encpath); + if (fileInfo == null || fileInfo.isFolder()) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return null; + } + + try + { + ContentWriter writer = contentService.getWriter(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true); + writer.putContent(content); + if (logger.isDebugEnabled()) + logger.debug("updateDocument: " + fileInfo.toString()); + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + throw ae; + } + return null; + } + }, runAsUser); + } + + /** + * Deletes an existing document. + *

+ * Delete methods are user authenticated, so the deletion of the document must be + * allowed for the current user. + * + * @param path document path + */ + @Override + protected void deleteDocument(final WebScriptResponse res, final String store, final String path) + { + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveFilePath(encpath); + if (fileInfo == null || fileInfo.isFolder()) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return; + } + + try + { + final NodeRef fileRef = fileInfo.getNodeRef(); + this.nodeService.addAspect(fileRef, ContentModel.ASPECT_TEMPORARY, null); + + // ALF-17729 + NodeRef parentFolderRef = unprotNodeService.getPrimaryParent(fileRef).getParentRef(); + behaviourFilter.disableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); + + try + { + this.nodeService.deleteNode(fileRef); + } + finally + { + behaviourFilter.enableBehaviour(parentFolderRef, ContentModel.ASPECT_AUDITABLE); + } + + if (logger.isDebugEnabled()) + logger.debug("deleteDocument: " + fileInfo.toString()); + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + throw ae; + } + } + + /** + * Lists the document paths under a given path. + *

+ * The output will be the list of relative document paths found under the path. + * Separated by newline characters. + * + * @param path document path + * @param recurse true to peform a recursive list, false for direct children only. + * + * @throws IOException if an error occurs listing the documents + */ + @Override + protected void listDocuments(final WebScriptResponse res, final String store, final String path, final boolean recurse) + throws IOException + { + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + res.setContentType("text/plain;charset=UTF-8"); + + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveNodePath(encpath, false, true); + if (fileInfo == null || !fileInfo.isFolder()) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return null; + } + + try + { + outputFileNodes(res.getWriter(), fileInfo, aquireSurfConfigRef(encpath, false), "*", recurse); + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + } + finally + { + res.getWriter().close(); + } + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } + + /** + * Lists the document paths matching a file pattern under a given path. + * + * The output will be the list of relative document paths found under the path that + * match the given file pattern. Separated by newline characters. + * + * @param path document path + * @param pattern file pattern to match - allows wildcards e.g. page.*.site.xml + * + * @throws IOException if an error occurs listing the documents + */ + @Override + protected void listDocuments(final WebScriptResponse res, final String store, final String path, final String pattern) + throws IOException + { + AuthenticationUtil.runAs(new RunAsWork() + { + @SuppressWarnings("synthetic-access") + public Void doWork() throws Exception + { + res.setContentType("text/plain;charset=UTF-8"); + + String filePattern; + if (pattern == null || pattern.length() == 0) + { + filePattern = "*"; + } + else + { + // need to ensure match pattern is path encoded - but don't encode * character! + StringBuilder buf = new StringBuilder(pattern.length()); + for (StringTokenizer t = new StringTokenizer(pattern, "*"); t.hasMoreTokens(); /**/) + { + buf.append(encodePath(t.nextToken())); + if (t.hasMoreTokens()) + { + buf.append('*'); + } + } + // ensure the escape character is itself escaped + filePattern = buf.toString().replace("\\", "\\\\"); + } + + // ensure we pass in the file pattern as it is used as part of the folder match - i.e. + // for a site component set e.g. /alfresco/site-data/components/page.*.site~xyz~dashboard.xml + final String encpath = encodePath(path); + final FileInfo fileInfo = resolveNodePath(encpath, filePattern, false, true); + if (fileInfo == null || !fileInfo.isFolder()) + { + res.setStatus(Status.STATUS_NOT_FOUND); + return null; + } + + if (logger.isDebugEnabled()) + logger.debug("listDocuments() pattern: " + filePattern); + + try + { + outputFileNodes( + res.getWriter(), fileInfo, + aquireSurfConfigRef(encpath + "/" + filePattern, false), + filePattern, false); + } + catch (AccessDeniedException ae) + { + res.setStatus(Status.STATUS_UNAUTHORIZED); + } + finally + { + res.getWriter().close(); + } + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } + + /** + * @param path cm:name based root relative path + * example: /alfresco/site-data/pages/customise-user-dashboard.xml + * + * @return FileInfo representing the file/folder at the specified path location + * or null if the supplied path does not exist in the store + */ + private FileInfo resolveFilePath(final String path) + { + return resolveNodePath(path, false, false); + } + + /** + * @param path cm:name based root relative path + * example: /alfresco/site-data/pages/customise-user-dashboard.xml + * /alfresco/site-data/components + * @param create if true create the config and folder dirs for the given path returning + * the FileInfo for the last parent in the path, if false only attempt to + * resolve the folder path if it exists returning the last element. + * @param isFolder True if the path is for a folder, false if it ends in a filename + * + * @return FileInfo representing the file/folder at the specified path location (see create + * parameter above) or null if the supplied path does not exist in the store. + */ + private FileInfo resolveNodePath(final String path, final boolean create, final boolean isFolder) + { + return resolveNodePath(path, null, create, isFolder); + } + + /** + * @param path cm:name based root relative path + * example: /alfresco/site-data/pages/customise-user-dashboard.xml + * /alfresco/site-data/components + * @param pattern optional pattern that is used as part of the match to aquire the surf-config + * folder under the appropriate sites or user location. + * @param create if true create the config and folder dirs for the given path returning + * the FileInfo for the last parent in the path, if false only attempt to + * resolve the folder path if it exists returning the last element. + * @param isFolder True if the path is for a folder, false if it ends in a filename + * + * @return FileInfo representing the file/folder at the specified path location (see create + * parameter above) or null if the supplied path does not exist in the store. + */ + private FileInfo resolveNodePath(final String path, final String pattern, final boolean create, final boolean isFolder) + { + if (logger.isDebugEnabled()) + logger.debug("Resolving path: " + path); + + FileInfo result = null; + if (path != null) + { + // break down the path into its component elements + List pathElements = new ArrayList(4); + final StringTokenizer t = new StringTokenizer(path, "/"); + // the store requires paths of the form /alfresco/site-data/[/]/.xml + if (t.countTokens() >= 3) + { + t.nextToken(); // skip /alfresco + t.nextToken(); // skip /site-data + // collect remaining folder path (and file) + while (t.hasMoreTokens()) + { + pathElements.add(t.nextToken()); + } + + NodeRef surfConfigRef = aquireSurfConfigRef(path + (pattern != null ? ("/" + pattern) : ""), create); + try + { + if (surfConfigRef != null) + { + if (create) + { + List folders = isFolder ? pathElements : pathElements.subList(0, pathElements.size() - 1); + + List folderDetails = new ArrayList<>(pathElements.size()); + Map prop = new HashMap<>(2); + prop.put(ContentModel.PROP_IS_INDEXED, false); + prop.put(ContentModel.PROP_IS_CONTENT_INDEXED, false); + for (String element : folders) + { + Map> aspects = Collections.singletonMap(ContentModel.ASPECT_INDEX_CONTROL, prop); + folderDetails.add(new FileFolderUtil.PathElementDetails(element, aspects)); + } + // ensure folders exist down to the specified parent + // ALF-17729 / ALF-17796 - disable auditable on parent folders + result = FileFolderUtil.makeFolders( + this.fileFolderService,nodeService, + surfConfigRef, + folderDetails, + ContentModel.TYPE_FOLDER, + behaviourFilter, + new HashSet(Arrays.asList(new QName[]{ContentModel.ASPECT_AUDITABLE}))); + } + else + { + // perform the cm:name path lookup against our config root node + result = this.fileFolderService.resolveNamePath(surfConfigRef, pathElements); + } + } + } + catch (FileNotFoundException fnfErr) + { + // this is a valid condition - we return null to indicate failed lookup + } + } + } + return result; + } + + /** + * Aquire (optionally create) the NodeRef to the "surf-config" folder as appropriate + * for the given path. + *

+ * Disassmbles the path to correct match either user, site or generic folder path. + * + * @param path String + * @param create boolean + * + * @return NodeRef to the "surf-config" folder, or null if it does not exist yet. + */ + private NodeRef aquireSurfConfigRef(final String path, final boolean create) + { + // remap the path into the appropriate Sites or site relative folder location + // by first matching the path to appropriate user or site regex + final boolean debug = logger.isDebugEnabled(); + String userId = null; + String siteName = null; + Matcher matcher; + if (debug) + { + // user data is stored directly under the Sites folder along with + // other generic config files - there is actually no need to match + // anything other than site specific config other than for debug + if ((matcher = USER_PATTERN_1.matcher(path)).matches()) + { + userId = matcher.group(1); + } + else if ((matcher = USER_PATTERN_2.matcher(path)).matches()) + { + userId = matcher.group(1); + } + else if ((matcher = SITE_PATTERN_1.matcher(path)).matches()) + { + siteName = matcher.group(1); + } + else if ((matcher = SITE_PATTERN_2.matcher(path)).matches()) + { + siteName = matcher.group(1); + } + } + else if ((matcher = SITE_PATTERN_1.matcher(path)).matches()) + { + siteName = matcher.group(1); + } + else if ((matcher = SITE_PATTERN_2.matcher(path)).matches()) + { + siteName = matcher.group(1); + } + + NodeRef surfConfigRef = null; + if (siteName != null) + { + if (debug) logger.debug("...resolved site path id: " + siteName); + NodeRef siteRef = getSiteNodeRef(siteName); + if (siteRef != null) + { + surfConfigRef = getSurfConfigNodeRef(siteRef, create); + } + } + else + { + if (debug) + { + if (userId != null) + { + logger.debug("...resolved user path id: " + userId); + } + else + { + logger.debug("...resolved to generic path."); + } + } + surfConfigRef = getSurfConfigNodeRef(getRootNodeRef(), create); + } + return surfConfigRef; + } + + /** + * Return the "surf-config" noderef under the given root. No attempt will be made + * to create the node if it does not exist yet. + * + * @param rootRef Root node reference where the "surf-config" folder should live + * + * @return surf-config folder ref if found, null otherwise + */ + private NodeRef getSurfConfigNodeRef(final NodeRef rootRef) + { + return getSurfConfigNodeRef(rootRef, false); + } + + /** + * Return the "surf-config" noderef under the given root. Optionally create the + * folder if it does not exist yet. NOTE: must only be set to create if within a + * WRITE transaction context. + *

+ * Adds the "isIndexed = false" property to the surf-config folder node. + * + * @param rootRef Root node reference where the "surf-config" folder should live + * @param create True to create the folder if missing, false otherwise + * + * @return surf-config folder ref if found, null otherwise if not creating + */ + protected NodeRef getSurfConfigNodeRef(final NodeRef rootRef, final boolean create) + { + NodeRef surfConfigRef = this.unprotNodeService.getChildByName( + rootRef, ContentModel.ASSOC_CONTAINS, SURF_CONFIG); + if (create && surfConfigRef == null) + { + if (logger.isDebugEnabled()) + logger.debug("'surf-config' folder not found under path, creating..."); + QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, SURF_CONFIG); + Map properties = new HashMap(1, 1.0f); + properties.put(ContentModel.PROP_NAME, (Serializable) SURF_CONFIG); + ChildAssociationRef ref = this.unprotNodeService.createNode( + rootRef, ContentModel.ASSOC_CONTAINS, assocQName, ContentModel.TYPE_FOLDER, properties); + surfConfigRef = ref.getChildRef(); + // surf-config needs to be hidden - applies index control aspect as part of the hidden aspect + hiddenAspect.hideNode(ref.getChildRef(), false, false, false); + } + return surfConfigRef; + } + + /** + * @return NodeRef to the shared components config folder + */ + protected NodeRef getGlobalComponentsNodeRef() + { + NodeRef result = null; + + NodeRef surfRef = getSurfConfigNodeRef(siteService.getSiteRoot()); + if (surfRef != null) + { + result = nodeService.getChildByName(surfRef, ContentModel.ASSOC_CONTAINS, PATH_COMPONENTS); + } + + return result; + } + + /** + * @return NodeRef to the shared user config folder + */ + protected NodeRef getGlobalUserFolderNodeRef() + { + NodeRef result = null; + + NodeRef surfRef = getSurfConfigNodeRef(siteService.getSiteRoot()); + if (surfRef != null) + { + NodeRef pagesRef = nodeService.getChildByName(surfRef, ContentModel.ASSOC_CONTAINS, PATH_PAGES); + if (pagesRef != null) + { + result = nodeService.getChildByName(pagesRef, ContentModel.ASSOC_CONTAINS, PATH_USER); + } + } + + return result; + } + + /** + * Generate the search pattern for a Surf config location for a user name. + * + * @param userName to build pattern for + * @return the search pattern + */ + protected String buildUserConfigSearchPattern(String userName) + { + return USER_CONFIG_PATTERN.replace("(*)", encodePath(userName)); + } + + /** + * @return the Sites folder root node reference + */ + private NodeRef getRootNodeRef() + { + return this.siteService.getSiteRoot(); + } + + /** + * @param shortName Site shortname + * + * @return the given Site folder node reference + */ + private NodeRef getSiteNodeRef(String shortName) + { + SiteInfo siteInfo = this.siteService.getSite(shortName); + return siteInfo != null ? siteInfo.getNodeRef() : null; + } + + /** + * Output the matching file paths a node contains based on a pattern search. + * + * @param out Writer for output - relative paths separated by newline characters + * @param surfConfigRef Surf-Config folder + * @param fileInfo The FileInfo node to use as the parent + * @param pattern Optional pattern to match filenames against ("*" is match all) + * @param recurse True to recurse sub-directories + * @throws IOException + */ + private void outputFileNodes(Writer out, FileInfo fileInfo, NodeRef surfConfigRef, String pattern, boolean recurse) throws IOException + { + if (surfConfigRef != null) + { + final boolean debug = logger.isDebugEnabled(); + PagingResults files = getFileNodes(fileInfo, pattern, recurse); + + final Map nameCache = new HashMap(); + for (final FileInfo file : files.getPage()) + { + // walking up the parent tree manually until the "surf-config" parent is hit + // and manually appending the rest of the cm:name path down to the node. + final StringBuilder displayPath = new StringBuilder(64); + NodeRef ref = unprotNodeService.getPrimaryParent(file.getNodeRef()).getParentRef(); + while (!ref.equals(surfConfigRef)) + { + String name = nameCache.get(ref); + if (name == null) + { + name = (String) unprotNodeService.getProperty(ref, ContentModel.PROP_NAME); + nameCache.put(ref, name); + } + displayPath.insert(0, '/'); + displayPath.insert(0, name); + ref = unprotNodeService.getPrimaryParent(ref).getParentRef(); + } + + out.write("/alfresco/site-data/"); + out.write(URLDecoder.decode(displayPath.toString())); + out.write(URLDecoder.decode(file.getName())); + out.write('\n'); + if (debug) logger.debug(" /alfresco/site-data/" + displayPath.toString() + file.getName()); + } + } + } + + protected PagingResults getFileNodes(FileInfo fileInfo, String pattern, boolean recurse) + { + return fileFolderService.list( + fileInfo.getNodeRef(), true, false, + pattern, null, null, + new PagingRequest(CannedQueryPageDetails.DEFAULT_PAGE_SIZE)); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/bean/AbstractLoginBean.java b/source/java/org/alfresco/repo/web/scripts/bean/AbstractLoginBean.java index 01ac636b94..eac6f8e5c6 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/AbstractLoginBean.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/AbstractLoginBean.java @@ -1,91 +1,91 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.events.types.Event; -import org.alfresco.events.types.RepositoryEventImpl; -import org.alfresco.repo.events.EventPreparator; -import org.alfresco.repo.events.EventPublisher; -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - - -/** - * Common code between Get based login and POST based login - */ -/* package scope */ abstract class AbstractLoginBean extends DeclarativeWebScript -{ - // dependencies - private AuthenticationService authenticationService; - protected EventPublisher eventPublisher; - - /** - * @param authenticationService AuthenticationService - */ - public void setAuthenticationService(AuthenticationService authenticationService) - { - this.authenticationService = authenticationService; - } - - /** - * @param eventPublisher EventPublisher - */ - public void setEventPublisher(EventPublisher eventPublisher) - { - this.eventPublisher = eventPublisher; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - return null; - } - - protected Map login(final String username, String password) - { - try - { - // get ticket - authenticationService.authenticate(username, password.toCharArray()); - - eventPublisher.publishEvent(new EventPreparator(){ - @Override - public Event prepareEvent(String user, String networkId, String transactionId) - { - // TODO need to fix up to pass correct seqNo and alfrescoClientId - return new RepositoryEventImpl(-1l, "login", transactionId, networkId, new Date().getTime(), - username, null); - } - }); - - // add ticket to model for javascript and template access - Map model = new HashMap(7, 1.0f); - model.put("username", username); - model.put("ticket", authenticationService.getCurrentTicket()); - - return model; - } - catch(AuthenticationException e) - { - throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Login failed"); - } - finally - { - AuthenticationUtil.clearCurrentSecurityContext(); - } - } - - +package org.alfresco.repo.web.scripts.bean; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.events.types.Event; +import org.alfresco.events.types.RepositoryEventImpl; +import org.alfresco.repo.events.EventPreparator; +import org.alfresco.repo.events.EventPublisher; +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + + +/** + * Common code between Get based login and POST based login + */ +/* package scope */ abstract class AbstractLoginBean extends DeclarativeWebScript +{ + // dependencies + private AuthenticationService authenticationService; + protected EventPublisher eventPublisher; + + /** + * @param authenticationService AuthenticationService + */ + public void setAuthenticationService(AuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + /** + * @param eventPublisher EventPublisher + */ + public void setEventPublisher(EventPublisher eventPublisher) + { + this.eventPublisher = eventPublisher; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + return null; + } + + protected Map login(final String username, String password) + { + try + { + // get ticket + authenticationService.authenticate(username, password.toCharArray()); + + eventPublisher.publishEvent(new EventPreparator(){ + @Override + public Event prepareEvent(String user, String networkId, String transactionId) + { + // TODO need to fix up to pass correct seqNo and alfrescoClientId + return new RepositoryEventImpl(-1l, "login", transactionId, networkId, new Date().getTime(), + username, null); + } + }); + + // add ticket to model for javascript and template access + Map model = new HashMap(7, 1.0f); + model.put("username", username); + model.put("ticket", authenticationService.getCurrentTicket()); + + return model; + } + catch(AuthenticationException e) + { + throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Login failed"); + } + finally + { + AuthenticationUtil.clearCurrentSecurityContext(); + } + } + + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/Authentication.java b/source/java/org/alfresco/repo/web/scripts/bean/Authentication.java index 7737ac5fe5..dfa63f4d85 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/Authentication.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/Authentication.java @@ -1,39 +1,39 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * WebScript java backed bean implementation - to return information about the - * authentication system, such as account mutability. - * - * @author Kevin Roast - */ -public class Authentication extends DeclarativeWebScript -{ - private MutableAuthenticationService authenticationService; - - public void setAuthenticationService(AuthenticationService authenticationService) - { - this.authenticationService = (MutableAuthenticationService)authenticationService; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - Map model = new HashMap(2); - - model.put("creationAllowed", this.authenticationService.isAuthenticationCreationAllowed()); - - return model; - } +package org.alfresco.repo.web.scripts.bean; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * WebScript java backed bean implementation - to return information about the + * authentication system, such as account mutability. + * + * @author Kevin Roast + */ +public class Authentication extends DeclarativeWebScript +{ + private MutableAuthenticationService authenticationService; + + public void setAuthenticationService(AuthenticationService authenticationService) + { + this.authenticationService = (MutableAuthenticationService)authenticationService; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + Map model = new HashMap(2); + + model.put("creationAllowed", this.authenticationService.isAuthenticationCreationAllowed()); + + return model; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java b/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java index 9228bb13a7..109c35eaaf 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/BaseRemoteStore.java @@ -1,541 +1,541 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import javax.servlet.http.HttpServletRequest; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerFactory; - -import org.alfresco.service.cmr.repository.MimetypeService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.WrappingWebScriptRequest; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; - -/** - * Remote Store service. - *

- * Responsible for providing remote HTTP based access to a store. Designed to be accessed - * from a web-tier application to remotely mirror a WebScript Store instance. - *

- * Request format: - *

- *      //[?]
- *      //s//[?]
- *      //s//w//[?]
- * 

- * Example: - *

- *      /service/remotestore/lastmodified/sites/xyz/pages/page.xml
- * 

- * where: - *

- *      /service/remotestore -> service path
- *      /lastmodified        -> method name
- *      /sites/../page.xml   -> document path
- * 

- * optional request parameters: - *

- *      s                    -> the store id
- * 

- * Note: path is relative to the root path as configured for this webscript bean - *

- * Further URL arguments may be provided if required by specific API methods. - *

- * For content create and update the request should be POSTed and the content sent as the - * payload of the request content. - *

- * Supported API methods: - *

- *      GET lastmodified -> return timestamp of a document in ms since 1970 as a long string value
- *      GET has -> return true or false string as existence for a document
- *      GET get -> return raw document content - in addition the appropriate HTTP headers for the
- *                 character encoding, content type, length and modified date will be set
- *      GET list -> return the list of available document paths under a path - UTF-8 response text
- *      GET listall -> return the list of available document paths (recursively) under a given path
- *                     - UTF-8 response text
- *      GET listpattern -> return the list of document paths matching a file pattern under a given path
- *                         - UTF-8 response text
- *      POST create -> create a new document with request content payload
- *      POST createmulti -> create multiple new documents with request content payload
- *      POST update -> update an existing document with request content payload
- *      DELETE delete -> delete an existing document 
- * 
- * @author Kevin Roast - */ -public abstract class BaseRemoteStore extends AbstractWebScript -{ - public static final String TOKEN_STORE = "s"; - - public static final String REQUEST_PARAM_STORE = "s"; - - private static final Log logger = LogFactory.getLog(BaseRemoteStore.class); - - protected String defaultStore; - protected MimetypeService mimetypeService; - - protected static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); - protected static ThreadLocal transformer = new ThreadLocal() - { - @Override - protected Transformer initialValue() - { - try - { - return TRANSFORMER_FACTORY.newTransformer(); - } - catch (TransformerConfigurationException e) - { - throw new RuntimeException(e); - } - } - }; - - - /** - * @param defaultStore the default store name of the store to process document requests against - */ - public void setStore(String defaultStore) - { - this.defaultStore = defaultStore; - } - - /** - * @param mimetypeService the MimetypeService to set - */ - public void setMimetypeService(MimetypeService mimetypeService) - { - this.mimetypeService = mimetypeService; - } - - /** - * Execute the webscript based on the request parameters - */ - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - // NOTE: This web script must be executed in a HTTP Servlet environment - - // Unwrap to a WebScriptServletRequest if we have one - WebScriptServletRequest webScriptServletRequest = null; - WebScriptRequest current = req; - do - { - if (current instanceof WebScriptServletRequest) - { - webScriptServletRequest = (WebScriptServletRequest) current; - current = null; - } - else if (current instanceof WrappingWebScriptRequest) - { - current = ((WrappingWebScriptRequest) req).getNext(); - } - else - { - current = null; - } - } - while (current != null); - - if (webScriptServletRequest == null) - { - throw new WebScriptException("Remote Store access must be executed in HTTP Servlet environment"); - } - - HttpServletRequest httpReq = webScriptServletRequest.getHttpServletRequest(); - - // the request path for the remote store - String extPath = req.getExtensionPath(); - - // values that we need to determine - String methodName = null; - String store = null; - StringBuilder pathBuilder = new StringBuilder(128); - - // tokenize the path and figure out tokenized values - StringTokenizer tokenizer = new StringTokenizer(extPath, "/"); - if (tokenizer.hasMoreTokens()) - { - methodName = tokenizer.nextToken(); - - if (tokenizer.hasMoreTokens()) - { - String el = tokenizer.nextToken(); - - if (TOKEN_STORE.equals(el)) - { - // if the token is TOKEN_STORE, then the next token is the id of the store - store = tokenizer.nextToken(); - - // reset element - el = (tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null); - } - - while (el != null) - { - pathBuilder.append('/'); - pathBuilder.append(el); - - el = (tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null); - } - } - } - else - { - throw new WebScriptException("Unable to tokenize web path: " + extPath); - } - - // if we don't have a store, check whether it came in on a request parameter - if (store == null) - { - store = req.getParameter(REQUEST_PARAM_STORE); - if (store == null) - { - store = this.defaultStore; - } - if (store == null) - { - // not good, we should have a store by this point - // this means that a store was not passed in and that we also didn't have a configured store - throw new WebScriptException("Unable to determine which store to operate against." + - " A store was not specified and a default was not provided."); - } - } - - String path = pathBuilder.toString(); - - long start = 0; - if (logger.isDebugEnabled()) - { - logger.debug("Remote method: " + methodName.toUpperCase() + " Store Id: " + store + " Path: " + path); - start = System.nanoTime(); - } - - try - { - // generate enum from string method name - so we can use a fast switch table lookup - APIMethod method = APIMethod.valueOf(methodName.toUpperCase()); - switch (method) - { - case LASTMODIFIED: - validatePath(path); - lastModified(res, store, path); - break; - - case HAS: - validatePath(path); - hasDocument(res, store, path); - break; - - case GET: - validatePath(path); - getDocument(res, store, path); - break; - - case LIST: - listDocuments(res, store, path, false); - break; - - case LISTALL: - listDocuments(res, store, path, true); - break; - - case LISTPATTERN: - listDocuments(res, store, path, req.getParameter("m")); - break; - - case CREATE: - validatePath(path); - if (logger.isDebugEnabled()) - logger.debug("CREATE: content length=" + httpReq.getContentLength()); - createDocument(res, store, path, httpReq.getInputStream()); - break; - - case CREATEMULTI: - if (logger.isDebugEnabled()) - logger.debug("CREATEMULTI: content length=" + httpReq.getContentLength()); - createDocuments(res, store, httpReq.getInputStream()); - break; - - case UPDATE: - validatePath(path); - if (logger.isDebugEnabled()) - logger.debug("UPDATE: content length=" + httpReq.getContentLength()); - updateDocument(res, store, path, httpReq.getInputStream()); - break; - - case DELETE: - validatePath(path); - deleteDocument(res, store, path); - break; - } - } - catch (IllegalArgumentException enumErr) - { - throw new WebScriptException("Unknown method specified to remote store API: " + methodName); - } - catch (IOException ioErr) - { - throw new WebScriptException("Error during remote store API: " + ioErr.getMessage()); - } - - if (logger.isDebugEnabled()) - { - long end = System.nanoTime(); - logger.debug("Time to execute method: " + (end - start)/1000000f + "ms"); - } - } - - /** - * Validate we have a path argument. - */ - private static void validatePath(String path) - { - if (path == null) - { - throw new WebScriptException("Remote Store expecting document path elements."); - } - } - - /** - * Helper to break down webscript extension path into path component elements - */ - protected List getPathParts(String[] extPaths) - { - List pathParts = new ArrayList(extPaths.length - 1); - for (int i=1; i> 6)]); - sb.append(hex[0x80 | (ch & 0x3F)]); - } - else // 0x7FF < ch <= 0xFFFF - { - if (sb == null) - { - final String soFar = s.substring(0, i); - sb = new StringBuilder(len + 16); - sb.append(soFar); - } - sb.append(hex[0xe0 | (ch >> 12)]); - sb.append(hex[0x80 | ((ch >> 6) & 0x3F)]); - sb.append(hex[0x80 | (ch & 0x3F)]); - } - } - return (sb != null ? sb.toString() : s); - } - - private final static String[] hex = { - "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", - "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", - "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", - "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", - "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", - "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f", - "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", - "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", - "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", - "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f", - "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", - "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", - "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", - "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f", - "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", - "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f", - "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", - "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", - "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", - "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", - "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", - "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af", - "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", - "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf", - "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", - "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf", - "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", - "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df", - "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", - "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef", - "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", - "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" - }; -} +package org.alfresco.repo.web.scripts.bean; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletRequest; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; + +import org.alfresco.service.cmr.repository.MimetypeService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.WrappingWebScriptRequest; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; + +/** + * Remote Store service. + *

+ * Responsible for providing remote HTTP based access to a store. Designed to be accessed + * from a web-tier application to remotely mirror a WebScript Store instance. + *

+ * Request format: + *

+ *      //[?]
+ *      //s//[?]
+ *      //s//w//[?]
+ * 

+ * Example: + *

+ *      /service/remotestore/lastmodified/sites/xyz/pages/page.xml
+ * 

+ * where: + *

+ *      /service/remotestore -> service path
+ *      /lastmodified        -> method name
+ *      /sites/../page.xml   -> document path
+ * 

+ * optional request parameters: + *

+ *      s                    -> the store id
+ * 

+ * Note: path is relative to the root path as configured for this webscript bean + *

+ * Further URL arguments may be provided if required by specific API methods. + *

+ * For content create and update the request should be POSTed and the content sent as the + * payload of the request content. + *

+ * Supported API methods: + *

+ *      GET lastmodified -> return timestamp of a document in ms since 1970 as a long string value
+ *      GET has -> return true or false string as existence for a document
+ *      GET get -> return raw document content - in addition the appropriate HTTP headers for the
+ *                 character encoding, content type, length and modified date will be set
+ *      GET list -> return the list of available document paths under a path - UTF-8 response text
+ *      GET listall -> return the list of available document paths (recursively) under a given path
+ *                     - UTF-8 response text
+ *      GET listpattern -> return the list of document paths matching a file pattern under a given path
+ *                         - UTF-8 response text
+ *      POST create -> create a new document with request content payload
+ *      POST createmulti -> create multiple new documents with request content payload
+ *      POST update -> update an existing document with request content payload
+ *      DELETE delete -> delete an existing document 
+ * 
+ * @author Kevin Roast + */ +public abstract class BaseRemoteStore extends AbstractWebScript +{ + public static final String TOKEN_STORE = "s"; + + public static final String REQUEST_PARAM_STORE = "s"; + + private static final Log logger = LogFactory.getLog(BaseRemoteStore.class); + + protected String defaultStore; + protected MimetypeService mimetypeService; + + protected static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); + protected static ThreadLocal transformer = new ThreadLocal() + { + @Override + protected Transformer initialValue() + { + try + { + return TRANSFORMER_FACTORY.newTransformer(); + } + catch (TransformerConfigurationException e) + { + throw new RuntimeException(e); + } + } + }; + + + /** + * @param defaultStore the default store name of the store to process document requests against + */ + public void setStore(String defaultStore) + { + this.defaultStore = defaultStore; + } + + /** + * @param mimetypeService the MimetypeService to set + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + /** + * Execute the webscript based on the request parameters + */ + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + // NOTE: This web script must be executed in a HTTP Servlet environment + + // Unwrap to a WebScriptServletRequest if we have one + WebScriptServletRequest webScriptServletRequest = null; + WebScriptRequest current = req; + do + { + if (current instanceof WebScriptServletRequest) + { + webScriptServletRequest = (WebScriptServletRequest) current; + current = null; + } + else if (current instanceof WrappingWebScriptRequest) + { + current = ((WrappingWebScriptRequest) req).getNext(); + } + else + { + current = null; + } + } + while (current != null); + + if (webScriptServletRequest == null) + { + throw new WebScriptException("Remote Store access must be executed in HTTP Servlet environment"); + } + + HttpServletRequest httpReq = webScriptServletRequest.getHttpServletRequest(); + + // the request path for the remote store + String extPath = req.getExtensionPath(); + + // values that we need to determine + String methodName = null; + String store = null; + StringBuilder pathBuilder = new StringBuilder(128); + + // tokenize the path and figure out tokenized values + StringTokenizer tokenizer = new StringTokenizer(extPath, "/"); + if (tokenizer.hasMoreTokens()) + { + methodName = tokenizer.nextToken(); + + if (tokenizer.hasMoreTokens()) + { + String el = tokenizer.nextToken(); + + if (TOKEN_STORE.equals(el)) + { + // if the token is TOKEN_STORE, then the next token is the id of the store + store = tokenizer.nextToken(); + + // reset element + el = (tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null); + } + + while (el != null) + { + pathBuilder.append('/'); + pathBuilder.append(el); + + el = (tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null); + } + } + } + else + { + throw new WebScriptException("Unable to tokenize web path: " + extPath); + } + + // if we don't have a store, check whether it came in on a request parameter + if (store == null) + { + store = req.getParameter(REQUEST_PARAM_STORE); + if (store == null) + { + store = this.defaultStore; + } + if (store == null) + { + // not good, we should have a store by this point + // this means that a store was not passed in and that we also didn't have a configured store + throw new WebScriptException("Unable to determine which store to operate against." + + " A store was not specified and a default was not provided."); + } + } + + String path = pathBuilder.toString(); + + long start = 0; + if (logger.isDebugEnabled()) + { + logger.debug("Remote method: " + methodName.toUpperCase() + " Store Id: " + store + " Path: " + path); + start = System.nanoTime(); + } + + try + { + // generate enum from string method name - so we can use a fast switch table lookup + APIMethod method = APIMethod.valueOf(methodName.toUpperCase()); + switch (method) + { + case LASTMODIFIED: + validatePath(path); + lastModified(res, store, path); + break; + + case HAS: + validatePath(path); + hasDocument(res, store, path); + break; + + case GET: + validatePath(path); + getDocument(res, store, path); + break; + + case LIST: + listDocuments(res, store, path, false); + break; + + case LISTALL: + listDocuments(res, store, path, true); + break; + + case LISTPATTERN: + listDocuments(res, store, path, req.getParameter("m")); + break; + + case CREATE: + validatePath(path); + if (logger.isDebugEnabled()) + logger.debug("CREATE: content length=" + httpReq.getContentLength()); + createDocument(res, store, path, httpReq.getInputStream()); + break; + + case CREATEMULTI: + if (logger.isDebugEnabled()) + logger.debug("CREATEMULTI: content length=" + httpReq.getContentLength()); + createDocuments(res, store, httpReq.getInputStream()); + break; + + case UPDATE: + validatePath(path); + if (logger.isDebugEnabled()) + logger.debug("UPDATE: content length=" + httpReq.getContentLength()); + updateDocument(res, store, path, httpReq.getInputStream()); + break; + + case DELETE: + validatePath(path); + deleteDocument(res, store, path); + break; + } + } + catch (IllegalArgumentException enumErr) + { + throw new WebScriptException("Unknown method specified to remote store API: " + methodName); + } + catch (IOException ioErr) + { + throw new WebScriptException("Error during remote store API: " + ioErr.getMessage()); + } + + if (logger.isDebugEnabled()) + { + long end = System.nanoTime(); + logger.debug("Time to execute method: " + (end - start)/1000000f + "ms"); + } + } + + /** + * Validate we have a path argument. + */ + private static void validatePath(String path) + { + if (path == null) + { + throw new WebScriptException("Remote Store expecting document path elements."); + } + } + + /** + * Helper to break down webscript extension path into path component elements + */ + protected List getPathParts(String[] extPaths) + { + List pathParts = new ArrayList(extPaths.length - 1); + for (int i=1; i> 6)]); + sb.append(hex[0x80 | (ch & 0x3F)]); + } + else // 0x7FF < ch <= 0xFFFF + { + if (sb == null) + { + final String soFar = s.substring(0, i); + sb = new StringBuilder(len + 16); + sb.append(soFar); + } + sb.append(hex[0xe0 | (ch >> 12)]); + sb.append(hex[0x80 | ((ch >> 6) & 0x3F)]); + sb.append(hex[0x80 | (ch & 0x3F)]); + } + } + return (sb != null ? sb.toString() : s); + } + + private final static String[] hex = { + "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", + "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", + "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", + "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", + "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", + "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f", + "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", + "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", + "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", + "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f", + "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", + "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", + "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", + "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f", + "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", + "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f", + "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", + "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", + "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", + "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", + "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", + "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af", + "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", + "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf", + "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", + "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf", + "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", + "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df", + "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", + "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef", + "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", + "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" + }; +} diff --git a/source/java/org/alfresco/repo/web/scripts/bean/KeywordSearch.java b/source/java/org/alfresco/repo/web/scripts/bean/KeywordSearch.java index 46ab7611ee..412ceb5f11 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/KeywordSearch.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/KeywordSearch.java @@ -1,389 +1,389 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.StringWriter; -import java.io.Writer; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import org.alfresco.repo.template.TemplateNode; -import org.alfresco.repo.web.scripts.RepositoryImageResolver; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.util.GUID; -import org.alfresco.util.SearchLanguageConversion; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.surf.util.I18NUtil; -import org.springframework.extensions.surf.util.ParameterCheck; -import org.springframework.extensions.surf.util.URLEncoder; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - - -/** - * Alfresco Keyword (simple) Search Service - * - * @author davidc - */ -public class KeywordSearch extends DeclarativeWebScript -{ - // Logger - private static final Log logger = LogFactory.getLog(KeywordSearch.class); - - // search parameters - // TODO: allow configuration of search store - protected static final StoreRef SEARCH_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); - protected static final int DEFAULT_ITEMS_PER_PAGE = 10; - protected static final String QUERY_FORMAT = "query_"; - - // dependencies - protected ServiceRegistry serviceRegistry; - protected RepositoryImageResolver imageResolver; - protected SearchService searchService; - protected NodeService nodeService; - - public void setSearchService(SearchService searchService) - { - this.searchService = searchService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setRepositoryImageResolver(RepositoryImageResolver imageResolver) - { - this.imageResolver = imageResolver; - } - - public void setServiceRegistry(ServiceRegistry serviceRegistry) - { - this.serviceRegistry = serviceRegistry; - } - - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - // - // process arguments - // - - String searchTerms = req.getParameter("q"); - ParameterCheck.mandatoryString("q", searchTerms); - String startPageArg = req.getParameter("p"); - int startPage = 1; - try - { - startPage = new Integer(startPageArg); - } - catch(NumberFormatException e) - { - // NOTE: use default startPage - } - String itemsPerPageArg = req.getParameter("c"); - int itemsPerPage = DEFAULT_ITEMS_PER_PAGE; - try - { - itemsPerPage = new Integer(itemsPerPageArg); - } - catch(NumberFormatException e) - { - // NOTE: use default itemsPerPage - } - Locale locale = I18NUtil.getLocale(); - String language = req.getParameter("l"); - if (language != null && language.length() > 0) - { - // NOTE: Simple conversion from XML Language Id to Java Locale Id - locale = new Locale(language.replace("-", "_")); - } - - // - // execute the search - // - - SearchResult results = search(searchTerms, startPage, itemsPerPage, locale, req); - - // - // create model - // - - Map model = new HashMap(7, 1.0f); - model.put("search", results); - return model; - } - - /** - * Execute the search - */ - private SearchResult search(String searchTerms, int startPage, int itemsPerPage, Locale locale, WebScriptRequest req) - { - SearchResult searchResult = null; - ResultSet results = null; - - try - { - // construct search statement - String[] terms = searchTerms.split(" "); - searchTerms = searchTerms.replaceAll("\"", """); - - // Escape special characters in the terms, so that they can't confuse the parser - for (int i=0; i statementModel = new HashMap(7, 1.0f); - statementModel.put("args", createArgs(req)); - statementModel.put("terms", terms); - Writer queryWriter = new StringWriter(1024); - renderFormatTemplate(QUERY_FORMAT, statementModel, queryWriter); - String query = queryWriter.toString(); - - // execute query - if (logger.isDebugEnabled()) - { - logger.debug("Search parameters: searchTerms=" + searchTerms + ", startPage=" + startPage + ", itemsPerPage=" + itemsPerPage + ", search locale=" + locale.toString()); - logger.debug("Issuing lucene search: " + query); - } - - SearchParameters parameters = new SearchParameters(); - parameters.addStore(SEARCH_STORE); - parameters.setLanguage(SearchService.LANGUAGE_LUCENE); - parameters.setQuery(query); - if (locale != null) - { - parameters.addLocale(locale); - } - results = searchService.query(parameters); - int totalResults = results.length(); - - if (logger.isDebugEnabled()) - logger.debug("Results: " + totalResults + " rows (limited: " + results.getResultSetMetaData().getLimitedBy() + ")"); - - // are we out-of-range - int totalPages = (totalResults / itemsPerPage); - totalPages += (totalResults % itemsPerPage != 0) ? 1 : 0; - if (totalPages != 0 && (startPage < 1 || startPage > totalPages)) - { - throw new WebScriptException("Start page " + startPage + " is outside boundary of " + totalPages + " pages"); - } - - // construct search result - searchResult = new SearchResult(); - searchResult.setSearchTerms(searchTerms); - searchResult.setLocale(locale); - searchResult.setItemsPerPage(itemsPerPage); - searchResult.setStartPage(startPage); - searchResult.setTotalResults(totalResults); - if (totalResults == 0) - { - searchResult.setTotalPages(0); - searchResult.setStartIndex(0); - searchResult.setTotalPageItems(0); - } - else - { - searchResult.setTotalPages(totalPages); - searchResult.setStartIndex(((startPage -1) * itemsPerPage) + 1); - searchResult.setTotalPageItems(Math.min(itemsPerPage, totalResults - searchResult.getStartIndex() + 1)); - } - SearchTemplateNode[] nodes = new SearchTemplateNode[searchResult.getTotalPageItems()]; - for (int i = 0; i < searchResult.getTotalPageItems(); i++) - { - NodeRef node = results.getNodeRef(i + searchResult.getStartIndex() - 1); - // Make the search resilient to invalid nodes - if (!nodeService.exists(node)) - { - continue; - } - float score = results.getScore(i + searchResult.getStartIndex() - 1); - nodes[i] = new SearchTemplateNode(node, score); - } - searchResult.setResults(nodes); - return searchResult; - } - finally - { - if (results != null) - { - results.close(); - } - } - } - - /** - * Search Result - * - * @author davidc - */ - public static class SearchResult - { - private String id; - private String searchTerms; - private Locale locale; - private int itemsPerPage; - private int totalPages; - private int totalResults; - private int totalPageItems; - private int startPage; - private int startIndex; - private SearchTemplateNode[] results; - - - public int getItemsPerPage() - { - return itemsPerPage; - } - - /*package*/ void setItemsPerPage(int itemsPerPage) - { - this.itemsPerPage = itemsPerPage; - } - - public TemplateNode[] getResults() - { - return results; - } - - /*package*/ void setResults(SearchTemplateNode[] results) - { - this.results = results; - } - - public int getStartIndex() - { - return startIndex; - } - - /*package*/ void setStartIndex(int startIndex) - { - this.startIndex = startIndex; - } - - public int getStartPage() - { - return startPage; - } - - /*package*/ void setStartPage(int startPage) - { - this.startPage = startPage; - } - - public int getTotalPageItems() - { - return totalPageItems; - } - - /*package*/ void setTotalPageItems(int totalPageItems) - { - this.totalPageItems = totalPageItems; - } - - public int getTotalPages() - { - return totalPages; - } - - /*package*/ void setTotalPages(int totalPages) - { - this.totalPages = totalPages; - } - - public int getTotalResults() - { - return totalResults; - } - - /*package*/ void setTotalResults(int totalResults) - { - this.totalResults = totalResults; - } - - public String getSearchTerms() - { - return searchTerms; - } - - /*package*/ void setSearchTerms(String searchTerms) - { - this.searchTerms = searchTerms; - } - - public Locale getLocale() - { - return locale; - } - - /** - * @return XML 1.0 Language Identification - */ - public String getLocaleId() - { - return locale.toString().replace('_', '-'); - } - - /*package*/ void setLocale(Locale locale) - { - this.locale = locale; - } - - public String getId() - { - if (id == null) - { - id = GUID.generate(); - } - return id; - } - } - - /** - * Search result row template node - */ - public class SearchTemplateNode extends TemplateNode - { - protected final static String URL = "/api/node/content/{0}/{1}/{2}/{3}"; - - private static final long serialVersionUID = -1791913270786140012L; - private float score; - - /** - * Construct - */ - public SearchTemplateNode(NodeRef nodeRef, float score) - { - super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver()); - this.score = score; - } - - /** - * Gets the result row score - */ - public float getScore() - { - return score; - } - - @Override - public String getUrl() - { - return MessageFormat.format(URL, new Object[] { - getNodeRef().getStoreRef().getProtocol(), - getNodeRef().getStoreRef().getIdentifier(), - getNodeRef().getId(), - URLEncoder.encode(getName()) } ); - } - } -} +package org.alfresco.repo.web.scripts.bean; + +import java.io.StringWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.alfresco.repo.template.TemplateNode; +import org.alfresco.repo.web.scripts.RepositoryImageResolver; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.util.GUID; +import org.alfresco.util.SearchLanguageConversion; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.extensions.surf.util.ParameterCheck; +import org.springframework.extensions.surf.util.URLEncoder; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + + +/** + * Alfresco Keyword (simple) Search Service + * + * @author davidc + */ +public class KeywordSearch extends DeclarativeWebScript +{ + // Logger + private static final Log logger = LogFactory.getLog(KeywordSearch.class); + + // search parameters + // TODO: allow configuration of search store + protected static final StoreRef SEARCH_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); + protected static final int DEFAULT_ITEMS_PER_PAGE = 10; + protected static final String QUERY_FORMAT = "query_"; + + // dependencies + protected ServiceRegistry serviceRegistry; + protected RepositoryImageResolver imageResolver; + protected SearchService searchService; + protected NodeService nodeService; + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setRepositoryImageResolver(RepositoryImageResolver imageResolver) + { + this.imageResolver = imageResolver; + } + + public void setServiceRegistry(ServiceRegistry serviceRegistry) + { + this.serviceRegistry = serviceRegistry; + } + + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + // + // process arguments + // + + String searchTerms = req.getParameter("q"); + ParameterCheck.mandatoryString("q", searchTerms); + String startPageArg = req.getParameter("p"); + int startPage = 1; + try + { + startPage = new Integer(startPageArg); + } + catch(NumberFormatException e) + { + // NOTE: use default startPage + } + String itemsPerPageArg = req.getParameter("c"); + int itemsPerPage = DEFAULT_ITEMS_PER_PAGE; + try + { + itemsPerPage = new Integer(itemsPerPageArg); + } + catch(NumberFormatException e) + { + // NOTE: use default itemsPerPage + } + Locale locale = I18NUtil.getLocale(); + String language = req.getParameter("l"); + if (language != null && language.length() > 0) + { + // NOTE: Simple conversion from XML Language Id to Java Locale Id + locale = new Locale(language.replace("-", "_")); + } + + // + // execute the search + // + + SearchResult results = search(searchTerms, startPage, itemsPerPage, locale, req); + + // + // create model + // + + Map model = new HashMap(7, 1.0f); + model.put("search", results); + return model; + } + + /** + * Execute the search + */ + private SearchResult search(String searchTerms, int startPage, int itemsPerPage, Locale locale, WebScriptRequest req) + { + SearchResult searchResult = null; + ResultSet results = null; + + try + { + // construct search statement + String[] terms = searchTerms.split(" "); + searchTerms = searchTerms.replaceAll("\"", """); + + // Escape special characters in the terms, so that they can't confuse the parser + for (int i=0; i statementModel = new HashMap(7, 1.0f); + statementModel.put("args", createArgs(req)); + statementModel.put("terms", terms); + Writer queryWriter = new StringWriter(1024); + renderFormatTemplate(QUERY_FORMAT, statementModel, queryWriter); + String query = queryWriter.toString(); + + // execute query + if (logger.isDebugEnabled()) + { + logger.debug("Search parameters: searchTerms=" + searchTerms + ", startPage=" + startPage + ", itemsPerPage=" + itemsPerPage + ", search locale=" + locale.toString()); + logger.debug("Issuing lucene search: " + query); + } + + SearchParameters parameters = new SearchParameters(); + parameters.addStore(SEARCH_STORE); + parameters.setLanguage(SearchService.LANGUAGE_LUCENE); + parameters.setQuery(query); + if (locale != null) + { + parameters.addLocale(locale); + } + results = searchService.query(parameters); + int totalResults = results.length(); + + if (logger.isDebugEnabled()) + logger.debug("Results: " + totalResults + " rows (limited: " + results.getResultSetMetaData().getLimitedBy() + ")"); + + // are we out-of-range + int totalPages = (totalResults / itemsPerPage); + totalPages += (totalResults % itemsPerPage != 0) ? 1 : 0; + if (totalPages != 0 && (startPage < 1 || startPage > totalPages)) + { + throw new WebScriptException("Start page " + startPage + " is outside boundary of " + totalPages + " pages"); + } + + // construct search result + searchResult = new SearchResult(); + searchResult.setSearchTerms(searchTerms); + searchResult.setLocale(locale); + searchResult.setItemsPerPage(itemsPerPage); + searchResult.setStartPage(startPage); + searchResult.setTotalResults(totalResults); + if (totalResults == 0) + { + searchResult.setTotalPages(0); + searchResult.setStartIndex(0); + searchResult.setTotalPageItems(0); + } + else + { + searchResult.setTotalPages(totalPages); + searchResult.setStartIndex(((startPage -1) * itemsPerPage) + 1); + searchResult.setTotalPageItems(Math.min(itemsPerPage, totalResults - searchResult.getStartIndex() + 1)); + } + SearchTemplateNode[] nodes = new SearchTemplateNode[searchResult.getTotalPageItems()]; + for (int i = 0; i < searchResult.getTotalPageItems(); i++) + { + NodeRef node = results.getNodeRef(i + searchResult.getStartIndex() - 1); + // Make the search resilient to invalid nodes + if (!nodeService.exists(node)) + { + continue; + } + float score = results.getScore(i + searchResult.getStartIndex() - 1); + nodes[i] = new SearchTemplateNode(node, score); + } + searchResult.setResults(nodes); + return searchResult; + } + finally + { + if (results != null) + { + results.close(); + } + } + } + + /** + * Search Result + * + * @author davidc + */ + public static class SearchResult + { + private String id; + private String searchTerms; + private Locale locale; + private int itemsPerPage; + private int totalPages; + private int totalResults; + private int totalPageItems; + private int startPage; + private int startIndex; + private SearchTemplateNode[] results; + + + public int getItemsPerPage() + { + return itemsPerPage; + } + + /*package*/ void setItemsPerPage(int itemsPerPage) + { + this.itemsPerPage = itemsPerPage; + } + + public TemplateNode[] getResults() + { + return results; + } + + /*package*/ void setResults(SearchTemplateNode[] results) + { + this.results = results; + } + + public int getStartIndex() + { + return startIndex; + } + + /*package*/ void setStartIndex(int startIndex) + { + this.startIndex = startIndex; + } + + public int getStartPage() + { + return startPage; + } + + /*package*/ void setStartPage(int startPage) + { + this.startPage = startPage; + } + + public int getTotalPageItems() + { + return totalPageItems; + } + + /*package*/ void setTotalPageItems(int totalPageItems) + { + this.totalPageItems = totalPageItems; + } + + public int getTotalPages() + { + return totalPages; + } + + /*package*/ void setTotalPages(int totalPages) + { + this.totalPages = totalPages; + } + + public int getTotalResults() + { + return totalResults; + } + + /*package*/ void setTotalResults(int totalResults) + { + this.totalResults = totalResults; + } + + public String getSearchTerms() + { + return searchTerms; + } + + /*package*/ void setSearchTerms(String searchTerms) + { + this.searchTerms = searchTerms; + } + + public Locale getLocale() + { + return locale; + } + + /** + * @return XML 1.0 Language Identification + */ + public String getLocaleId() + { + return locale.toString().replace('_', '-'); + } + + /*package*/ void setLocale(Locale locale) + { + this.locale = locale; + } + + public String getId() + { + if (id == null) + { + id = GUID.generate(); + } + return id; + } + } + + /** + * Search result row template node + */ + public class SearchTemplateNode extends TemplateNode + { + protected final static String URL = "/api/node/content/{0}/{1}/{2}/{3}"; + + private static final long serialVersionUID = -1791913270786140012L; + private float score; + + /** + * Construct + */ + public SearchTemplateNode(NodeRef nodeRef, float score) + { + super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver()); + this.score = score; + } + + /** + * Gets the result row score + */ + public float getScore() + { + return score; + } + + @Override + public String getUrl() + { + return MessageFormat.format(URL, new Object[] { + getNodeRef().getStoreRef().getProtocol(), + getNodeRef().getStoreRef().getIdentifier(), + getNodeRef().getId(), + URLEncoder.encode(getName()) } ); + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/bean/Login.java b/source/java/org/alfresco/repo/web/scripts/bean/Login.java index cd098a3a16..c1575628b6 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/Login.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/Login.java @@ -1,47 +1,47 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Login and establish a ticket - * - * @author davidc - */ -public class Login extends AbstractLoginBean -{ - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - protected Map executeImpl(WebScriptRequest req, Status status) - { - // extract username and password - String username = req.getParameter("u"); - if (username == null || username.length() == 0) - { - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified"); - } - String password = req.getParameter("pw"); - if (password == null) - { - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified"); - } - - try - { - return login(username, password); - } - catch(WebScriptException e) - { - status.setCode(e.getStatus()); - status.setMessage(e.getMessage()); - status.setRedirect(true); - return null; - } - } +package org.alfresco.repo.web.scripts.bean; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Login and establish a ticket + * + * @author davidc + */ +public class Login extends AbstractLoginBean +{ + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + protected Map executeImpl(WebScriptRequest req, Status status) + { + // extract username and password + String username = req.getParameter("u"); + if (username == null || username.length() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified"); + } + String password = req.getParameter("pw"); + if (password == null) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified"); + } + + try + { + return login(username, password); + } + catch(WebScriptException e) + { + status.setCode(e.getStatus()); + status.setMessage(e.getMessage()); + status.setRedirect(true); + return null; + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/LoginPost.java b/source/java/org/alfresco/repo/web/scripts/bean/LoginPost.java index d9fbc197f5..369ea81dfc 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/LoginPost.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/LoginPost.java @@ -1,75 +1,75 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.IOException; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Post based login script - */ -public class LoginPost extends AbstractLoginBean -{ - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - protected Map executeImpl(WebScriptRequest req, Status status) - { - // Extract user and password from JSON POST - Content c = req.getContent(); - if (c == null) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body."); - } - - // TODO accept xml type. - - // extract username and password from JSON object - JSONObject json; - try - { - json = new JSONObject(c.getContent()); - String username = json.getString("username"); - String password = json.getString("password"); - - if (username == null || username.length() == 0) - { - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified"); - } - - if (password == null) - { - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified"); - } - - try - { - return login(username, password); - } - catch(WebScriptException e) - { - status.setCode(e.getStatus()); - status.setMessage(e.getMessage()); - status.setRedirect(true); - return null; - } - } - catch (JSONException jErr) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Unable to parse JSON POST body: " + jErr.getMessage()); - } - catch (IOException ioErr) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, - "Unable to retrieve POST body: " + ioErr.getMessage()); - } - } +package org.alfresco.repo.web.scripts.bean; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Post based login script + */ +public class LoginPost extends AbstractLoginBean +{ + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + protected Map executeImpl(WebScriptRequest req, Status status) + { + // Extract user and password from JSON POST + Content c = req.getContent(); + if (c == null) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body."); + } + + // TODO accept xml type. + + // extract username and password from JSON object + JSONObject json; + try + { + json = new JSONObject(c.getContent()); + String username = json.getString("username"); + String password = json.getString("password"); + + if (username == null || username.length() == 0) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified"); + } + + if (password == null) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified"); + } + + try + { + return login(username, password); + } + catch(WebScriptException e) + { + status.setCode(e.getStatus()); + status.setMessage(e.getMessage()); + status.setRedirect(true); + return null; + } + } + catch (JSONException jErr) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Unable to parse JSON POST body: " + jErr.getMessage()); + } + catch (IOException ioErr) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, + "Unable to retrieve POST body: " + ioErr.getMessage()); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/SearchEngines.java b/source/java/org/alfresco/repo/web/scripts/bean/SearchEngines.java index 31cf4496b9..036fe48f1a 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/SearchEngines.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/SearchEngines.java @@ -1,186 +1,186 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.springframework.extensions.config.Config; -import org.springframework.extensions.config.ConfigService; -import org.springframework.extensions.surf.util.I18NUtil; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -/** - * List of (server-side) registered Search Engines - * - * @author davidc - */ -public class SearchEngines extends DeclarativeWebScript -{ - // url argument values - public static final String URL_ARG_DESCRIPTION = "description"; - public static final String URL_ARG_TEMPLATE = "template"; - public static final String URL_ARG_ALL = "all"; - - // Logger - private static final Log logger = LogFactory.getLog(SearchEngines.class); - - // dependencies - protected ConfigService configService; - protected SearchProxy searchProxy; - - /** - * @param configService ConfigService - */ - public void setConfigService(ConfigService configService) - { - this.configService = configService; - } - - /** - * @param searchProxy SearchProxy - */ - public void setSearchProxy(SearchProxy searchProxy) - { - this.searchProxy = searchProxy; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - @SuppressWarnings("deprecation") - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - String urlType = req.getParameter("type"); - if (urlType == null || urlType.length() == 0) - { - urlType = URL_ARG_DESCRIPTION; - } - else if (!urlType.equals(URL_ARG_DESCRIPTION) && !urlType.equals(URL_ARG_TEMPLATE) && !urlType.equals(URL_ARG_ALL)) - { - urlType = URL_ARG_DESCRIPTION; - } - - // - // retrieve open search engines configuration - // - - Set urls = getUrls(urlType); - Map model = new HashMap(7, 1.0f); - model.put("urltype", urlType); - model.put("engines", urls); - return model; - } - - /** - * Retrieve registered search engines - * - * @return set of search engines - */ - private Set getUrls(String urlType) - { - if (logger.isDebugEnabled()) - logger.debug("Search Engine parameters: urltype=" + urlType); - - Set urls = new HashSet(); - Config config = configService.getConfig("OpenSearch"); - - OpenSearchConfigElement searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID); - for (OpenSearchConfigElement.EngineConfig engineConfig : searchConfig.getEngines()) - { - Map engineUrls = engineConfig.getUrls(); - for (Map.Entry engineUrl : engineUrls.entrySet()) - { - String type = engineUrl.getKey(); - String url = searchProxy.createUrl(engineConfig, type); - - if ((urlType.equals(URL_ARG_ALL)) || - (urlType.equals(URL_ARG_DESCRIPTION) && type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) || - (urlType.equals(URL_ARG_TEMPLATE) && !type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION))) - { - String label = engineConfig.getLabel(); - String labelId = engineConfig.getLabelId(); - if (labelId != null && labelId.length() > 0) - { - String i18nLabel = I18NUtil.getMessage(labelId); - if (i18nLabel == null && label == null) - { - label = (i18nLabel == null) ? "$$" + labelId + "$$" : i18nLabel; - } - } - urls.add(new UrlTemplate(label, type, url)); - } - - // TODO: Extract URL templates from OpenSearch description - else if (urlType.equals(URL_ARG_TEMPLATE) && - type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) - { - } - } - } - - if (logger.isDebugEnabled()) - logger.debug("Retrieved " + urls.size() + " engine registrations"); - - return urls; - } - - /** - * Model object for representing a registered search engine - */ - public static class UrlTemplate - { - private String type; - private String label; - private String url; - private UrlTemplate engine; - - public UrlTemplate(String label, String type, String url) - { - this.label = label; - this.type = type; - this.url = url; - this.engine = null; - } - - public UrlTemplate(String label, String type, String url, UrlTemplate engine) - { - this(label, type, url); - this.engine = engine; - } - - public String getLabel() - { - return label; - } - - public String getType() - { - return type; - } - - public String getUrl() - { - return url; - } - - public String getUrlType() - { - return (type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION) ? "description" : "template"); - } - - public UrlTemplate getEngine() - { - return engine; - } - } - +package org.alfresco.repo.web.scripts.bean; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.extensions.config.Config; +import org.springframework.extensions.config.ConfigService; +import org.springframework.extensions.surf.util.I18NUtil; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * List of (server-side) registered Search Engines + * + * @author davidc + */ +public class SearchEngines extends DeclarativeWebScript +{ + // url argument values + public static final String URL_ARG_DESCRIPTION = "description"; + public static final String URL_ARG_TEMPLATE = "template"; + public static final String URL_ARG_ALL = "all"; + + // Logger + private static final Log logger = LogFactory.getLog(SearchEngines.class); + + // dependencies + protected ConfigService configService; + protected SearchProxy searchProxy; + + /** + * @param configService ConfigService + */ + public void setConfigService(ConfigService configService) + { + this.configService = configService; + } + + /** + * @param searchProxy SearchProxy + */ + public void setSearchProxy(SearchProxy searchProxy) + { + this.searchProxy = searchProxy; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + @SuppressWarnings("deprecation") + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + String urlType = req.getParameter("type"); + if (urlType == null || urlType.length() == 0) + { + urlType = URL_ARG_DESCRIPTION; + } + else if (!urlType.equals(URL_ARG_DESCRIPTION) && !urlType.equals(URL_ARG_TEMPLATE) && !urlType.equals(URL_ARG_ALL)) + { + urlType = URL_ARG_DESCRIPTION; + } + + // + // retrieve open search engines configuration + // + + Set urls = getUrls(urlType); + Map model = new HashMap(7, 1.0f); + model.put("urltype", urlType); + model.put("engines", urls); + return model; + } + + /** + * Retrieve registered search engines + * + * @return set of search engines + */ + private Set getUrls(String urlType) + { + if (logger.isDebugEnabled()) + logger.debug("Search Engine parameters: urltype=" + urlType); + + Set urls = new HashSet(); + Config config = configService.getConfig("OpenSearch"); + + OpenSearchConfigElement searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID); + for (OpenSearchConfigElement.EngineConfig engineConfig : searchConfig.getEngines()) + { + Map engineUrls = engineConfig.getUrls(); + for (Map.Entry engineUrl : engineUrls.entrySet()) + { + String type = engineUrl.getKey(); + String url = searchProxy.createUrl(engineConfig, type); + + if ((urlType.equals(URL_ARG_ALL)) || + (urlType.equals(URL_ARG_DESCRIPTION) && type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) || + (urlType.equals(URL_ARG_TEMPLATE) && !type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION))) + { + String label = engineConfig.getLabel(); + String labelId = engineConfig.getLabelId(); + if (labelId != null && labelId.length() > 0) + { + String i18nLabel = I18NUtil.getMessage(labelId); + if (i18nLabel == null && label == null) + { + label = (i18nLabel == null) ? "$$" + labelId + "$$" : i18nLabel; + } + } + urls.add(new UrlTemplate(label, type, url)); + } + + // TODO: Extract URL templates from OpenSearch description + else if (urlType.equals(URL_ARG_TEMPLATE) && + type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) + { + } + } + } + + if (logger.isDebugEnabled()) + logger.debug("Retrieved " + urls.size() + " engine registrations"); + + return urls; + } + + /** + * Model object for representing a registered search engine + */ + public static class UrlTemplate + { + private String type; + private String label; + private String url; + private UrlTemplate engine; + + public UrlTemplate(String label, String type, String url) + { + this.label = label; + this.type = type; + this.url = url; + this.engine = null; + } + + public UrlTemplate(String label, String type, String url, UrlTemplate engine) + { + this(label, type, url); + this.engine = engine; + } + + public String getLabel() + { + return label; + } + + public String getType() + { + return type; + } + + public String getUrl() + { + return url; + } + + public String getUrlType() + { + return (type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION) ? "description" : "template"); + } + + public UrlTemplate getEngine() + { + return engine; + } + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java b/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java index d9ca3adda3..c669b730a9 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java @@ -1,317 +1,317 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URLConnection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig; -import org.alfresco.web.app.servlet.HTTPProxy; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.XPath; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.extensions.config.Config; -import org.springframework.extensions.config.ConfigService; -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.FormatRegistry; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; - - -/** - * Alfresco OpenSearch Proxy Service - * - * Provides the ability to submit a request to a registered search engine - * via the Alfresco server. - * - * @author davidc - */ -public class SearchProxy extends AbstractWebScript implements InitializingBean -{ - // Logger - private static final Log logger = LogFactory.getLog(SearchProxy.class); - - // dependencies - protected FormatRegistry formatRegistry; - protected ConfigService configService; - protected OpenSearchConfigElement searchConfig; - protected String proxyPath; - - /** - * @param formatRegistry FormatRegistry - */ - public void setFormatRegistry(FormatRegistry formatRegistry) - { - this.formatRegistry = formatRegistry; - } - - /** - * @param configService ConfigService - */ - public void setConfigService(ConfigService configService) - { - this.configService = configService; - } - - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception - { - Config config = configService.getConfig("OpenSearch"); - searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID); - if (searchConfig == null) - { - throw new WebScriptException("OpenSearch configuration not found"); - } - ProxyConfig proxyConfig = searchConfig.getProxy(); - if (proxyConfig == null) - { - throw new WebScriptException("OpenSearch proxy configuration not found"); - } - proxyPath = proxyConfig.getUrl(); - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - public void execute(WebScriptRequest req, WebScriptResponse res) - throws IOException - { - String extensionPath = req.getExtensionPath(); - String[] extensionPaths = extensionPath.split("/"); - if (extensionPaths.length != 2) - { - throw new WebScriptException("OpenSearch engine has not been specified as /{engine}/{format}"); - } - - // retrieve search engine configuration - String engine = extensionPaths[0]; - EngineConfig engineConfig = searchConfig.getEngine(engine); - if (engineConfig == null) - { - throw new WebScriptException("OpenSearch engine '" + engine + "' does not exist"); - } - - // retrieve engine url as specified by format - String format = extensionPaths[1]; - String mimetype = formatRegistry.getMimeType(null, format); - if (mimetype == null) - { - throw new WebScriptException("Format '" + format + "' does not map to a registered mimetype"); - } - Map engineUrls = engineConfig.getUrls(); - String engineUrl = engineUrls.get(mimetype); - if (engineUrl == null) - { - throw new WebScriptException("Url mimetype '" + mimetype + "' does not exist for engine '" + engine + "'"); - } - - // replace template url arguments with actual arguments specified on request - int engineUrlArgIdx = engineUrl.indexOf("?"); - if (engineUrlArgIdx != -1) - { - engineUrl = engineUrl.substring(0, engineUrlArgIdx); - } - if (req.getQueryString() != null) - { - engineUrl += "?" + req.getQueryString(); - } - - if (logger.isDebugEnabled()) - logger.debug("Mapping engine '" + engine + "' (mimetype '" + mimetype + "') to url '" + engineUrl + "'"); - - // issue request against search engine - // NOTE: This web script must be executed in a HTTP servlet environment - if (!(res.getRuntime() instanceof WebScriptServletRuntime)) - { - throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment"); - } - - HttpServletResponse servletRes = WebScriptServletRuntime.getHttpServletResponse(res); - SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServerPath() + req.getServiceContextPath(), - engine, engineUrl, servletRes, Collections.singletonMap("User-Agent", req.getHeader("User-Agent"))); - proxy.service(); - } - - /** - * OpenSearch HTTPProxy - * - * This proxy remaps OpenSearch links (e.g. previous, next) found in search results. - * - * @author davidc - */ - private class SearchEngineHttpProxy extends HTTPProxy - { - private final static String ATOM_NS_URI = "http://www.w3.org/2005/Atom"; - private final static String ATOM_NS_PREFIX = "atom"; - private final static String ATOM_LINK_XPATH = "atom:link[@rel=\"first\" or @rel=\"last\" or @rel=\"next\" or @rel=\"previous\" or @rel=\"self\" or @rel=\"alternate\"]"; - private String engine; - private String rootPath; - private Map headers; - - /** - * Construct - * - * @param rootPath String - * @param engine String - * @param engineUrl String - * @param response HttpServletResponse - * @param headers request headers - * @throws MalformedURLException - */ - public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response, Map headers) - throws MalformedURLException - { - super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response); - this.engine = engine; - this.rootPath = rootPath; - this.headers = headers; - } - - /* (non-Javadoc) - * @see org.alfresco.web.app.servlet.HTTPProxy#setRequestHeaders(java.net.URLConnection) - */ - @Override - protected void setRequestHeaders(URLConnection urlConnection) - { - if (headers != null) - { - for (Map.Entry entry: headers.entrySet()) - { - urlConnection.setRequestProperty(entry.getKey(), entry.getValue()); - } - } - } - - /* (non-Javadoc) - * @see org.alfresco.web.app.servlet.HTTPProxy#writeResponse(java.io.InputStream, java.io.OutputStream) - */ - @Override - protected void writeResponse(InputStream input, OutputStream output) - throws IOException - { - if (response.getContentType().startsWith(MimetypeMap.MIMETYPE_ATOM) || - response.getContentType().startsWith(MimetypeMap.MIMETYPE_RSS)) - { - // Only post-process ATOM and RSS feeds - // Replace all navigation links with "proxied" versions - SAXReader reader = new SAXReader(); - try - { - Document document = reader.read(input); - Element rootElement = document.getRootElement(); - - XPath xpath = rootElement.createXPath(ATOM_LINK_XPATH); - Map uris = new HashMap(); - uris.put(ATOM_NS_PREFIX, ATOM_NS_URI); - xpath.setNamespaceURIs(uris); - - List nodes = xpath.selectNodes(rootElement); - Iterator iter = nodes.iterator(); - while (iter.hasNext()) - { - Element element = (Element)iter.next(); - Attribute hrefAttr = element.attribute("href"); - String mimetype = element.attributeValue("type"); - if (mimetype == null || mimetype.length() == 0) - { - mimetype = MimetypeMap.MIMETYPE_HTML; - } - String url = createUrl(engine, hrefAttr.getValue(), mimetype); - if (url.startsWith("/")) - { - url = rootPath + url; - } - hrefAttr.setValue(url); - } - - OutputFormat outputFormat = OutputFormat.createPrettyPrint(); - XMLWriter writer = new XMLWriter(output, outputFormat); - writer.write(rootElement); - writer.flush(); - } - catch(DocumentException e) - { - throw new IOException(e.toString()); - } - } - else - { - super.writeResponse(input, output); - } - } - } - - /** - * Construct a "proxied" search engine url - * - * @param engine engine name (as identified by ) - * @param mimetype url to proxy (as identified by mimetype) - * @return "proxied" url - */ - public String createUrl(OpenSearchConfigElement.EngineConfig engine, String mimetype) - { - Map urls = engine.getUrls(); - String url = urls.get(mimetype); - if (url != null) - { - String proxy = engine.getProxy(); - if (proxy != null && !mimetype.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) - { - url = createUrl(proxy, url, mimetype); - } - } - return url; - } - - /** - * Construct a "proxied" search engine url - * - * @param engine engine name (as identified by ) - * @param url engine url - * @param mimetype mimetype of url - * @return "proxied" url - */ - public String createUrl(String engine, String url, String mimetype) - { - String format = formatRegistry.getFormat(null, mimetype); - if (format == null) - { - throw new WebScriptException("Mimetype '" + mimetype + "' is not registered."); - } - - String proxyUrl = null; - int argIdx = url.indexOf("?"); - if (argIdx == -1) - { - proxyUrl = proxyPath + "/" + engine + "/" + format; - } - else - { - proxyUrl = proxyPath + "/" + engine + "/" + format + url.substring(argIdx); - } - return proxyUrl; - } +package org.alfresco.repo.web.scripts.bean; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig; +import org.alfresco.web.app.servlet.HTTPProxy; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.XPath; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.extensions.config.Config; +import org.springframework.extensions.config.ConfigService; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.FormatRegistry; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + + +/** + * Alfresco OpenSearch Proxy Service + * + * Provides the ability to submit a request to a registered search engine + * via the Alfresco server. + * + * @author davidc + */ +public class SearchProxy extends AbstractWebScript implements InitializingBean +{ + // Logger + private static final Log logger = LogFactory.getLog(SearchProxy.class); + + // dependencies + protected FormatRegistry formatRegistry; + protected ConfigService configService; + protected OpenSearchConfigElement searchConfig; + protected String proxyPath; + + /** + * @param formatRegistry FormatRegistry + */ + public void setFormatRegistry(FormatRegistry formatRegistry) + { + this.formatRegistry = formatRegistry; + } + + /** + * @param configService ConfigService + */ + public void setConfigService(ConfigService configService) + { + this.configService = configService; + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception + { + Config config = configService.getConfig("OpenSearch"); + searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID); + if (searchConfig == null) + { + throw new WebScriptException("OpenSearch configuration not found"); + } + ProxyConfig proxyConfig = searchConfig.getProxy(); + if (proxyConfig == null) + { + throw new WebScriptException("OpenSearch proxy configuration not found"); + } + proxyPath = proxyConfig.getUrl(); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) + throws IOException + { + String extensionPath = req.getExtensionPath(); + String[] extensionPaths = extensionPath.split("/"); + if (extensionPaths.length != 2) + { + throw new WebScriptException("OpenSearch engine has not been specified as /{engine}/{format}"); + } + + // retrieve search engine configuration + String engine = extensionPaths[0]; + EngineConfig engineConfig = searchConfig.getEngine(engine); + if (engineConfig == null) + { + throw new WebScriptException("OpenSearch engine '" + engine + "' does not exist"); + } + + // retrieve engine url as specified by format + String format = extensionPaths[1]; + String mimetype = formatRegistry.getMimeType(null, format); + if (mimetype == null) + { + throw new WebScriptException("Format '" + format + "' does not map to a registered mimetype"); + } + Map engineUrls = engineConfig.getUrls(); + String engineUrl = engineUrls.get(mimetype); + if (engineUrl == null) + { + throw new WebScriptException("Url mimetype '" + mimetype + "' does not exist for engine '" + engine + "'"); + } + + // replace template url arguments with actual arguments specified on request + int engineUrlArgIdx = engineUrl.indexOf("?"); + if (engineUrlArgIdx != -1) + { + engineUrl = engineUrl.substring(0, engineUrlArgIdx); + } + if (req.getQueryString() != null) + { + engineUrl += "?" + req.getQueryString(); + } + + if (logger.isDebugEnabled()) + logger.debug("Mapping engine '" + engine + "' (mimetype '" + mimetype + "') to url '" + engineUrl + "'"); + + // issue request against search engine + // NOTE: This web script must be executed in a HTTP servlet environment + if (!(res.getRuntime() instanceof WebScriptServletRuntime)) + { + throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment"); + } + + HttpServletResponse servletRes = WebScriptServletRuntime.getHttpServletResponse(res); + SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServerPath() + req.getServiceContextPath(), + engine, engineUrl, servletRes, Collections.singletonMap("User-Agent", req.getHeader("User-Agent"))); + proxy.service(); + } + + /** + * OpenSearch HTTPProxy + * + * This proxy remaps OpenSearch links (e.g. previous, next) found in search results. + * + * @author davidc + */ + private class SearchEngineHttpProxy extends HTTPProxy + { + private final static String ATOM_NS_URI = "http://www.w3.org/2005/Atom"; + private final static String ATOM_NS_PREFIX = "atom"; + private final static String ATOM_LINK_XPATH = "atom:link[@rel=\"first\" or @rel=\"last\" or @rel=\"next\" or @rel=\"previous\" or @rel=\"self\" or @rel=\"alternate\"]"; + private String engine; + private String rootPath; + private Map headers; + + /** + * Construct + * + * @param rootPath String + * @param engine String + * @param engineUrl String + * @param response HttpServletResponse + * @param headers request headers + * @throws MalformedURLException + */ + public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response, Map headers) + throws MalformedURLException + { + super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response); + this.engine = engine; + this.rootPath = rootPath; + this.headers = headers; + } + + /* (non-Javadoc) + * @see org.alfresco.web.app.servlet.HTTPProxy#setRequestHeaders(java.net.URLConnection) + */ + @Override + protected void setRequestHeaders(URLConnection urlConnection) + { + if (headers != null) + { + for (Map.Entry entry: headers.entrySet()) + { + urlConnection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + } + + /* (non-Javadoc) + * @see org.alfresco.web.app.servlet.HTTPProxy#writeResponse(java.io.InputStream, java.io.OutputStream) + */ + @Override + protected void writeResponse(InputStream input, OutputStream output) + throws IOException + { + if (response.getContentType().startsWith(MimetypeMap.MIMETYPE_ATOM) || + response.getContentType().startsWith(MimetypeMap.MIMETYPE_RSS)) + { + // Only post-process ATOM and RSS feeds + // Replace all navigation links with "proxied" versions + SAXReader reader = new SAXReader(); + try + { + Document document = reader.read(input); + Element rootElement = document.getRootElement(); + + XPath xpath = rootElement.createXPath(ATOM_LINK_XPATH); + Map uris = new HashMap(); + uris.put(ATOM_NS_PREFIX, ATOM_NS_URI); + xpath.setNamespaceURIs(uris); + + List nodes = xpath.selectNodes(rootElement); + Iterator iter = nodes.iterator(); + while (iter.hasNext()) + { + Element element = (Element)iter.next(); + Attribute hrefAttr = element.attribute("href"); + String mimetype = element.attributeValue("type"); + if (mimetype == null || mimetype.length() == 0) + { + mimetype = MimetypeMap.MIMETYPE_HTML; + } + String url = createUrl(engine, hrefAttr.getValue(), mimetype); + if (url.startsWith("/")) + { + url = rootPath + url; + } + hrefAttr.setValue(url); + } + + OutputFormat outputFormat = OutputFormat.createPrettyPrint(); + XMLWriter writer = new XMLWriter(output, outputFormat); + writer.write(rootElement); + writer.flush(); + } + catch(DocumentException e) + { + throw new IOException(e.toString()); + } + } + else + { + super.writeResponse(input, output); + } + } + } + + /** + * Construct a "proxied" search engine url + * + * @param engine engine name (as identified by ) + * @param mimetype url to proxy (as identified by mimetype) + * @return "proxied" url + */ + public String createUrl(OpenSearchConfigElement.EngineConfig engine, String mimetype) + { + Map urls = engine.getUrls(); + String url = urls.get(mimetype); + if (url != null) + { + String proxy = engine.getProxy(); + if (proxy != null && !mimetype.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) + { + url = createUrl(proxy, url, mimetype); + } + } + return url; + } + + /** + * Construct a "proxied" search engine url + * + * @param engine engine name (as identified by ) + * @param url engine url + * @param mimetype mimetype of url + * @return "proxied" url + */ + public String createUrl(String engine, String url, String mimetype) + { + String format = formatRegistry.getFormat(null, mimetype); + if (format == null) + { + throw new WebScriptException("Mimetype '" + mimetype + "' is not registered."); + } + + String proxyUrl = null; + int argIdx = url.indexOf("?"); + if (argIdx == -1) + { + proxyUrl = proxyPath + "/" + engine + "/" + format; + } + else + { + proxyUrl = proxyPath + "/" + engine + "/" + format + url.substring(argIdx); + } + return proxyUrl; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bean/Touch.java b/source/java/org/alfresco/repo/web/scripts/bean/Touch.java index 9b5b7f7728..7e8c7b2090 100644 --- a/source/java/org/alfresco/repo/web/scripts/bean/Touch.java +++ b/source/java/org/alfresco/repo/web/scripts/bean/Touch.java @@ -1,26 +1,26 @@ -package org.alfresco.repo.web.scripts.bean; - -import java.io.IOException; - -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * WebScript java backed bean implementation - to simple return a STATUS_OK message - * as a touch point for SSO authentication mechanisms on the web-tier. Such as NTLM. - * - * @author Kevin Roast - */ -public class Touch extends AbstractWebScript -{ - /* (non-Javadoc) - * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) - */ - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - res.setStatus(Status.STATUS_OK); - res.getWriter().close(); - } +package org.alfresco.repo.web.scripts.bean; + +import java.io.IOException; + +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * WebScript java backed bean implementation - to simple return a STATUS_OK message + * as a touch point for SSO authentication mechanisms on the web-tier. Such as NTLM. + * + * @author Kevin Roast + */ +public class Touch extends AbstractWebScript +{ + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + res.setStatus(Status.STATUS_OK); + res.getWriter().close(); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bulkimport/AbstractBulkFileSystemImportWebScript.java b/source/java/org/alfresco/repo/web/scripts/bulkimport/AbstractBulkFileSystemImportWebScript.java index d50e750f49..7582407864 100644 --- a/source/java/org/alfresco/repo/web/scripts/bulkimport/AbstractBulkFileSystemImportWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/bulkimport/AbstractBulkFileSystemImportWebScript.java @@ -1,196 +1,196 @@ - -package org.alfresco.repo.web.scripts.bulkimport; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Date; - -import org.alfresco.repo.bulkimport.BulkFilesystemImporter; -import org.alfresco.repo.model.Repository; -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.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.WebScriptException; - -/** - * contains common fields and methods for the import web scripts. - */ -public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript -{ - protected static final Log logger = LogFactory.getLog(BulkFilesystemImporter.class); - - protected static final String WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS = "/bulkfsimport/status"; - - protected static final String PARAMETER_TARGET_NODEREF = "targetNodeRef"; - protected static final String PARAMETER_TARGET_PATH = "targetPath"; - - protected static final String COMPANY_HOME_NAME = "Company Home"; - protected static final String COMPANY_HOME_PATH = "/" + COMPANY_HOME_NAME; - - // Web scripts parameters (common) - protected static final String PARAMETER_REPLACE_EXISTING = "replaceExisting"; - protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "replaceExisting"; - protected static final String PARAMETER_SOURCE_DIRECTORY = "sourceDirectory"; - protected static final String PARAMETER_DISABLE_RULES = "disableRules"; - protected static final String PARAMETER_VALUE_DISABLE_RULES = "disableRules"; - - protected static final String IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY = "importInProgress"; - protected static final String IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY ="bfsit.error.importAlreadyInProgress"; - - protected static final String PARAMETER_BATCH_SIZE = "batchSize"; - protected static final String PARAMETER_NUM_THREADS = "numThreads"; - - protected FileFolderService fileFolderService; - protected Repository repository; - - protected volatile boolean importInProgress; - - protected NodeRef getTargetNodeRef(String targetNodeRefStr, String targetPath) throws FileNotFoundException - { - NodeRef targetNodeRef; - - if (targetNodeRefStr == null || targetNodeRefStr.trim().length() == 0) - { - if (targetPath == null || targetPath.trim().length() == 0) - { - throw new WebScriptException("Error: neither parameter '" + PARAMETER_TARGET_NODEREF + - "' nor parameter '" + PARAMETER_TARGET_PATH + - "' was provided, but at least one is required !"); - } - targetNodeRef = convertPathToNodeRef(targetPath.trim()); - } - else - { - targetNodeRef = new NodeRef(targetNodeRefStr.trim()); - } - - return targetNodeRef; - } - - protected NodeRef convertPathToNodeRef(String targetPath) throws FileNotFoundException - { - NodeRef result = null; - NodeRef companyHome = repository.getCompanyHome(); - String cleanTargetPath = targetPath.replaceAll("/+", "/"); - - if (cleanTargetPath.startsWith(COMPANY_HOME_PATH)) - cleanTargetPath = cleanTargetPath.substring(COMPANY_HOME_PATH.length()); - - if (cleanTargetPath.startsWith("/")) - cleanTargetPath = cleanTargetPath.substring(1); - - if (cleanTargetPath.endsWith("/")) - cleanTargetPath = cleanTargetPath.substring(0, cleanTargetPath.length() - 1); - - if (cleanTargetPath.length() == 0) - result = companyHome; - else - { - FileInfo info = fileFolderService.resolveNamePath(companyHome, Arrays.asList(cleanTargetPath.split("/"))); - if(info == null) - throw new WebScriptException("could not determine NodeRef for path :'"+cleanTargetPath+"'"); - - result = info.getNodeRef(); - } - - return(result); - } - - protected String buildTextMessage(Throwable t) - { - StringBuffer result = new StringBuffer(); - String timeOfFailure = (new Date()).toString(); - String hostName = null; - String ipAddress = null; - - try - { - hostName = InetAddress.getLocalHost().getHostName(); - ipAddress = InetAddress.getLocalHost().getHostAddress(); - } - catch (UnknownHostException uhe) - { - hostName = "unknown"; - ipAddress = "unknown"; - } - - result.append("\nTime of failure: " + timeOfFailure); - result.append("\nHost where failure occurred: " + hostName + " (" + ipAddress + ")"); - - if (t != null) - { - result.append("\nRoot exception:"); - result.append(renderExceptionStackAsText(t)); - } - else - { - result.append("\nNo exception was provided."); - } - - return(result.toString()); - } - - private String renderExceptionStackAsText( Throwable t) - { - StringBuffer result = new StringBuffer(); - - if (t != null) - { - String message = t.getMessage(); - Throwable cause = t.getCause(); - - if (cause != null) - { - result.append(renderExceptionStackAsText(cause)); - result.append("\nWrapped by:"); - } - - if (message == null) - { - message = ""; - } - - result.append("\n"); - result.append(t.getClass().getName()); - result.append(": "); - result.append(message); - result.append("\n"); - result.append(renderStackTraceElements(t.getStackTrace())); - } - - return(result.toString()); - } - - private String renderStackTraceElements(StackTraceElement[] elements) - { - StringBuffer result = new StringBuffer(); - - if (elements != null) - { - for (int i = 0; i < elements.length; i++) - { - result.append("\tat " + elements[i].toString() + "\n"); - } - } - - return(result.toString()); - } - - // boilerplate setters - - public void setFileFolderService(FileFolderService fileFolderService) - { - this.fileFolderService = fileFolderService; - } - - public void setRepository(Repository repository) - { - this.repository = repository; - } - + +package org.alfresco.repo.web.scripts.bulkimport; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Date; + +import org.alfresco.repo.bulkimport.BulkFilesystemImporter; +import org.alfresco.repo.model.Repository; +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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * contains common fields and methods for the import web scripts. + */ +public class AbstractBulkFileSystemImportWebScript extends DeclarativeWebScript +{ + protected static final Log logger = LogFactory.getLog(BulkFilesystemImporter.class); + + protected static final String WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS = "/bulkfsimport/status"; + + protected static final String PARAMETER_TARGET_NODEREF = "targetNodeRef"; + protected static final String PARAMETER_TARGET_PATH = "targetPath"; + + protected static final String COMPANY_HOME_NAME = "Company Home"; + protected static final String COMPANY_HOME_PATH = "/" + COMPANY_HOME_NAME; + + // Web scripts parameters (common) + protected static final String PARAMETER_REPLACE_EXISTING = "replaceExisting"; + protected static final String PARAMETER_VALUE_REPLACE_EXISTING = "replaceExisting"; + protected static final String PARAMETER_SOURCE_DIRECTORY = "sourceDirectory"; + protected static final String PARAMETER_DISABLE_RULES = "disableRules"; + protected static final String PARAMETER_VALUE_DISABLE_RULES = "disableRules"; + + protected static final String IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY = "importInProgress"; + protected static final String IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY ="bfsit.error.importAlreadyInProgress"; + + protected static final String PARAMETER_BATCH_SIZE = "batchSize"; + protected static final String PARAMETER_NUM_THREADS = "numThreads"; + + protected FileFolderService fileFolderService; + protected Repository repository; + + protected volatile boolean importInProgress; + + protected NodeRef getTargetNodeRef(String targetNodeRefStr, String targetPath) throws FileNotFoundException + { + NodeRef targetNodeRef; + + if (targetNodeRefStr == null || targetNodeRefStr.trim().length() == 0) + { + if (targetPath == null || targetPath.trim().length() == 0) + { + throw new WebScriptException("Error: neither parameter '" + PARAMETER_TARGET_NODEREF + + "' nor parameter '" + PARAMETER_TARGET_PATH + + "' was provided, but at least one is required !"); + } + targetNodeRef = convertPathToNodeRef(targetPath.trim()); + } + else + { + targetNodeRef = new NodeRef(targetNodeRefStr.trim()); + } + + return targetNodeRef; + } + + protected NodeRef convertPathToNodeRef(String targetPath) throws FileNotFoundException + { + NodeRef result = null; + NodeRef companyHome = repository.getCompanyHome(); + String cleanTargetPath = targetPath.replaceAll("/+", "/"); + + if (cleanTargetPath.startsWith(COMPANY_HOME_PATH)) + cleanTargetPath = cleanTargetPath.substring(COMPANY_HOME_PATH.length()); + + if (cleanTargetPath.startsWith("/")) + cleanTargetPath = cleanTargetPath.substring(1); + + if (cleanTargetPath.endsWith("/")) + cleanTargetPath = cleanTargetPath.substring(0, cleanTargetPath.length() - 1); + + if (cleanTargetPath.length() == 0) + result = companyHome; + else + { + FileInfo info = fileFolderService.resolveNamePath(companyHome, Arrays.asList(cleanTargetPath.split("/"))); + if(info == null) + throw new WebScriptException("could not determine NodeRef for path :'"+cleanTargetPath+"'"); + + result = info.getNodeRef(); + } + + return(result); + } + + protected String buildTextMessage(Throwable t) + { + StringBuffer result = new StringBuffer(); + String timeOfFailure = (new Date()).toString(); + String hostName = null; + String ipAddress = null; + + try + { + hostName = InetAddress.getLocalHost().getHostName(); + ipAddress = InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException uhe) + { + hostName = "unknown"; + ipAddress = "unknown"; + } + + result.append("\nTime of failure: " + timeOfFailure); + result.append("\nHost where failure occurred: " + hostName + " (" + ipAddress + ")"); + + if (t != null) + { + result.append("\nRoot exception:"); + result.append(renderExceptionStackAsText(t)); + } + else + { + result.append("\nNo exception was provided."); + } + + return(result.toString()); + } + + private String renderExceptionStackAsText( Throwable t) + { + StringBuffer result = new StringBuffer(); + + if (t != null) + { + String message = t.getMessage(); + Throwable cause = t.getCause(); + + if (cause != null) + { + result.append(renderExceptionStackAsText(cause)); + result.append("\nWrapped by:"); + } + + if (message == null) + { + message = ""; + } + + result.append("\n"); + result.append(t.getClass().getName()); + result.append(": "); + result.append(message); + result.append("\n"); + result.append(renderStackTraceElements(t.getStackTrace())); + } + + return(result.toString()); + } + + private String renderStackTraceElements(StackTraceElement[] elements) + { + StringBuffer result = new StringBuffer(); + + if (elements != null) + { + for (int i = 0; i < elements.length; i++) + { + result.append("\tat " + elements[i].toString() + "\n"); + } + } + + return(result.toString()); + } + + // boilerplate setters + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + public void setRepository(Repository repository) + { + this.repository = repository; + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/bulkimport/BulkFilesystemImportStatusWebScript.java b/source/java/org/alfresco/repo/web/scripts/bulkimport/BulkFilesystemImportStatusWebScript.java index f00e05d62c..a02a796163 100644 --- a/source/java/org/alfresco/repo/web/scripts/bulkimport/BulkFilesystemImportStatusWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/bulkimport/BulkFilesystemImportStatusWebScript.java @@ -1,63 +1,63 @@ - -package org.alfresco.repo.web.scripts.bulkimport; - -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.repo.bulkimport.BulkFilesystemImporter; -import org.alfresco.service.cmr.admin.RepoUsage.LicenseMode; -import org.alfresco.service.descriptor.DescriptorService; -import org.alfresco.service.license.LicenseDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Web Script class that provides status information on the bulk filesystem import process. - * - * @since 4.0 - */ -public class BulkFilesystemImportStatusWebScript extends DeclarativeWebScript -{ - private final static Log logger = LogFactory.getLog(BulkFilesystemImportStatusWebScript.class); - - // Output parameters (for Freemarker) - private final static String RESULT_IMPORT_STATUS = "importStatus"; - private final static String IS_ENTERPRISE = "isEnterprise"; - - // Attributes - private BulkFilesystemImporter bulkImporter; - private DescriptorService descriptorService; - - public void setBulkImporter(BulkFilesystemImporter bulkImporter) - { - this.bulkImporter = bulkImporter; - } - - public void setDescriptorService(DescriptorService descriptorService) - { - this.descriptorService = descriptorService; - } - - /** - * @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(WebScriptRequest, Status, Cache) - */ - @Override - protected Map executeImpl(WebScriptRequest request, Status status, Cache cache) - { - Map result = new HashMap(); - - cache.setNeverCache(true); - - LicenseDescriptor licenseDescriptor = descriptorService.getLicenseDescriptor(); - boolean isEnterprise = (licenseDescriptor == null ? false : (licenseDescriptor.getLicenseMode() == LicenseMode.ENTERPRISE)); - - result.put(IS_ENTERPRISE, Boolean.valueOf(isEnterprise)); - result.put(RESULT_IMPORT_STATUS, bulkImporter.getStatus()); - - return(result); - } -} + +package org.alfresco.repo.web.scripts.bulkimport; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.bulkimport.BulkFilesystemImporter; +import org.alfresco.service.cmr.admin.RepoUsage.LicenseMode; +import org.alfresco.service.descriptor.DescriptorService; +import org.alfresco.service.license.LicenseDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Web Script class that provides status information on the bulk filesystem import process. + * + * @since 4.0 + */ +public class BulkFilesystemImportStatusWebScript extends DeclarativeWebScript +{ + private final static Log logger = LogFactory.getLog(BulkFilesystemImportStatusWebScript.class); + + // Output parameters (for Freemarker) + private final static String RESULT_IMPORT_STATUS = "importStatus"; + private final static String IS_ENTERPRISE = "isEnterprise"; + + // Attributes + private BulkFilesystemImporter bulkImporter; + private DescriptorService descriptorService; + + public void setBulkImporter(BulkFilesystemImporter bulkImporter) + { + this.bulkImporter = bulkImporter; + } + + public void setDescriptorService(DescriptorService descriptorService) + { + this.descriptorService = descriptorService; + } + + /** + * @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(WebScriptRequest, Status, Cache) + */ + @Override + protected Map executeImpl(WebScriptRequest request, Status status, Cache cache) + { + Map result = new HashMap(); + + cache.setNeverCache(true); + + LicenseDescriptor licenseDescriptor = descriptorService.getLicenseDescriptor(); + boolean isEnterprise = (licenseDescriptor == null ? false : (licenseDescriptor.getLicenseMode() == LicenseMode.ENTERPRISE)); + + result.put(IS_ENTERPRISE, Boolean.valueOf(isEnterprise)); + result.put(RESULT_IMPORT_STATUS, bulkImporter.getStatus()); + + return(result); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/bulkimport/copy/BulkFilesystemImportWebScript.java b/source/java/org/alfresco/repo/web/scripts/bulkimport/copy/BulkFilesystemImportWebScript.java index 89527d086f..05f89a8824 100644 --- a/source/java/org/alfresco/repo/web/scripts/bulkimport/copy/BulkFilesystemImportWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/bulkimport/copy/BulkFilesystemImportWebScript.java @@ -1,185 +1,185 @@ - -package org.alfresco.repo.web.scripts.bulkimport.copy; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.repo.bulkimport.BulkImportParameters; -import org.alfresco.repo.bulkimport.NodeImporter; -import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter; -import org.alfresco.repo.bulkimport.impl.StreamingNodeImporterFactory; -import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript; -import org.alfresco.service.cmr.model.FileNotFoundException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.springframework.extensions.surf.util.I18NUtil; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Web Script class that invokes a BulkFilesystemImporter implementation. - * - * @since 4.0 - */ -public class BulkFilesystemImportWebScript extends AbstractBulkFileSystemImportWebScript -{ - private MultiThreadedBulkFilesystemImporter bulkImporter; - private StreamingNodeImporterFactory nodeImporterFactory; - - public void setBulkImporter(MultiThreadedBulkFilesystemImporter bulkImporter) - { - this.bulkImporter = bulkImporter; - } - - public void setNodeImporterFactory(StreamingNodeImporterFactory nodeImporterFactory) - { - this.nodeImporterFactory = nodeImporterFactory; - } - - /** - * @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.Status, org.springframework.extensions.webscripts.Cache) - */ - @Override - protected Map executeImpl(final WebScriptRequest request, final Status status, final Cache cache) - { - Map model = new HashMap(); - String targetNodeRefStr = null; - String targetPath = null; - String sourceDirectoryStr = null; - String replaceExistingStr = null; - String batchSizeStr = null; - String numThreadsStr = null; - String disableRulesStr = null; - - cache.setNeverCache(true); - - try - { - if(!bulkImporter.getStatus().inProgress()) - { - NodeRef targetNodeRef = null; - File sourceDirectory = null; - boolean replaceExisting = false; - int batchSize = bulkImporter.getDefaultBatchSize(); - int numThreads = bulkImporter.getDefaultNumThreads(); - boolean disableRules = false; - - // Retrieve, validate and convert parameters - targetNodeRefStr = request.getParameter(PARAMETER_TARGET_NODEREF); - targetPath = request.getParameter(PARAMETER_TARGET_PATH); - sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY); - replaceExistingStr = request.getParameter(PARAMETER_REPLACE_EXISTING); - batchSizeStr = request.getParameter(PARAMETER_BATCH_SIZE); - numThreadsStr = request.getParameter(PARAMETER_NUM_THREADS); - disableRulesStr = request.getParameter(PARAMETER_DISABLE_RULES); - - targetNodeRef = getTargetNodeRef(targetNodeRefStr, targetPath); - - if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0) - { - throw new RuntimeException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided."); - } - - sourceDirectory = new File(sourceDirectoryStr.trim()); - - if (replaceExistingStr != null && replaceExistingStr.trim().length() > 0) - { - replaceExisting = PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr); - } - - if (disableRulesStr != null && disableRulesStr.trim().length() > 0) - { - disableRules = PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr); - } - - // Initiate the import - NodeImporter nodeImporter = nodeImporterFactory.getNodeImporter(sourceDirectory); - BulkImportParameters bulkImportParameters = new BulkImportParameters(); - - if (numThreadsStr != null && numThreadsStr.trim().length() > 0) - { - try - { - numThreads = Integer.parseInt(numThreadsStr); - if(numThreads < 1) - { - throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0."); - } - bulkImportParameters.setNumThreads(numThreads); - } - catch(NumberFormatException e) - { - throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0."); - } - } - - if (batchSizeStr != null && batchSizeStr.trim().length() > 0) - { - try - { - batchSize = Integer.parseInt(batchSizeStr); - if(batchSize < 1) - { - throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0."); - } - bulkImportParameters.setBatchSize(batchSize); - } - catch(NumberFormatException e) - { - throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0."); - } - } - - bulkImportParameters.setReplaceExisting(replaceExisting); - bulkImportParameters.setTarget(targetNodeRef); - bulkImportParameters.setDisableRulesService(disableRules); - - bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter); - - // ACE-3047 fix, since bulk import is started asynchronously there is a chance that client - // will get into the status page before import is actually started. - // In this case wrong information (for previous import) will be displayed. - // So lets ensure that import started before redirecting client to status page. - int i = 0; - while (!bulkImporter.getStatus().inProgress() && i < 10) - { - Thread.sleep(100); - i++; - } - - // redirect to the status Web Script - status.setCode(Status.STATUS_MOVED_TEMPORARILY); - status.setRedirect(true); - status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS); - } - else - { - model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY)); - } - } - catch (WebScriptException wse) - { - status.setCode(Status.STATUS_BAD_REQUEST, wse.getMessage()); - status.setRedirect(true); - } - catch (FileNotFoundException fnfe) - { - status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !"); - status.setRedirect(true); - } - catch(IllegalArgumentException iae) - { - status.setCode(Status.STATUS_BAD_REQUEST,iae.getMessage()); - status.setRedirect(true); - } - catch (Throwable t) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t); - } - - return model; - } - -} + +package org.alfresco.repo.web.scripts.bulkimport.copy; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.bulkimport.BulkImportParameters; +import org.alfresco.repo.bulkimport.NodeImporter; +import org.alfresco.repo.bulkimport.impl.MultiThreadedBulkFilesystemImporter; +import org.alfresco.repo.bulkimport.impl.StreamingNodeImporterFactory; +import org.alfresco.repo.web.scripts.bulkimport.AbstractBulkFileSystemImportWebScript; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Web Script class that invokes a BulkFilesystemImporter implementation. + * + * @since 4.0 + */ +public class BulkFilesystemImportWebScript extends AbstractBulkFileSystemImportWebScript +{ + private MultiThreadedBulkFilesystemImporter bulkImporter; + private StreamingNodeImporterFactory nodeImporterFactory; + + public void setBulkImporter(MultiThreadedBulkFilesystemImporter bulkImporter) + { + this.bulkImporter = bulkImporter; + } + + public void setNodeImporterFactory(StreamingNodeImporterFactory nodeImporterFactory) + { + this.nodeImporterFactory = nodeImporterFactory; + } + + /** + * @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.Status, org.springframework.extensions.webscripts.Cache) + */ + @Override + protected Map executeImpl(final WebScriptRequest request, final Status status, final Cache cache) + { + Map model = new HashMap(); + String targetNodeRefStr = null; + String targetPath = null; + String sourceDirectoryStr = null; + String replaceExistingStr = null; + String batchSizeStr = null; + String numThreadsStr = null; + String disableRulesStr = null; + + cache.setNeverCache(true); + + try + { + if(!bulkImporter.getStatus().inProgress()) + { + NodeRef targetNodeRef = null; + File sourceDirectory = null; + boolean replaceExisting = false; + int batchSize = bulkImporter.getDefaultBatchSize(); + int numThreads = bulkImporter.getDefaultNumThreads(); + boolean disableRules = false; + + // Retrieve, validate and convert parameters + targetNodeRefStr = request.getParameter(PARAMETER_TARGET_NODEREF); + targetPath = request.getParameter(PARAMETER_TARGET_PATH); + sourceDirectoryStr = request.getParameter(PARAMETER_SOURCE_DIRECTORY); + replaceExistingStr = request.getParameter(PARAMETER_REPLACE_EXISTING); + batchSizeStr = request.getParameter(PARAMETER_BATCH_SIZE); + numThreadsStr = request.getParameter(PARAMETER_NUM_THREADS); + disableRulesStr = request.getParameter(PARAMETER_DISABLE_RULES); + + targetNodeRef = getTargetNodeRef(targetNodeRefStr, targetPath); + + if (sourceDirectoryStr == null || sourceDirectoryStr.trim().length() == 0) + { + throw new RuntimeException("Error: mandatory parameter '" + PARAMETER_SOURCE_DIRECTORY + "' was not provided."); + } + + sourceDirectory = new File(sourceDirectoryStr.trim()); + + if (replaceExistingStr != null && replaceExistingStr.trim().length() > 0) + { + replaceExisting = PARAMETER_VALUE_REPLACE_EXISTING.equals(replaceExistingStr); + } + + if (disableRulesStr != null && disableRulesStr.trim().length() > 0) + { + disableRules = PARAMETER_VALUE_DISABLE_RULES.equals(disableRulesStr); + } + + // Initiate the import + NodeImporter nodeImporter = nodeImporterFactory.getNodeImporter(sourceDirectory); + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + + if (numThreadsStr != null && numThreadsStr.trim().length() > 0) + { + try + { + numThreads = Integer.parseInt(numThreadsStr); + if(numThreads < 1) + { + throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0."); + } + bulkImportParameters.setNumThreads(numThreads); + } + catch(NumberFormatException e) + { + throw new RuntimeException("Error: parameter '" + PARAMETER_NUM_THREADS + "' must be an integer > 0."); + } + } + + if (batchSizeStr != null && batchSizeStr.trim().length() > 0) + { + try + { + batchSize = Integer.parseInt(batchSizeStr); + if(batchSize < 1) + { + throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0."); + } + bulkImportParameters.setBatchSize(batchSize); + } + catch(NumberFormatException e) + { + throw new RuntimeException("Error: parameter '" + PARAMETER_BATCH_SIZE + "' must be an integer > 0."); + } + } + + bulkImportParameters.setReplaceExisting(replaceExisting); + bulkImportParameters.setTarget(targetNodeRef); + bulkImportParameters.setDisableRulesService(disableRules); + + bulkImporter.asyncBulkImport(bulkImportParameters, nodeImporter); + + // ACE-3047 fix, since bulk import is started asynchronously there is a chance that client + // will get into the status page before import is actually started. + // In this case wrong information (for previous import) will be displayed. + // So lets ensure that import started before redirecting client to status page. + int i = 0; + while (!bulkImporter.getStatus().inProgress() && i < 10) + { + Thread.sleep(100); + i++; + } + + // redirect to the status Web Script + status.setCode(Status.STATUS_MOVED_TEMPORARILY); + status.setRedirect(true); + status.setLocation(request.getServiceContextPath() + WEB_SCRIPT_URI_BULK_FILESYSTEM_IMPORT_STATUS); + } + else + { + model.put(IMPORT_ALREADY_IN_PROGRESS_MODEL_KEY, I18NUtil.getMessage(IMPORT_ALREADY_IN_PROGRESS_ERROR_KEY)); + } + } + catch (WebScriptException wse) + { + status.setCode(Status.STATUS_BAD_REQUEST, wse.getMessage()); + status.setRedirect(true); + } + catch (FileNotFoundException fnfe) + { + status.setCode(Status.STATUS_BAD_REQUEST,"The repository path '" + targetPath + "' does not exist !"); + status.setRedirect(true); + } + catch(IllegalArgumentException iae) + { + status.setCode(Status.STATUS_BAD_REQUEST,iae.getMessage()); + status.setRedirect(true); + } + catch (Throwable t) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, buildTextMessage(t), t); + } + + return model; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/comments/AbstractCommentsWebScript.java b/source/java/org/alfresco/repo/web/scripts/comments/AbstractCommentsWebScript.java index 46ca6b46eb..98fa921f76 100644 --- a/source/java/org/alfresco/repo/web/scripts/comments/AbstractCommentsWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/comments/AbstractCommentsWebScript.java @@ -1,324 +1,324 @@ -package org.alfresco.repo.web.scripts.comments; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; - -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.policy.BehaviourFilter; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.activities.ActivityService; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONStringer; -import org.json.JSONWriter; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * This class is the abstract controller for the comments web scripts (delete - * and post) - * - * @author Ramona Popa - * @since 4.2.6 - */ -public abstract class AbstractCommentsWebScript extends DeclarativeWebScript -{ - - protected final static String COMMENTS_TOPIC_NAME = "Comments"; - - private static Log logger = LogFactory.getLog(CommentsPost.class); - - protected final static String JSON_KEY_SITE = "site"; - protected final static String JSON_KEY_SITE_ID = "siteid"; - protected final static String JSON_KEY_ITEM_TITLE = "itemTitle"; - protected final static String JSON_KEY_PAGE = "page"; - protected final static String JSON_KEY_TITLE = "title"; - protected final static String JSON_KEY_PAGE_PARAMS = "pageParams"; - protected final static String JSON_KEY_NODEREF = "nodeRef"; - protected final static String JSON_KEY_CONTENT = "content"; - - protected final static String COMMENT_CREATED_ACTIVITY = "org.alfresco.comments.comment-created"; - protected final static String COMMENT_DELETED_ACTIVITY = "org.alfresco.comments.comment-deleted"; - - protected ServiceRegistry serviceRegistry; - protected NodeService nodeService; - protected ContentService contentService; - protected PersonService personService; - protected SiteService siteService; - protected PermissionService permissionService; - protected ActivityService activityService; - - protected BehaviourFilter behaviourFilter; - - protected static final String PARAM_MESSAGE = "message"; - protected static final String PARAM_NODE = "node"; - protected static final String PARAM_ITEM = "item"; - - public void setServiceRegistry(ServiceRegistry serviceRegistry) - { - this.serviceRegistry = serviceRegistry; - this.nodeService = serviceRegistry.getNodeService(); - this.siteService = serviceRegistry.getSiteService(); - this.contentService = serviceRegistry.getContentService(); - this.personService = serviceRegistry.getPersonService(); - this.permissionService = serviceRegistry.getPermissionService(); - } - - public void setBehaviourFilter(BehaviourFilter behaviourFilter) - { - this.behaviourFilter = behaviourFilter; - } - - public void setActivityService(ActivityService activityService) - { - this.activityService = activityService; - } - - /** - * returns the nodeRef from web script request - * @param req - * @return - */ - protected NodeRef parseRequestForNodeRef(WebScriptRequest req) - { - Map templateVars = req.getServiceMatch().getTemplateVars(); - String storeType = templateVars.get("store_type"); - String storeId = templateVars.get("store_id"); - String nodeId = templateVars.get("id"); - - // create the NodeRef and ensure it is valid - StoreRef storeRef = new StoreRef(storeType, storeId); - return new NodeRef(storeRef, nodeId); - } - - /** - * get the value from JSON for given key if exists - * @param json - * @param key - * @return - */ - protected String getOrNull(JSONObject json, String key) - { - if (json != null && json.containsKey(key)) - { - return (String) json.get(key); - } - return null; - } - - /** - * parse JSON from request - * @param req - * @return - */ - protected JSONObject parseJSON(WebScriptRequest req) - { - JSONObject json = null; - String contentType = req.getContentType(); - if (contentType != null && contentType.indexOf(';') != -1) - { - contentType = contentType.substring(0, contentType.indexOf(';')); - } - if (MimetypeMap.MIMETYPE_JSON.equals(contentType)) - { - JSONParser parser = new JSONParser(); - try - { - json = (JSONObject) parser.parse(req.getContent().getContent()); - } - catch (IOException io) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage()); - } - catch (ParseException pe) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage()); - } - } - return json; - } - - /** - * parse JSON for a given input string - * @param input - * @return - */ - protected JSONObject parseJSONFromString(String input) - { - JSONObject json = null; - - JSONParser parser = new JSONParser(); - try - { - if (input != null) - { - json = (JSONObject) parser.parse(input); - return json; - } - } - catch (ParseException pe) - { - if (logger.isDebugEnabled()) - { - logger.debug("Invalid JSON: " + pe.getMessage()); - } - } - - return null; - } - - /** - * Post an activity entry for the comment added or deleted - * - * @param json - * - is not sent null with this activity type - only for delete - * @param req - * @param nodeRef - * @param activityType - */ - protected void postActivity(JSONObject json, WebScriptRequest req, NodeRef nodeRef, String activityType) - { - String jsonActivityData = ""; - String siteId = ""; - String page = ""; - String title = ""; - - if (nodeRef == null) - { - // in case we don't have an parent nodeRef provided we do not need - // to post activity for parent node - return; - } - - String strNodeRef = nodeRef.toString(); - - SiteInfo siteInfo = getSiteInfo(req, COMMENT_CREATED_ACTIVITY.equals(activityType)); - - // post an activity item, but only if we've got a site - if (siteInfo != null) - { - siteId = siteInfo.getShortName(); - if (siteId == null || siteId.length() == 0) - { - return; - } - } - - // json is not sent null with this activity type - only for delete - if (COMMENT_CREATED_ACTIVITY.equals(activityType)) - { - try - { - org.json.JSONObject params = new org.json.JSONObject(getOrNull(json, JSON_KEY_PAGE_PARAMS)); - String strParams = ""; - - Iterator itr = params.keys(); - while (itr.hasNext()) - { - String strParam = itr.next().toString(); - strParams += strParam + "=" + params.getString(strParam) + "&"; - } - page = getOrNull(json, JSON_KEY_PAGE) + "?" + (strParams != "" ? strParams.substring(0, strParams.length() - 1) : ""); - title = getOrNull(json, JSON_KEY_ITEM_TITLE); - - } - catch (Exception e) - { - logger.warn("Error parsing JSON", e); - } - } - else - { - // COMMENT_DELETED_ACTIVITY - title = req.getParameter(JSON_KEY_ITEM_TITLE); - page = req.getParameter(JSON_KEY_PAGE) + "?" + JSON_KEY_NODEREF + "=" + strNodeRef; - } - - try - { - JSONWriter jsonWriter = new JSONStringer().object(); - jsonWriter.key(JSON_KEY_TITLE).value(title); - jsonWriter.key(JSON_KEY_PAGE).value(page); - jsonWriter.key(JSON_KEY_NODEREF).value(strNodeRef); - - jsonActivityData = jsonWriter.endObject().toString(); - activityService.postActivity(activityType, siteId, COMMENTS_TOPIC_NAME, jsonActivityData); - } - catch (Exception e) - { - logger.warn("Error adding comment to activities feed", e); - } - - } - - /** - * returns SiteInfo needed for post activity - * @param req - * @return - */ - protected SiteInfo getSiteInfo(WebScriptRequest req, boolean searchForSiteInJSON) - { - String siteName = req.getParameter(JSON_KEY_SITE); - - if (siteName == null && searchForSiteInJSON ) - { - JSONObject json = parseJSON(req); - if (json != null){ - if (json.containsKey(JSON_KEY_SITE)) - { - siteName = (String) json.get(JSON_KEY_SITE); - } - else if (json.containsKey(JSON_KEY_SITE_ID)) - { - siteName = (String) json.get(JSON_KEY_SITE_ID); - } - } - } - if (siteName != null) - { - SiteInfo site = siteService.getSite(siteName); - return site; - } - - return null; - } - - /** - * Overrides DeclarativeWebScript with parse request for nodeRef - */ - @Override - protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) - { - // get requested node - NodeRef nodeRef = parseRequestForNodeRef(req); - - // Have the real work done - return executeImpl(nodeRef, req, status, cache); - } - - /** - * - * @param nodeRef - * @param req - * @param status - * @param cache - * @return - */ - protected abstract Map executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache); - -} +package org.alfresco.repo.web.scripts.comments; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; + +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONStringer; +import org.json.JSONWriter; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * This class is the abstract controller for the comments web scripts (delete + * and post) + * + * @author Ramona Popa + * @since 4.2.6 + */ +public abstract class AbstractCommentsWebScript extends DeclarativeWebScript +{ + + protected final static String COMMENTS_TOPIC_NAME = "Comments"; + + private static Log logger = LogFactory.getLog(CommentsPost.class); + + protected final static String JSON_KEY_SITE = "site"; + protected final static String JSON_KEY_SITE_ID = "siteid"; + protected final static String JSON_KEY_ITEM_TITLE = "itemTitle"; + protected final static String JSON_KEY_PAGE = "page"; + protected final static String JSON_KEY_TITLE = "title"; + protected final static String JSON_KEY_PAGE_PARAMS = "pageParams"; + protected final static String JSON_KEY_NODEREF = "nodeRef"; + protected final static String JSON_KEY_CONTENT = "content"; + + protected final static String COMMENT_CREATED_ACTIVITY = "org.alfresco.comments.comment-created"; + protected final static String COMMENT_DELETED_ACTIVITY = "org.alfresco.comments.comment-deleted"; + + protected ServiceRegistry serviceRegistry; + protected NodeService nodeService; + protected ContentService contentService; + protected PersonService personService; + protected SiteService siteService; + protected PermissionService permissionService; + protected ActivityService activityService; + + protected BehaviourFilter behaviourFilter; + + protected static final String PARAM_MESSAGE = "message"; + protected static final String PARAM_NODE = "node"; + protected static final String PARAM_ITEM = "item"; + + public void setServiceRegistry(ServiceRegistry serviceRegistry) + { + this.serviceRegistry = serviceRegistry; + this.nodeService = serviceRegistry.getNodeService(); + this.siteService = serviceRegistry.getSiteService(); + this.contentService = serviceRegistry.getContentService(); + this.personService = serviceRegistry.getPersonService(); + this.permissionService = serviceRegistry.getPermissionService(); + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + public void setActivityService(ActivityService activityService) + { + this.activityService = activityService; + } + + /** + * returns the nodeRef from web script request + * @param req + * @return + */ + protected NodeRef parseRequestForNodeRef(WebScriptRequest req) + { + Map templateVars = req.getServiceMatch().getTemplateVars(); + String storeType = templateVars.get("store_type"); + String storeId = templateVars.get("store_id"); + String nodeId = templateVars.get("id"); + + // create the NodeRef and ensure it is valid + StoreRef storeRef = new StoreRef(storeType, storeId); + return new NodeRef(storeRef, nodeId); + } + + /** + * get the value from JSON for given key if exists + * @param json + * @param key + * @return + */ + protected String getOrNull(JSONObject json, String key) + { + if (json != null && json.containsKey(key)) + { + return (String) json.get(key); + } + return null; + } + + /** + * parse JSON from request + * @param req + * @return + */ + protected JSONObject parseJSON(WebScriptRequest req) + { + JSONObject json = null; + String contentType = req.getContentType(); + if (contentType != null && contentType.indexOf(';') != -1) + { + contentType = contentType.substring(0, contentType.indexOf(';')); + } + if (MimetypeMap.MIMETYPE_JSON.equals(contentType)) + { + JSONParser parser = new JSONParser(); + try + { + json = (JSONObject) parser.parse(req.getContent().getContent()); + } + catch (IOException io) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage()); + } + catch (ParseException pe) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage()); + } + } + return json; + } + + /** + * parse JSON for a given input string + * @param input + * @return + */ + protected JSONObject parseJSONFromString(String input) + { + JSONObject json = null; + + JSONParser parser = new JSONParser(); + try + { + if (input != null) + { + json = (JSONObject) parser.parse(input); + return json; + } + } + catch (ParseException pe) + { + if (logger.isDebugEnabled()) + { + logger.debug("Invalid JSON: " + pe.getMessage()); + } + } + + return null; + } + + /** + * Post an activity entry for the comment added or deleted + * + * @param json + * - is not sent null with this activity type - only for delete + * @param req + * @param nodeRef + * @param activityType + */ + protected void postActivity(JSONObject json, WebScriptRequest req, NodeRef nodeRef, String activityType) + { + String jsonActivityData = ""; + String siteId = ""; + String page = ""; + String title = ""; + + if (nodeRef == null) + { + // in case we don't have an parent nodeRef provided we do not need + // to post activity for parent node + return; + } + + String strNodeRef = nodeRef.toString(); + + SiteInfo siteInfo = getSiteInfo(req, COMMENT_CREATED_ACTIVITY.equals(activityType)); + + // post an activity item, but only if we've got a site + if (siteInfo != null) + { + siteId = siteInfo.getShortName(); + if (siteId == null || siteId.length() == 0) + { + return; + } + } + + // json is not sent null with this activity type - only for delete + if (COMMENT_CREATED_ACTIVITY.equals(activityType)) + { + try + { + org.json.JSONObject params = new org.json.JSONObject(getOrNull(json, JSON_KEY_PAGE_PARAMS)); + String strParams = ""; + + Iterator itr = params.keys(); + while (itr.hasNext()) + { + String strParam = itr.next().toString(); + strParams += strParam + "=" + params.getString(strParam) + "&"; + } + page = getOrNull(json, JSON_KEY_PAGE) + "?" + (strParams != "" ? strParams.substring(0, strParams.length() - 1) : ""); + title = getOrNull(json, JSON_KEY_ITEM_TITLE); + + } + catch (Exception e) + { + logger.warn("Error parsing JSON", e); + } + } + else + { + // COMMENT_DELETED_ACTIVITY + title = req.getParameter(JSON_KEY_ITEM_TITLE); + page = req.getParameter(JSON_KEY_PAGE) + "?" + JSON_KEY_NODEREF + "=" + strNodeRef; + } + + try + { + JSONWriter jsonWriter = new JSONStringer().object(); + jsonWriter.key(JSON_KEY_TITLE).value(title); + jsonWriter.key(JSON_KEY_PAGE).value(page); + jsonWriter.key(JSON_KEY_NODEREF).value(strNodeRef); + + jsonActivityData = jsonWriter.endObject().toString(); + activityService.postActivity(activityType, siteId, COMMENTS_TOPIC_NAME, jsonActivityData); + } + catch (Exception e) + { + logger.warn("Error adding comment to activities feed", e); + } + + } + + /** + * returns SiteInfo needed for post activity + * @param req + * @return + */ + protected SiteInfo getSiteInfo(WebScriptRequest req, boolean searchForSiteInJSON) + { + String siteName = req.getParameter(JSON_KEY_SITE); + + if (siteName == null && searchForSiteInJSON ) + { + JSONObject json = parseJSON(req); + if (json != null){ + if (json.containsKey(JSON_KEY_SITE)) + { + siteName = (String) json.get(JSON_KEY_SITE); + } + else if (json.containsKey(JSON_KEY_SITE_ID)) + { + siteName = (String) json.get(JSON_KEY_SITE_ID); + } + } + } + if (siteName != null) + { + SiteInfo site = siteService.getSite(siteName); + return site; + } + + return null; + } + + /** + * Overrides DeclarativeWebScript with parse request for nodeRef + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + // get requested node + NodeRef nodeRef = parseRequestForNodeRef(req); + + // Have the real work done + return executeImpl(nodeRef, req, status, cache); + } + + /** + * + * @param nodeRef + * @param req + * @param status + * @param cache + * @return + */ + protected abstract Map executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache); + +} diff --git a/source/java/org/alfresco/repo/web/scripts/comments/CommentDelete.java b/source/java/org/alfresco/repo/web/scripts/comments/CommentDelete.java index 8ba6864e9e..2668d61479 100644 --- a/source/java/org/alfresco/repo/web/scripts/comments/CommentDelete.java +++ b/source/java/org/alfresco/repo/web/scripts/comments/CommentDelete.java @@ -1,113 +1,113 @@ -package org.alfresco.repo.web.scripts.comments; - -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.model.ForumModel; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * This class is the controller for the comment.delete web script. - * - * @author Ramona Popa - * @since 4.2.6 - */ - -public class CommentDelete extends AbstractCommentsWebScript -{ - - private static Log logger = LogFactory.getLog(CommentDelete.class); - - /** - * Overrides AbstractCommentsWebScript to delete comment - */ - @Override - protected Map executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache) - { - String pageParams = req.getParameter(JSON_KEY_PAGE_PARAMS); - - JSONObject jsonPageParams = parseJSONFromString(pageParams); - - String parentNodeRefStr = getOrNull(jsonPageParams, JSON_KEY_NODEREF); - NodeRef parentNodeRef = null; - if (parentNodeRefStr != null) - { - parentNodeRef = new NodeRef((String) getOrNull(jsonPageParams, JSON_KEY_NODEREF)); - } - - if (parentNodeRef != null) - { - this.behaviourFilter.disableBehaviour(parentNodeRef, ContentModel.ASPECT_AUDITABLE); - } - - try - { - // delete node - deleteComment(nodeRef); - - if (nodeService.exists(nodeRef)) - { - // comment was not removed - status.setCode(Status.STATUS_INTERNAL_SERVER_ERROR, "Unable to delete node: " + nodeRef); - return null; - } - - // generate response model for a comment node - Map model = generateModel(nodeRef); - - // post an activity item - it is ok to send json as null since the - // infos that we need are as parameters on request - postActivity(null, req, parentNodeRef, COMMENT_DELETED_ACTIVITY); - - status.setCode(Status.STATUS_OK); - return model; - - } - finally - { - if (parentNodeRef != null) - { - this.behaviourFilter.enableBehaviour(parentNodeRef, ContentModel.ASPECT_AUDITABLE); - } - } - } - - /** - * deletes comment node - * - * @param commentNodeRef - */ - private void deleteComment(NodeRef commentNodeRef) - { - QName nodeType = nodeService.getType(commentNodeRef); - if (!nodeType.equals(ForumModel.TYPE_POST)) - { - throw new IllegalArgumentException("Node to delete is not a comment node."); - } - - nodeService.deleteNode(commentNodeRef); - } - - /** - * generates model for delete comment script - * - * @param commentNodeRef - * @return - */ - private Map generateModel(NodeRef commentNodeRef) - { - Map model = new HashMap(2, 1.0f); - - model.put(PARAM_MESSAGE, "Node " + commentNodeRef + " deleted"); - - return model; - } -} +package org.alfresco.repo.web.scripts.comments; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONObject; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * This class is the controller for the comment.delete web script. + * + * @author Ramona Popa + * @since 4.2.6 + */ + +public class CommentDelete extends AbstractCommentsWebScript +{ + + private static Log logger = LogFactory.getLog(CommentDelete.class); + + /** + * Overrides AbstractCommentsWebScript to delete comment + */ + @Override + protected Map executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache) + { + String pageParams = req.getParameter(JSON_KEY_PAGE_PARAMS); + + JSONObject jsonPageParams = parseJSONFromString(pageParams); + + String parentNodeRefStr = getOrNull(jsonPageParams, JSON_KEY_NODEREF); + NodeRef parentNodeRef = null; + if (parentNodeRefStr != null) + { + parentNodeRef = new NodeRef((String) getOrNull(jsonPageParams, JSON_KEY_NODEREF)); + } + + if (parentNodeRef != null) + { + this.behaviourFilter.disableBehaviour(parentNodeRef, ContentModel.ASPECT_AUDITABLE); + } + + try + { + // delete node + deleteComment(nodeRef); + + if (nodeService.exists(nodeRef)) + { + // comment was not removed + status.setCode(Status.STATUS_INTERNAL_SERVER_ERROR, "Unable to delete node: " + nodeRef); + return null; + } + + // generate response model for a comment node + Map model = generateModel(nodeRef); + + // post an activity item - it is ok to send json as null since the + // infos that we need are as parameters on request + postActivity(null, req, parentNodeRef, COMMENT_DELETED_ACTIVITY); + + status.setCode(Status.STATUS_OK); + return model; + + } + finally + { + if (parentNodeRef != null) + { + this.behaviourFilter.enableBehaviour(parentNodeRef, ContentModel.ASPECT_AUDITABLE); + } + } + } + + /** + * deletes comment node + * + * @param commentNodeRef + */ + private void deleteComment(NodeRef commentNodeRef) + { + QName nodeType = nodeService.getType(commentNodeRef); + if (!nodeType.equals(ForumModel.TYPE_POST)) + { + throw new IllegalArgumentException("Node to delete is not a comment node."); + } + + nodeService.deleteNode(commentNodeRef); + } + + /** + * generates model for delete comment script + * + * @param commentNodeRef + * @return + */ + private Map generateModel(NodeRef commentNodeRef) + { + Map model = new HashMap(2, 1.0f); + + model.put(PARAM_MESSAGE, "Node " + commentNodeRef + " deleted"); + + return model; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/config/OpenSearchConfigElement.java b/source/java/org/alfresco/repo/web/scripts/config/OpenSearchConfigElement.java index 2c35313b77..fa3d6d0d3d 100644 --- a/source/java/org/alfresco/repo/web/scripts/config/OpenSearchConfigElement.java +++ b/source/java/org/alfresco/repo/web/scripts/config/OpenSearchConfigElement.java @@ -1,259 +1,259 @@ -package org.alfresco.repo.web.scripts.config; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.extensions.config.ConfigElement; -import org.springframework.extensions.config.ConfigException; -import org.springframework.extensions.config.element.ConfigElementAdapter; - - -/** - * Custom config element that represents the config data for open search - * - * @author davidc - */ -public class OpenSearchConfigElement extends ConfigElementAdapter -{ - public static final String CONFIG_ELEMENT_ID = "opensearch"; - - private ProxyConfig proxy; - private Set engines = new HashSet(8, 10f); - private Map enginesByProxy = new HashMap(); - - - /** - * Default constructor - */ - public OpenSearchConfigElement() - { - super(CONFIG_ELEMENT_ID); - } - - /** - * Constructor - * - * @param name Name of the element this config element represents - */ - public OpenSearchConfigElement(String name) - { - super(name); - } - - /** - * @see ConfigElement#getChildren() - */ - public List getChildren() - { - throw new ConfigException("Reading the open search config via the generic interfaces is not supported"); - } - - /** - * @see ConfigElement#combine(ConfigElement) - */ - public ConfigElement combine(ConfigElement configElement) - { - OpenSearchConfigElement newElement = (OpenSearchConfigElement) configElement; - OpenSearchConfigElement combinedElement = new OpenSearchConfigElement(); - - // add all the plugins from this element - for (EngineConfig plugin : this.getEngines()) - { - combinedElement.addEngine(plugin); - } - - // add all the plugins from the given element - for (EngineConfig plugin : newElement.getEngines()) - { - combinedElement.addEngine(plugin); - } - - // set the proxy configuration - ProxyConfig proxyConfig = this.getProxy(); - if (proxyConfig != null) - { - combinedElement.setProxy(proxyConfig); - } - - return combinedElement; - } - - /** - * Sets the proxy configuration - * - * @param proxyConfig ProxyConfig - */ - /*package*/ void setProxy(ProxyConfig proxyConfig) - { - this.proxy = proxyConfig; - } - - /** - * Gets the proxy configuration - * - * @return The proxy configuration - */ - public ProxyConfig getProxy() - { - return this.proxy; - } - - /** - * @return Returns a set of the engines - */ - public Set getEngines() - { - return this.engines; - } - - /** - * @param proxy name of engine proxy - * @return associated engine config (or null, if none registered against proxy) - */ - public EngineConfig getEngine(String proxy) - { - return this.enginesByProxy.get(proxy); - } - - /** - * Adds an engine - * - * @param engineConfig A pre-configured engine config object - */ - /*package*/ void addEngine(EngineConfig engineConfig) - { - this.engines.add(engineConfig); - String proxy = engineConfig.getProxy(); - if (proxy != null && proxy.length() > 0) - { - this.enginesByProxy.put(proxy, engineConfig); - } - } - - - /** - * Inner class representing the configuration of an OpenSearch engine - * - * @author davidc - */ - public static class EngineConfig - { - protected String label; - protected String labelId; - protected String proxy; - protected Map urls = new HashMap(8, 10f); - - - /** - * Construct - * - * @param label String - * @param labelId String - */ - public EngineConfig(String label, String labelId) - { - if ((label == null || label.length() == 0) && (labelId == null || labelId.length() == 0)) - { - throw new IllegalArgumentException("'label' or 'label-id' must be specified"); - } - this.label = label; - this.labelId = labelId; - } - - /** - * Construct - * - * @param label String - * @param labelId String - * @param proxy String - */ - public EngineConfig(String label, String labelId, String proxy) - { - this(label, labelId); - this.proxy = proxy; - } - - /** - * @return I18N label id - */ - public String getLabelId() - { - return labelId; - } - - /** - * @return label - */ - public String getLabel() - { - return label; - } - - /** - * @return proxy - */ - public String getProxy() - { - return proxy; - } - - /** - * Gets the urls supported by this engine - * - * @return urls - */ - public Map getUrls() - { - return urls; - } - - /** - * Adds a url - * - * @param mimetype mime type - * @param uri uri - */ - /*package*/ void addUrl(String mimetype, String uri) - { - this.urls.put(mimetype, uri); - } - - } - - - /** - * Inner class representing the configuration of the OpenSearch proxy - * - * @author davidc - */ - public static class ProxyConfig - { - protected String url; - - /** - * Construct - * - * @param url String - */ - public ProxyConfig(String url) - { - if (url == null || url.length() == 0) - { - throw new IllegalArgumentException("'url' must be specified"); - } - this.url = url; - } - - /** - * @return url - */ - public String getUrl() - { - return url; - } - } - -} +package org.alfresco.repo.web.scripts.config; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.extensions.config.ConfigElement; +import org.springframework.extensions.config.ConfigException; +import org.springframework.extensions.config.element.ConfigElementAdapter; + + +/** + * Custom config element that represents the config data for open search + * + * @author davidc + */ +public class OpenSearchConfigElement extends ConfigElementAdapter +{ + public static final String CONFIG_ELEMENT_ID = "opensearch"; + + private ProxyConfig proxy; + private Set engines = new HashSet(8, 10f); + private Map enginesByProxy = new HashMap(); + + + /** + * Default constructor + */ + public OpenSearchConfigElement() + { + super(CONFIG_ELEMENT_ID); + } + + /** + * Constructor + * + * @param name Name of the element this config element represents + */ + public OpenSearchConfigElement(String name) + { + super(name); + } + + /** + * @see ConfigElement#getChildren() + */ + public List getChildren() + { + throw new ConfigException("Reading the open search config via the generic interfaces is not supported"); + } + + /** + * @see ConfigElement#combine(ConfigElement) + */ + public ConfigElement combine(ConfigElement configElement) + { + OpenSearchConfigElement newElement = (OpenSearchConfigElement) configElement; + OpenSearchConfigElement combinedElement = new OpenSearchConfigElement(); + + // add all the plugins from this element + for (EngineConfig plugin : this.getEngines()) + { + combinedElement.addEngine(plugin); + } + + // add all the plugins from the given element + for (EngineConfig plugin : newElement.getEngines()) + { + combinedElement.addEngine(plugin); + } + + // set the proxy configuration + ProxyConfig proxyConfig = this.getProxy(); + if (proxyConfig != null) + { + combinedElement.setProxy(proxyConfig); + } + + return combinedElement; + } + + /** + * Sets the proxy configuration + * + * @param proxyConfig ProxyConfig + */ + /*package*/ void setProxy(ProxyConfig proxyConfig) + { + this.proxy = proxyConfig; + } + + /** + * Gets the proxy configuration + * + * @return The proxy configuration + */ + public ProxyConfig getProxy() + { + return this.proxy; + } + + /** + * @return Returns a set of the engines + */ + public Set getEngines() + { + return this.engines; + } + + /** + * @param proxy name of engine proxy + * @return associated engine config (or null, if none registered against proxy) + */ + public EngineConfig getEngine(String proxy) + { + return this.enginesByProxy.get(proxy); + } + + /** + * Adds an engine + * + * @param engineConfig A pre-configured engine config object + */ + /*package*/ void addEngine(EngineConfig engineConfig) + { + this.engines.add(engineConfig); + String proxy = engineConfig.getProxy(); + if (proxy != null && proxy.length() > 0) + { + this.enginesByProxy.put(proxy, engineConfig); + } + } + + + /** + * Inner class representing the configuration of an OpenSearch engine + * + * @author davidc + */ + public static class EngineConfig + { + protected String label; + protected String labelId; + protected String proxy; + protected Map urls = new HashMap(8, 10f); + + + /** + * Construct + * + * @param label String + * @param labelId String + */ + public EngineConfig(String label, String labelId) + { + if ((label == null || label.length() == 0) && (labelId == null || labelId.length() == 0)) + { + throw new IllegalArgumentException("'label' or 'label-id' must be specified"); + } + this.label = label; + this.labelId = labelId; + } + + /** + * Construct + * + * @param label String + * @param labelId String + * @param proxy String + */ + public EngineConfig(String label, String labelId, String proxy) + { + this(label, labelId); + this.proxy = proxy; + } + + /** + * @return I18N label id + */ + public String getLabelId() + { + return labelId; + } + + /** + * @return label + */ + public String getLabel() + { + return label; + } + + /** + * @return proxy + */ + public String getProxy() + { + return proxy; + } + + /** + * Gets the urls supported by this engine + * + * @return urls + */ + public Map getUrls() + { + return urls; + } + + /** + * Adds a url + * + * @param mimetype mime type + * @param uri uri + */ + /*package*/ void addUrl(String mimetype, String uri) + { + this.urls.put(mimetype, uri); + } + + } + + + /** + * Inner class representing the configuration of the OpenSearch proxy + * + * @author davidc + */ + public static class ProxyConfig + { + protected String url; + + /** + * Construct + * + * @param url String + */ + public ProxyConfig(String url) + { + if (url == null || url.length() == 0) + { + throw new IllegalArgumentException("'url' must be specified"); + } + this.url = url; + } + + /** + * @return url + */ + public String getUrl() + { + return url; + } + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/config/OpenSearchElementReader.java b/source/java/org/alfresco/repo/web/scripts/config/OpenSearchElementReader.java index 23bcb95ece..faea8aa56b 100644 --- a/source/java/org/alfresco/repo/web/scripts/config/OpenSearchElementReader.java +++ b/source/java/org/alfresco/repo/web/scripts/config/OpenSearchElementReader.java @@ -1,95 +1,95 @@ -package org.alfresco.repo.web.scripts.config; - -import java.util.Iterator; - -import org.springframework.extensions.config.ConfigElement; -import org.springframework.extensions.config.ConfigException; -import org.springframework.extensions.config.xml.elementreader.ConfigElementReader; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig; -import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig; -import org.dom4j.Element; - - -/** - * Custom element reader to parse config for the open search - * - * @author davidc - */ -public class OpenSearchElementReader implements ConfigElementReader -{ - public static final String ELEMENT_OPENSEARCH = "opensearch"; - public static final String ELEMENT_ENGINES = "engines"; - public static final String ELEMENT_ENGINE = "engine"; - public static final String ELEMENT_URL = "url"; - public static final String ELEMENT_PROXY = "proxy"; - public static final String ATTR_TYPE = "type"; - public static final String ATTR_LABEL = "label"; - public static final String ATTR_LABEL_ID = "label-id"; - public static final String ATTR_PROXY = "proxy"; - - - /** - * @see org.springframework.extensions.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element) - */ - @SuppressWarnings("unchecked") - public ConfigElement parse(Element element) - { - OpenSearchConfigElement configElement = null; - - if (element != null) - { - String elementName = element.getName(); - if (elementName.equals(ELEMENT_OPENSEARCH) == false) - { - throw new ConfigException("OpenSearchElementReader can only parse " + ELEMENT_OPENSEARCH - + "elements, the element passed was '" + elementName + "'"); - } - - // go through the registered engines - configElement = new OpenSearchConfigElement(); - Element pluginsElem = element.element(ELEMENT_ENGINES); - if (pluginsElem != null) - { - Iterator engines = pluginsElem.elementIterator(ELEMENT_ENGINE); - while(engines.hasNext()) - { - // construct engine - Element engineElem = engines.next(); - String label = engineElem.attributeValue(ATTR_LABEL); - String labelId = engineElem.attributeValue(ATTR_LABEL_ID); - String proxy = engineElem.attributeValue(ATTR_PROXY); - EngineConfig engineCfg = new EngineConfig(label, labelId, proxy); - - // construct urls for engine - Iterator urlsConfig = engineElem.elementIterator(ELEMENT_URL); - while (urlsConfig.hasNext()) - { - Element urlConfig = urlsConfig.next(); - String type = urlConfig.attributeValue(ATTR_TYPE); - String url = urlConfig.getTextTrim(); - engineCfg.addUrl(type, url); - } - - // register engine config - configElement.addEngine(engineCfg); - } - } - - // extract proxy configuration - String url = null; - Element proxyElem = element.element(ELEMENT_PROXY); - if (proxyElem != null) - { - Element urlElem = proxyElem.element(ELEMENT_URL); - if (urlElem != null) - { - url = urlElem.getTextTrim(); - ProxyConfig proxyCfg = new ProxyConfig(url); - configElement.setProxy(proxyCfg); - } - } - } - - return configElement; - } -} +package org.alfresco.repo.web.scripts.config; + +import java.util.Iterator; + +import org.springframework.extensions.config.ConfigElement; +import org.springframework.extensions.config.ConfigException; +import org.springframework.extensions.config.xml.elementreader.ConfigElementReader; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig; +import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig; +import org.dom4j.Element; + + +/** + * Custom element reader to parse config for the open search + * + * @author davidc + */ +public class OpenSearchElementReader implements ConfigElementReader +{ + public static final String ELEMENT_OPENSEARCH = "opensearch"; + public static final String ELEMENT_ENGINES = "engines"; + public static final String ELEMENT_ENGINE = "engine"; + public static final String ELEMENT_URL = "url"; + public static final String ELEMENT_PROXY = "proxy"; + public static final String ATTR_TYPE = "type"; + public static final String ATTR_LABEL = "label"; + public static final String ATTR_LABEL_ID = "label-id"; + public static final String ATTR_PROXY = "proxy"; + + + /** + * @see org.springframework.extensions.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element) + */ + @SuppressWarnings("unchecked") + public ConfigElement parse(Element element) + { + OpenSearchConfigElement configElement = null; + + if (element != null) + { + String elementName = element.getName(); + if (elementName.equals(ELEMENT_OPENSEARCH) == false) + { + throw new ConfigException("OpenSearchElementReader can only parse " + ELEMENT_OPENSEARCH + + "elements, the element passed was '" + elementName + "'"); + } + + // go through the registered engines + configElement = new OpenSearchConfigElement(); + Element pluginsElem = element.element(ELEMENT_ENGINES); + if (pluginsElem != null) + { + Iterator engines = pluginsElem.elementIterator(ELEMENT_ENGINE); + while(engines.hasNext()) + { + // construct engine + Element engineElem = engines.next(); + String label = engineElem.attributeValue(ATTR_LABEL); + String labelId = engineElem.attributeValue(ATTR_LABEL_ID); + String proxy = engineElem.attributeValue(ATTR_PROXY); + EngineConfig engineCfg = new EngineConfig(label, labelId, proxy); + + // construct urls for engine + Iterator urlsConfig = engineElem.elementIterator(ELEMENT_URL); + while (urlsConfig.hasNext()) + { + Element urlConfig = urlsConfig.next(); + String type = urlConfig.attributeValue(ATTR_TYPE); + String url = urlConfig.getTextTrim(); + engineCfg.addUrl(type, url); + } + + // register engine config + configElement.addEngine(engineCfg); + } + } + + // extract proxy configuration + String url = null; + Element proxyElem = element.element(ELEMENT_PROXY); + if (proxyElem != null) + { + Element urlElem = proxyElem.element(ELEMENT_URL); + if (urlElem != null) + { + url = urlElem.getTextTrim(); + ProxyConfig proxyCfg = new ProxyConfig(url); + configElement.setProxy(proxyCfg); + } + } + } + + return configElement; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/content/StreamACP.java b/source/java/org/alfresco/repo/web/scripts/content/StreamACP.java index a35de3e2d6..a30bf337a4 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/StreamACP.java +++ b/source/java/org/alfresco/repo/web/scripts/content/StreamACP.java @@ -1,219 +1,219 @@ -package org.alfresco.repo.web.scripts.content; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.repo.exporter.ACPExportPackageHandler; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.view.ExporterCrawlerParameters; -import org.alfresco.service.cmr.view.ExporterService; -import org.alfresco.service.cmr.view.Location; -import org.alfresco.util.GUID; -import org.alfresco.util.TempFileProvider; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; - -/** - * Base class for Java backed webscripts that wish to generate an ACP and - * stream the contents back to the caller. - *

- * The default implementation generates an ACP file containing the provided - * NodeRefs and all their respective children. - * - * @author Gavin Cornwell - */ -public class StreamACP extends StreamContent -{ - /** Logger */ - private static Log logger = LogFactory.getLog(StreamACP.class); - - protected static final String TEMP_FILE_PREFIX = "export_"; - protected static final String MULTIPART_FORMDATA = "multipart/form-data"; - protected static final String ZIP_EXTENSION = "zip"; - - protected static final String PARAM_NODE_REFS = "nodeRefs"; - - protected ExporterService exporterService; - - /** - * Sets the ExporterService to use - * - * @param exporterService The ExporterService - */ - public void setExporterService(ExporterService exporterService) - { - this.exporterService = exporterService; - } - - /** - * @see org.springframework.extensions.webscripts.WebScript#execute(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) - */ - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - File tempACPFile = null; - try - { - NodeRef[] nodeRefs = null; - String contentType = req.getContentType(); - if (MULTIPART_FORMDATA.equals(contentType)) - { - // get nodeRefs parameter from form - nodeRefs = getNodeRefs(req.getParameter(PARAM_NODE_REFS)); - } - else - { - // presume the request is a JSON request so get nodeRefs from JSON body - nodeRefs = getNodeRefs(new JSONObject(new JSONTokener(req.getContent().getContent()))); - } - - // setup the ACP parameters - ExporterCrawlerParameters params = new ExporterCrawlerParameters(); - params.setCrawlSelf(true); - params.setCrawlChildNodes(true); - params.setExportFrom(new Location(nodeRefs)); - - // create an ACP of the nodes - tempACPFile = createACP(params, ACPExportPackageHandler.ACP_EXTENSION, false); - - // stream the ACP back to the client as an attachment (forcing save as) - streamContent(req, res, tempACPFile, true, tempACPFile.getName(), null); - } - catch (IOException ioe) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Could not read content from req.", ioe); - } - catch (JSONException je) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Could not parse JSON from req.", je); - } - finally - { - // try and delete the temporary file - if (tempACPFile != null) - { - if (logger.isDebugEnabled()) - logger.debug("Deleting temporary archive: " + tempACPFile.getAbsolutePath()); - - tempACPFile.delete(); - } - } - } - - /** - * Converts the given comma delimited string of NodeRefs to an array - * of NodeRefs. If the string is null a WebScriptException is thrown. - * - * @param nodeRefsParam Comma delimited string of NodeRefs - * @return Array of NodeRef objects - */ - protected NodeRef[] getNodeRefs(String nodeRefsParam) - { - // check the list of NodeRefs is present - if (nodeRefsParam == null) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Mandatory 'nodeRefs' parameter was not provided in form data"); - } - - List listNodeRefs = new ArrayList(8); - StringTokenizer tokenizer = new StringTokenizer(nodeRefsParam, ","); - while (tokenizer.hasMoreTokens()) - { - listNodeRefs.add(new NodeRef(tokenizer.nextToken().trim())); - } - - NodeRef[] nodeRefs = new NodeRef[listNodeRefs.size()]; - nodeRefs = listNodeRefs.toArray(nodeRefs); - - return nodeRefs; - } - - /** - * Attempts to retrieve and convert a JSON array of - * NodeRefs from the given JSON object. If the nodeRefs - * property is not present a WebScriptException is thrown. - * - * @param json JSONObject - * @return Array of NodeRef objects - */ - protected NodeRef[] getNodeRefs(JSONObject json) throws JSONException - { - // check the list of NodeRefs is present - if (!json.has(PARAM_NODE_REFS)) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Mandatory 'nodeRefs' parameter was not provided in request body"); - } - - NodeRef[] nodeRefs = new NodeRef[0]; - JSONArray jsonArray = json.getJSONArray(PARAM_NODE_REFS); - if (jsonArray.length() != 0) - { - // build the list of NodeRefs - nodeRefs = new NodeRef[jsonArray.length()]; - for (int i = 0; i < jsonArray.length(); i++) - { - NodeRef nodeRef = new NodeRef(jsonArray.getString(i)); - nodeRefs[i] = nodeRef; - } - } - - return nodeRefs; - } - - /** - * Returns an ACP file containing the nodes represented by the given list of NodeRefs. - * - * @param params The parameters for the ACP exporter - * @param extension The file extenstion to use for the ACP file - * @param keepFolderStructure Determines whether the folder structure is maintained for - * the content inside the ACP file - * @return File object representing the created ACP - */ - protected File createACP(ExporterCrawlerParameters params, String extension, boolean keepFolderStructure) - { - try - { - // generate temp file and folder name - File dataFile = new File(GUID.generate()); - File contentDir = new File(GUID.generate()); - - // setup export package handler - File acpFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, "." + extension); - ACPExportPackageHandler handler = new ACPExportPackageHandler(new FileOutputStream(acpFile), - dataFile, contentDir, this.mimetypeService); - handler.setExportAsFolders(keepFolderStructure); - handler.setNodeService(this.nodeService); - - // perform the actual export - this.exporterService.exportView(handler, params, null); - - if (logger.isDebugEnabled()) - logger.debug("Created temporary archive: " + acpFile.getAbsolutePath()); - - return acpFile; - } - catch (FileNotFoundException fnfe) - { - throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Failed to create archive", fnfe); - } - } +package org.alfresco.repo.web.scripts.content; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.exporter.ACPExportPackageHandler; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.view.ExporterCrawlerParameters; +import org.alfresco.service.cmr.view.ExporterService; +import org.alfresco.service.cmr.view.Location; +import org.alfresco.util.GUID; +import org.alfresco.util.TempFileProvider; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +/** + * Base class for Java backed webscripts that wish to generate an ACP and + * stream the contents back to the caller. + *

+ * The default implementation generates an ACP file containing the provided + * NodeRefs and all their respective children. + * + * @author Gavin Cornwell + */ +public class StreamACP extends StreamContent +{ + /** Logger */ + private static Log logger = LogFactory.getLog(StreamACP.class); + + protected static final String TEMP_FILE_PREFIX = "export_"; + protected static final String MULTIPART_FORMDATA = "multipart/form-data"; + protected static final String ZIP_EXTENSION = "zip"; + + protected static final String PARAM_NODE_REFS = "nodeRefs"; + + protected ExporterService exporterService; + + /** + * Sets the ExporterService to use + * + * @param exporterService The ExporterService + */ + public void setExporterService(ExporterService exporterService) + { + this.exporterService = exporterService; + } + + /** + * @see org.springframework.extensions.webscripts.WebScript#execute(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + File tempACPFile = null; + try + { + NodeRef[] nodeRefs = null; + String contentType = req.getContentType(); + if (MULTIPART_FORMDATA.equals(contentType)) + { + // get nodeRefs parameter from form + nodeRefs = getNodeRefs(req.getParameter(PARAM_NODE_REFS)); + } + else + { + // presume the request is a JSON request so get nodeRefs from JSON body + nodeRefs = getNodeRefs(new JSONObject(new JSONTokener(req.getContent().getContent()))); + } + + // setup the ACP parameters + ExporterCrawlerParameters params = new ExporterCrawlerParameters(); + params.setCrawlSelf(true); + params.setCrawlChildNodes(true); + params.setExportFrom(new Location(nodeRefs)); + + // create an ACP of the nodes + tempACPFile = createACP(params, ACPExportPackageHandler.ACP_EXTENSION, false); + + // stream the ACP back to the client as an attachment (forcing save as) + streamContent(req, res, tempACPFile, true, tempACPFile.getName(), null); + } + catch (IOException ioe) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Could not read content from req.", ioe); + } + catch (JSONException je) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Could not parse JSON from req.", je); + } + finally + { + // try and delete the temporary file + if (tempACPFile != null) + { + if (logger.isDebugEnabled()) + logger.debug("Deleting temporary archive: " + tempACPFile.getAbsolutePath()); + + tempACPFile.delete(); + } + } + } + + /** + * Converts the given comma delimited string of NodeRefs to an array + * of NodeRefs. If the string is null a WebScriptException is thrown. + * + * @param nodeRefsParam Comma delimited string of NodeRefs + * @return Array of NodeRef objects + */ + protected NodeRef[] getNodeRefs(String nodeRefsParam) + { + // check the list of NodeRefs is present + if (nodeRefsParam == null) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Mandatory 'nodeRefs' parameter was not provided in form data"); + } + + List listNodeRefs = new ArrayList(8); + StringTokenizer tokenizer = new StringTokenizer(nodeRefsParam, ","); + while (tokenizer.hasMoreTokens()) + { + listNodeRefs.add(new NodeRef(tokenizer.nextToken().trim())); + } + + NodeRef[] nodeRefs = new NodeRef[listNodeRefs.size()]; + nodeRefs = listNodeRefs.toArray(nodeRefs); + + return nodeRefs; + } + + /** + * Attempts to retrieve and convert a JSON array of + * NodeRefs from the given JSON object. If the nodeRefs + * property is not present a WebScriptException is thrown. + * + * @param json JSONObject + * @return Array of NodeRef objects + */ + protected NodeRef[] getNodeRefs(JSONObject json) throws JSONException + { + // check the list of NodeRefs is present + if (!json.has(PARAM_NODE_REFS)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Mandatory 'nodeRefs' parameter was not provided in request body"); + } + + NodeRef[] nodeRefs = new NodeRef[0]; + JSONArray jsonArray = json.getJSONArray(PARAM_NODE_REFS); + if (jsonArray.length() != 0) + { + // build the list of NodeRefs + nodeRefs = new NodeRef[jsonArray.length()]; + for (int i = 0; i < jsonArray.length(); i++) + { + NodeRef nodeRef = new NodeRef(jsonArray.getString(i)); + nodeRefs[i] = nodeRef; + } + } + + return nodeRefs; + } + + /** + * Returns an ACP file containing the nodes represented by the given list of NodeRefs. + * + * @param params The parameters for the ACP exporter + * @param extension The file extenstion to use for the ACP file + * @param keepFolderStructure Determines whether the folder structure is maintained for + * the content inside the ACP file + * @return File object representing the created ACP + */ + protected File createACP(ExporterCrawlerParameters params, String extension, boolean keepFolderStructure) + { + try + { + // generate temp file and folder name + File dataFile = new File(GUID.generate()); + File contentDir = new File(GUID.generate()); + + // setup export package handler + File acpFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, "." + extension); + ACPExportPackageHandler handler = new ACPExportPackageHandler(new FileOutputStream(acpFile), + dataFile, contentDir, this.mimetypeService); + handler.setExportAsFolders(keepFolderStructure); + handler.setNodeService(this.nodeService); + + // perform the actual export + this.exporterService.exportView(handler, params, null); + + if (logger.isDebugEnabled()) + logger.debug("Created temporary archive: " + acpFile.getAbsolutePath()); + + return acpFile; + } + catch (FileNotFoundException fnfe) + { + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Failed to create archive", fnfe); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/content/StreamJMXDump.java b/source/java/org/alfresco/repo/web/scripts/content/StreamJMXDump.java index 14775894a4..a64cdebd13 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/StreamJMXDump.java +++ b/source/java/org/alfresco/repo/web/scripts/content/StreamJMXDump.java @@ -1,102 +1,102 @@ -package org.alfresco.repo.web.scripts.content; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import javax.management.MBeanServerConnection; - -import org.alfresco.repo.management.JmxDumpUtil; -import org.alfresco.util.TempFileProvider; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.util.FileCopyUtils; - -/** - * WebScript java backed bean implementation to stream the JMX property - * dump as a .zip content file. - * - * @author Kevin Roast - */ -public class StreamJMXDump extends StreamContent -{ - /** Logger */ - private static Log logger = LogFactory.getLog(StreamJMXDump.class); - - /** The MBean server. */ - private MBeanServerConnection mbeanServer; - - - /** - * @param mBeanServer MBeanServerConnection bean - */ - public void setMBeanServer(MBeanServerConnection mBeanServer) - { - this.mbeanServer = mBeanServer; - } - - /** - * @see org.springframework.extensions.webscripts.WebScript#execute(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) - */ - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - PrintWriter tempFileOut = null; - ZipOutputStream zout = null; - try - { - // content type and caching - res.setContentType("application/zip"); - Cache cache = new Cache(); - cache.setNeverCache(true); - cache.setMustRevalidate(true); - cache.setMaxAge(0L); - res.setCache(cache); - - Date date = new Date(); - String attachFileName = "jmxdump_" + (date.getYear()+1900) + '_' + (date.getMonth()+1) + '_' + (date.getDate()); - String headerValue = "attachment; filename=\"" + attachFileName + ".zip\""; - - // set header based on filename - will force a Save As from the browse if it doesn't recognize it - // this is better than the default response of the browser trying to display the contents - res.setHeader("Content-Disposition", headerValue); - - // write JMX data to temp file - File tempFile = TempFileProvider.createTempFile("jmxdump", ".txt"); - tempFileOut = new PrintWriter(tempFile); - JmxDumpUtil.dumpConnection(mbeanServer, tempFileOut); - tempFileOut.flush(); - tempFileOut.close(); - tempFileOut = null; - - // zip output - zout = new ZipOutputStream(res.getOutputStream()); - ZipEntry zipEntry = new ZipEntry(attachFileName + ".txt"); - zout.putNextEntry(zipEntry); - FileCopyUtils.copy(new FileInputStream(tempFile), zout); - zout = null; - } - catch (IOException ioe) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Could not output JMX dump: " + ioe.getMessage(), ioe); - } - finally - { - if (tempFileOut != null) tempFileOut.close(); - try - { - if (zout != null) zout.close(); - } - catch (IOException e1) {} - } - } +package org.alfresco.repo.web.scripts.content; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Date; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.management.MBeanServerConnection; + +import org.alfresco.repo.management.JmxDumpUtil; +import org.alfresco.util.TempFileProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.util.FileCopyUtils; + +/** + * WebScript java backed bean implementation to stream the JMX property + * dump as a .zip content file. + * + * @author Kevin Roast + */ +public class StreamJMXDump extends StreamContent +{ + /** Logger */ + private static Log logger = LogFactory.getLog(StreamJMXDump.class); + + /** The MBean server. */ + private MBeanServerConnection mbeanServer; + + + /** + * @param mBeanServer MBeanServerConnection bean + */ + public void setMBeanServer(MBeanServerConnection mBeanServer) + { + this.mbeanServer = mBeanServer; + } + + /** + * @see org.springframework.extensions.webscripts.WebScript#execute(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) + */ + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + PrintWriter tempFileOut = null; + ZipOutputStream zout = null; + try + { + // content type and caching + res.setContentType("application/zip"); + Cache cache = new Cache(); + cache.setNeverCache(true); + cache.setMustRevalidate(true); + cache.setMaxAge(0L); + res.setCache(cache); + + Date date = new Date(); + String attachFileName = "jmxdump_" + (date.getYear()+1900) + '_' + (date.getMonth()+1) + '_' + (date.getDate()); + String headerValue = "attachment; filename=\"" + attachFileName + ".zip\""; + + // set header based on filename - will force a Save As from the browse if it doesn't recognize it + // this is better than the default response of the browser trying to display the contents + res.setHeader("Content-Disposition", headerValue); + + // write JMX data to temp file + File tempFile = TempFileProvider.createTempFile("jmxdump", ".txt"); + tempFileOut = new PrintWriter(tempFile); + JmxDumpUtil.dumpConnection(mbeanServer, tempFileOut); + tempFileOut.flush(); + tempFileOut.close(); + tempFileOut = null; + + // zip output + zout = new ZipOutputStream(res.getOutputStream()); + ZipEntry zipEntry = new ZipEntry(attachFileName + ".txt"); + zout.putNextEntry(zipEntry); + FileCopyUtils.copy(new FileInputStream(tempFile), zout); + zout = null; + } + catch (IOException ioe) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Could not output JMX dump: " + ioe.getMessage(), ioe); + } + finally + { + if (tempFileOut != null) tempFileOut.close(); + try + { + if (zout != null) zout.close(); + } + catch (IOException e1) {} + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationGet.java index 05d1349464..e8a55e3005 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationGet.java @@ -1,44 +1,44 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/* - * Webscript to get the Associationdefinition for a given classname and association-name - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class AssociationGet extends AbstractAssociationGet -{ - private static final String DICTIONARY_CLASS_NAME = "classname"; - private static final String DICTIONARY_ASSOCIATION_NAME = "assocname"; - - @Override - protected QName getAssociationQname(WebScriptRequest req) - { - String associationName = req.getServiceMatch().getTemplateVars().get(DICTIONARY_ASSOCIATION_NAME); - if(associationName == null) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Missing parameter association name in the URL"); - } - - return QName.createQName(getFullNamespaceURI(associationName)); - } - - @Override - protected QName getClassQname(WebScriptRequest req) - { - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - - // validate the classname - if (isValidClassname(className) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); - } - - return QName.createQName(getFullNamespaceURI(className)); - } - +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/* + * Webscript to get the Associationdefinition for a given classname and association-name + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class AssociationGet extends AbstractAssociationGet +{ + private static final String DICTIONARY_CLASS_NAME = "classname"; + private static final String DICTIONARY_ASSOCIATION_NAME = "assocname"; + + @Override + protected QName getAssociationQname(WebScriptRequest req) + { + String associationName = req.getServiceMatch().getTemplateVars().get(DICTIONARY_ASSOCIATION_NAME); + if(associationName == null) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Missing parameter association name in the URL"); + } + + return QName.createQName(getFullNamespaceURI(associationName)); + } + + @Override + protected QName getClassQname(WebScriptRequest req) + { + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + + // validate the classname + if (isValidClassname(className) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); + } + + return QName.createQName(getFullNamespaceURI(className)); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationsGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationsGet.java index dc28b02ef3..e08a5765d1 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationsGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/AssociationsGet.java @@ -1,35 +1,35 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript to get the Associationdefinitions for a given classname - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class AssociationsGet extends AbstractAssociationsGet -{ - private static final String DICTIONARY_CLASS_NAME = "classname"; - - @Override - protected QName getClassQname(WebScriptRequest req) - { - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - //validate classname - if (isValidClassname(className) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); - } - return QName.createQName(getFullNamespaceURI(className)); - } - - @Override - protected QName getAssociationQname(String namespacePrefix, String name) - { - return QName.createQName(getFullNamespaceURI(namespacePrefix + "_" + name)); - } - +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript to get the Associationdefinitions for a given classname + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class AssociationsGet extends AbstractAssociationsGet +{ + private static final String DICTIONARY_CLASS_NAME = "classname"; + + @Override + protected QName getClassQname(WebScriptRequest req) + { + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + //validate classname + if (isValidClassname(className) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); + } + return QName.createQName(getFullNamespaceURI(className)); + } + + @Override + protected QName getAssociationQname(String namespacePrefix, String name) + { + return QName.createQName(getFullNamespaceURI(namespacePrefix + "_" + name)); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/ClassGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/ClassGet.java index e0ea3d8760..e16df157c3 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/ClassGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/ClassGet.java @@ -1,32 +1,32 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript to get the Classdefinitions for a classname eg. =>cm_author - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class ClassGet extends AbstractClassGet -{ - private static final String DICTIONARY_CLASS_NAME = "className"; - - /** - * Override method from AbstractClassGet - */ - @Override - protected QName getClassQname(WebScriptRequest req) - { - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - //validate the classname and throw appropriate error message - if (isValidClassname(className) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); - } - return QName.createQName(getFullNamespaceURI(className)); - } - +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript to get the Classdefinitions for a classname eg. =>cm_author + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class ClassGet extends AbstractClassGet +{ + private static final String DICTIONARY_CLASS_NAME = "className"; + + /** + * Override method from AbstractClassGet + */ + @Override + protected QName getClassQname(WebScriptRequest req) + { + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + //validate the classname and throw appropriate error message + if (isValidClassname(className) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); + } + return QName.createQName(getFullNamespaceURI(className)); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/ClassesGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/ClassesGet.java index 0c3336be6d..c78671cd53 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/ClassesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/ClassesGet.java @@ -1,32 +1,32 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; - -/** - * Webscript to get the Classdefinitions using classfilter , namespaceprefix and name - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class ClassesGet extends AbstractClassesGet -{ - - @Override - protected QName getQNameForModel(String namespacePrefix, String name) - { - return QName.createQName(getFullNamespaceURI(namespacePrefix + "_" + name)); - } - - @Override - protected QName getClassQname(String namespacePrefix, String name) - { - String className = namespacePrefix + "_" + name; - if(isValidClassname(className) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the name - " + name + "parameter in the URL"); - } - return QName.createQName(getFullNamespaceURI(className)); - } - +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Webscript to get the Classdefinitions using classfilter , namespaceprefix and name + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class ClassesGet extends AbstractClassesGet +{ + + @Override + protected QName getQNameForModel(String namespacePrefix, String name) + { + return QName.createQName(getFullNamespaceURI(namespacePrefix + "_" + name)); + } + + @Override + protected QName getClassQname(String namespacePrefix, String name) + { + String className = namespacePrefix + "_" + name; + if(isValidClassname(className) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the name - " + name + "parameter in the URL"); + } + return QName.createQName(getFullNamespaceURI(className)); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryGet.java index 87f49a0a3a..fa5e9fb13a 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryGet.java @@ -1,109 +1,109 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.service.cmr.dictionary.AssociationDefinition; -import org.alfresco.service.cmr.dictionary.ClassDefinition; -import org.alfresco.service.cmr.dictionary.ModelDefinition; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * WebScript implementation to retrieve a complete dictionary required to implement - * a lightweight remote web-tier dictionary. - * - * @author Kevin Roast - */ -public class DictionaryGet extends DictionaryWebServiceBase -{ - private static final String MODEL_CLASS_DEFS = "classdefs"; - private static final String MODEL_PROPERTY_DEFS = "propertydefs"; - private static final String MODEL_ASSOCIATION_DEFS = "assocdefs"; - - /** Set of model namespaces to ignore when outputing dictionary classes and aspects */ - private Set ignoreNamespaces = Collections.emptySet(); - - /** - * Set of model namespaces to ignore when outputing dictionary classes and aspects - * - * @param namespaces Set of model namespaces to ignore - */ - public void setIgnoreNamespaces(Set namespaces) - { - this.ignoreNamespaces = namespaces; - } - - /** - * Execute the webscript - * - * @param req WebScriptRequest - * @param status Status - */ - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - List qnames = new ArrayList(256); - Set namespaces = new HashSet(); - Map classdef = new HashMap(); - Map> propdef = new HashMap>(); - Map> assocdef = new HashMap>(); - - // check configured list of model namespaces to ignore when retrieving all models - for (String ns : this.namespaceService.getURIs()) - { - if (!ignoreNamespaces.contains(ns)) - { - namespaces.add(ns); - } - } - // specific model qname provided or will process all available models - String strModel = req.getParameter("model"); - if (strModel != null && strModel.length() != 0) - { - // handle full QName and prefixed shortname of a model - QName modelQName = (strModel.charAt(0) == QName.NAMESPACE_BEGIN ? QName.createQName(strModel) : QName.createQName(strModel, this.namespaceService)); - ModelDefinition modelDef = this.dictionaryservice.getModel(modelQName); - if (modelDef != null) - { - qnames.addAll(this.dictionaryservice.getAspects(modelQName)); - qnames.addAll(this.dictionaryservice.getTypes(modelQName)); - } - } - else - { - // walk all models and extract the aspects and types - for (QName qname : this.dictionaryservice.getAllModels()) - { - if (namespaces.contains(qname.getNamespaceURI())) - { - qnames.addAll(this.dictionaryservice.getAspects(qname)); - qnames.addAll(this.dictionaryservice.getTypes(qname)); - } - } - } - // get the class definitions and the properties and associations - for (QName qname : qnames) - { - ClassDefinition classDef = this.dictionaryservice.getClass(qname); - classdef.put(qname, classDef); - propdef.put(qname, classDef.getProperties().values()); - assocdef.put(qname, classDef.getAssociations().values()); - } - - Map model = new HashMap(); - model.put(MODEL_CLASS_DEFS, classdef.values()); - model.put(MODEL_PROPERTY_DEFS, propdef.values()); - model.put(MODEL_ASSOCIATION_DEFS, assocdef.values()); - model.put(MODEL_PROP_KEY_MESSAGE_LOOKUP, this.dictionaryservice); - return model; - } -} +package org.alfresco.repo.web.scripts.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * WebScript implementation to retrieve a complete dictionary required to implement + * a lightweight remote web-tier dictionary. + * + * @author Kevin Roast + */ +public class DictionaryGet extends DictionaryWebServiceBase +{ + private static final String MODEL_CLASS_DEFS = "classdefs"; + private static final String MODEL_PROPERTY_DEFS = "propertydefs"; + private static final String MODEL_ASSOCIATION_DEFS = "assocdefs"; + + /** Set of model namespaces to ignore when outputing dictionary classes and aspects */ + private Set ignoreNamespaces = Collections.emptySet(); + + /** + * Set of model namespaces to ignore when outputing dictionary classes and aspects + * + * @param namespaces Set of model namespaces to ignore + */ + public void setIgnoreNamespaces(Set namespaces) + { + this.ignoreNamespaces = namespaces; + } + + /** + * Execute the webscript + * + * @param req WebScriptRequest + * @param status Status + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + List qnames = new ArrayList(256); + Set namespaces = new HashSet(); + Map classdef = new HashMap(); + Map> propdef = new HashMap>(); + Map> assocdef = new HashMap>(); + + // check configured list of model namespaces to ignore when retrieving all models + for (String ns : this.namespaceService.getURIs()) + { + if (!ignoreNamespaces.contains(ns)) + { + namespaces.add(ns); + } + } + // specific model qname provided or will process all available models + String strModel = req.getParameter("model"); + if (strModel != null && strModel.length() != 0) + { + // handle full QName and prefixed shortname of a model + QName modelQName = (strModel.charAt(0) == QName.NAMESPACE_BEGIN ? QName.createQName(strModel) : QName.createQName(strModel, this.namespaceService)); + ModelDefinition modelDef = this.dictionaryservice.getModel(modelQName); + if (modelDef != null) + { + qnames.addAll(this.dictionaryservice.getAspects(modelQName)); + qnames.addAll(this.dictionaryservice.getTypes(modelQName)); + } + } + else + { + // walk all models and extract the aspects and types + for (QName qname : this.dictionaryservice.getAllModels()) + { + if (namespaces.contains(qname.getNamespaceURI())) + { + qnames.addAll(this.dictionaryservice.getAspects(qname)); + qnames.addAll(this.dictionaryservice.getTypes(qname)); + } + } + } + // get the class definitions and the properties and associations + for (QName qname : qnames) + { + ClassDefinition classDef = this.dictionaryservice.getClass(qname); + classdef.put(qname, classDef); + propdef.put(qname, classDef.getProperties().values()); + assocdef.put(qname, classDef.getAssociations().values()); + } + + Map model = new HashMap(); + model.put(MODEL_CLASS_DEFS, classdef.values()); + model.put(MODEL_PROPERTY_DEFS, propdef.values()); + model.put(MODEL_ASSOCIATION_DEFS, assocdef.values()); + model.put(MODEL_PROP_KEY_MESSAGE_LOOKUP, this.dictionaryservice); + return model; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryWebServiceBase.java b/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryWebServiceBase.java index b8ae0eb66b..ebc91309ca 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryWebServiceBase.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/DictionaryWebServiceBase.java @@ -1,357 +1,357 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.alfresco.service.cmr.dictionary.ClassDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.namespace.InvalidQNameException; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; - -/** - * Base class for Dictionary web scripts - * - * @author Saravanan Sellathurai - */ -public abstract class DictionaryWebServiceBase extends DeclarativeWebScript -{ - private static final String NAME_DELIMITER = "_"; - protected static final String MODEL_PROP_KEY_MESSAGE_LOOKUP = "messages"; - - /** Namespace service */ - protected NamespaceService namespaceService; - - /** Dictionary service */ - protected DictionaryService dictionaryservice; - - private static final String CLASS_FILTER_OPTION_TYPE1 = "all"; - private static final String CLASS_FILTER_OPTION_TYPE2 = "aspect"; - private static final String CLASS_FILTER_OPTION_TYPE3 = "type"; - - private static final String ASSOCIATION_FILTER_OPTION_TYPE1 = "all"; - private static final String ASSOCIATION_FILTER_OPTION_TYPE2 = "general"; - private static final String ASSOCIATION_FILTER_OPTION_TYPE3 = "child"; - - - /** - * Set the namespaceService property. - * - * @param namespaceservice The namespace service instance to set - */ - public void setNamespaceService(NamespaceService namespaceservice) - { - this.namespaceService = namespaceservice; - } - - /** - * Set the dictionaryService property. - * - * @param dictionaryService The dictionary service instance to set - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryservice = dictionaryService; - } - - protected QName createClassQName(String className) - { - QName result = null; - int index = className.indexOf(NAME_DELIMITER); - if (index > 0) - { - String prefix = className.substring(0, index); - String shortName = className.substring(index+1); - String url = namespaceService.getNamespaceURI(prefix); - if (url != null && url.length() != 0 && - shortName != null && shortName.length() != 0) - { - QName classQName = QName.createQName(url, shortName); - if (dictionaryservice.getClass(classQName) != null) - { - result = classQName; - } - } - } - - return result; - } - - /** - * @param prefix - prefix for class name - * @param shortName - short class name - * @return qualified name for class name - */ - protected QName createClassQName(String prefix, String shortName) - { - QName result = null; - String url = namespaceService.getNamespaceURI(prefix); - if (url != null && url.length() != 0 && shortName != null && shortName.length() != 0) - { - QName classQName = QName.createQName(url, shortName); - if (dictionaryservice.getClass(classQName) != null) - { - result = classQName; - } - } - return result; - } - - - /** - * @param qname QName - * @return the namespaceuri from a qname - */ - public String getNamespaceURIfromQname(QName qname) - { - return qname.getNamespaceURI(); - } - - /** - * @param classname the class name as cm_person - * @return String the full name in the following format {namespaceuri}shorname - */ - public String getFullNamespaceURI(String classname) - { - try - { - String result = null; - String prefix = this.getPrefix(classname); - String url = this.namespaceService.getNamespaceURI(prefix); - String name = this.getShortName(classname); - result = "{" + url + "}"+ name; - return result; - } - catch (Exception e) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "The exact classname - " + classname + " parameter has not been provided in the URL"); - } - } - - /** - * @param prefix prefix for classname as cm - * @param shorname the short class name as person - * @return String the full name in the following format {namespaceuri}shorname - */ - public String getFullNamespaceURI(String prefix, String shorname) - { - try - { - String result = null; - String url = this.namespaceService.getNamespaceURI(prefix); - result = "{" + url + "}" + shorname; - return result; - } - catch (Exception e) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "The exact classname - " + prefix + ":" + shorname + " parameter has not been provided in the URL"); - } - } - - /** - * @param classname - checks whether the classname is valid , gets the classname as input e.g cm_person - * @return true - if the class is valid , false - if the class is invalid - */ - public boolean isValidClassname(String classname) - { - QName qname = null; - try - { - qname = QName.createQName(this.getFullNamespaceURI(classname)); - return (dictionaryservice.getClass(qname) != null); - } - catch (InvalidQNameException e) - { - //just ignore - } - return false; - } - - /** - * Checks whether the classname is valid - * @param prefix - gets the prefix as input e.g cm - * @param shorname - gets the short classname as input e.g person - * @return true - if the class is valid , false - if the class is invalid - */ - public boolean isValidClassname(String prefix, String shorname) - { - QName qname = null; - try - { - qname = QName.createQName(this.getFullNamespaceURI(prefix, shorname)); - return (dictionaryservice.getClass(qname) != null); - } - catch (InvalidQNameException e) - { - //just ignore - } - return false; - } - - /** - * @param modelname String - * @return modelname from namespaceprefix - returns null if invalid namespaceprefix is given - */ - public String getPrefixFromModelName(String modelname) - { - String namespaceprefix = null; - for(QName qnameObj:this.dictionaryservice.getAllModels()) - { - if(qnameObj.getLocalName().equals(modelname)) - { - Collection prefixes = this.namespaceService.getPrefixes(qnameObj.getNamespaceURI()); - if (!prefixes.isEmpty()) - { - namespaceprefix = prefixes.iterator().next(); - } - break; - } - } - return namespaceprefix; - } - - public boolean isValidAssociationFilter(String af) - { - return (af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE1) || - af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE2) || - af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE3)); - } - - /** - * @param classname as the input - * @return true if it is a aspect or false if it is a Type - */ - public boolean isValidTypeorAspect(String classname) - { - try - { - QName qname = QName.createQName(this.getFullNamespaceURI(classname)); - return ((this.dictionaryservice.getClass(qname) != null) && - (this.dictionaryservice.getClass(qname).isAspect())); - } - catch (InvalidQNameException e) - { - // ignore - } - return false; - } - - /** - * @param prefix as the input - * @param shorname as the input - * @return true if it is a aspect or false if it is a Type - */ - public boolean isValidTypeorAspect(String prefix, String shorname) - { - try - { - QName qname = QName.createQName(this.getFullNamespaceURI(prefix, shorname)); - return ((this.dictionaryservice.getClass(qname) != null) && - (this.dictionaryservice.getClass(qname).isAspect())); - } - catch (InvalidQNameException e) - { - // ignore - } - return false; - } - - /** - * @param modelname - gets the modelname as the input (modelname is without prefix ie. cm:contentmodel => where modelname = contentmodel) - * @return true if valid or false - */ - public boolean isValidModelName(String modelname) - { - boolean value = false; - for (QName qnameObj:this.dictionaryservice.getAllModels()) - { - if (qnameObj.getLocalName().equalsIgnoreCase(modelname)) - { - value = true; - break; - } - } - return value; - } - - /** - * @param classname - returns the prefix from the classname of the format namespaceprefix:name eg. cm_person - * @return prefix - returns the prefix of the classname - */ - public String getPrefix(String classname) - { - String prefix = null; - int index = classname.indexOf(NAME_DELIMITER); - if (index > 0) - { - prefix = classname.substring(0, index); - } - return prefix; - } - - /** - * @param classname String - * @return the shortname from the classname of the format cm_person - * here person represents the shortname - */ - public String getShortName(String classname) - { - String shortname = null; - int index = classname.indexOf(NAME_DELIMITER); - if (index > 0) - { - shortname = classname.substring(index+1); - } - return shortname; - } - - /** - * @param input -gets a string input and validates it - * @return null if invalid or the string itself if its valid - */ - public String getValidInput(String input) - { - if ((input != null) && (input.length() != 0)) - { - return input; - } - else - { - return null; - } - } - - /** - * @param classfilter =>valid class filters are all,apect or type - * @return true if valid or false if invalid - */ - public boolean isValidClassFilter(String classfilter) - { - return (classfilter.equals(CLASS_FILTER_OPTION_TYPE1) || - classfilter.equals(CLASS_FILTER_OPTION_TYPE2) || - classfilter.equals(CLASS_FILTER_OPTION_TYPE3)); - } - - /** - * Returns dependent collections (properties or associations) - * in order that complies to order of class definitions - * @param sortedClassDefs - list of sorted class definitions - * @param dependent - collections that depend on class definitions - * @return collection of dependent values - */ - protected Collection reorderedValues(List sortedClassDefs, Map dependent) - { - Collection result = new ArrayList(sortedClassDefs.size()); - for (ClassDefinition classDef : sortedClassDefs) - { - result.add(dependent.get(classDef.getName())); - } - return result; - } - -} +package org.alfresco.repo.web.scripts.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.InvalidQNameException; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Base class for Dictionary web scripts + * + * @author Saravanan Sellathurai + */ +public abstract class DictionaryWebServiceBase extends DeclarativeWebScript +{ + private static final String NAME_DELIMITER = "_"; + protected static final String MODEL_PROP_KEY_MESSAGE_LOOKUP = "messages"; + + /** Namespace service */ + protected NamespaceService namespaceService; + + /** Dictionary service */ + protected DictionaryService dictionaryservice; + + private static final String CLASS_FILTER_OPTION_TYPE1 = "all"; + private static final String CLASS_FILTER_OPTION_TYPE2 = "aspect"; + private static final String CLASS_FILTER_OPTION_TYPE3 = "type"; + + private static final String ASSOCIATION_FILTER_OPTION_TYPE1 = "all"; + private static final String ASSOCIATION_FILTER_OPTION_TYPE2 = "general"; + private static final String ASSOCIATION_FILTER_OPTION_TYPE3 = "child"; + + + /** + * Set the namespaceService property. + * + * @param namespaceservice The namespace service instance to set + */ + public void setNamespaceService(NamespaceService namespaceservice) + { + this.namespaceService = namespaceservice; + } + + /** + * Set the dictionaryService property. + * + * @param dictionaryService The dictionary service instance to set + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryservice = dictionaryService; + } + + protected QName createClassQName(String className) + { + QName result = null; + int index = className.indexOf(NAME_DELIMITER); + if (index > 0) + { + String prefix = className.substring(0, index); + String shortName = className.substring(index+1); + String url = namespaceService.getNamespaceURI(prefix); + if (url != null && url.length() != 0 && + shortName != null && shortName.length() != 0) + { + QName classQName = QName.createQName(url, shortName); + if (dictionaryservice.getClass(classQName) != null) + { + result = classQName; + } + } + } + + return result; + } + + /** + * @param prefix - prefix for class name + * @param shortName - short class name + * @return qualified name for class name + */ + protected QName createClassQName(String prefix, String shortName) + { + QName result = null; + String url = namespaceService.getNamespaceURI(prefix); + if (url != null && url.length() != 0 && shortName != null && shortName.length() != 0) + { + QName classQName = QName.createQName(url, shortName); + if (dictionaryservice.getClass(classQName) != null) + { + result = classQName; + } + } + return result; + } + + + /** + * @param qname QName + * @return the namespaceuri from a qname + */ + public String getNamespaceURIfromQname(QName qname) + { + return qname.getNamespaceURI(); + } + + /** + * @param classname the class name as cm_person + * @return String the full name in the following format {namespaceuri}shorname + */ + public String getFullNamespaceURI(String classname) + { + try + { + String result = null; + String prefix = this.getPrefix(classname); + String url = this.namespaceService.getNamespaceURI(prefix); + String name = this.getShortName(classname); + result = "{" + url + "}"+ name; + return result; + } + catch (Exception e) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "The exact classname - " + classname + " parameter has not been provided in the URL"); + } + } + + /** + * @param prefix prefix for classname as cm + * @param shorname the short class name as person + * @return String the full name in the following format {namespaceuri}shorname + */ + public String getFullNamespaceURI(String prefix, String shorname) + { + try + { + String result = null; + String url = this.namespaceService.getNamespaceURI(prefix); + result = "{" + url + "}" + shorname; + return result; + } + catch (Exception e) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "The exact classname - " + prefix + ":" + shorname + " parameter has not been provided in the URL"); + } + } + + /** + * @param classname - checks whether the classname is valid , gets the classname as input e.g cm_person + * @return true - if the class is valid , false - if the class is invalid + */ + public boolean isValidClassname(String classname) + { + QName qname = null; + try + { + qname = QName.createQName(this.getFullNamespaceURI(classname)); + return (dictionaryservice.getClass(qname) != null); + } + catch (InvalidQNameException e) + { + //just ignore + } + return false; + } + + /** + * Checks whether the classname is valid + * @param prefix - gets the prefix as input e.g cm + * @param shorname - gets the short classname as input e.g person + * @return true - if the class is valid , false - if the class is invalid + */ + public boolean isValidClassname(String prefix, String shorname) + { + QName qname = null; + try + { + qname = QName.createQName(this.getFullNamespaceURI(prefix, shorname)); + return (dictionaryservice.getClass(qname) != null); + } + catch (InvalidQNameException e) + { + //just ignore + } + return false; + } + + /** + * @param modelname String + * @return modelname from namespaceprefix - returns null if invalid namespaceprefix is given + */ + public String getPrefixFromModelName(String modelname) + { + String namespaceprefix = null; + for(QName qnameObj:this.dictionaryservice.getAllModels()) + { + if(qnameObj.getLocalName().equals(modelname)) + { + Collection prefixes = this.namespaceService.getPrefixes(qnameObj.getNamespaceURI()); + if (!prefixes.isEmpty()) + { + namespaceprefix = prefixes.iterator().next(); + } + break; + } + } + return namespaceprefix; + } + + public boolean isValidAssociationFilter(String af) + { + return (af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE1) || + af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE2) || + af.equalsIgnoreCase(ASSOCIATION_FILTER_OPTION_TYPE3)); + } + + /** + * @param classname as the input + * @return true if it is a aspect or false if it is a Type + */ + public boolean isValidTypeorAspect(String classname) + { + try + { + QName qname = QName.createQName(this.getFullNamespaceURI(classname)); + return ((this.dictionaryservice.getClass(qname) != null) && + (this.dictionaryservice.getClass(qname).isAspect())); + } + catch (InvalidQNameException e) + { + // ignore + } + return false; + } + + /** + * @param prefix as the input + * @param shorname as the input + * @return true if it is a aspect or false if it is a Type + */ + public boolean isValidTypeorAspect(String prefix, String shorname) + { + try + { + QName qname = QName.createQName(this.getFullNamespaceURI(prefix, shorname)); + return ((this.dictionaryservice.getClass(qname) != null) && + (this.dictionaryservice.getClass(qname).isAspect())); + } + catch (InvalidQNameException e) + { + // ignore + } + return false; + } + + /** + * @param modelname - gets the modelname as the input (modelname is without prefix ie. cm:contentmodel => where modelname = contentmodel) + * @return true if valid or false + */ + public boolean isValidModelName(String modelname) + { + boolean value = false; + for (QName qnameObj:this.dictionaryservice.getAllModels()) + { + if (qnameObj.getLocalName().equalsIgnoreCase(modelname)) + { + value = true; + break; + } + } + return value; + } + + /** + * @param classname - returns the prefix from the classname of the format namespaceprefix:name eg. cm_person + * @return prefix - returns the prefix of the classname + */ + public String getPrefix(String classname) + { + String prefix = null; + int index = classname.indexOf(NAME_DELIMITER); + if (index > 0) + { + prefix = classname.substring(0, index); + } + return prefix; + } + + /** + * @param classname String + * @return the shortname from the classname of the format cm_person + * here person represents the shortname + */ + public String getShortName(String classname) + { + String shortname = null; + int index = classname.indexOf(NAME_DELIMITER); + if (index > 0) + { + shortname = classname.substring(index+1); + } + return shortname; + } + + /** + * @param input -gets a string input and validates it + * @return null if invalid or the string itself if its valid + */ + public String getValidInput(String input) + { + if ((input != null) && (input.length() != 0)) + { + return input; + } + else + { + return null; + } + } + + /** + * @param classfilter =>valid class filters are all,apect or type + * @return true if valid or false if invalid + */ + public boolean isValidClassFilter(String classfilter) + { + return (classfilter.equals(CLASS_FILTER_OPTION_TYPE1) || + classfilter.equals(CLASS_FILTER_OPTION_TYPE2) || + classfilter.equals(CLASS_FILTER_OPTION_TYPE3)); + } + + /** + * Returns dependent collections (properties or associations) + * in order that complies to order of class definitions + * @param sortedClassDefs - list of sorted class definitions + * @param dependent - collections that depend on class definitions + * @return collection of dependent values + */ + protected Collection reorderedValues(List sortedClassDefs, Map dependent) + { + Collection result = new ArrayList(sortedClassDefs.size()); + for (ClassDefinition classDef : sortedClassDefs) + { + result.add(dependent.get(classDef.getName())); + } + return result; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/PropertiesGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/PropertiesGet.java index 153c8832a0..9bfbc68095 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/PropertiesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/PropertiesGet.java @@ -1,35 +1,35 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript to get the Propertydefinitions for a given classname eg. =>cm_person - * - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class PropertiesGet extends AbstractPropertiesGet -{ - private static final String DICTIONARY_CLASS_NAME = "classname"; - - @Override - protected QName getClassQName(WebScriptRequest req) - { - QName classQName = null; - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - if (className != null && className.length() != 0) - { - classQName = createClassQName(className); - if (classQName == null) - { - // Error - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the className - " + className + " - parameter in the URL"); - } - } - return classQName; - } - -} +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript to get the Propertydefinitions for a given classname eg. =>cm_person + * + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class PropertiesGet extends AbstractPropertiesGet +{ + private static final String DICTIONARY_CLASS_NAME = "classname"; + + @Override + protected QName getClassQName(WebScriptRequest req) + { + QName classQName = null; + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + if (className != null && className.length() != 0) + { + classQName = createClassQName(className); + if (classQName == null) + { + // Error + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the className - " + className + " - parameter in the URL"); + } + } + return classQName; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/PropertyGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/PropertyGet.java index 1a204e67f1..676d84edaa 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/PropertyGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/PropertyGet.java @@ -1,46 +1,46 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript to get the Propertydefinition for a given classname and propname - * - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class PropertyGet extends AbstractPropertyGet -{ - private static final String DICTIONARY_CLASS_NAME = "classname"; - private static final String DICTIONARY_PROPERTY_NAME = "propname"; - - @Override - protected QName getPropertyQname(WebScriptRequest req) - { - String propertyName = req.getServiceMatch().getTemplateVars().get(DICTIONARY_PROPERTY_NAME); - //validate the presence of property name - if(propertyName == null) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Missing parameter propertyname in the URL"); - } - - return QName.createQName(getFullNamespaceURI(propertyName)); - } - - @Override - protected QName getClassQname(WebScriptRequest req) - { - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - - // validate the classname - if (isValidClassname(className) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); - } - - return QName.createQName(getFullNamespaceURI(className)); - } - +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript to get the Propertydefinition for a given classname and propname + * + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class PropertyGet extends AbstractPropertyGet +{ + private static final String DICTIONARY_CLASS_NAME = "classname"; + private static final String DICTIONARY_PROPERTY_NAME = "propname"; + + @Override + protected QName getPropertyQname(WebScriptRequest req) + { + String propertyName = req.getServiceMatch().getTemplateVars().get(DICTIONARY_PROPERTY_NAME); + //validate the presence of property name + if(propertyName == null) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Missing parameter propertyname in the URL"); + } + + return QName.createQName(getFullNamespaceURI(propertyName)); + } + + @Override + protected QName getClassQname(WebScriptRequest req) + { + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + + // validate the classname + if (isValidClassname(className) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the classname - " + className + " - parameter in the URL"); + } + + return QName.createQName(getFullNamespaceURI(className)); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/dictionary/SubClassesGet.java b/source/java/org/alfresco/repo/web/scripts/dictionary/SubClassesGet.java index 84b3b0fecf..0dddab3291 100644 --- a/source/java/org/alfresco/repo/web/scripts/dictionary/SubClassesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/dictionary/SubClassesGet.java @@ -1,61 +1,61 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import java.util.Collection; - -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript to get the Sub-Classdefinitions using classfilter , namespacePrefix and name - * - * @author Saravanan Sellathurai, Viachaslau Tsikhanovich - */ - -public class SubClassesGet extends AbstractSubClassesGet -{ - private static final String DICTIONARY_CLASS_NAME = "classname"; - - @Override - protected Collection getQNameCollection(WebScriptRequest req, boolean recursive) - { - QName classQName = null; - boolean isAspect = false; - String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); - - //validate the className - if(isValidClassname(className) == true) - { - classQName = QName.createQName(getFullNamespaceURI(className)); - if(isValidTypeorAspect(className) == true) - { - isAspect = true; - } - } - else - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the className - " + className + " parameter in the URL"); - } - - // collect the subaspects or subtypes of the class - if(isAspect == true) - { - return this.dictionaryservice.getSubAspects(classQName, recursive); - } - else - { - return this.dictionaryservice.getSubTypes(classQName, recursive); - } - } - - @Override - protected void validateClassname(String namespacePrefix, String name) - { - if(isValidClassname(namespacePrefix + "_" + name) == false) - { - throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the namespacePrefix - " + namespacePrefix + " and name - "+ name + " - parameter in the URL"); - } - } - +package org.alfresco.repo.web.scripts.dictionary; + +import java.util.Collection; + +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript to get the Sub-Classdefinitions using classfilter , namespacePrefix and name + * + * @author Saravanan Sellathurai, Viachaslau Tsikhanovich + */ + +public class SubClassesGet extends AbstractSubClassesGet +{ + private static final String DICTIONARY_CLASS_NAME = "classname"; + + @Override + protected Collection getQNameCollection(WebScriptRequest req, boolean recursive) + { + QName classQName = null; + boolean isAspect = false; + String className = req.getServiceMatch().getTemplateVars().get(DICTIONARY_CLASS_NAME); + + //validate the className + if(isValidClassname(className) == true) + { + classQName = QName.createQName(getFullNamespaceURI(className)); + if(isValidTypeorAspect(className) == true) + { + isAspect = true; + } + } + else + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the className - " + className + " parameter in the URL"); + } + + // collect the subaspects or subtypes of the class + if(isAspect == true) + { + return this.dictionaryservice.getSubAspects(classQName, recursive); + } + else + { + return this.dictionaryservice.getSubTypes(classQName, recursive); + } + } + + @Override + protected void validateClassname(String namespacePrefix, String name) + { + if(isValidClassname(namespacePrefix + "_" + name) == false) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "Check the namespacePrefix - " + namespacePrefix + " and name - "+ name + " - parameter in the URL"); + } + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/metadata/BulkMetadataGet.java b/source/java/org/alfresco/repo/web/scripts/metadata/BulkMetadataGet.java index 2dc599cce2..def6619baa 100644 --- a/source/java/org/alfresco/repo/web/scripts/metadata/BulkMetadataGet.java +++ b/source/java/org/alfresco/repo/web/scripts/metadata/BulkMetadataGet.java @@ -1,166 +1,166 @@ -package org.alfresco.repo.web.scripts.metadata; - -import java.io.IOException; -import java.io.Serializable; -import java.nio.charset.Charset; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.surf.util.I18NUtil; -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.json.JSONWriter; - -/** - * This class is the webscript implementation for the url api/bulkmetadata - * It returns basic metadata such as title, parent noderef, name, ... for each noderef that is passed in - * - * @since 3.4 - */ -public class BulkMetadataGet extends AbstractWebScript -{ - private ServiceRegistry services; - private NodeService nodeService; - private DictionaryService dictionaryService; - private PermissionService permissionService; - - private String getMimeType(ContentData contentProperty) - { - String mimetype = null; - - if(contentProperty != null) - { - mimetype = contentProperty.getMimetype(); - } - - return mimetype; - } - - @Override - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - JSONObject jsonIn; - JSONArray nodeRefsArray; - - try - { - Content c = req.getContent(); - if (c == null) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body."); - } - - jsonIn = new JSONObject(c.getContent()); - - nodeRefsArray = jsonIn.getJSONArray("nodeRefs"); - if(nodeRefsArray == null || nodeRefsArray.length() == 0) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Must provide node refs"); - } - - JSONWriter jsonOut = new JSONWriter(res.getWriter()); - - res.setContentType("application/json"); - res.setContentEncoding(Charset.defaultCharset().displayName()); // TODO: Should be settable on JSONWriter - - jsonOut.startObject(); - { - jsonOut.startValue("nodes"); - { - jsonOut.startArray(); - { - for(int i = 0; i < nodeRefsArray.length(); i++) - { - NodeRef nodeRef = new NodeRef(nodeRefsArray.getString(i)); - - if(nodeService.exists(nodeRef)) - { - NodeRef parentNodeRef = null; - ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef); - if(childAssocRef != null) - { - parentNodeRef = childAssocRef.getParentRef(); - } - QName type = nodeService.getType(nodeRef); - - String shortType = type.toPrefixString(services.getNamespaceService()); - Map properties = nodeService.getProperties(nodeRef); - - jsonOut.startObject(); - { - jsonOut.writeValue("nodeRef", nodeRef.toString()); - jsonOut.writeValue("parentNodeRef", parentNodeRef.toString()); - jsonOut.writeValue("type", type.toString()); - jsonOut.writeValue("shortType", shortType); - TypeDefinition typeDef = dictionaryService.getType(type); - jsonOut.writeValue("typeTitle", typeDef.getTitle(dictionaryService)); - - jsonOut.writeValue("name", (String)properties.get(ContentModel.PROP_NAME)); - jsonOut.writeValue("title", (String)properties.get(ContentModel.PROP_TITLE)); - jsonOut.writeValue("mimeType", getMimeType((ContentData)properties.get(ContentModel.PROP_CONTENT))); - jsonOut.writeValue("hasWritePermission", permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED); - jsonOut.writeValue("hasDeletePermission", permissionService.hasPermission(nodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED); - } - jsonOut.endObject(); - } - else - { - jsonOut.startObject(); - { - jsonOut.writeValue("nodeRef", nodeRef.toString()); - jsonOut.writeValue("error", "true"); - jsonOut.writeValue("errorCode", "invalidNodeRef"); - jsonOut.writeValue("errorText", I18NUtil.getMessage("msg.invalidNodeRef", nodeRef.toString())); - } - jsonOut.endObject(); - } - } - } - jsonOut.endArray(); - } - jsonOut.endValue(); - } - jsonOut.endObject(); - } - catch (JSONException jErr) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Unable to parse JSON POST body: " + jErr.getMessage()); - } - - res.getWriter().close(); - - res.setStatus(Status.STATUS_OK); - } - - /** - * Set the service registry - * - * @param services the service registry - */ - public void setServiceRegistry(ServiceRegistry services) - { - this.services = services; - this.nodeService = services.getNodeService(); - this.dictionaryService = services.getDictionaryService(); - this.permissionService = services.getPermissionService(); - } - -} +package org.alfresco.repo.web.scripts.metadata; + +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.json.JSONWriter; + +/** + * This class is the webscript implementation for the url api/bulkmetadata + * It returns basic metadata such as title, parent noderef, name, ... for each noderef that is passed in + * + * @since 3.4 + */ +public class BulkMetadataGet extends AbstractWebScript +{ + private ServiceRegistry services; + private NodeService nodeService; + private DictionaryService dictionaryService; + private PermissionService permissionService; + + private String getMimeType(ContentData contentProperty) + { + String mimetype = null; + + if(contentProperty != null) + { + mimetype = contentProperty.getMimetype(); + } + + return mimetype; + } + + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + JSONObject jsonIn; + JSONArray nodeRefsArray; + + try + { + Content c = req.getContent(); + if (c == null) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body."); + } + + jsonIn = new JSONObject(c.getContent()); + + nodeRefsArray = jsonIn.getJSONArray("nodeRefs"); + if(nodeRefsArray == null || nodeRefsArray.length() == 0) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Must provide node refs"); + } + + JSONWriter jsonOut = new JSONWriter(res.getWriter()); + + res.setContentType("application/json"); + res.setContentEncoding(Charset.defaultCharset().displayName()); // TODO: Should be settable on JSONWriter + + jsonOut.startObject(); + { + jsonOut.startValue("nodes"); + { + jsonOut.startArray(); + { + for(int i = 0; i < nodeRefsArray.length(); i++) + { + NodeRef nodeRef = new NodeRef(nodeRefsArray.getString(i)); + + if(nodeService.exists(nodeRef)) + { + NodeRef parentNodeRef = null; + ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef); + if(childAssocRef != null) + { + parentNodeRef = childAssocRef.getParentRef(); + } + QName type = nodeService.getType(nodeRef); + + String shortType = type.toPrefixString(services.getNamespaceService()); + Map properties = nodeService.getProperties(nodeRef); + + jsonOut.startObject(); + { + jsonOut.writeValue("nodeRef", nodeRef.toString()); + jsonOut.writeValue("parentNodeRef", parentNodeRef.toString()); + jsonOut.writeValue("type", type.toString()); + jsonOut.writeValue("shortType", shortType); + TypeDefinition typeDef = dictionaryService.getType(type); + jsonOut.writeValue("typeTitle", typeDef.getTitle(dictionaryService)); + + jsonOut.writeValue("name", (String)properties.get(ContentModel.PROP_NAME)); + jsonOut.writeValue("title", (String)properties.get(ContentModel.PROP_TITLE)); + jsonOut.writeValue("mimeType", getMimeType((ContentData)properties.get(ContentModel.PROP_CONTENT))); + jsonOut.writeValue("hasWritePermission", permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED); + jsonOut.writeValue("hasDeletePermission", permissionService.hasPermission(nodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED); + } + jsonOut.endObject(); + } + else + { + jsonOut.startObject(); + { + jsonOut.writeValue("nodeRef", nodeRef.toString()); + jsonOut.writeValue("error", "true"); + jsonOut.writeValue("errorCode", "invalidNodeRef"); + jsonOut.writeValue("errorText", I18NUtil.getMessage("msg.invalidNodeRef", nodeRef.toString())); + } + jsonOut.endObject(); + } + } + } + jsonOut.endArray(); + } + jsonOut.endValue(); + } + jsonOut.endObject(); + } + catch (JSONException jErr) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Unable to parse JSON POST body: " + jErr.getMessage()); + } + + res.getWriter().close(); + + res.setStatus(Status.STATUS_OK); + } + + /** + * Set the service registry + * + * @param services the service registry + */ + public void setServiceRegistry(ServiceRegistry services) + { + this.services = services; + this.nodeService = services.getNodeService(); + this.dictionaryService = services.getDictionaryService(); + this.permissionService = services.getPermissionService(); + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/person/ChangePasswordPost.java b/source/java/org/alfresco/repo/web/scripts/person/ChangePasswordPost.java index f6d1544fd1..3cfe2e19ed 100644 --- a/source/java/org/alfresco/repo/web/scripts/person/ChangePasswordPost.java +++ b/source/java/org/alfresco/repo/web/scripts/person/ChangePasswordPost.java @@ -1,120 +1,120 @@ -package org.alfresco.repo.web.scripts.person; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Webscript implementation for the POST method for 'changepassword' API. - * - * @author Kevin Roast - */ -public class ChangePasswordPost extends DeclarativeWebScript -{ - private static final String PARAM_NEWPW = "newpw"; - private static final String PARAM_OLDPW = "oldpw"; - private MutableAuthenticationService authenticationService; - private AuthorityService authorityService; - - - /** - * @param authenticationService the AuthenticationService to set - */ - public void setAuthenticationService(MutableAuthenticationService authenticationService) - { - this.authenticationService = authenticationService; - } - - /** - * @param authorityService the AuthorityService to set - */ - public void setAuthorityService(AuthorityService authorityService) - { - this.authorityService = authorityService; - } - - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status) - */ - @Override - protected Map executeImpl(WebScriptRequest req, Status status) - { - // Extract user name from the URL - cannot be null or webscript desc would not match - String userName = req.getExtensionPath(); - - // Extract old and new password details from JSON POST - Content c = req.getContent(); - if (c == null) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Missing POST body."); - } - JSONObject json; - try - { - json = new JSONObject(c.getContent()); - - String oldPassword = null; - String newPassword; - - // admin users can change/set a password without knowing the old one - boolean isAdmin = authorityService.hasAdminAuthority(); - if (!isAdmin || (userName.equalsIgnoreCase(authenticationService.getCurrentUserName()))) - { - if (!json.has(PARAM_OLDPW) || json.getString(PARAM_OLDPW).length() == 0) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "Old password 'oldpw' is a required POST parameter."); - } - oldPassword = json.getString(PARAM_OLDPW); - } - if (!json.has(PARAM_NEWPW) || json.getString(PARAM_NEWPW).length() == 0) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, - "New password 'newpw' is a required POST parameter."); - } - newPassword = json.getString(PARAM_NEWPW); - - // update the password - // an Admin user can update without knowing the original pass - but must know their own! - if (!isAdmin || (userName.equalsIgnoreCase(authenticationService.getCurrentUserName()))) - { - authenticationService.updateAuthentication(userName, oldPassword.toCharArray(), newPassword.toCharArray()); - } - else - { - authenticationService.setAuthentication(userName, newPassword.toCharArray()); - } - } - catch (AuthenticationException err) - { - throw new WebScriptException(Status.STATUS_UNAUTHORIZED, - "Do not have appropriate auth or wrong auth details provided."); - } - catch (JSONException jErr) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, - "Unable to parse JSON POST body: " + jErr.getMessage()); - } - catch (IOException ioErr) - { - throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, - "Unable to retrieve POST body: " + ioErr.getMessage()); - } - - Map model = new HashMap(1, 1.0f); - model.put("success", Boolean.TRUE); - return model; - } +package org.alfresco.repo.web.scripts.person; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Webscript implementation for the POST method for 'changepassword' API. + * + * @author Kevin Roast + */ +public class ChangePasswordPost extends DeclarativeWebScript +{ + private static final String PARAM_NEWPW = "newpw"; + private static final String PARAM_OLDPW = "oldpw"; + private MutableAuthenticationService authenticationService; + private AuthorityService authorityService; + + + /** + * @param authenticationService the AuthenticationService to set + */ + public void setAuthenticationService(MutableAuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + /** + * @param authorityService the AuthorityService to set + */ + public void setAuthorityService(AuthorityService authorityService) + { + this.authorityService = authorityService; + } + + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status) + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status) + { + // Extract user name from the URL - cannot be null or webscript desc would not match + String userName = req.getExtensionPath(); + + // Extract old and new password details from JSON POST + Content c = req.getContent(); + if (c == null) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Missing POST body."); + } + JSONObject json; + try + { + json = new JSONObject(c.getContent()); + + String oldPassword = null; + String newPassword; + + // admin users can change/set a password without knowing the old one + boolean isAdmin = authorityService.hasAdminAuthority(); + if (!isAdmin || (userName.equalsIgnoreCase(authenticationService.getCurrentUserName()))) + { + if (!json.has(PARAM_OLDPW) || json.getString(PARAM_OLDPW).length() == 0) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "Old password 'oldpw' is a required POST parameter."); + } + oldPassword = json.getString(PARAM_OLDPW); + } + if (!json.has(PARAM_NEWPW) || json.getString(PARAM_NEWPW).length() == 0) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, + "New password 'newpw' is a required POST parameter."); + } + newPassword = json.getString(PARAM_NEWPW); + + // update the password + // an Admin user can update without knowing the original pass - but must know their own! + if (!isAdmin || (userName.equalsIgnoreCase(authenticationService.getCurrentUserName()))) + { + authenticationService.updateAuthentication(userName, oldPassword.toCharArray(), newPassword.toCharArray()); + } + else + { + authenticationService.setAuthentication(userName, newPassword.toCharArray()); + } + } + catch (AuthenticationException err) + { + throw new WebScriptException(Status.STATUS_UNAUTHORIZED, + "Do not have appropriate auth or wrong auth details provided."); + } + catch (JSONException jErr) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, + "Unable to parse JSON POST body: " + jErr.getMessage()); + } + catch (IOException ioErr) + { + throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, + "Unable to retrieve POST body: " + ioErr.getMessage()); + } + + Map model = new HashMap(1, 1.0f); + model.put("success", Boolean.TRUE); + return model; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/portlet/JSR168PortletAuthenticatorFactory.java b/source/java/org/alfresco/repo/web/scripts/portlet/JSR168PortletAuthenticatorFactory.java index 7121e3acc7..d59745d5b7 100644 --- a/source/java/org/alfresco/repo/web/scripts/portlet/JSR168PortletAuthenticatorFactory.java +++ b/source/java/org/alfresco/repo/web/scripts/portlet/JSR168PortletAuthenticatorFactory.java @@ -1,161 +1,161 @@ -package org.alfresco.repo.web.scripts.portlet; - -import javax.portlet.RenderRequest; -import javax.portlet.RenderResponse; -import javax.servlet.http.HttpServletResponse; -import javax.transaction.UserTransaction; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.transaction.TransactionService; -import org.springframework.extensions.webscripts.Authenticator; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.Description.RequiredAuthentication; -import org.springframework.extensions.webscripts.portlet.PortletAuthenticatorFactory; -import org.springframework.extensions.webscripts.portlet.WebScriptPortletRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -/** - * Portlet authenticator - * - * @author davidc - */ -public class JSR168PortletAuthenticatorFactory implements PortletAuthenticatorFactory -{ - // Logger - private static final Log logger = LogFactory.getLog(JSR168PortletAuthenticatorFactory.class); - - // dependencies - private AuthenticationService unprotAuthenticationService; - private TransactionService txnService; - - /** - * @param authenticationService AuthenticationService - */ - public void setUnprotAuthenticationService(AuthenticationService authenticationService) - { - this.unprotAuthenticationService = authenticationService; - } - - /** - * @param transactionService TransactionService - */ - public void setTransactionService(TransactionService transactionService) - { - this.txnService = transactionService; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse) - */ - public Authenticator create(RenderRequest req, RenderResponse res) - { - return new JSR168PortletAuthenticator(req, res); - } - - - /** - * Portlet authenticator - * - * @author davidc - */ - public class JSR168PortletAuthenticator implements Authenticator - { - // dependencies - private RenderRequest req; - - /** - * Construct - * - * @param req RenderRequest - * @param res RenderResponse - */ - public JSR168PortletAuthenticator(RenderRequest req, RenderResponse res) - { - this.req = req; - } - - /*(non-Javadoc) - * @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean) - */ - public boolean authenticate(RequiredAuthentication required, boolean isGuest) - { - // first look for the username key in the session - we add this by hand for some portals - // when the WebScriptPortletRequest is created - String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME); - if (portalUser == null) - { - portalUser = req.getRemoteUser(); - } - - if (logger.isDebugEnabled()) - { - logger.debug("JSR-168 Remote user: " + portalUser); - } - - if (isGuest || portalUser == null) - { - if (logger.isDebugEnabled()) - logger.debug("Authenticating as Guest"); - - // authenticate as guest - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getGuestUserName()); - } - else - { - if (logger.isDebugEnabled()) - logger.debug("Authenticating as user " + portalUser); - - UserTransaction txn = null; - try - { - txn = txnService.getUserTransaction(); - txn.begin(); - - if (!unprotAuthenticationService.authenticationExists(portalUser)) - { - throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "User " + portalUser + " is not a known Alfresco user"); - } - AuthenticationUtil.setFullyAuthenticatedUser(portalUser); - } - catch (Throwable err) - { - throw new AlfrescoRuntimeException("Error authenticating user: " + portalUser, err); - } - finally - { - try - { - if (txn != null) - { - txn.rollback(); - } - } - catch (Exception tex) - { - // nothing useful we can do with this - } - } - } - - return true; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.Authenticator#emptyCredentials() - */ - public boolean emptyCredentials() - { - String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME); - if (portalUser == null) - { - portalUser = req.getRemoteUser(); - } - return (portalUser == null); - } - } - -} +package org.alfresco.repo.web.scripts.portlet; + +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; +import javax.servlet.http.HttpServletResponse; +import javax.transaction.UserTransaction; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.transaction.TransactionService; +import org.springframework.extensions.webscripts.Authenticator; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.Description.RequiredAuthentication; +import org.springframework.extensions.webscripts.portlet.PortletAuthenticatorFactory; +import org.springframework.extensions.webscripts.portlet.WebScriptPortletRequest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Portlet authenticator + * + * @author davidc + */ +public class JSR168PortletAuthenticatorFactory implements PortletAuthenticatorFactory +{ + // Logger + private static final Log logger = LogFactory.getLog(JSR168PortletAuthenticatorFactory.class); + + // dependencies + private AuthenticationService unprotAuthenticationService; + private TransactionService txnService; + + /** + * @param authenticationService AuthenticationService + */ + public void setUnprotAuthenticationService(AuthenticationService authenticationService) + { + this.unprotAuthenticationService = authenticationService; + } + + /** + * @param transactionService TransactionService + */ + public void setTransactionService(TransactionService transactionService) + { + this.txnService = transactionService; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse) + */ + public Authenticator create(RenderRequest req, RenderResponse res) + { + return new JSR168PortletAuthenticator(req, res); + } + + + /** + * Portlet authenticator + * + * @author davidc + */ + public class JSR168PortletAuthenticator implements Authenticator + { + // dependencies + private RenderRequest req; + + /** + * Construct + * + * @param req RenderRequest + * @param res RenderResponse + */ + public JSR168PortletAuthenticator(RenderRequest req, RenderResponse res) + { + this.req = req; + } + + /*(non-Javadoc) + * @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean) + */ + public boolean authenticate(RequiredAuthentication required, boolean isGuest) + { + // first look for the username key in the session - we add this by hand for some portals + // when the WebScriptPortletRequest is created + String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME); + if (portalUser == null) + { + portalUser = req.getRemoteUser(); + } + + if (logger.isDebugEnabled()) + { + logger.debug("JSR-168 Remote user: " + portalUser); + } + + if (isGuest || portalUser == null) + { + if (logger.isDebugEnabled()) + logger.debug("Authenticating as Guest"); + + // authenticate as guest + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getGuestUserName()); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Authenticating as user " + portalUser); + + UserTransaction txn = null; + try + { + txn = txnService.getUserTransaction(); + txn.begin(); + + if (!unprotAuthenticationService.authenticationExists(portalUser)) + { + throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "User " + portalUser + " is not a known Alfresco user"); + } + AuthenticationUtil.setFullyAuthenticatedUser(portalUser); + } + catch (Throwable err) + { + throw new AlfrescoRuntimeException("Error authenticating user: " + portalUser, err); + } + finally + { + try + { + if (txn != null) + { + txn.rollback(); + } + } + catch (Exception tex) + { + // nothing useful we can do with this + } + } + } + + return true; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.Authenticator#emptyCredentials() + */ + public boolean emptyCredentials() + { + String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME); + if (portalUser == null) + { + portalUser = req.getRemoteUser(); + } + return (portalUser == null); + } + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelGet.java b/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelGet.java index 7ed3d36815..fef3a91418 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelGet.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelGet.java @@ -1,75 +1,75 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.IOException; -import java.util.Map; - -import org.alfresco.repo.solr.AlfrescoModel; -import org.alfresco.repo.solr.SOLRTrackingComponent; -import org.alfresco.service.cmr.dictionary.ModelDefinition; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONException; -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * Support for SOLR: Get Alfresco model - * - * @since 4.0 - */ -public class AlfrescoModelGet extends AbstractWebScript -{ - protected static final Log logger = LogFactory.getLog(AlfrescoModelGet.class); - - private NamespaceService namespaceService; - private SOLRTrackingComponent solrTrackingComponent; - - public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent) - { - this.solrTrackingComponent = solrTrackingComponent; - } - - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - - public void execute(WebScriptRequest req, WebScriptResponse res) - { - try - { - handle(req, res); - } - catch(IOException e) - { - throw new WebScriptException("IO exception parsing request", e); - } - catch(JSONException e) - { - throw new WebScriptException("Invalid JSON", e); - } - } - - private void handle(WebScriptRequest req, WebScriptResponse res) throws JSONException, IOException - { - // create map of template vars - String modelQName = req.getParameter("modelQName"); - if(modelQName == null) - { - throw new WebScriptException( - Status.STATUS_BAD_REQUEST, - "URL parameter 'modelQName' not provided."); - } - - ModelDefinition.XMLBindingType bindingType = ModelDefinition.XMLBindingType.DEFAULT; - AlfrescoModel model = solrTrackingComponent.getModel(QName.createQName(modelQName)); - res.setHeader("XAlfresco-modelChecksum", String.valueOf(model.getModelDef().getChecksum(bindingType))); - model.getModelDef().toXML(bindingType, res.getOutputStream()); - } - -} +package org.alfresco.repo.web.scripts.solr; + +import java.io.IOException; +import java.util.Map; + +import org.alfresco.repo.solr.AlfrescoModel; +import org.alfresco.repo.solr.SOLRTrackingComponent; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * Support for SOLR: Get Alfresco model + * + * @since 4.0 + */ +public class AlfrescoModelGet extends AbstractWebScript +{ + protected static final Log logger = LogFactory.getLog(AlfrescoModelGet.class); + + private NamespaceService namespaceService; + private SOLRTrackingComponent solrTrackingComponent; + + public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent) + { + this.solrTrackingComponent = solrTrackingComponent; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + public void execute(WebScriptRequest req, WebScriptResponse res) + { + try + { + handle(req, res); + } + catch(IOException e) + { + throw new WebScriptException("IO exception parsing request", e); + } + catch(JSONException e) + { + throw new WebScriptException("Invalid JSON", e); + } + } + + private void handle(WebScriptRequest req, WebScriptResponse res) throws JSONException, IOException + { + // create map of template vars + String modelQName = req.getParameter("modelQName"); + if(modelQName == null) + { + throw new WebScriptException( + Status.STATUS_BAD_REQUEST, + "URL parameter 'modelQName' not provided."); + } + + ModelDefinition.XMLBindingType bindingType = ModelDefinition.XMLBindingType.DEFAULT; + AlfrescoModel model = solrTrackingComponent.getModel(QName.createQName(modelQName)); + res.setHeader("XAlfresco-modelChecksum", String.valueOf(model.getModelDef().getChecksum(bindingType))); + model.getModelDef().toXML(bindingType, res.getOutputStream()); + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelsDiff.java b/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelsDiff.java index 91538b9531..9e64679eb5 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelsDiff.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/AlfrescoModelsDiff.java @@ -1,110 +1,110 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.solr.AlfrescoModelDiff; -import org.alfresco.repo.solr.SOLRTrackingComponent; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.webscripts.DeclarativeWebScript; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Support for SOLR: Track Alfresco model changes - * - * @since 4.0 - */ -public class AlfrescoModelsDiff extends DeclarativeWebScript -{ - protected static final Log logger = LogFactory.getLog(AlfrescoModelsDiff.class); - - private static final String MSG_IO_EXCEPTION = "IO exception parsing request "; - - private static final String MSG_JSON_EXCEPTION = "Unable to fetch model changes from "; - - private SOLRTrackingComponent solrTrackingComponent; - - public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent) - { - this.solrTrackingComponent = solrTrackingComponent; - } - - protected Map executeImpl(WebScriptRequest req, Status status) - { - try - { - Map model = buildModel(req); - if (logger.isDebugEnabled()) - { - logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); - } - return model; - } - catch (IOException e) - { - setExceptionResponse(req, status, MSG_IO_EXCEPTION, Status.STATUS_INTERNAL_SERVER_ERROR, e); - return null; - } - catch (JSONException e) - { - setExceptionResponse(req, status, MSG_JSON_EXCEPTION, Status.STATUS_BAD_REQUEST, e); - return null; - } - } - - private void setExceptionResponse(WebScriptRequest req, Status responseStatus, String responseMessage, int statusCode, Exception e) - { - String message = responseMessage + req; - - if (logger.isDebugEnabled()) - { - logger.warn(message, e); - } - else - { - logger.warn(message); - } - - responseStatus.setCode(statusCode, message); - responseStatus.setException(e); - } - - private Map buildModel(WebScriptRequest req) throws JSONException, IOException - { - Map model = new HashMap(1, 1.0f); - - Content content = req.getContent(); - if(content == null) - { - throw new WebScriptException("Failed to convert request to String"); - } - JSONObject o = new JSONObject(content.getContent()); - JSONArray jsonModels = o.getJSONArray("models"); - Map models = new HashMap(jsonModels.length()); - for(int i = 0; i < jsonModels.length(); i++) - { - JSONObject jsonModel = jsonModels.getJSONObject(i); - models.put(QName.createQName(jsonModel.getString("name")), jsonModel.getLong("checksum")); - } - - List diffs = solrTrackingComponent.getModelDiffs(models); - model.put("diffs", diffs); - - if (logger.isDebugEnabled()) - { - logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); - } - - return model; - } -} +package org.alfresco.repo.web.scripts.solr; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.solr.AlfrescoModelDiff; +import org.alfresco.repo.solr.SOLRTrackingComponent; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Support for SOLR: Track Alfresco model changes + * + * @since 4.0 + */ +public class AlfrescoModelsDiff extends DeclarativeWebScript +{ + protected static final Log logger = LogFactory.getLog(AlfrescoModelsDiff.class); + + private static final String MSG_IO_EXCEPTION = "IO exception parsing request "; + + private static final String MSG_JSON_EXCEPTION = "Unable to fetch model changes from "; + + private SOLRTrackingComponent solrTrackingComponent; + + public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent) + { + this.solrTrackingComponent = solrTrackingComponent; + } + + protected Map executeImpl(WebScriptRequest req, Status status) + { + try + { + Map model = buildModel(req); + if (logger.isDebugEnabled()) + { + logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); + } + return model; + } + catch (IOException e) + { + setExceptionResponse(req, status, MSG_IO_EXCEPTION, Status.STATUS_INTERNAL_SERVER_ERROR, e); + return null; + } + catch (JSONException e) + { + setExceptionResponse(req, status, MSG_JSON_EXCEPTION, Status.STATUS_BAD_REQUEST, e); + return null; + } + } + + private void setExceptionResponse(WebScriptRequest req, Status responseStatus, String responseMessage, int statusCode, Exception e) + { + String message = responseMessage + req; + + if (logger.isDebugEnabled()) + { + logger.warn(message, e); + } + else + { + logger.warn(message); + } + + responseStatus.setCode(statusCode, message); + responseStatus.setException(e); + } + + private Map buildModel(WebScriptRequest req) throws JSONException, IOException + { + Map model = new HashMap(1, 1.0f); + + Content content = req.getContent(); + if(content == null) + { + throw new WebScriptException("Failed to convert request to String"); + } + JSONObject o = new JSONObject(content.getContent()); + JSONArray jsonModels = o.getJSONArray("models"); + Map models = new HashMap(jsonModels.length()); + for(int i = 0; i < jsonModels.length(); i++) + { + JSONObject jsonModel = jsonModels.getJSONObject(i); + models.put(QName.createQName(jsonModel.getString("name")), jsonModel.getLong("checksum")); + } + + List diffs = solrTrackingComponent.getModelDiffs(models); + model.put("diffs", diffs); + + if (logger.isDebugEnabled()) + { + logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); + } + + return model; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/GetNodesParameters.java b/source/java/org/alfresco/repo/web/scripts/solr/GetNodesParameters.java index 5544c0fb11..21ae5369dc 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/GetNodesParameters.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/GetNodesParameters.java @@ -1,123 +1,123 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.util.List; -import java.util.Set; - -import org.alfresco.service.namespace.QName; - -/** - * Input parameters for retrieving node details for SOLR. - * - * @since 4.0 - */ -public class GetNodesParameters -{ - private List transactionIds; - private Long fromNodeId; - private Long toNodeId; - - private String storeProtocol; - private String storeIdentifier; - - private Set includeNodeTypes; - private Set excludeNodeTypes; - - private Set includeAspects; - private Set excludeAspects; - - public boolean getStoreFilter() - { - return (storeProtocol != null || storeIdentifier != null); - } - - public void setStoreProtocol(String storeProtocol) - { - this.storeProtocol = storeProtocol; - } - - public String getStoreProtocol() - { - return storeProtocol; - } - - public void setStoreIdentifier(String storeIdentifier) - { - this.storeIdentifier = storeIdentifier; - } - - public String getStoreIdentifier() - { - return storeIdentifier; - } - - public void setTransactionIds(List txnIds) - { - this.transactionIds = txnIds; - } - - public List getTransactionIds() - { - return transactionIds; - } - - public Long getFromNodeId() - { - return fromNodeId; - } - - public void setFromNodeId(Long fromNodeId) - { - this.fromNodeId = fromNodeId; - } - - public Long getToNodeId() - { - return toNodeId; - } - - public void setToNodeId(Long toNodeId) - { - this.toNodeId = toNodeId; - } - - public Set getIncludeNodeTypes() - { - return includeNodeTypes; - } - - public Set getExcludeNodeTypes() - { - return excludeNodeTypes; - } - - public Set getIncludeAspects() - { - return includeAspects; - } - - public Set getExcludeAspects() - { - return excludeAspects; - } - - public void setIncludeNodeTypes(Set includeNodeTypes) - { - this.includeNodeTypes = includeNodeTypes; - } - - public void setExcludeNodeTypes(Set excludeNodeTypes) - { - this.excludeNodeTypes = excludeNodeTypes; - } - - public void setIncludeAspects(Set includeAspects) - { - this.includeAspects = includeAspects; - } - - public void setExcludeAspects(Set excludeAspects) - { - this.excludeAspects = excludeAspects; - } - -} +package org.alfresco.repo.web.scripts.solr; + +import java.util.List; +import java.util.Set; + +import org.alfresco.service.namespace.QName; + +/** + * Input parameters for retrieving node details for SOLR. + * + * @since 4.0 + */ +public class GetNodesParameters +{ + private List transactionIds; + private Long fromNodeId; + private Long toNodeId; + + private String storeProtocol; + private String storeIdentifier; + + private Set includeNodeTypes; + private Set excludeNodeTypes; + + private Set includeAspects; + private Set excludeAspects; + + public boolean getStoreFilter() + { + return (storeProtocol != null || storeIdentifier != null); + } + + public void setStoreProtocol(String storeProtocol) + { + this.storeProtocol = storeProtocol; + } + + public String getStoreProtocol() + { + return storeProtocol; + } + + public void setStoreIdentifier(String storeIdentifier) + { + this.storeIdentifier = storeIdentifier; + } + + public String getStoreIdentifier() + { + return storeIdentifier; + } + + public void setTransactionIds(List txnIds) + { + this.transactionIds = txnIds; + } + + public List getTransactionIds() + { + return transactionIds; + } + + public Long getFromNodeId() + { + return fromNodeId; + } + + public void setFromNodeId(Long fromNodeId) + { + this.fromNodeId = fromNodeId; + } + + public Long getToNodeId() + { + return toNodeId; + } + + public void setToNodeId(Long toNodeId) + { + this.toNodeId = toNodeId; + } + + public Set getIncludeNodeTypes() + { + return includeNodeTypes; + } + + public Set getExcludeNodeTypes() + { + return excludeNodeTypes; + } + + public Set getIncludeAspects() + { + return includeAspects; + } + + public Set getExcludeAspects() + { + return excludeAspects; + } + + public void setIncludeNodeTypes(Set includeNodeTypes) + { + this.includeNodeTypes = includeNodeTypes; + } + + public void setExcludeNodeTypes(Set excludeNodeTypes) + { + this.excludeNodeTypes = excludeNodeTypes; + } + + public void setIncludeAspects(Set includeAspects) + { + this.includeAspects = includeAspects; + } + + public void setExcludeAspects(Set excludeAspects) + { + this.excludeAspects = excludeAspects; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/NodeMetaData.java b/source/java/org/alfresco/repo/web/scripts/solr/NodeMetaData.java index c98c5fa85a..689cc28712 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/NodeMetaData.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/NodeMetaData.java @@ -1,90 +1,90 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.Serializable; -import java.util.Map; -import java.util.Set; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.namespace.QName; - -/** - * Bean to carry node metadata - * - * @since 4.0 - */ -public class NodeMetaData -{ - private long id; - private NodeRef nodeRef; - private QName type; - private long aclId; - private Map properties; - private Set aspects; - private Path paths; - public long getId() - { - return id; - } - public void setId(long id) - { - this.id = id; - } - public NodeRef getNodeRef() - { - return nodeRef; - } - public void setNodeRef(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - } - public QName getType() - { - return type; - } - public void setType(QName type) - { - this.type = type; - } - public long getAclId() - { - return aclId; - } - public void setAclId(long aclId) - { - this.aclId = aclId; - } - public Map getProperties() - { - return properties; - } - public void setProperties(Map properties) - { - this.properties = properties; - } - public Set getAspects() - { - return aspects; - } - public void setAspects(Set aspects) - { - this.aspects = aspects; - } - public Path getPaths() - { - return paths; - } - public void setPaths(Path paths) - { - this.paths = paths; - } - - @Override - public String toString() - { - return "NodeMetaData [id=" + id + ", nodeRef=" + nodeRef + ", type=" + type + ", aclId=" + aclId - + ", properties=" + properties + ", aspects=" + aspects + ", paths=" + paths + "]"; - } - - -} +package org.alfresco.repo.web.scripts.solr; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.namespace.QName; + +/** + * Bean to carry node metadata + * + * @since 4.0 + */ +public class NodeMetaData +{ + private long id; + private NodeRef nodeRef; + private QName type; + private long aclId; + private Map properties; + private Set aspects; + private Path paths; + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public NodeRef getNodeRef() + { + return nodeRef; + } + public void setNodeRef(NodeRef nodeRef) + { + this.nodeRef = nodeRef; + } + public QName getType() + { + return type; + } + public void setType(QName type) + { + this.type = type; + } + public long getAclId() + { + return aclId; + } + public void setAclId(long aclId) + { + this.aclId = aclId; + } + public Map getProperties() + { + return properties; + } + public void setProperties(Map properties) + { + this.properties = properties; + } + public Set getAspects() + { + return aspects; + } + public void setAspects(Set aspects) + { + this.aspects = aspects; + } + public Path getPaths() + { + return paths; + } + public void setPaths(Path paths) + { + this.paths = paths; + } + + @Override + public String toString() + { + return "NodeMetaData [id=" + id + ", nodeRef=" + nodeRef + ", type=" + type + ", aclId=" + aclId + + ", properties=" + properties + ", aspects=" + aspects + ", paths=" + paths + "]"; + } + + +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/PropertyValue.java b/source/java/org/alfresco/repo/web/scripts/solr/PropertyValue.java index 87b327fc67..64a4820c85 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/PropertyValue.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/PropertyValue.java @@ -1,46 +1,46 @@ -package org.alfresco.repo.web.scripts.solr; - -/** - * Represents a property value to be used by Freemarker - * - * @since 4.0 - */ -class PropertyValue -{ - // is value actually a string or a JSON object or array - // if true, enclose the value in double quotes (to represent a JSON string) - // when converting to a string. - private boolean isString = true; - - private String value; - - public PropertyValue(boolean isString, String value) - { - super(); - this.isString = isString; - this.value = value; - } - public boolean isString() - { - return isString; - } - public String getValue() - { - return value; - } - - public String toString() - { - StringBuilder sb = new StringBuilder(); - if(isString) - { - sb.append("\""); // for json strings - } - sb.append(value); - if(isString) - { - sb.append("\""); // for json strings - } - return sb.toString(); - } -} +package org.alfresco.repo.web.scripts.solr; + +/** + * Represents a property value to be used by Freemarker + * + * @since 4.0 + */ +class PropertyValue +{ + // is value actually a string or a JSON object or array + // if true, enclose the value in double quotes (to represent a JSON string) + // when converting to a string. + private boolean isString = true; + + private String value; + + public PropertyValue(boolean isString, String value) + { + super(); + this.isString = isString; + this.value = value; + } + public boolean isString() + { + return isString; + } + public String getValue() + { + return value; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + if(isString) + { + sb.append("\""); // for json strings + } + sb.append(value); + if(isString) + { + sb.append("\""); // for json strings + } + return sb.toString(); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/SOLRAuthenticationFilter.java b/source/java/org/alfresco/repo/web/scripts/solr/SOLRAuthenticationFilter.java index 3e703d084e..ab618befa2 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/SOLRAuthenticationFilter.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/SOLRAuthenticationFilter.java @@ -1,260 +1,260 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * This filter protects the solr callback urls by verifying MACs on requests and encrypting responses - * and generating MACs on responses, if the secureComms property is set to "md5". If it is set to "https" - * or "none", the filter does nothing to the request and response. - * - * @since 4.0 - * - */ -public class SOLRAuthenticationFilter implements DependencyInjectedFilter -{ - public static enum SecureCommsType - { - HTTPS, NONE; - - public static SecureCommsType getType(String type) - { - if(type.equalsIgnoreCase("https")) - { - return HTTPS; - } - else if(type.equalsIgnoreCase("none")) - { - return NONE; - } - else - { - throw new IllegalArgumentException("Invalid communications type"); - } - } - }; - - // Logger - private static Log logger = LogFactory.getLog(SOLRAuthenticationFilter.class); - - private SecureCommsType secureComms = SecureCommsType.HTTPS; - - public void setSecureComms(String type) - { - try - { - this.secureComms = SecureCommsType.getType(type); - } - catch(IllegalArgumentException e) - { - throw new AlfrescoRuntimeException("", e); - } - } - - public void doFilter(ServletContext context, ServletRequest request, - ServletResponse response, FilterChain chain) throws IOException, - ServletException - { - HttpServletRequest httpRequest = (HttpServletRequest)request; - HttpServletResponse httpResponse = (HttpServletResponse)response; - -/* if(secureComms == SecureCommsType.ALFRESCO) - { - // Need to get as a byte array because we need to read the request twice, once for authentication - // and again by the web service. - SOLRHttpServletRequestWrapper requestWrapper = new SOLRHttpServletRequestWrapper(httpRequest, encryptionUtils); - - if(logger.isDebugEnabled()) - { - logger.debug("Authenticating " + httpRequest.getRequestURI()); - } - - if(encryptionUtils.authenticate(httpRequest, requestWrapper.getDecryptedBody())) - { - try - { - OutputStream out = response.getOutputStream(); - - GenericResponseWrapper responseWrapper = new GenericResponseWrapper(httpResponse); - - // TODO - do I need to chain to other authenticating filters - probably not? - // Could also remove sending of credentials with http request - chain.doFilter(requestWrapper, responseWrapper); - - Pair pair = encryptor.encrypt(KeyProvider.ALIAS_SOLR, null, responseWrapper.getData()); - - encryptionUtils.setResponseAuthentication(httpRequest, httpResponse, responseWrapper.getData(), pair.getSecond()); - - httpResponse.setHeader("Content-Length", Long.toString(pair.getFirst().length)); - out.write(pair.getFirst()); - out.close(); - } - catch(Exception e) - { - throw new AlfrescoRuntimeException("", e); - } - } - else - { - httpResponse.setStatus(401); - } - } - else */if(secureComms == SecureCommsType.HTTPS) - { - if(httpRequest.isSecure()) - { - // https authentication - chain.doFilter(request, response); - } - else - { - throw new AlfrescoRuntimeException("Expected a https request"); - } - } - else - { - chain.doFilter(request, response); - } - } - - protected boolean validateTimestamp(String timestampStr) - { - if(timestampStr == null || timestampStr.equals("")) - { - throw new AlfrescoRuntimeException("Missing timestamp on request"); - } - long timestamp = -1; - try - { - timestamp = Long.valueOf(timestampStr); - } - catch(NumberFormatException e) - { - throw new AlfrescoRuntimeException("Invalid timestamp on request"); - } - if(timestamp == -1) - { - throw new AlfrescoRuntimeException("Invalid timestamp on request"); - } - long currentTime = System.currentTimeMillis(); - return((currentTime - timestamp) < 30 * 1000); // 5s - } - -/* private static class SOLRHttpServletRequestWrapper extends HttpServletRequestWrapper - { - private byte[] body; - - SOLRHttpServletRequestWrapper(HttpServletRequest req, EncryptionUtils encryptionUtils) throws IOException - { - super(req); - this.body = encryptionUtils.decryptBody(req); - } - - byte[] getDecryptedBody() - { - return body; - } - - public ServletInputStream getInputStream() - { - final InputStream in = (body != null ? new ByteArrayInputStream(body) : null); - return new ServletInputStream() - { - public int read() throws IOException - { - if(in == null) - { - return -1; - } - else - { - int i = in.read(); - if(i == -1) - { - in.close(); - } - return i; - } - } - }; - } - }*/ - - private static class ByteArrayServletOutputStream extends ServletOutputStream - { - private ByteArrayOutputStream out = new ByteArrayOutputStream(); - - ByteArrayServletOutputStream() - { - } - - public byte[] getData() - { - return out.toByteArray(); - } - - @Override - public void write(int b) throws IOException - { - out.write(b); - } - } - - public static class GenericResponseWrapper extends HttpServletResponseWrapper { - private ByteArrayServletOutputStream output; - private int contentLength; - private String contentType; - - public GenericResponseWrapper(HttpServletResponse response) { - super(response); - output = new ByteArrayServletOutputStream(); - } - - public byte[] getData() { - return output.getData(); - } - - public ServletOutputStream getOutputStream() { - return output; - } - - public PrintWriter getWriter() { - return new PrintWriter(getOutputStream(),true); - } - - public void setContentLength(int length) { - this.contentLength = length; - super.setContentLength(length); - } - - public int getContentLength() { - return contentLength; - } - - public void setContentType(String type) { - this.contentType = type; - super.setContentType(type); - } - - - public String getContentType() { - return contentType; - } - } -} +package org.alfresco.repo.web.scripts.solr; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This filter protects the solr callback urls by verifying MACs on requests and encrypting responses + * and generating MACs on responses, if the secureComms property is set to "md5". If it is set to "https" + * or "none", the filter does nothing to the request and response. + * + * @since 4.0 + * + */ +public class SOLRAuthenticationFilter implements DependencyInjectedFilter +{ + public static enum SecureCommsType + { + HTTPS, NONE; + + public static SecureCommsType getType(String type) + { + if(type.equalsIgnoreCase("https")) + { + return HTTPS; + } + else if(type.equalsIgnoreCase("none")) + { + return NONE; + } + else + { + throw new IllegalArgumentException("Invalid communications type"); + } + } + }; + + // Logger + private static Log logger = LogFactory.getLog(SOLRAuthenticationFilter.class); + + private SecureCommsType secureComms = SecureCommsType.HTTPS; + + public void setSecureComms(String type) + { + try + { + this.secureComms = SecureCommsType.getType(type); + } + catch(IllegalArgumentException e) + { + throw new AlfrescoRuntimeException("", e); + } + } + + public void doFilter(ServletContext context, ServletRequest request, + ServletResponse response, FilterChain chain) throws IOException, + ServletException + { + HttpServletRequest httpRequest = (HttpServletRequest)request; + HttpServletResponse httpResponse = (HttpServletResponse)response; + +/* if(secureComms == SecureCommsType.ALFRESCO) + { + // Need to get as a byte array because we need to read the request twice, once for authentication + // and again by the web service. + SOLRHttpServletRequestWrapper requestWrapper = new SOLRHttpServletRequestWrapper(httpRequest, encryptionUtils); + + if(logger.isDebugEnabled()) + { + logger.debug("Authenticating " + httpRequest.getRequestURI()); + } + + if(encryptionUtils.authenticate(httpRequest, requestWrapper.getDecryptedBody())) + { + try + { + OutputStream out = response.getOutputStream(); + + GenericResponseWrapper responseWrapper = new GenericResponseWrapper(httpResponse); + + // TODO - do I need to chain to other authenticating filters - probably not? + // Could also remove sending of credentials with http request + chain.doFilter(requestWrapper, responseWrapper); + + Pair pair = encryptor.encrypt(KeyProvider.ALIAS_SOLR, null, responseWrapper.getData()); + + encryptionUtils.setResponseAuthentication(httpRequest, httpResponse, responseWrapper.getData(), pair.getSecond()); + + httpResponse.setHeader("Content-Length", Long.toString(pair.getFirst().length)); + out.write(pair.getFirst()); + out.close(); + } + catch(Exception e) + { + throw new AlfrescoRuntimeException("", e); + } + } + else + { + httpResponse.setStatus(401); + } + } + else */if(secureComms == SecureCommsType.HTTPS) + { + if(httpRequest.isSecure()) + { + // https authentication + chain.doFilter(request, response); + } + else + { + throw new AlfrescoRuntimeException("Expected a https request"); + } + } + else + { + chain.doFilter(request, response); + } + } + + protected boolean validateTimestamp(String timestampStr) + { + if(timestampStr == null || timestampStr.equals("")) + { + throw new AlfrescoRuntimeException("Missing timestamp on request"); + } + long timestamp = -1; + try + { + timestamp = Long.valueOf(timestampStr); + } + catch(NumberFormatException e) + { + throw new AlfrescoRuntimeException("Invalid timestamp on request"); + } + if(timestamp == -1) + { + throw new AlfrescoRuntimeException("Invalid timestamp on request"); + } + long currentTime = System.currentTimeMillis(); + return((currentTime - timestamp) < 30 * 1000); // 5s + } + +/* private static class SOLRHttpServletRequestWrapper extends HttpServletRequestWrapper + { + private byte[] body; + + SOLRHttpServletRequestWrapper(HttpServletRequest req, EncryptionUtils encryptionUtils) throws IOException + { + super(req); + this.body = encryptionUtils.decryptBody(req); + } + + byte[] getDecryptedBody() + { + return body; + } + + public ServletInputStream getInputStream() + { + final InputStream in = (body != null ? new ByteArrayInputStream(body) : null); + return new ServletInputStream() + { + public int read() throws IOException + { + if(in == null) + { + return -1; + } + else + { + int i = in.read(); + if(i == -1) + { + in.close(); + } + return i; + } + } + }; + } + }*/ + + private static class ByteArrayServletOutputStream extends ServletOutputStream + { + private ByteArrayOutputStream out = new ByteArrayOutputStream(); + + ByteArrayServletOutputStream() + { + } + + public byte[] getData() + { + return out.toByteArray(); + } + + @Override + public void write(int b) throws IOException + { + out.write(b); + } + } + + public static class GenericResponseWrapper extends HttpServletResponseWrapper { + private ByteArrayServletOutputStream output; + private int contentLength; + private String contentType; + + public GenericResponseWrapper(HttpServletResponse response) { + super(response); + output = new ByteArrayServletOutputStream(); + } + + public byte[] getData() { + return output.getData(); + } + + public ServletOutputStream getOutputStream() { + return output; + } + + public PrintWriter getWriter() { + return new PrintWriter(getOutputStream(),true); + } + + public void setContentLength(int length) { + this.contentLength = length; + super.setContentLength(length); + } + + public int getContentLength() { + return contentLength; + } + + public void setContentType(String type) { + this.contentType = type; + super.setContentType(type); + } + + + public String getContentType() { + return contentType; + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java b/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java index 7348e255c6..df38c666be 100644 --- a/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java +++ b/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java @@ -1,456 +1,456 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.domain.node.ContentDataWithId; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.MLText; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.cmr.repository.Path.AttributeElement; -import org.alfresco.service.cmr.repository.Path.ChildAssocElement; -import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; -import org.alfresco.service.cmr.repository.datatype.TypeConverter; -import org.alfresco.service.cmr.repository.datatype.TypeConverter.Converter; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.extensions.webscripts.json.JSONUtils; - -/** - * SOLR conversions of values to JSON-compatible String. - * - * @since 4.0 - */ -/* package */ class SOLRSerializer -{ - protected static final Log logger = LogFactory.getLog(SOLRSerializer.class); - - private JSONUtils jsonUtils = new JSONUtils(); - - private Set NUMBER_TYPES; - - private DictionaryService dictionaryService; - private NamespaceService namespaceService; - - private SOLRTypeConverter typeConverter; - - public void init() - { - PropertyCheck.mandatory(this, "dictionaryService", dictionaryService); - PropertyCheck.mandatory(this, "namespaceService", namespaceService); - - NUMBER_TYPES = new HashSet(4); - NUMBER_TYPES.add(DataTypeDefinition.DOUBLE); - NUMBER_TYPES.add(DataTypeDefinition.FLOAT); - NUMBER_TYPES.add(DataTypeDefinition.INT); - NUMBER_TYPES.add(DataTypeDefinition.LONG); - - typeConverter = new SOLRTypeConverter(namespaceService); - } - - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - - public String serializeToJSONString(Serializable value) - { - if (value != null && typeConverter.INSTANCE.getConverter(value.getClass(), String.class) == null) - { - // There is no converter - return value.toString(); - } - else - { - return typeConverter.INSTANCE.convert(String.class, value); - } - } - - public T serializeValue(Class targetClass, Object value) throws JSONException - { - return typeConverter.INSTANCE.convert(targetClass, value); - } - - @SuppressWarnings("unchecked") - public PropertyValue serialize(QName propName, Serializable value) throws IOException, JSONException - { - if(value == null) - { - return new PropertyValue(false, "null"); - } - - PropertyDefinition propertyDef = dictionaryService.getProperty(propName); - if (propertyDef == null) - { - // Treat it as text - return new PropertyValue(true, serializeToJSONString(value)); - } - DataTypeDefinition dataType = propertyDef.getDataType(); - QName dataTypeName = dataType.getName(); - if (propertyDef.isMultiValued()) - { - if(!(value instanceof Collection)) - { - throw new IllegalArgumentException("Multi value: expected a collection, got " + value.getClass().getName()); - } - - Collection c = (Collection)value; - - JSONArray body = new JSONArray(); - for(Serializable o : c) - { - if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) - { - MLText source = (MLText)o; - JSONArray array = new JSONArray(); - for(Locale locale : source.getLocales()) - { - JSONObject json = new JSONObject(); - json.put("locale", DefaultTypeConverter.INSTANCE.convert(String.class, locale)); - json.put("value", source.getValue(locale)); - array.put(json); - } - body.put(array); - } - else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) - { - throw new RuntimeException("Multi-valued content properties are not supported"); - } - else - { - body.put(serializeToJSONString(o)); - } - - } - - return new PropertyValue(false, body.toString()); - } - else - { - boolean encodeString = true; - if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) - { - encodeString = false; - } - else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) - { - encodeString = false; - } - else - { - encodeString = true; - } - - String sValue = null; - if (value instanceof String && encodeString) { - sValue = (String)jsonUtils.encodeJSONString(value); - } else { - sValue = serializeToJSONString(value); - } - - return new PropertyValue(encodeString, sValue); - } - } - - @SuppressWarnings("rawtypes") - private class SOLRTypeConverter - { - private NamespaceService namespaceService; - TypeConverter INSTANCE = new TypeConverter(); - - @SuppressWarnings("unchecked") - SOLRTypeConverter(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - - // add all default converters to this converter - // TODO find a better way of doing this - Map, Map, Converter>> converters = DefaultTypeConverter.INSTANCE.getConverters(); - for(Class source : converters.keySet()) - { - Map, Converter> converters1 = converters.get(source); - for(Class dest : converters1.keySet()) - { - Converter converter = converters1.get(dest); - INSTANCE.addConverter(source, dest, converter); - } - } - - // MLText - INSTANCE.addConverter(MLText.class, String.class, new TypeConverter.Converter() - { - public String convert(MLText source) - { - try - { - JSONArray array = new JSONArray(); - for(Locale locale : source.getLocales()) - { - JSONObject json = new JSONObject(); - json.put("locale", DefaultTypeConverter.INSTANCE.convert(String.class, locale)); - json.put("value", source.getValue(locale)); - array.put(json); - } - - return array.toString(3); - } - catch(JSONException e) - { - throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); - } - } - }); - - // QName - INSTANCE.addConverter(QName.class, String.class, new TypeConverter.Converter() - { - public String convert(QName source) - { - return source.toString(); - } - }); - - // content - INSTANCE.addConverter(ContentDataWithId.class, String.class, new TypeConverter.Converter() - { - public String convert(ContentDataWithId source) - { - JSONObject json = new JSONObject(); - try - { - json.put("contentId", String.valueOf(source.getId())); - String locale = INSTANCE.convert(String.class, source.getLocale()); - json.put("locale", locale == null ? JSONObject.NULL : locale); - String encoding = source.getEncoding(); - json.put("encoding", encoding == null ? JSONObject.NULL : encoding); - String mimetype = source.getMimetype(); - json.put("mimetype", mimetype == null ? JSONObject.NULL : mimetype); - json.put("size", String.valueOf(source.getSize())); - return json.toString(3); - } - catch(JSONException e) - { - throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); - } - } - }); - - INSTANCE.addConverter(ContentData.class, String.class, new TypeConverter.Converter() - { - public String convert(ContentData source) - { - JSONObject json = new JSONObject(); - try - { - String locale = INSTANCE.convert(String.class, source.getLocale()); - json.put("locale", locale == null ? JSONObject.NULL : locale); - String encoding = source.getEncoding(); - json.put("encoding", encoding == null ? JSONObject.NULL : encoding); - String mimetype = source.getMimetype(); - json.put("mimetype", mimetype == null ? JSONObject.NULL : mimetype); - json.put("size", String.valueOf(source.getSize())); - return json.toString(3); - } - catch(JSONException e) - { - throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); - } - } - }); - - // node refs - INSTANCE.addConverter(NodeRef.class, String.class, new TypeConverter.Converter() - { - public String convert(NodeRef source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(String.class, NodeRef.class, new TypeConverter.Converter() - { - public NodeRef convert(String source) - { - return new NodeRef(source); - } - }); - - // paths - INSTANCE.addConverter(AttributeElement.class, String.class, new TypeConverter.Converter() - { - public String convert(AttributeElement source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(ChildAssocElement.class, String.class, new TypeConverter.Converter() - { - public String convert(ChildAssocElement source) - { - return source.getRef().toString(); - } - }); - - INSTANCE.addConverter(Path.DescendentOrSelfElement.class, String.class, new TypeConverter.Converter() - { - public String convert(Path.DescendentOrSelfElement source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(Path.ParentElement.class, String.class, new TypeConverter.Converter() - { - public String convert(Path.ParentElement source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(Path.SelfElement.class, String.class, new TypeConverter.Converter() - { - public String convert(Path.SelfElement source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(String.class, AttributeElement.class, new TypeConverter.Converter() - { - public AttributeElement convert(String source) - { - return new Path.AttributeElement(source); - } - }); - - INSTANCE.addConverter(String.class, ChildAssocElement.class, new TypeConverter.Converter() - { - public ChildAssocElement convert(String source) - { - return new Path.ChildAssocElement(INSTANCE.convert(ChildAssociationRef.class, source)); - } - }); - - INSTANCE.addConverter(String.class, Path.DescendentOrSelfElement.class, new TypeConverter.Converter() - { - public Path.DescendentOrSelfElement convert(String source) - { - return new Path.DescendentOrSelfElement(); - } - }); - - INSTANCE.addConverter(String.class, Path.ParentElement.class, new TypeConverter.Converter() - { - public Path.ParentElement convert(String source) - { - return new Path.ParentElement(); - } - }); - - INSTANCE.addConverter(String.class, Path.SelfElement.class, new TypeConverter.Converter() - { - public Path.SelfElement convert(String source) - { - return new Path.SelfElement(); - } - }); - - - INSTANCE.addConverter(Path.class, List.class, new TypeConverter.Converter() - { - public List convert(Path source) - { - List pathArray = new ArrayList(source.size()); - for(Path.Element element : source) - { - pathArray.add(INSTANCE.convert(String.class, element)); - } - return pathArray; - } - }); - - INSTANCE.addConverter(Path.class, String.class, new TypeConverter.Converter() - { - public String convert(Path source) - { - return source.toString(); - } - }); - - // associations - INSTANCE.addConverter(ChildAssociationRef.class, String.class, new TypeConverter.Converter() - { - public String convert(ChildAssociationRef source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(String.class, ChildAssociationRef.class, new TypeConverter.Converter() - { - public ChildAssociationRef convert(String source) - { - return new ChildAssociationRef(source); - } - }); - - INSTANCE.addConverter(AssociationRef.class, String.class, new TypeConverter.Converter() - { - public String convert(AssociationRef source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(String.class, AssociationRef.class, new TypeConverter.Converter() - { - public AssociationRef convert(String source) - { - return new AssociationRef(source); - } - }); - - INSTANCE.addConverter(Number.class, String.class, new TypeConverter.Converter() - { - public String convert(Number source) - { - return source.toString(); - } - }); - - INSTANCE.addConverter(Boolean.class, String.class, new TypeConverter.Converter() - { - public String convert(Boolean source) - { - return source.toString(); - } - }); - } - } -} +package org.alfresco.repo.web.scripts.solr; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.domain.node.ContentDataWithId; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Path.AttributeElement; +import org.alfresco.service.cmr.repository.Path.ChildAssocElement; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConverter.Converter; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.PropertyCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.extensions.webscripts.json.JSONUtils; + +/** + * SOLR conversions of values to JSON-compatible String. + * + * @since 4.0 + */ +/* package */ class SOLRSerializer +{ + protected static final Log logger = LogFactory.getLog(SOLRSerializer.class); + + private JSONUtils jsonUtils = new JSONUtils(); + + private Set NUMBER_TYPES; + + private DictionaryService dictionaryService; + private NamespaceService namespaceService; + + private SOLRTypeConverter typeConverter; + + public void init() + { + PropertyCheck.mandatory(this, "dictionaryService", dictionaryService); + PropertyCheck.mandatory(this, "namespaceService", namespaceService); + + NUMBER_TYPES = new HashSet(4); + NUMBER_TYPES.add(DataTypeDefinition.DOUBLE); + NUMBER_TYPES.add(DataTypeDefinition.FLOAT); + NUMBER_TYPES.add(DataTypeDefinition.INT); + NUMBER_TYPES.add(DataTypeDefinition.LONG); + + typeConverter = new SOLRTypeConverter(namespaceService); + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + public String serializeToJSONString(Serializable value) + { + if (value != null && typeConverter.INSTANCE.getConverter(value.getClass(), String.class) == null) + { + // There is no converter + return value.toString(); + } + else + { + return typeConverter.INSTANCE.convert(String.class, value); + } + } + + public T serializeValue(Class targetClass, Object value) throws JSONException + { + return typeConverter.INSTANCE.convert(targetClass, value); + } + + @SuppressWarnings("unchecked") + public PropertyValue serialize(QName propName, Serializable value) throws IOException, JSONException + { + if(value == null) + { + return new PropertyValue(false, "null"); + } + + PropertyDefinition propertyDef = dictionaryService.getProperty(propName); + if (propertyDef == null) + { + // Treat it as text + return new PropertyValue(true, serializeToJSONString(value)); + } + DataTypeDefinition dataType = propertyDef.getDataType(); + QName dataTypeName = dataType.getName(); + if (propertyDef.isMultiValued()) + { + if(!(value instanceof Collection)) + { + throw new IllegalArgumentException("Multi value: expected a collection, got " + value.getClass().getName()); + } + + Collection c = (Collection)value; + + JSONArray body = new JSONArray(); + for(Serializable o : c) + { + if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) + { + MLText source = (MLText)o; + JSONArray array = new JSONArray(); + for(Locale locale : source.getLocales()) + { + JSONObject json = new JSONObject(); + json.put("locale", DefaultTypeConverter.INSTANCE.convert(String.class, locale)); + json.put("value", source.getValue(locale)); + array.put(json); + } + body.put(array); + } + else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) + { + throw new RuntimeException("Multi-valued content properties are not supported"); + } + else + { + body.put(serializeToJSONString(o)); + } + + } + + return new PropertyValue(false, body.toString()); + } + else + { + boolean encodeString = true; + if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) + { + encodeString = false; + } + else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) + { + encodeString = false; + } + else + { + encodeString = true; + } + + String sValue = null; + if (value instanceof String && encodeString) { + sValue = (String)jsonUtils.encodeJSONString(value); + } else { + sValue = serializeToJSONString(value); + } + + return new PropertyValue(encodeString, sValue); + } + } + + @SuppressWarnings("rawtypes") + private class SOLRTypeConverter + { + private NamespaceService namespaceService; + TypeConverter INSTANCE = new TypeConverter(); + + @SuppressWarnings("unchecked") + SOLRTypeConverter(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + + // add all default converters to this converter + // TODO find a better way of doing this + Map, Map, Converter>> converters = DefaultTypeConverter.INSTANCE.getConverters(); + for(Class source : converters.keySet()) + { + Map, Converter> converters1 = converters.get(source); + for(Class dest : converters1.keySet()) + { + Converter converter = converters1.get(dest); + INSTANCE.addConverter(source, dest, converter); + } + } + + // MLText + INSTANCE.addConverter(MLText.class, String.class, new TypeConverter.Converter() + { + public String convert(MLText source) + { + try + { + JSONArray array = new JSONArray(); + for(Locale locale : source.getLocales()) + { + JSONObject json = new JSONObject(); + json.put("locale", DefaultTypeConverter.INSTANCE.convert(String.class, locale)); + json.put("value", source.getValue(locale)); + array.put(json); + } + + return array.toString(3); + } + catch(JSONException e) + { + throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); + } + } + }); + + // QName + INSTANCE.addConverter(QName.class, String.class, new TypeConverter.Converter() + { + public String convert(QName source) + { + return source.toString(); + } + }); + + // content + INSTANCE.addConverter(ContentDataWithId.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentDataWithId source) + { + JSONObject json = new JSONObject(); + try + { + json.put("contentId", String.valueOf(source.getId())); + String locale = INSTANCE.convert(String.class, source.getLocale()); + json.put("locale", locale == null ? JSONObject.NULL : locale); + String encoding = source.getEncoding(); + json.put("encoding", encoding == null ? JSONObject.NULL : encoding); + String mimetype = source.getMimetype(); + json.put("mimetype", mimetype == null ? JSONObject.NULL : mimetype); + json.put("size", String.valueOf(source.getSize())); + return json.toString(3); + } + catch(JSONException e) + { + throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); + } + } + }); + + INSTANCE.addConverter(ContentData.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentData source) + { + JSONObject json = new JSONObject(); + try + { + String locale = INSTANCE.convert(String.class, source.getLocale()); + json.put("locale", locale == null ? JSONObject.NULL : locale); + String encoding = source.getEncoding(); + json.put("encoding", encoding == null ? JSONObject.NULL : encoding); + String mimetype = source.getMimetype(); + json.put("mimetype", mimetype == null ? JSONObject.NULL : mimetype); + json.put("size", String.valueOf(source.getSize())); + return json.toString(3); + } + catch(JSONException e) + { + throw new AlfrescoRuntimeException("Unable to serialize content data to JSON", e); + } + } + }); + + // node refs + INSTANCE.addConverter(NodeRef.class, String.class, new TypeConverter.Converter() + { + public String convert(NodeRef source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(String.class, NodeRef.class, new TypeConverter.Converter() + { + public NodeRef convert(String source) + { + return new NodeRef(source); + } + }); + + // paths + INSTANCE.addConverter(AttributeElement.class, String.class, new TypeConverter.Converter() + { + public String convert(AttributeElement source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(ChildAssocElement.class, String.class, new TypeConverter.Converter() + { + public String convert(ChildAssocElement source) + { + return source.getRef().toString(); + } + }); + + INSTANCE.addConverter(Path.DescendentOrSelfElement.class, String.class, new TypeConverter.Converter() + { + public String convert(Path.DescendentOrSelfElement source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(Path.ParentElement.class, String.class, new TypeConverter.Converter() + { + public String convert(Path.ParentElement source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(Path.SelfElement.class, String.class, new TypeConverter.Converter() + { + public String convert(Path.SelfElement source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(String.class, AttributeElement.class, new TypeConverter.Converter() + { + public AttributeElement convert(String source) + { + return new Path.AttributeElement(source); + } + }); + + INSTANCE.addConverter(String.class, ChildAssocElement.class, new TypeConverter.Converter() + { + public ChildAssocElement convert(String source) + { + return new Path.ChildAssocElement(INSTANCE.convert(ChildAssociationRef.class, source)); + } + }); + + INSTANCE.addConverter(String.class, Path.DescendentOrSelfElement.class, new TypeConverter.Converter() + { + public Path.DescendentOrSelfElement convert(String source) + { + return new Path.DescendentOrSelfElement(); + } + }); + + INSTANCE.addConverter(String.class, Path.ParentElement.class, new TypeConverter.Converter() + { + public Path.ParentElement convert(String source) + { + return new Path.ParentElement(); + } + }); + + INSTANCE.addConverter(String.class, Path.SelfElement.class, new TypeConverter.Converter() + { + public Path.SelfElement convert(String source) + { + return new Path.SelfElement(); + } + }); + + + INSTANCE.addConverter(Path.class, List.class, new TypeConverter.Converter() + { + public List convert(Path source) + { + List pathArray = new ArrayList(source.size()); + for(Path.Element element : source) + { + pathArray.add(INSTANCE.convert(String.class, element)); + } + return pathArray; + } + }); + + INSTANCE.addConverter(Path.class, String.class, new TypeConverter.Converter() + { + public String convert(Path source) + { + return source.toString(); + } + }); + + // associations + INSTANCE.addConverter(ChildAssociationRef.class, String.class, new TypeConverter.Converter() + { + public String convert(ChildAssociationRef source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(String.class, ChildAssociationRef.class, new TypeConverter.Converter() + { + public ChildAssociationRef convert(String source) + { + return new ChildAssociationRef(source); + } + }); + + INSTANCE.addConverter(AssociationRef.class, String.class, new TypeConverter.Converter() + { + public String convert(AssociationRef source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(String.class, AssociationRef.class, new TypeConverter.Converter() + { + public AssociationRef convert(String source) + { + return new AssociationRef(source); + } + }); + + INSTANCE.addConverter(Number.class, String.class, new TypeConverter.Converter() + { + public String convert(Number source) + { + return source.toString(); + } + }); + + INSTANCE.addConverter(Boolean.class, String.class, new TypeConverter.Converter() + { + public String convert(Boolean source) + { + return source.toString(); + } + }); + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java index 6f54de9742..9bdf3ef8c3 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java @@ -1,190 +1,190 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.Date; -import java.util.List; - -import org.alfresco.model.ContentModel; -import org.alfresco.query.PagingRequest; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.NoSuchPersonException; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.subscriptions.PrivateSubscriptionListException; -import org.alfresco.service.cmr.subscriptions.SubscriptionService; -import org.alfresco.service.cmr.subscriptions.SubscriptionsDisabledException; -import org.alfresco.util.ISO8601DateFormat; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Format; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public abstract class AbstractSubscriptionServiceWebScript extends AbstractWebScript -{ - protected SubscriptionService subscriptionService; - protected NodeService nodeService; - protected PersonService personService; - - public void setSubscriptionService(SubscriptionService subscriptionService) - { - this.subscriptionService = subscriptionService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setPersonService(PersonService personService) - { - this.personService = personService; - } - - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - if (!subscriptionService.isActive()) - { - res.setStatus(404); - return; - } - - try - { - String userId = req.getServiceMatch().getTemplateVars().get("userid"); - Object obj = executeImpl(userId, req, res); - - if (obj instanceof JSONObject || obj instanceof JSONArray) - { - res.setContentEncoding(Charset.defaultCharset().displayName()); - res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); - - Writer writer = res.getWriter(); - if (obj instanceof JSONObject) - { - ((JSONObject) obj).writeJSONString(writer); - } else - { - ((JSONArray) obj).writeJSONString(writer); - } - writer.flush(); - } else - { - res.setStatus(204); - } - } catch (SubscriptionsDisabledException sde) - { - throw new WebScriptException(404, "Subscription service is disabled!", sde); - } catch (NoSuchPersonException nspe) - { - throw new WebScriptException(404, "Unknown user '" + nspe.getUserName() + "'!", nspe); - } catch (PrivateSubscriptionListException psle) - { - throw new WebScriptException(403, "Subscription list is private!", psle); - } catch (ParseException pe) - { - throw new WebScriptException(400, "Unable to parse JSON!", pe); - } catch (ClassCastException cce) - { - throw new WebScriptException(400, "Unable to parse JSON!", cce); - } catch (IOException ioe) - { - throw new WebScriptException(500, "Unable to serialize JSON!", ioe); - } - } - - public abstract Object executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException; - - protected int parseNumber(String name, String number, int def) - { - if (number != null && number.length() > 0) - { - try - { - return Integer.parseInt(number); - - } catch (NumberFormatException e) - { - throw new WebScriptException(400, name + " is not a number!", e); - } - } else - { - return def; - } - } - - protected PagingRequest createPagingRequest(WebScriptRequest req) - { - int skipCount = parseNumber("skipCount", req.getParameter("skipCount"), 0); - int maxItems = parseNumber("maxItems", req.getParameter("maxItems"), -1); - - PagingRequest result = new PagingRequest(skipCount, maxItems, null); - result.setRequestTotalCountMax(Integer.MAX_VALUE); - - return result; - } - - @SuppressWarnings("unchecked") - protected JSONObject getUserDetails(String username) - { - NodeRef node = personService.getPerson(username); - - JSONObject result = new JSONObject(); - result.put("userName", username); - result.put("firstName", nodeService.getProperty(node, ContentModel.PROP_FIRSTNAME)); - result.put("lastName", nodeService.getProperty(node, ContentModel.PROP_LASTNAME)); - result.put("jobtitle", nodeService.getProperty(node, ContentModel.PROP_JOBTITLE)); - result.put("organization", nodeService.getProperty(node, ContentModel.PROP_ORGANIZATION)); - - String status = (String) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS); - if (status != null) - { - result.put("userStatus", status); - } - - Date statusTime = (Date) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS_TIME); - if (statusTime != null) - { - JSONObject statusTimeJson = new JSONObject(); - statusTimeJson.put("iso8601", ISO8601DateFormat.format(statusTime)); - result.put("userStatusTime", statusTimeJson); - } - - // Get the avatar for the user id if one is available - List assocRefs = this.nodeService.getTargetAssocs(node, ContentModel.ASSOC_AVATAR); - if (!assocRefs.isEmpty()) - { - NodeRef avatarNodeRef = assocRefs.get(0).getTargetRef(); - result.put("avatar", avatarNodeRef.toString()); - } - else - { - result.put("avatar", "avatar"); // This indicates to just use a placeholder - } - - return result; - } - - @SuppressWarnings("unchecked") - protected JSONArray getUserArray(List usernames) - { - JSONArray result = new JSONArray(); - - if (usernames != null) - { - for (String username : usernames) - { - result.add(getUserDetails(username)); - } - } - - return result; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Date; +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.query.PagingRequest; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.NoSuchPersonException; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.subscriptions.PrivateSubscriptionListException; +import org.alfresco.service.cmr.subscriptions.SubscriptionService; +import org.alfresco.service.cmr.subscriptions.SubscriptionsDisabledException; +import org.alfresco.util.ISO8601DateFormat; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Format; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public abstract class AbstractSubscriptionServiceWebScript extends AbstractWebScript +{ + protected SubscriptionService subscriptionService; + protected NodeService nodeService; + protected PersonService personService; + + public void setSubscriptionService(SubscriptionService subscriptionService) + { + this.subscriptionService = subscriptionService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + if (!subscriptionService.isActive()) + { + res.setStatus(404); + return; + } + + try + { + String userId = req.getServiceMatch().getTemplateVars().get("userid"); + Object obj = executeImpl(userId, req, res); + + if (obj instanceof JSONObject || obj instanceof JSONArray) + { + res.setContentEncoding(Charset.defaultCharset().displayName()); + res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); + + Writer writer = res.getWriter(); + if (obj instanceof JSONObject) + { + ((JSONObject) obj).writeJSONString(writer); + } else + { + ((JSONArray) obj).writeJSONString(writer); + } + writer.flush(); + } else + { + res.setStatus(204); + } + } catch (SubscriptionsDisabledException sde) + { + throw new WebScriptException(404, "Subscription service is disabled!", sde); + } catch (NoSuchPersonException nspe) + { + throw new WebScriptException(404, "Unknown user '" + nspe.getUserName() + "'!", nspe); + } catch (PrivateSubscriptionListException psle) + { + throw new WebScriptException(403, "Subscription list is private!", psle); + } catch (ParseException pe) + { + throw new WebScriptException(400, "Unable to parse JSON!", pe); + } catch (ClassCastException cce) + { + throw new WebScriptException(400, "Unable to parse JSON!", cce); + } catch (IOException ioe) + { + throw new WebScriptException(500, "Unable to serialize JSON!", ioe); + } + } + + public abstract Object executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException; + + protected int parseNumber(String name, String number, int def) + { + if (number != null && number.length() > 0) + { + try + { + return Integer.parseInt(number); + + } catch (NumberFormatException e) + { + throw new WebScriptException(400, name + " is not a number!", e); + } + } else + { + return def; + } + } + + protected PagingRequest createPagingRequest(WebScriptRequest req) + { + int skipCount = parseNumber("skipCount", req.getParameter("skipCount"), 0); + int maxItems = parseNumber("maxItems", req.getParameter("maxItems"), -1); + + PagingRequest result = new PagingRequest(skipCount, maxItems, null); + result.setRequestTotalCountMax(Integer.MAX_VALUE); + + return result; + } + + @SuppressWarnings("unchecked") + protected JSONObject getUserDetails(String username) + { + NodeRef node = personService.getPerson(username); + + JSONObject result = new JSONObject(); + result.put("userName", username); + result.put("firstName", nodeService.getProperty(node, ContentModel.PROP_FIRSTNAME)); + result.put("lastName", nodeService.getProperty(node, ContentModel.PROP_LASTNAME)); + result.put("jobtitle", nodeService.getProperty(node, ContentModel.PROP_JOBTITLE)); + result.put("organization", nodeService.getProperty(node, ContentModel.PROP_ORGANIZATION)); + + String status = (String) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS); + if (status != null) + { + result.put("userStatus", status); + } + + Date statusTime = (Date) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS_TIME); + if (statusTime != null) + { + JSONObject statusTimeJson = new JSONObject(); + statusTimeJson.put("iso8601", ISO8601DateFormat.format(statusTime)); + result.put("userStatusTime", statusTimeJson); + } + + // Get the avatar for the user id if one is available + List assocRefs = this.nodeService.getTargetAssocs(node, ContentModel.ASSOC_AVATAR); + if (!assocRefs.isEmpty()) + { + NodeRef avatarNodeRef = assocRefs.get(0).getTargetRef(); + result.put("avatar", avatarNodeRef.toString()); + } + else + { + result.put("avatar", "avatar"); // This indicates to just use a placeholder + } + + return result; + } + + @SuppressWarnings("unchecked") + protected JSONArray getUserArray(List usernames) + { + JSONArray result = new JSONArray(); + + if (usernames != null) + { + for (String username : usernames) + { + result.add(getUserDetails(username)); + } + } + + return result; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowPost.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowPost.java index a92af88382..cf84b092fb 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowPost.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowPost.java @@ -1,30 +1,30 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowPost extends AbstractSubscriptionServiceWebScript -{ - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException - { - JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); - - for (Object o : jsonUsers) - { - String user = (o == null ? null : o.toString()); - if (user != null) - { - subscriptionService.follow(userId, user); - } - } - - return null; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowPost extends AbstractSubscriptionServiceWebScript +{ + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException + { + JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); + + for (Object o : jsonUsers) + { + String user = (o == null ? null : o.toString()); + if (user != null) + { + subscriptionService.follow(userId, user); + } + } + + return null; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java index 0f090341d2..ef748bed51 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java @@ -1,21 +1,21 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONObject; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowersCountGet extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException - { - int count = subscriptionService.getFollowersCount(userId); - - JSONObject obj = new JSONObject(); - obj.put("count", count); - - return obj; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONObject; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowersCountGet extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException + { + int count = subscriptionService.getFollowersCount(userId); + + JSONObject obj = new JSONObject(); + obj.put("count", count); + + return obj; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java index 5eaf63e0eb..1c73b3ff2e 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java @@ -1,27 +1,27 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.alfresco.service.cmr.subscriptions.PagingFollowingResults; -import org.json.simple.JSONObject; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowersGet extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException - { - PagingFollowingResults result = subscriptionService.getFollowers(userId, createPagingRequest(req)); - - JSONObject obj = new JSONObject(); - obj.put("people", getUserArray(result.getPage())); - obj.put("hasMoreItems", result.hasMoreItems()); - if (result.getTotalResultCount() != null) - { - obj.put("totalCount", result.getTotalResultCount().getFirst()); - } - - return obj; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.alfresco.service.cmr.subscriptions.PagingFollowingResults; +import org.json.simple.JSONObject; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowersGet extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException + { + PagingFollowingResults result = subscriptionService.getFollowers(userId, createPagingRequest(req)); + + JSONObject obj = new JSONObject(); + obj.put("people", getUserArray(result.getPage())); + obj.put("hasMoreItems", result.hasMoreItems()); + if (result.getTotalResultCount() != null) + { + obj.put("totalCount", result.getTotalResultCount().getFirst()); + } + + return obj; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java index 0f9b4450d5..95c47ab940 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java @@ -1,21 +1,21 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONObject; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowingCountGet extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException - { - int count = subscriptionService.getFollowingCount(userId); - - JSONObject obj = new JSONObject(); - obj.put("count", count); - - return obj; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONObject; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowingCountGet extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException + { + int count = subscriptionService.getFollowingCount(userId); + + JSONObject obj = new JSONObject(); + obj.put("count", count); + + return obj; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java index dc375a0a3c..b6ccf4e635 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java @@ -1,27 +1,27 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.alfresco.service.cmr.subscriptions.PagingFollowingResults; -import org.json.simple.JSONObject; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowingGet extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException - { - PagingFollowingResults result = subscriptionService.getFollowing(userId, createPagingRequest(req)); - - JSONObject obj = new JSONObject(); - obj.put("people", getUserArray(result.getPage())); - obj.put("hasMoreItems", result.hasMoreItems()); - if (result.getTotalResultCount() != null) - { - obj.put("totalCount", result.getTotalResultCount().getFirst()); - } - - return obj; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.alfresco.service.cmr.subscriptions.PagingFollowingResults; +import org.json.simple.JSONObject; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowingGet extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException + { + PagingFollowingResults result = subscriptionService.getFollowing(userId, createPagingRequest(req)); + + JSONObject obj = new JSONObject(); + obj.put("people", getUserArray(result.getPage())); + obj.put("hasMoreItems", result.hasMoreItems()); + if (result.getTotalResultCount() != null) + { + obj.put("totalCount", result.getTotalResultCount().getFirst()); + } + + return obj; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowsPost.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowsPost.java index 4043177bbc..9c1c28d5b6 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowsPost.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowsPost.java @@ -1,35 +1,35 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceFollowsPost extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONArray executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException - { - JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); - - JSONArray result = new JSONArray(); - - for (Object o : jsonUsers) - { - String user = (o == null ? null : o.toString()); - if (user != null) - { - JSONObject item = new JSONObject(); - item.put(user, subscriptionService.follows(userId, user)); - result.add(item); - } - } - - return result; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceFollowsPost extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONArray executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException + { + JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); + + JSONArray result = new JSONArray(); + + for (Object o : jsonUsers) + { + String user = (o == null ? null : o.toString()); + if (user != null) + { + JSONObject item = new JSONObject(); + item.put(user, subscriptionService.follows(userId, user)); + result.add(item); + } + } + + return result; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListGet.java index c76f153a01..4882a9452d 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListGet.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListGet.java @@ -1,21 +1,21 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONObject; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServicePrivateListGet extends AbstractSubscriptionServiceWebScript -{ - @SuppressWarnings("unchecked") - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException - { - JSONObject obj = new JSONObject(); - obj.put("private", subscriptionService.isSubscriptionListPrivate(userId)); - - return obj; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONObject; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServicePrivateListGet extends AbstractSubscriptionServiceWebScript +{ + @SuppressWarnings("unchecked") + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException + { + JSONObject obj = new JSONObject(); + obj.put("private", subscriptionService.isSubscriptionListPrivate(userId)); + + return obj; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListPut.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListPut.java index 177e4ce79e..1ebab79453 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListPut.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServicePrivateListPut.java @@ -1,33 +1,33 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServicePrivateListPut extends SubscriptionServicePrivateListGet -{ - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException - { - JSONObject obj = (JSONObject) JSONValue.parseWithException(req.getContent().getContent()); - - Object setPrivate = obj.get("private"); - - if (setPrivate != null) - { - if (setPrivate.toString().equalsIgnoreCase("true")) - { - subscriptionService.setSubscriptionListPrivate(userId, true); - } else if (setPrivate.toString().equalsIgnoreCase("false")) - { - subscriptionService.setSubscriptionListPrivate(userId, false); - } - } - - return super.executeImpl(userId, req, res); - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServicePrivateListPut extends SubscriptionServicePrivateListGet +{ + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException + { + JSONObject obj = (JSONObject) JSONValue.parseWithException(req.getContent().getContent()); + + Object setPrivate = obj.get("private"); + + if (setPrivate != null) + { + if (setPrivate.toString().equalsIgnoreCase("true")) + { + subscriptionService.setSubscriptionListPrivate(userId, true); + } else if (setPrivate.toString().equalsIgnoreCase("false")) + { + subscriptionService.setSubscriptionListPrivate(userId, false); + } + } + + return super.executeImpl(userId, req, res); + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowPost.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowPost.java index b3a8d2f09a..af017cf476 100644 --- a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowPost.java +++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowPost.java @@ -1,30 +1,30 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.io.IOException; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.ParseException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class SubscriptionServiceUnfollowPost extends AbstractSubscriptionServiceWebScript -{ - public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, - ParseException - { - JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); - - for (Object o : jsonUsers) - { - String user = (o == null ? null : o.toString()); - if (user != null) - { - subscriptionService.unfollow(userId, user); - } - } - - return null; - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.io.IOException; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class SubscriptionServiceUnfollowPost extends AbstractSubscriptionServiceWebScript +{ + public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException, + ParseException + { + JSONArray jsonUsers = (JSONArray) JSONValue.parseWithException(req.getContent().getContent()); + + for (Object o : jsonUsers) + { + String user = (o == null ? null : o.toString()); + if (user != null) + { + subscriptionService.unfollow(userId, user); + } + } + + return null; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceDiagramGet.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceDiagramGet.java index 626f63758b..8f80193870 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceDiagramGet.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceDiagramGet.java @@ -1,67 +1,67 @@ -package org.alfresco.repo.web.scripts.workflow; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.repo.web.scripts.content.StreamContent; -import org.alfresco.service.cmr.workflow.WorkflowInstance; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.util.TempFileProvider; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.util.FileCopyUtils; - -/** - * Java backed implementation for REST API to retrieve a diagram of a workflow instance. - * - * @author Gavin Cornwell - * @since 4.0 - */ -public class WorkflowInstanceDiagramGet extends StreamContent -{ - protected WorkflowService workflowService; - - public void setWorkflowService(WorkflowService workflowService) - { - this.workflowService = workflowService; - } - - @Override - public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException - { - Map params = req.getServiceMatch().getTemplateVars(); - - // getting workflow instance id from request parameters - String workflowInstanceId = params.get("workflow_instance_id"); - - WorkflowInstance workflowInstance = workflowService.getWorkflowById(workflowInstanceId); - - // workflow instance was not found -> return 404 - if (workflowInstance == null) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find workflow instance with id: " + workflowInstanceId); - } - - // check whether there is a diagram available - if (!workflowService.hasWorkflowImage(workflowInstanceId)) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find diagram for workflow instance with id: " + workflowInstanceId); - } - - // copy image data into temporary file - File file = TempFileProvider.createTempFile("workflow-diagram-", ".png"); - InputStream imageData = workflowService.getWorkflowImage(workflowInstanceId); - OutputStream os = new FileOutputStream(file); - FileCopyUtils.copy(imageData, os); - - // stream temporary file back to client - streamContent(req, res, file); - } -} +package org.alfresco.repo.web.scripts.workflow; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.web.scripts.content.StreamContent; +import org.alfresco.service.cmr.workflow.WorkflowInstance; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.util.TempFileProvider; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.util.FileCopyUtils; + +/** + * Java backed implementation for REST API to retrieve a diagram of a workflow instance. + * + * @author Gavin Cornwell + * @since 4.0 + */ +public class WorkflowInstanceDiagramGet extends StreamContent +{ + protected WorkflowService workflowService; + + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + Map params = req.getServiceMatch().getTemplateVars(); + + // getting workflow instance id from request parameters + String workflowInstanceId = params.get("workflow_instance_id"); + + WorkflowInstance workflowInstance = workflowService.getWorkflowById(workflowInstanceId); + + // workflow instance was not found -> return 404 + if (workflowInstance == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find workflow instance with id: " + workflowInstanceId); + } + + // check whether there is a diagram available + if (!workflowService.hasWorkflowImage(workflowInstanceId)) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find diagram for workflow instance with id: " + workflowInstanceId); + } + + // copy image data into temporary file + File file = TempFileProvider.createTempFile("workflow-diagram-", ".png"); + InputStream imageData = workflowService.getWorkflowImage(workflowInstanceId); + OutputStream os = new FileOutputStream(file); + FileCopyUtils.copy(imageData, os); + + // stream temporary file back to client + streamContent(req, res, file); + } +} diff --git a/source/java/org/alfresco/repo/web/util/PagingCursor.java b/source/java/org/alfresco/repo/web/util/PagingCursor.java index abbe94bada..8880110601 100644 --- a/source/java/org/alfresco/repo/web/util/PagingCursor.java +++ b/source/java/org/alfresco/repo/web/util/PagingCursor.java @@ -1,430 +1,430 @@ -package org.alfresco.repo.web.util; - -/** - * Paging cursor. A utility for maintaining paged indexes for a collection of N items. - * - * There are two types of cursor: - * - * a) Paged - * - * This type of cursor is driven from a page number and page size. Random access within - * the collection is possible by jumping straight to a page. A simple scroll through - * the collection is supported by iterating through each next page. - * - * b) Rows - * - * This type of cursor is driven from a skip row count and maximum number of rows. Random - * access is not supported. The collection of items is simply scrolled through from - * start to end by iterating through each next set of rows. - * - * In either case, a paging cursor provides a start row and end row which may be used - * to extract the items for the page from the collection of N items. - * - * A zero (or less) page size or row maximum means "unlimited". - * - * Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and - * Rows are 0 based. - * - * At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page - * and next skip count. - * - * Pseudo-code for traversing through a collection of N items (10 at a time): - * - * PagingCursor cursor = new PagingCursor(); - * Page page = cursor.createPageCursor(N, 10, 1); - * while (page.isInRange()) - * { - * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) - * { - * ...collection[i]... - * } - * page = cursor.createPageCursor(N, 10, page.getNextPage()); - * } - * - * Rows rows = cursor.createRowsCursor(N, 10, 0); - * while (rows.isInRange()) - * { - * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) - * { - * ...collection[i]... - * } - * rows = cursor.createRowsCursor(N, 10, rows.getNextSkipRows()); - * } - * - * @author davidc - */ -public class PagingCursor -{ - boolean zeroBasedPage = false; - boolean zeroBasedRow = true; - - /** - * Sets zero based page index - * - * Note: scoped to this paging cursor instance - * - * @param zeroBasedPage true => 0 based, false => 1 based - */ - public void setZeroBasedPage(boolean zeroBasedPage) - { - this.zeroBasedPage = zeroBasedPage; - } - - /** - * Is zero based page index? - * - * Note: scoped to this paging cursor instance - * - * @return true => 0 based, false => 1 based - */ - public boolean isZeroBasedPage() - { - return zeroBasedPage; - } - - /** - * Sets zero based row index - * - * Note: scoped to this paging cursor instance - * - * @param zeroBasedRow true => 0 based, false => 1 based - */ - public void setZeroBasedRow(boolean zeroBasedRow) - { - this.zeroBasedRow = zeroBasedRow; - } - - /** - * Is zero based row index? - * - * Note: scoped to this paging cursor instance - * - * @return true => 0 based, false => 1 based - */ - public boolean isZeroBasedRow() - { - return zeroBasedRow; - } - - /** - * Create a Page based Cursor - * - * @param totalRows total rows in collection - * @param rowsPerPage page size - * @param page page number (0 or 1 based) - * @return Page Cursor - */ - public Page createPageCursor(long totalRows, int rowsPerPage, int page) - { - return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow); - } - - /** - * Create a Page based Cursor - * - * @param totalRows total rows in collection - * @param rowsPerPage page size - * @param page page number (0 or 1 based) - * @param zeroBasedPage true => 0 based, false => 1 based - * @param zeroBasedRow true => 0 based, false => 1 based - * @return Page Cursor - */ - public Page createPageCursor(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow) - { - return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow); - } - - /** - * Create a Rows based Cursor - * - * @param totalRows total rows in collection - * @param maxRows maximum number of rows in page - * @param skipRows number of rows to skip (0 - none) - * @return Rows Cursor - */ - public Rows createRowsCursor(long totalRows, long maxRows, long skipRows) - { - return new Rows(totalRows, maxRows, skipRows, zeroBasedRow); - } - - /** - * Create a Rows based Cursor - * - * @param totalRows total rows in collection - * @param maxRows maximum number of rows in page - * @param skipRows number of rows to skip (0 - none) - * @param zeroBasedRow true => 0 based, false => 1 based - * @return Rows Cursor - */ - public Rows createRowsCursor(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow) - { - return new Rows(totalRows, maxRows, skipRows, zeroBasedRow); - } - - - /** - * Page based Cursor - */ - public static class Page - { - boolean zeroBasedPage; - boolean zeroBasedRow; - long totalRows; - int rowsPerPage; - long pageSize; - int currentPage; - int currentRow; - - /** - * Create a Page based Cursor - * - * @param totalRows total rows in collection - * @param rowsPerPage page size - * @param page page number (0 or 1 based) - * @param zeroBasedPage true => 0 based, false => 1 based - * @param zeroBasedRow true => 0 based, false => 1 based - */ - public Page(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow) - { - this.zeroBasedPage = zeroBasedPage; - this.zeroBasedRow = zeroBasedRow; - this.totalRows = totalRows; - this.rowsPerPage = rowsPerPage; - this.pageSize = (rowsPerPage <=0) ? totalRows : rowsPerPage; - this.currentPage = (zeroBasedPage) ? page : page - 1; - } - - /** - * Gets total rows - * - * @return total rows - */ - public long getTotalRows() - { - return totalRows; - } - - /** - * Gets total number of pages - * - * @return total number of pages - */ - public int getTotalPages() - { - if (totalRows == 0) - return 0; - - int totalPages = (int)(totalRows / pageSize); - totalPages += (totalRows % pageSize != 0) ? 1 : 0; - return totalPages; - } - - /** - * Gets page size - * - * @return page size - */ - public int getRowsPerPage() - { - return rowsPerPage; - } - - /** - * Is the cursor within range of the total number of rows - * - * @return true => within range of total rows - */ - public boolean isInRange() - { - return currentPage >= 0 && getCurrentPage() <= getLastPage(); - } - - /** - * Gets the current page number - * - * @return current page number - */ - public int getCurrentPage() - { - return currentPage + (zeroBasedPage ? 0 : 1); - } - - /** - * Gets the next page number - * - * @return next page number (-1 if no more pages) - */ - public int getNextPage() - { - return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1; - } - - /** - * Gets the previous page number - * - * @return previous page number (-1 if no previous pages) - */ - public int getPreviousPage() - { - return currentPage > 0 ? getCurrentPage() - 1 : - 1; - } - - /** - * Gets the first page number - * - * @return first page number - */ - public int getFirstPage() - { - if (totalRows == 0) - return -1; - - return zeroBasedPage ? 0 : 1; - } - - /** - * Gets the last page number - * - * @return last page number - */ - public int getLastPage() - { - if (totalRows == 0) - return -1; - - return getTotalPages() - (zeroBasedPage ? 1 : 0); - } - - /** - * Gets the start row within collection for this page - * - * @return start row index - */ - public long getStartRow() - { - if (totalRows == 0) - return -1; - - return (currentPage * pageSize) + (zeroBasedRow ? 0 : 1); - } - - /** - * Gets the end row within collection for this page - * - * @return end row index - */ - public long getEndRow() - { - if (totalRows == 0) - return -1; - - return getStartRow() + Math.min(pageSize, totalRows - (currentPage * pageSize)) - 1; - } - } - - /** - * Rows based Cursor - */ - public static class Rows - { - boolean zeroBasedRow; - long totalRows; - long skipRows; - long maxRows; - long pageSize; - - /** - * Create a Rows based Cursor - * - * @param totalRows total rows in collection - * @param maxRows maximum number of rows in page - * @param skipRows number of rows to skip (0 - none) - * @param zeroBasedRow true => 0 based, false => 1 based - */ - public Rows(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow) - { - this.zeroBasedRow = zeroBasedRow; - this.totalRows = totalRows; - this.maxRows = maxRows; - this.skipRows = skipRows; - this.pageSize = (maxRows <= 0) ? totalRows - skipRows : maxRows; - } - - /** - * Gets the total number of rows - * - * @return total rows - */ - public long getTotalRows() - { - return totalRows; - } - - /** - * Gets the number rows skipped - * - * @return skipped row count - */ - public long getSkipRows() - { - return skipRows; - } - - /** - * Gets the maximum number of rows to include in this page - * - * @return maximum of numbers - */ - public long getMaxRows() - { - return maxRows; - } - - /** - * Is the cursor within range of the total number of rows - * - * @return true => within range of total rows - */ - public boolean isInRange() - { - return skipRows >= 0 && skipRows < totalRows; - } - - /** - * Gets the start row within collection for this page - * - * @return start row index - */ - public long getStartRow() - { - if (totalRows == 0) - return -1; - - return skipRows + (zeroBasedRow ? 0 : 1); - } - - /** - * Gets the end row within collection for this page - * - * @return end row index - */ - public long getEndRow() - { - if (totalRows == 0) - return -1; - - return getStartRow() + Math.min(pageSize, totalRows - skipRows) - 1; - } - - /** - * Gets the next skip count - * - * @return next skip row - */ - public long getNextSkipRows() - { - return (skipRows + pageSize < totalRows) ? skipRows + pageSize : -1; - } - } - -} +package org.alfresco.repo.web.util; + +/** + * Paging cursor. A utility for maintaining paged indexes for a collection of N items. + * + * There are two types of cursor: + * + * a) Paged + * + * This type of cursor is driven from a page number and page size. Random access within + * the collection is possible by jumping straight to a page. A simple scroll through + * the collection is supported by iterating through each next page. + * + * b) Rows + * + * This type of cursor is driven from a skip row count and maximum number of rows. Random + * access is not supported. The collection of items is simply scrolled through from + * start to end by iterating through each next set of rows. + * + * In either case, a paging cursor provides a start row and end row which may be used + * to extract the items for the page from the collection of N items. + * + * A zero (or less) page size or row maximum means "unlimited". + * + * Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and + * Rows are 0 based. + * + * At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page + * and next skip count. + * + * Pseudo-code for traversing through a collection of N items (10 at a time): + * + * PagingCursor cursor = new PagingCursor(); + * Page page = cursor.createPageCursor(N, 10, 1); + * while (page.isInRange()) + * { + * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) + * { + * ...collection[i]... + * } + * page = cursor.createPageCursor(N, 10, page.getNextPage()); + * } + * + * Rows rows = cursor.createRowsCursor(N, 10, 0); + * while (rows.isInRange()) + * { + * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) + * { + * ...collection[i]... + * } + * rows = cursor.createRowsCursor(N, 10, rows.getNextSkipRows()); + * } + * + * @author davidc + */ +public class PagingCursor +{ + boolean zeroBasedPage = false; + boolean zeroBasedRow = true; + + /** + * Sets zero based page index + * + * Note: scoped to this paging cursor instance + * + * @param zeroBasedPage true => 0 based, false => 1 based + */ + public void setZeroBasedPage(boolean zeroBasedPage) + { + this.zeroBasedPage = zeroBasedPage; + } + + /** + * Is zero based page index? + * + * Note: scoped to this paging cursor instance + * + * @return true => 0 based, false => 1 based + */ + public boolean isZeroBasedPage() + { + return zeroBasedPage; + } + + /** + * Sets zero based row index + * + * Note: scoped to this paging cursor instance + * + * @param zeroBasedRow true => 0 based, false => 1 based + */ + public void setZeroBasedRow(boolean zeroBasedRow) + { + this.zeroBasedRow = zeroBasedRow; + } + + /** + * Is zero based row index? + * + * Note: scoped to this paging cursor instance + * + * @return true => 0 based, false => 1 based + */ + public boolean isZeroBasedRow() + { + return zeroBasedRow; + } + + /** + * Create a Page based Cursor + * + * @param totalRows total rows in collection + * @param rowsPerPage page size + * @param page page number (0 or 1 based) + * @return Page Cursor + */ + public Page createPageCursor(long totalRows, int rowsPerPage, int page) + { + return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow); + } + + /** + * Create a Page based Cursor + * + * @param totalRows total rows in collection + * @param rowsPerPage page size + * @param page page number (0 or 1 based) + * @param zeroBasedPage true => 0 based, false => 1 based + * @param zeroBasedRow true => 0 based, false => 1 based + * @return Page Cursor + */ + public Page createPageCursor(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow) + { + return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow); + } + + /** + * Create a Rows based Cursor + * + * @param totalRows total rows in collection + * @param maxRows maximum number of rows in page + * @param skipRows number of rows to skip (0 - none) + * @return Rows Cursor + */ + public Rows createRowsCursor(long totalRows, long maxRows, long skipRows) + { + return new Rows(totalRows, maxRows, skipRows, zeroBasedRow); + } + + /** + * Create a Rows based Cursor + * + * @param totalRows total rows in collection + * @param maxRows maximum number of rows in page + * @param skipRows number of rows to skip (0 - none) + * @param zeroBasedRow true => 0 based, false => 1 based + * @return Rows Cursor + */ + public Rows createRowsCursor(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow) + { + return new Rows(totalRows, maxRows, skipRows, zeroBasedRow); + } + + + /** + * Page based Cursor + */ + public static class Page + { + boolean zeroBasedPage; + boolean zeroBasedRow; + long totalRows; + int rowsPerPage; + long pageSize; + int currentPage; + int currentRow; + + /** + * Create a Page based Cursor + * + * @param totalRows total rows in collection + * @param rowsPerPage page size + * @param page page number (0 or 1 based) + * @param zeroBasedPage true => 0 based, false => 1 based + * @param zeroBasedRow true => 0 based, false => 1 based + */ + public Page(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow) + { + this.zeroBasedPage = zeroBasedPage; + this.zeroBasedRow = zeroBasedRow; + this.totalRows = totalRows; + this.rowsPerPage = rowsPerPage; + this.pageSize = (rowsPerPage <=0) ? totalRows : rowsPerPage; + this.currentPage = (zeroBasedPage) ? page : page - 1; + } + + /** + * Gets total rows + * + * @return total rows + */ + public long getTotalRows() + { + return totalRows; + } + + /** + * Gets total number of pages + * + * @return total number of pages + */ + public int getTotalPages() + { + if (totalRows == 0) + return 0; + + int totalPages = (int)(totalRows / pageSize); + totalPages += (totalRows % pageSize != 0) ? 1 : 0; + return totalPages; + } + + /** + * Gets page size + * + * @return page size + */ + public int getRowsPerPage() + { + return rowsPerPage; + } + + /** + * Is the cursor within range of the total number of rows + * + * @return true => within range of total rows + */ + public boolean isInRange() + { + return currentPage >= 0 && getCurrentPage() <= getLastPage(); + } + + /** + * Gets the current page number + * + * @return current page number + */ + public int getCurrentPage() + { + return currentPage + (zeroBasedPage ? 0 : 1); + } + + /** + * Gets the next page number + * + * @return next page number (-1 if no more pages) + */ + public int getNextPage() + { + return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1; + } + + /** + * Gets the previous page number + * + * @return previous page number (-1 if no previous pages) + */ + public int getPreviousPage() + { + return currentPage > 0 ? getCurrentPage() - 1 : - 1; + } + + /** + * Gets the first page number + * + * @return first page number + */ + public int getFirstPage() + { + if (totalRows == 0) + return -1; + + return zeroBasedPage ? 0 : 1; + } + + /** + * Gets the last page number + * + * @return last page number + */ + public int getLastPage() + { + if (totalRows == 0) + return -1; + + return getTotalPages() - (zeroBasedPage ? 1 : 0); + } + + /** + * Gets the start row within collection for this page + * + * @return start row index + */ + public long getStartRow() + { + if (totalRows == 0) + return -1; + + return (currentPage * pageSize) + (zeroBasedRow ? 0 : 1); + } + + /** + * Gets the end row within collection for this page + * + * @return end row index + */ + public long getEndRow() + { + if (totalRows == 0) + return -1; + + return getStartRow() + Math.min(pageSize, totalRows - (currentPage * pageSize)) - 1; + } + } + + /** + * Rows based Cursor + */ + public static class Rows + { + boolean zeroBasedRow; + long totalRows; + long skipRows; + long maxRows; + long pageSize; + + /** + * Create a Rows based Cursor + * + * @param totalRows total rows in collection + * @param maxRows maximum number of rows in page + * @param skipRows number of rows to skip (0 - none) + * @param zeroBasedRow true => 0 based, false => 1 based + */ + public Rows(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow) + { + this.zeroBasedRow = zeroBasedRow; + this.totalRows = totalRows; + this.maxRows = maxRows; + this.skipRows = skipRows; + this.pageSize = (maxRows <= 0) ? totalRows - skipRows : maxRows; + } + + /** + * Gets the total number of rows + * + * @return total rows + */ + public long getTotalRows() + { + return totalRows; + } + + /** + * Gets the number rows skipped + * + * @return skipped row count + */ + public long getSkipRows() + { + return skipRows; + } + + /** + * Gets the maximum number of rows to include in this page + * + * @return maximum of numbers + */ + public long getMaxRows() + { + return maxRows; + } + + /** + * Is the cursor within range of the total number of rows + * + * @return true => within range of total rows + */ + public boolean isInRange() + { + return skipRows >= 0 && skipRows < totalRows; + } + + /** + * Gets the start row within collection for this page + * + * @return start row index + */ + public long getStartRow() + { + if (totalRows == 0) + return -1; + + return skipRows + (zeroBasedRow ? 0 : 1); + } + + /** + * Gets the end row within collection for this page + * + * @return end row index + */ + public long getEndRow() + { + if (totalRows == 0) + return -1; + + return getStartRow() + Math.min(pageSize, totalRows - skipRows) - 1; + } + + /** + * Gets the next skip count + * + * @return next skip row + */ + public long getNextSkipRows() + { + return (skipRows + pageSize < totalRows) ? skipRows + pageSize : -1; + } + } + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/Cursor.java b/source/java/org/alfresco/repo/web/util/paging/Cursor.java index 9e8c53a4cc..40aab5aae9 100644 --- a/source/java/org/alfresco/repo/web/util/paging/Cursor.java +++ b/source/java/org/alfresco/repo/web/util/paging/Cursor.java @@ -1,130 +1,130 @@ -package org.alfresco.repo.web.util.paging; - - -/** - * Cursor - Allows for scrolling through a row set. - * - * @author davidc - */ -public interface Cursor -{ - /** - * Gets the page type - * - * @return page type - */ - public String getPageType(); - - /** - * Gets the page size - * - * @return page size - */ - int getPageSize(); - - /** - * Gets total number of pages - * - * @return total number of pages - */ - int getTotalPages(); - - /** - * Gets total rows - * - * @return total rows - */ - int getTotalRows(); - - /** - * Gets the current page number - * - * @return current page number - */ - int getCurrentPage(); - - /** - * Gets the first page number - * - * @return first page number - */ - int getFirstPage(); - - /** - * Gets the last page number - * - * @return last page number - */ - int getLastPage(); - - /** - * Gets the next page number - * - * @return next page number (-1 if no more pages) - */ - int getNextPage(); - - /** - * Gets the previous page number - * - * @return previous page number (-1 if no previous pages) - */ - int getPrevPage(); - - /** - * Is the page within range of the result set - * - * @return true => page is within range - */ - boolean isInRange(); - - /** - * Is there a known first page? - * - * @return true => getFirstPage() will succeed - */ - boolean getHasFirstPage(); - - /** - * Is there a known last page? - * - * @return true => getLastPage() will succeed - */ - boolean getHasLastPage(); - - /** - * Is there a known next page? - * - * @return true => getNextPage() will succeed - */ - boolean getHasNextPage(); - - /** - * Is there a known prev page? - * - * @return true => getPrevPage() will succeed - */ - boolean getHasPrevPage(); - - /** - * Gets the start row within result set for this page - * - * @return start row index - */ - int getStartRow(); - - /** - * Gets the end row within result set for this page - * - * @return end row index - */ - int getEndRow(); - - /** - * Gets the count of rows within result set for this page - * - * @return row count - */ - int getRowCount(); - -} +package org.alfresco.repo.web.util.paging; + + +/** + * Cursor - Allows for scrolling through a row set. + * + * @author davidc + */ +public interface Cursor +{ + /** + * Gets the page type + * + * @return page type + */ + public String getPageType(); + + /** + * Gets the page size + * + * @return page size + */ + int getPageSize(); + + /** + * Gets total number of pages + * + * @return total number of pages + */ + int getTotalPages(); + + /** + * Gets total rows + * + * @return total rows + */ + int getTotalRows(); + + /** + * Gets the current page number + * + * @return current page number + */ + int getCurrentPage(); + + /** + * Gets the first page number + * + * @return first page number + */ + int getFirstPage(); + + /** + * Gets the last page number + * + * @return last page number + */ + int getLastPage(); + + /** + * Gets the next page number + * + * @return next page number (-1 if no more pages) + */ + int getNextPage(); + + /** + * Gets the previous page number + * + * @return previous page number (-1 if no previous pages) + */ + int getPrevPage(); + + /** + * Is the page within range of the result set + * + * @return true => page is within range + */ + boolean isInRange(); + + /** + * Is there a known first page? + * + * @return true => getFirstPage() will succeed + */ + boolean getHasFirstPage(); + + /** + * Is there a known last page? + * + * @return true => getLastPage() will succeed + */ + boolean getHasLastPage(); + + /** + * Is there a known next page? + * + * @return true => getNextPage() will succeed + */ + boolean getHasNextPage(); + + /** + * Is there a known prev page? + * + * @return true => getPrevPage() will succeed + */ + boolean getHasPrevPage(); + + /** + * Gets the start row within result set for this page + * + * @return start row index + */ + int getStartRow(); + + /** + * Gets the end row within result set for this page + * + * @return end row index + */ + int getEndRow(); + + /** + * Gets the count of rows within result set for this page + * + * @return row count + */ + int getRowCount(); + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/Page.java b/source/java/org/alfresco/repo/web/util/paging/Page.java index 81d9eddd7a..fc1390d18f 100644 --- a/source/java/org/alfresco/repo/web/util/paging/Page.java +++ b/source/java/org/alfresco/repo/web/util/paging/Page.java @@ -1,72 +1,72 @@ -package org.alfresco.repo.web.util.paging; - - -/** - * A Page within a Cursor. - * - * @author davidc - */ -public class Page -{ - Paging.PageType pageType; - boolean zeroBasedIdx; - int startIdx; - int pageSize; - - /** - * Construct - * - * @param pageType Page or Window - * @param zeroBasedIdx true => start index from 0 - * @param startIdx start index - * @param pageSize page size - */ - /*package*/ Page(Paging.PageType pageType, boolean zeroBasedIdx, int startIdx, int pageSize) - { - this.pageType = pageType; - this.zeroBasedIdx = zeroBasedIdx; - this.startIdx = startIdx; - this.pageSize = pageSize; - } - - /** - * Gets the Page Type - * - * @return page type - */ - /*package*/ Paging.PageType getType() - { - return pageType; - } - - /** - * Gets the page number - * - * @return page number - */ - public int getNumber() - { - return startIdx; - } - - /** - * Gets the page size - * - * @return page size - */ - public int getSize() - { - return pageSize; - } - - /** - * Is zero based page index - * - * @return true => page number starts from zero - */ - public boolean isZeroBasedIdx() - { - return zeroBasedIdx; - } - -} +package org.alfresco.repo.web.util.paging; + + +/** + * A Page within a Cursor. + * + * @author davidc + */ +public class Page +{ + Paging.PageType pageType; + boolean zeroBasedIdx; + int startIdx; + int pageSize; + + /** + * Construct + * + * @param pageType Page or Window + * @param zeroBasedIdx true => start index from 0 + * @param startIdx start index + * @param pageSize page size + */ + /*package*/ Page(Paging.PageType pageType, boolean zeroBasedIdx, int startIdx, int pageSize) + { + this.pageType = pageType; + this.zeroBasedIdx = zeroBasedIdx; + this.startIdx = startIdx; + this.pageSize = pageSize; + } + + /** + * Gets the Page Type + * + * @return page type + */ + /*package*/ Paging.PageType getType() + { + return pageType; + } + + /** + * Gets the page number + * + * @return page number + */ + public int getNumber() + { + return startIdx; + } + + /** + * Gets the page size + * + * @return page size + */ + public int getSize() + { + return pageSize; + } + + /** + * Is zero based page index + * + * @return true => page number starts from zero + */ + public boolean isZeroBasedIdx() + { + return zeroBasedIdx; + } + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/PagedCursor.java b/source/java/org/alfresco/repo/web/util/paging/PagedCursor.java index 0d35323708..21a0bcdc25 100644 --- a/source/java/org/alfresco/repo/web/util/paging/PagedCursor.java +++ b/source/java/org/alfresco/repo/web/util/paging/PagedCursor.java @@ -1,200 +1,200 @@ -package org.alfresco.repo.web.util.paging; - -import java.io.Serializable; - -import org.alfresco.repo.web.util.paging.Paging.PageType; - - -/** - * Implementation of cursor based on notion of a Page. - * - * @author davidc - */ -public class PagedCursor implements Cursor, Serializable -{ - private static final long serialVersionUID = -1041155610387669590L; - - private boolean zeroBasedPage; - private boolean zeroBasedRow; - private int totalRows; - private int pageSize; - private int rowsPerPage; - private int page; - - - /** - * Construct - * - * @param zeroBasedRow true => row index starts at zero - * @param totalRows total number of rows (-1 for don't know) - * @param zeroBasedPage true => page number starts at zero - * @param page page number - * @param pageSize page size - */ - /*package*/ PagedCursor(boolean zeroBasedRow, int totalRows, boolean zeroBasedPage, int page, int pageSize) - { - this.zeroBasedRow = zeroBasedRow; - this.totalRows = totalRows; - this.zeroBasedPage = zeroBasedPage; - this.page = (zeroBasedPage) ? page : page - 1; - this.pageSize = pageSize; - this.rowsPerPage = (pageSize <=0) ? totalRows : pageSize; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPageType() - */ - public String getPageType() - { - return PageType.PAGE.toString(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPageSize() - */ - public int getPageSize() - { - return pageSize; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages() - */ - public int getTotalPages() - { - if (totalRows <= 0) - return 0; - - int totalPages = (int)(totalRows / rowsPerPage); - totalPages += (totalRows % rowsPerPage != 0) ? 1 : 0; - return totalPages; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows() - */ - public int getTotalRows() - { - return totalRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage() - */ - public int getCurrentPage() - { - return page + (zeroBasedPage ? 0 : 1); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage() - */ - public int getFirstPage() - { - if (totalRows <= 0) - return -1; - - return zeroBasedPage ? 0 : 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getLastPage() - */ - public int getLastPage() - { - if (totalRows <= 0) - return -1; - - return getTotalPages() - (zeroBasedPage ? 1 : 0); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getNextPage() - */ - public int getNextPage() - { - return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage() - */ - public int getPrevPage() - { - return page > 0 ? getCurrentPage() - 1 : - 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#isInRange() - */ - public boolean isInRange() - { - return page >= 0 && getCurrentPage() <= getLastPage(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage() - */ - public boolean getHasFirstPage() - { - return getFirstPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage() - */ - public boolean getHasLastPage() - { - return getLastPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage() - */ - public boolean getHasNextPage() - { - return getNextPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage() - */ - public boolean getHasPrevPage() - { - return getPrevPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getStartRow() - */ - public int getStartRow() - { - if (totalRows <= 0) - return 0; - - return (page * rowsPerPage) + (zeroBasedRow ? 0 : 1); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getEndRow() - */ - public int getEndRow() - { - if (totalRows <= 0) - return -1; - - return getStartRow() + Math.min(rowsPerPage, totalRows - (page * rowsPerPage)) - 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getRowCount() - */ - public int getRowCount() - { - if (totalRows <= 0) - return 0; - - return getEndRow() - getStartRow() + 1; - } - -} +package org.alfresco.repo.web.util.paging; + +import java.io.Serializable; + +import org.alfresco.repo.web.util.paging.Paging.PageType; + + +/** + * Implementation of cursor based on notion of a Page. + * + * @author davidc + */ +public class PagedCursor implements Cursor, Serializable +{ + private static final long serialVersionUID = -1041155610387669590L; + + private boolean zeroBasedPage; + private boolean zeroBasedRow; + private int totalRows; + private int pageSize; + private int rowsPerPage; + private int page; + + + /** + * Construct + * + * @param zeroBasedRow true => row index starts at zero + * @param totalRows total number of rows (-1 for don't know) + * @param zeroBasedPage true => page number starts at zero + * @param page page number + * @param pageSize page size + */ + /*package*/ PagedCursor(boolean zeroBasedRow, int totalRows, boolean zeroBasedPage, int page, int pageSize) + { + this.zeroBasedRow = zeroBasedRow; + this.totalRows = totalRows; + this.zeroBasedPage = zeroBasedPage; + this.page = (zeroBasedPage) ? page : page - 1; + this.pageSize = pageSize; + this.rowsPerPage = (pageSize <=0) ? totalRows : pageSize; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPageType() + */ + public String getPageType() + { + return PageType.PAGE.toString(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPageSize() + */ + public int getPageSize() + { + return pageSize; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages() + */ + public int getTotalPages() + { + if (totalRows <= 0) + return 0; + + int totalPages = (int)(totalRows / rowsPerPage); + totalPages += (totalRows % rowsPerPage != 0) ? 1 : 0; + return totalPages; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows() + */ + public int getTotalRows() + { + return totalRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage() + */ + public int getCurrentPage() + { + return page + (zeroBasedPage ? 0 : 1); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage() + */ + public int getFirstPage() + { + if (totalRows <= 0) + return -1; + + return zeroBasedPage ? 0 : 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getLastPage() + */ + public int getLastPage() + { + if (totalRows <= 0) + return -1; + + return getTotalPages() - (zeroBasedPage ? 1 : 0); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getNextPage() + */ + public int getNextPage() + { + return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage() + */ + public int getPrevPage() + { + return page > 0 ? getCurrentPage() - 1 : - 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#isInRange() + */ + public boolean isInRange() + { + return page >= 0 && getCurrentPage() <= getLastPage(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage() + */ + public boolean getHasFirstPage() + { + return getFirstPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage() + */ + public boolean getHasLastPage() + { + return getLastPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage() + */ + public boolean getHasNextPage() + { + return getNextPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage() + */ + public boolean getHasPrevPage() + { + return getPrevPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getStartRow() + */ + public int getStartRow() + { + if (totalRows <= 0) + return 0; + + return (page * rowsPerPage) + (zeroBasedRow ? 0 : 1); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getEndRow() + */ + public int getEndRow() + { + if (totalRows <= 0) + return -1; + + return getStartRow() + Math.min(rowsPerPage, totalRows - (page * rowsPerPage)) - 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getRowCount() + */ + public int getRowCount() + { + if (totalRows <= 0) + return 0; + + return getEndRow() - getStartRow() + 1; + } + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/PagedResults.java b/source/java/org/alfresco/repo/web/util/paging/PagedResults.java index c1edb7b94b..0e87cff1dd 100644 --- a/source/java/org/alfresco/repo/web/util/paging/PagedResults.java +++ b/source/java/org/alfresco/repo/web/util/paging/PagedResults.java @@ -1,83 +1,83 @@ -package org.alfresco.repo.web.util.paging; - -import java.io.Serializable; - - -/** - * A Paged Result Set - * - * @author davidc - */ -public class PagedResults implements Serializable -{ - private static final long serialVersionUID = 5905699888354619269L; - - private Object result; - private Object[] results; - private Cursor cursor; - - - /** - * Construct - * - * @param results results for the page within cursor - * @param cursor the cursor - */ - /*Package*/ PagedResults(Object[] results, Cursor cursor) - { - this.result = results; - this.results = results; - this.cursor = cursor; - } - - /** - * Construct - * - * @param result results for the page within cursor - * @param cursor the cursor - */ - /*Package*/ PagedResults(Object result, Cursor cursor) - { - this.result = result; - this.results = null; - this.cursor = cursor; - } - - /** - * Get Results - * - * @return results - */ - public Object[] getResults() - { - if (results == null) - { - if (result != null) - { - results = new Object[] {result}; - } - } - return results; - } - - /** - * Get Result - * - * @return result - */ - public Object getResult() - { - return result; - } - - /** - * Get Cursor - * - * @return cursor - */ - public Cursor getCursor() - { - return cursor; - } - -} +package org.alfresco.repo.web.util.paging; + +import java.io.Serializable; + + +/** + * A Paged Result Set + * + * @author davidc + */ +public class PagedResults implements Serializable +{ + private static final long serialVersionUID = 5905699888354619269L; + + private Object result; + private Object[] results; + private Cursor cursor; + + + /** + * Construct + * + * @param results results for the page within cursor + * @param cursor the cursor + */ + /*Package*/ PagedResults(Object[] results, Cursor cursor) + { + this.result = results; + this.results = results; + this.cursor = cursor; + } + + /** + * Construct + * + * @param result results for the page within cursor + * @param cursor the cursor + */ + /*Package*/ PagedResults(Object result, Cursor cursor) + { + this.result = result; + this.results = null; + this.cursor = cursor; + } + + /** + * Get Results + * + * @return results + */ + public Object[] getResults() + { + if (results == null) + { + if (result != null) + { + results = new Object[] {result}; + } + } + return results; + } + + /** + * Get Result + * + * @return result + */ + public Object getResult() + { + return result; + } + + /** + * Get Cursor + * + * @return cursor + */ + public Cursor getCursor() + { + return cursor; + } + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/Paging.java b/source/java/org/alfresco/repo/web/util/paging/Paging.java index 6d37a898ce..30c3377ac0 100644 --- a/source/java/org/alfresco/repo/web/util/paging/Paging.java +++ b/source/java/org/alfresco/repo/web/util/paging/Paging.java @@ -1,286 +1,286 @@ -package org.alfresco.repo.web.util.paging; - -import java.util.Map; - -/** - * Paging. A utility for maintaining paged indexes for a collection of N items. - * - * There are two types of cursor: - * - * a) Paged - * - * This type of cursor is driven from a page number and page size. Random access within - * the collection is possible by jumping straight to a page. A simple scroll through - * the collection is supported by iterating through each next page. - * - * b) Windowed - * - * This type of cursor is driven from a skip row count and maximum number of rows. Random - * access is not supported. The collection of items is simply scrolled through from - * start to end by iterating through each next set of rows. - * - * In either case, a paging cursor provides a start row and end row which may be used - * to extract the items for the page from the collection of N items. - * - * A zero (or less) page size or row maximum means "unlimited". - * - * Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and - * Rows are 0 based. - * - * At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page. - * - * Pseudo-code for traversing through a collection of N items (10 at a time): - * - * Paging paging = new Paging(); - * Cursor page = paging.createCursor(N, paging.createPage(1, 10)); - * while (page.isInRange()) - * { - * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) - * { - * ...collection[i]... - * } - * page = paging.createCursor(N, paging.createPage(page.getNextPage(), page.getPageSize()); - * } - * - * Cursor window = paging.createCursor(N, paging.createWindow(0, 10)); - * while (window.isInRange()) - * { - * for (long i = window.getStartRow(); i <= window.getEndRow(); i++) - * { - * ...collection[i]... - * } - * window = paging.createCursor(N, paging.createWindow(window.getNextPage(), window.getPageSize()); - * } - * - * @author davidc - */ -public class Paging -{ - public enum PageType - { - PAGE, - WINDOW - }; - - boolean zeroBasedPage = false; - boolean zeroBasedRow = true; - - /** - * Sets zero based page index - * - * Note: scoped to this paging cursor instance - * - * @param zeroBasedPage true => 0 based, false => 1 based - */ - public void setZeroBasedPage(boolean zeroBasedPage) - { - this.zeroBasedPage = zeroBasedPage; - } - - /** - * Is zero based page index? - * - * Note: scoped to this paging cursor instance - * - * @return true => 0 based, false => 1 based - */ - public boolean isZeroBasedPage() - { - return zeroBasedPage; - } - - /** - * Sets zero based row index - * - * Note: scoped to this paging cursor instance - * - * @param zeroBasedRow true => 0 based, false => 1 based - */ - public void setZeroBasedRow(boolean zeroBasedRow) - { - this.zeroBasedRow = zeroBasedRow; - } - - /** - * Is zero based row index? - * - * Note: scoped to this paging cursor instance - * - * @return true => 0 based, false => 1 based - */ - public boolean isZeroBasedRow() - { - return zeroBasedRow; - } - - /** - * Create a Page or Window from standardised request arguments - * - * For Paged based index (take precedence over window based index, if both are specified): - * - * - request args - * pageNo => page number index - * pageSize => size of page - * - * For Window based index (as defined by CMIS): - * - * - request args (take precedence over header values if both are specified) - * skipCount => row number start index - * maxItems => size of page - * - * @param args request args - * @return page (if pageNumber driven) or window (if skipCount driven) - */ - public Page createPageOrWindow(Map args) - { - // page number - Integer pageNo = null; - String strPageNo = args.get("pageNo"); - if (strPageNo != null) - { - try - { - pageNo = new Integer(strPageNo); - } - catch(NumberFormatException e) {}; - } - - // page size - Integer pageSize = null; - String strPageSize = args.get("pageSize"); - if (strPageSize != null) - { - try - { - pageSize = new Integer(strPageSize); - } - catch(NumberFormatException e) {}; - } - - // skip count - Integer skipCount = null; - String strSkipCount = args.get("skipCount"); - if (strSkipCount != null) - { - try - { - skipCount = new Integer(strSkipCount); - } - catch(NumberFormatException e) {}; - } - - // max items - Integer maxItems = null; - String strMaxItems = args.get("maxItems"); - if (strMaxItems != null) - { - try - { - maxItems = new Integer(strMaxItems); - } - catch(NumberFormatException e) {}; - } - - return createPageOrWindow(pageNo, pageSize, skipCount, maxItems); - } - - /** - * Create a Page or Window - * - * @param pageNumber page number (optional and paired with pageSize) - * @param pageSize page size (optional and paired with pageNumber) - * @param skipCount skipCount (optional and paired with maxItems) - * @param maxItems maxItems (optional and paired with skipCount) - * @return page (if pageNumber driven) or window (if skipCount driven) - */ - public Page createPageOrWindow(Integer pageNumber, Integer pageSize, Integer skipCount, Integer maxItems) - { - if (pageNumber != null || pageSize != null) - { - return createPage(pageNumber == null ? isZeroBasedPage() ? 0 : 1 : pageNumber, pageSize == null ? -1 : pageSize); - } - else if (skipCount != null || maxItems != null) - { - return createWindow(skipCount == null ? isZeroBasedRow() ? 0 : 1 : skipCount, maxItems == null ? -1 : maxItems); - } - return createUnlimitedPage(); - } - - /** - * Create a Page - * - * @param pageNumber page number - * @param pageSize page size - * @return the page - */ - public Page createPage(int pageNumber, int pageSize) - { - return new Page(PageType.PAGE, zeroBasedPage, pageNumber, pageSize); - } - - /** - * Create an unlimited Page - * - * @return page (single Page starting at first page of unlimited page size) - */ - public Page createUnlimitedPage() - { - return new Page(PageType.PAGE, zeroBasedPage, zeroBasedPage ? 0 : 1, -1); - } - - /** - * Create a Window - * @param skipRows number of rows to skip - * @param maxRows maximum number of rows in window - * @return the window - */ - public Page createWindow(int skipRows, int maxRows) - { - return new Page(PageType.WINDOW, zeroBasedRow, skipRows, maxRows); - } - - /** - * Create a Cursor - * - * @param totalRows total number of rows in cursor (< 0 for don't know) - * @param page the page / window within cursor - * @return the cursor - */ - public Cursor createCursor(int totalRows, Page page) - { - if (page.getType() == PageType.PAGE) - { - return new PagedCursor(zeroBasedRow, totalRows, page.zeroBasedIdx, page.startIdx, page.pageSize); - } - else if (page.getType() == PageType.WINDOW) - { - return new WindowedCursor(zeroBasedRow, totalRows, page.startIdx, page.pageSize); - } - return null; - } - - /** - * Create a Paged Result Set - * - * @param results the results for the page within the cursor - * @param cursor the cursor - * @return the paged result set - */ - public PagedResults createPagedResults(Object[] results, Cursor cursor) - { - return new PagedResults(results, cursor); - } - - /** - * Create a Paged Result Set - * - * @param result the results for the page within the cursor - * @param cursor the cursor - * @return the paged result set - */ - public PagedResults createPagedResult(Object result, Cursor cursor) - { - return new PagedResults(result, cursor); - } - -} +package org.alfresco.repo.web.util.paging; + +import java.util.Map; + +/** + * Paging. A utility for maintaining paged indexes for a collection of N items. + * + * There are two types of cursor: + * + * a) Paged + * + * This type of cursor is driven from a page number and page size. Random access within + * the collection is possible by jumping straight to a page. A simple scroll through + * the collection is supported by iterating through each next page. + * + * b) Windowed + * + * This type of cursor is driven from a skip row count and maximum number of rows. Random + * access is not supported. The collection of items is simply scrolled through from + * start to end by iterating through each next set of rows. + * + * In either case, a paging cursor provides a start row and end row which may be used + * to extract the items for the page from the collection of N items. + * + * A zero (or less) page size or row maximum means "unlimited". + * + * Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and + * Rows are 0 based. + * + * At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page. + * + * Pseudo-code for traversing through a collection of N items (10 at a time): + * + * Paging paging = new Paging(); + * Cursor page = paging.createCursor(N, paging.createPage(1, 10)); + * while (page.isInRange()) + * { + * for (long i = page.getStartRow(); i <= page.getEndRow(); i++) + * { + * ...collection[i]... + * } + * page = paging.createCursor(N, paging.createPage(page.getNextPage(), page.getPageSize()); + * } + * + * Cursor window = paging.createCursor(N, paging.createWindow(0, 10)); + * while (window.isInRange()) + * { + * for (long i = window.getStartRow(); i <= window.getEndRow(); i++) + * { + * ...collection[i]... + * } + * window = paging.createCursor(N, paging.createWindow(window.getNextPage(), window.getPageSize()); + * } + * + * @author davidc + */ +public class Paging +{ + public enum PageType + { + PAGE, + WINDOW + }; + + boolean zeroBasedPage = false; + boolean zeroBasedRow = true; + + /** + * Sets zero based page index + * + * Note: scoped to this paging cursor instance + * + * @param zeroBasedPage true => 0 based, false => 1 based + */ + public void setZeroBasedPage(boolean zeroBasedPage) + { + this.zeroBasedPage = zeroBasedPage; + } + + /** + * Is zero based page index? + * + * Note: scoped to this paging cursor instance + * + * @return true => 0 based, false => 1 based + */ + public boolean isZeroBasedPage() + { + return zeroBasedPage; + } + + /** + * Sets zero based row index + * + * Note: scoped to this paging cursor instance + * + * @param zeroBasedRow true => 0 based, false => 1 based + */ + public void setZeroBasedRow(boolean zeroBasedRow) + { + this.zeroBasedRow = zeroBasedRow; + } + + /** + * Is zero based row index? + * + * Note: scoped to this paging cursor instance + * + * @return true => 0 based, false => 1 based + */ + public boolean isZeroBasedRow() + { + return zeroBasedRow; + } + + /** + * Create a Page or Window from standardised request arguments + * + * For Paged based index (take precedence over window based index, if both are specified): + * + * - request args + * pageNo => page number index + * pageSize => size of page + * + * For Window based index (as defined by CMIS): + * + * - request args (take precedence over header values if both are specified) + * skipCount => row number start index + * maxItems => size of page + * + * @param args request args + * @return page (if pageNumber driven) or window (if skipCount driven) + */ + public Page createPageOrWindow(Map args) + { + // page number + Integer pageNo = null; + String strPageNo = args.get("pageNo"); + if (strPageNo != null) + { + try + { + pageNo = new Integer(strPageNo); + } + catch(NumberFormatException e) {}; + } + + // page size + Integer pageSize = null; + String strPageSize = args.get("pageSize"); + if (strPageSize != null) + { + try + { + pageSize = new Integer(strPageSize); + } + catch(NumberFormatException e) {}; + } + + // skip count + Integer skipCount = null; + String strSkipCount = args.get("skipCount"); + if (strSkipCount != null) + { + try + { + skipCount = new Integer(strSkipCount); + } + catch(NumberFormatException e) {}; + } + + // max items + Integer maxItems = null; + String strMaxItems = args.get("maxItems"); + if (strMaxItems != null) + { + try + { + maxItems = new Integer(strMaxItems); + } + catch(NumberFormatException e) {}; + } + + return createPageOrWindow(pageNo, pageSize, skipCount, maxItems); + } + + /** + * Create a Page or Window + * + * @param pageNumber page number (optional and paired with pageSize) + * @param pageSize page size (optional and paired with pageNumber) + * @param skipCount skipCount (optional and paired with maxItems) + * @param maxItems maxItems (optional and paired with skipCount) + * @return page (if pageNumber driven) or window (if skipCount driven) + */ + public Page createPageOrWindow(Integer pageNumber, Integer pageSize, Integer skipCount, Integer maxItems) + { + if (pageNumber != null || pageSize != null) + { + return createPage(pageNumber == null ? isZeroBasedPage() ? 0 : 1 : pageNumber, pageSize == null ? -1 : pageSize); + } + else if (skipCount != null || maxItems != null) + { + return createWindow(skipCount == null ? isZeroBasedRow() ? 0 : 1 : skipCount, maxItems == null ? -1 : maxItems); + } + return createUnlimitedPage(); + } + + /** + * Create a Page + * + * @param pageNumber page number + * @param pageSize page size + * @return the page + */ + public Page createPage(int pageNumber, int pageSize) + { + return new Page(PageType.PAGE, zeroBasedPage, pageNumber, pageSize); + } + + /** + * Create an unlimited Page + * + * @return page (single Page starting at first page of unlimited page size) + */ + public Page createUnlimitedPage() + { + return new Page(PageType.PAGE, zeroBasedPage, zeroBasedPage ? 0 : 1, -1); + } + + /** + * Create a Window + * @param skipRows number of rows to skip + * @param maxRows maximum number of rows in window + * @return the window + */ + public Page createWindow(int skipRows, int maxRows) + { + return new Page(PageType.WINDOW, zeroBasedRow, skipRows, maxRows); + } + + /** + * Create a Cursor + * + * @param totalRows total number of rows in cursor (< 0 for don't know) + * @param page the page / window within cursor + * @return the cursor + */ + public Cursor createCursor(int totalRows, Page page) + { + if (page.getType() == PageType.PAGE) + { + return new PagedCursor(zeroBasedRow, totalRows, page.zeroBasedIdx, page.startIdx, page.pageSize); + } + else if (page.getType() == PageType.WINDOW) + { + return new WindowedCursor(zeroBasedRow, totalRows, page.startIdx, page.pageSize); + } + return null; + } + + /** + * Create a Paged Result Set + * + * @param results the results for the page within the cursor + * @param cursor the cursor + * @return the paged result set + */ + public PagedResults createPagedResults(Object[] results, Cursor cursor) + { + return new PagedResults(results, cursor); + } + + /** + * Create a Paged Result Set + * + * @param result the results for the page within the cursor + * @param cursor the cursor + * @return the paged result set + */ + public PagedResults createPagedResult(Object result, Cursor cursor) + { + return new PagedResults(result, cursor); + } + +} diff --git a/source/java/org/alfresco/repo/web/util/paging/WindowedCursor.java b/source/java/org/alfresco/repo/web/util/paging/WindowedCursor.java index 8191fa4ed9..396a104f3e 100644 --- a/source/java/org/alfresco/repo/web/util/paging/WindowedCursor.java +++ b/source/java/org/alfresco/repo/web/util/paging/WindowedCursor.java @@ -1,188 +1,188 @@ -package org.alfresco.repo.web.util.paging; - -import java.io.Serializable; - -import org.alfresco.repo.web.util.paging.Paging.PageType; - - -/** - * Cursor implementation based on notion of a Window. - * - * @author davidc - */ -public class WindowedCursor implements Cursor, Serializable -{ - private static final long serialVersionUID = 521131539938276413L; - - private boolean zeroBasedRow; - private int totalRows; - private int skipRows; - private int maxRows; - private int rowsPerPage; - - /** - * Construct - * - * @param zeroBasedRow true => 0 based, false => 1 based - * @param totalRows total rows in collection - * @param skipRows number of rows to skip (0 - none) - * @param maxRows maximum number of rows in window - */ - WindowedCursor(boolean zeroBasedRow, int totalRows, int skipRows, int maxRows) - { - this.zeroBasedRow = zeroBasedRow; - this.totalRows = totalRows; - this.skipRows = skipRows; - this.maxRows = maxRows; - this.rowsPerPage = (maxRows <= 0) ? totalRows - skipRows : maxRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPageType() - */ - public String getPageType() - { - return PageType.WINDOW.toString(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPageSize() - */ - public int getPageSize() - { - return maxRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages() - */ - public int getTotalPages() - { - return -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows() - */ - public int getTotalRows() - { - return totalRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage() - */ - public int getCurrentPage() - { - return skipRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage() - */ - public int getFirstPage() - { - if (totalRows <=0) - return -1; - - return zeroBasedRow ? 0 : 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getLastPage() - */ - public int getLastPage() - { - return -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getNextPage() - */ - public int getNextPage() - { - return (skipRows + rowsPerPage < totalRows) ? skipRows + maxRows : -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage() - */ - public int getPrevPage() - { - return (skipRows > 0) ? Math.max(0, skipRows - maxRows) : -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#isInRange() - */ - public boolean isInRange() - { - return skipRows >= 0 && skipRows < totalRows; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage() - */ - public boolean getHasFirstPage() - { - return getFirstPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage() - */ - public boolean getHasLastPage() - { - return getLastPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage() - */ - public boolean getHasNextPage() - { - return getNextPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage() - */ - public boolean getHasPrevPage() - { - return getPrevPage() != -1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getStartRow() - */ - public int getStartRow() - { - if (totalRows <= 0) - return 0; - - return skipRows + (zeroBasedRow ? 0 : 1); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getEndRow() - */ - public int getEndRow() - { - if (totalRows <= 0) - return -1; - - return getStartRow() + Math.min(rowsPerPage, totalRows - skipRows) - 1; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.web.util.paging.Cursor#getRowCount() - */ - public int getRowCount() - { - if (totalRows <= 0) - return 0; - - return getEndRow() - getStartRow() + 1; - } - -} +package org.alfresco.repo.web.util.paging; + +import java.io.Serializable; + +import org.alfresco.repo.web.util.paging.Paging.PageType; + + +/** + * Cursor implementation based on notion of a Window. + * + * @author davidc + */ +public class WindowedCursor implements Cursor, Serializable +{ + private static final long serialVersionUID = 521131539938276413L; + + private boolean zeroBasedRow; + private int totalRows; + private int skipRows; + private int maxRows; + private int rowsPerPage; + + /** + * Construct + * + * @param zeroBasedRow true => 0 based, false => 1 based + * @param totalRows total rows in collection + * @param skipRows number of rows to skip (0 - none) + * @param maxRows maximum number of rows in window + */ + WindowedCursor(boolean zeroBasedRow, int totalRows, int skipRows, int maxRows) + { + this.zeroBasedRow = zeroBasedRow; + this.totalRows = totalRows; + this.skipRows = skipRows; + this.maxRows = maxRows; + this.rowsPerPage = (maxRows <= 0) ? totalRows - skipRows : maxRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPageType() + */ + public String getPageType() + { + return PageType.WINDOW.toString(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPageSize() + */ + public int getPageSize() + { + return maxRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages() + */ + public int getTotalPages() + { + return -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows() + */ + public int getTotalRows() + { + return totalRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage() + */ + public int getCurrentPage() + { + return skipRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage() + */ + public int getFirstPage() + { + if (totalRows <=0) + return -1; + + return zeroBasedRow ? 0 : 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getLastPage() + */ + public int getLastPage() + { + return -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getNextPage() + */ + public int getNextPage() + { + return (skipRows + rowsPerPage < totalRows) ? skipRows + maxRows : -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage() + */ + public int getPrevPage() + { + return (skipRows > 0) ? Math.max(0, skipRows - maxRows) : -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#isInRange() + */ + public boolean isInRange() + { + return skipRows >= 0 && skipRows < totalRows; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage() + */ + public boolean getHasFirstPage() + { + return getFirstPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage() + */ + public boolean getHasLastPage() + { + return getLastPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage() + */ + public boolean getHasNextPage() + { + return getNextPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage() + */ + public boolean getHasPrevPage() + { + return getPrevPage() != -1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getStartRow() + */ + public int getStartRow() + { + if (totalRows <= 0) + return 0; + + return skipRows + (zeroBasedRow ? 0 : 1); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getEndRow() + */ + public int getEndRow() + { + if (totalRows <= 0) + return -1; + + return getStartRow() + Math.min(rowsPerPage, totalRows - skipRows) - 1; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.web.util.paging.Cursor#getRowCount() + */ + public int getRowCount() + { + if (totalRows <= 0) + return 0; + + return getEndRow() - getStartRow() + 1; + } + +} diff --git a/source/java/org/alfresco/repo/webdav/ExceptionHandler.java b/source/java/org/alfresco/repo/webdav/ExceptionHandler.java index acfa108bd7..202979f6f9 100644 --- a/source/java/org/alfresco/repo/webdav/ExceptionHandler.java +++ b/source/java/org/alfresco/repo/webdav/ExceptionHandler.java @@ -1,88 +1,88 @@ -package org.alfresco.repo.webdav; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Create a suitable HttpServletResponse when face with an exception. - * - * @author Matt Ward - */ -public class ExceptionHandler -{ - private static final Log logger = LogFactory.getLog(ExceptionHandler.class); - private Throwable e; - private final HttpServletRequest request; - private final HttpServletResponse response; - - /** - * Create an ExceptionHandler. - * - * @param e Throwable - * @param request HttpServletRequest - * @param response HttpServletResponse - */ - public ExceptionHandler(Throwable e, HttpServletRequest request, HttpServletResponse response) - { - this.e = e; - this.request = request; - this.response = response; - } - - - public void handle() throws IOException - { - if (!(e instanceof WebDAVServerException) && e.getCause() != null) - { - if (e.getCause() instanceof WebDAVServerException) - { - e = e.getCause(); - } - } - // Work out how to handle the error - if (e instanceof WebDAVServerException) - { - WebDAVServerException error = (WebDAVServerException) e; - if (error.getCause() != null) - { - logger.error("Exception thrown.", e); - } - - if (logger.isDebugEnabled()) - { - // Show what status code the method sent back - - logger.debug(request.getMethod() + " is returning status code: " + error.getHttpStatusCode()); - } - - if (response.isCommitted()) - { - logger.warn("Could not return the status code to the client as the response has already been committed!"); - } - else - { - response.sendError(error.getHttpStatusCode()); - } - } - else - { - logger.error("Exception thrown.", e); - - if (response.isCommitted()) - { - logger.warn("Could not return the internal server error code to the client as the response has already been committed!"); - } - else - { - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - } -} +package org.alfresco.repo.webdav; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Create a suitable HttpServletResponse when face with an exception. + * + * @author Matt Ward + */ +public class ExceptionHandler +{ + private static final Log logger = LogFactory.getLog(ExceptionHandler.class); + private Throwable e; + private final HttpServletRequest request; + private final HttpServletResponse response; + + /** + * Create an ExceptionHandler. + * + * @param e Throwable + * @param request HttpServletRequest + * @param response HttpServletResponse + */ + public ExceptionHandler(Throwable e, HttpServletRequest request, HttpServletResponse response) + { + this.e = e; + this.request = request; + this.response = response; + } + + + public void handle() throws IOException + { + if (!(e instanceof WebDAVServerException) && e.getCause() != null) + { + if (e.getCause() instanceof WebDAVServerException) + { + e = e.getCause(); + } + } + // Work out how to handle the error + if (e instanceof WebDAVServerException) + { + WebDAVServerException error = (WebDAVServerException) e; + if (error.getCause() != null) + { + logger.error("Exception thrown.", e); + } + + if (logger.isDebugEnabled()) + { + // Show what status code the method sent back + + logger.debug(request.getMethod() + " is returning status code: " + error.getHttpStatusCode()); + } + + if (response.isCommitted()) + { + logger.warn("Could not return the status code to the client as the response has already been committed!"); + } + else + { + response.sendError(error.getHttpStatusCode()); + } + } + else + { + logger.error("Exception thrown.", e); + + if (response.isCommitted()) + { + logger.warn("Could not return the internal server error code to the client as the response has already been committed!"); + } + else + { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + } +} diff --git a/source/java/org/alfresco/repo/webdav/auth/BaseNTLMAuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/BaseNTLMAuthenticationFilter.java index a306430efc..3b93fcd8b4 100644 --- a/source/java/org/alfresco/repo/webdav/auth/BaseNTLMAuthenticationFilter.java +++ b/source/java/org/alfresco/repo/webdav/auth/BaseNTLMAuthenticationFilter.java @@ -1,1086 +1,1086 @@ -package org.alfresco.repo.webdav.auth; - -import java.io.IOException; -import java.io.PrintWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.List; -import java.util.Random; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.transaction.Status; -import javax.transaction.UserTransaction; - -import net.sf.acegisecurity.BadCredentialsException; - -import org.alfresco.jlan.server.auth.PasswordEncryptor; -import org.alfresco.jlan.server.auth.ntlm.NTLM; -import org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails; -import org.alfresco.jlan.server.auth.ntlm.NTLMMessage; -import org.alfresco.jlan.server.auth.ntlm.NTLMv2Blob; -import org.alfresco.jlan.server.auth.ntlm.TargetInfo; -import org.alfresco.jlan.server.auth.ntlm.Type1NTLMMessage; -import org.alfresco.jlan.server.auth.ntlm.Type2NTLMMessage; -import org.alfresco.jlan.server.auth.ntlm.Type3NTLMMessage; -import org.alfresco.jlan.util.DataPacker; -import org.alfresco.repo.SessionUser; -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.MD4PasswordEncoder; -import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl; -import org.alfresco.repo.security.authentication.NTLMMode; -import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator; -import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.web.auth.GuestCredentials; -import org.alfresco.repo.web.auth.NTLMCredentials; -import org.alfresco.repo.web.auth.TicketCredentials; -import org.alfresco.repo.web.auth.UnknownCredentials; -import org.alfresco.repo.web.auth.WebCredentials; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.logging.Log; - -/** - * Base class with common code and initialisation for NTLM authentication filters. - */ -public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthenticationFilter -{ - // NTLM authentication session object names - public static final String NTLM_AUTH_SESSION = "_alfNTLMAuthSess"; - public static final String NTLM_AUTH_DETAILS = "_alfNTLMDetails"; - - protected static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - protected static final String AUTHORIZATION = "Authorization"; - protected static final String AUTH_NTLM = "NTLM"; - - // NTLM flags mask for use with an authentication component that supports MD4 hashed password - // Enable NTLMv1 and NTLMv2 - private static final int NTLM_FLAGS_NTLM2 = NTLM.Flag56Bit + - NTLM.Flag128Bit + - NTLM.FlagLanManKey + - NTLM.FlagNegotiateNTLM + - NTLM.FlagNTLM2Key + - NTLM.FlagNegotiateUnicode; - - // NTLM flags mask for use with an authentication component that uses passthru auth - // Enable NTLMv1 only - private static final int NTLM_FLAGS_NTLM1 = NTLM.Flag56Bit + - NTLM.FlagLanManKey + - NTLM.FlagNegotiateNTLM + - NTLM.FlagNegotiateOEM + - NTLM.FlagNegotiateUnicode; - - // NTLM flags to send to the client with the allowed logon types - private int m_ntlmFlags; - - // Password encryptor - private PasswordEncryptor m_encryptor = new PasswordEncryptor(); - - // Random number generator used to generate challenge keys - private Random m_random = new Random(System.currentTimeMillis()); - - // MD4 hash decoder - private MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl(); - - // Allow guest access - private boolean m_allowGuest = false; - - // Allow guest access, map unknown users to the guest account - private boolean m_mapUnknownUserToGuest = false; - - // Disable NTLMv2 support - private boolean m_disableNTLMv2 = false; - - // SSO enabled authentication component (required) - private NLTMAuthenticator nltmAuthenticator; - - - /** - * @param mapUnknownUserToGuest should an unknown user be mapped to guest? - */ - public void setMapUnknownUserToGuest(boolean mapUnknownUserToGuest) - { - m_mapUnknownUserToGuest = mapUnknownUserToGuest; - } - - - /* (non-Javadoc) - * @see org.alfresco.repo.webdav.auth.BaseSSOAuthenticationFilter#init() - */ - @Override - protected void init() throws ServletException - { - // Call the base SSO filter initialization - super.init(); - - // Check that the authentication component supports the required mode - - if (!(authenticationComponent instanceof NLTMAuthenticator)) - { - throw new ServletException("Authentication component does not support NTLM"); - } - this.nltmAuthenticator = (NLTMAuthenticator)this.authenticationComponent; - if (nltmAuthenticator.getNTLMMode() != NTLMMode.MD4_PROVIDER && - nltmAuthenticator.getNTLMMode() != NTLMMode.PASS_THROUGH) - { - throw new ServletException("Required authentication mode not available"); - } - - // Check if guest access is to be allowed - m_allowGuest = this.authenticationComponent.guestUserAuthenticationAllowed(); - - if (getLogger().isDebugEnabled() && m_allowGuest) - getLogger().debug("NTLM filter guest access allowed"); - - // Check if unknown users should be mapped to guest access - if (getLogger().isDebugEnabled() && m_mapUnknownUserToGuest) - getLogger().debug("NTLM filter map unknown users to guest"); - - // Set the NTLM flags depending on the authentication component supporting MD4 passwords, - // or is using passthru auth - - if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER && m_disableNTLMv2 == false) - { - // Allow the client to use an NTLMv2 logon - - m_ntlmFlags = NTLM_FLAGS_NTLM2; - } - else - { - // Only allows NTLMv1 type logons as passthru authentication is being used - - m_ntlmFlags = NTLM_FLAGS_NTLM1; - } - } - - public boolean authenticateRequest(ServletContext context, HttpServletRequest sreq, HttpServletResponse sresp) throws IOException, ServletException - { - // Check if there is an authorization header with an NTLM security blob - String authHdr = sreq.getHeader(AUTHORIZATION); - boolean reqAuth = false; - - // Check if an NTLM authorization header was received - - if ( authHdr != null) - { - // Check for an NTLM authorization header - - if ( authHdr.startsWith(AUTH_NTLM)) - reqAuth = true; - else if ( authHdr.startsWith( "Negotiate")) - { - if ( getLogger().isDebugEnabled()) - getLogger().debug("Received 'Negotiate' from client, may be SPNEGO/Kerberos logon"); - - // Restart the authentication - - restartLoginChallenge(context, sreq, sresp); - return false; - } - else if (isFallbackEnabled()) - { - return performFallbackAuthentication(context, sreq, sresp); - } - } - - // Check if the user is already authenticated - SessionUser user = getSessionUser(context, sreq, sresp, true); - - // If the user has been validated and we do not require re-authentication then continue to - // the next filter - if (user != null && reqAuth == false) - { - // Filter validate hook - onValidate( context, sreq, sresp, new TicketCredentials(user.getTicket())); - - if (getLogger().isDebugEnabled()) - getLogger().debug("Authentication not required (user), chaining ..."); - - // Chain to the next filter - return true; - } - - // Check if the login page is being accessed, do not intercept the login page - if (hasLoginPage() && sreq.getRequestURI().endsWith(getLoginPage()) == true) - { - if (getLogger().isDebugEnabled()) - getLogger().debug("Login page requested, chaining ..."); - - // Chain to the next filter - return true; - } - - // Check if the browser is Opera, if so then display the login page as Opera does not - // support NTLM and displays an error page if a request to use NTLM is sent to it - String userAgent = sreq.getHeader("user-agent"); - if (userAgent != null && userAgent.indexOf("Opera ") != -1) - { - if (getLogger().isDebugEnabled()) - getLogger().debug("Opera detected, redirecting to login page"); - - // If there is no login page configured (WebDAV) then just keep requesting the user details from the client - - if ( hasLoginPage()) - redirectToLoginPage(sreq, sresp); - else - restartLoginChallenge(context, sreq, sresp); - return false; - } - - // Check the authorization header - if (authHdr == null) - { - // Check for a ticket based logon, if enabled - - if ( allowsTicketLogons()) - { - // Check if the request includes an authentication ticket - - if (checkForTicketParameter(context, sreq, sresp)) - { - - // Authentication was bypassed using a ticket parameter - return true; - } - } - - // DEBUG - - if (getLogger().isDebugEnabled()) - getLogger().debug("New NTLM auth request from " + sreq.getRemoteHost() + " (" + - sreq.getRemoteAddr() + ":" + sreq.getRemotePort() + ") SID:" + sreq.getSession().getId()); - - // Send back a request for NTLM authentication - restartLoginChallenge(context, sreq, sresp); - return false; - } - else - { - // Decode the received NTLM blob and validate - final byte[] ntlmByts = Base64.decodeBase64(authHdr.substring(5).getBytes()); - int ntlmTyp = NTLMMessage.isNTLMType(ntlmByts); - if (ntlmTyp == NTLM.Type1) - { - // Process the type 1 NTLM message - Type1NTLMMessage type1Msg = new Type1NTLMMessage(ntlmByts); - processType1(type1Msg, sreq, sresp); - return false; - } - else if (ntlmTyp == NTLM.Type3) - { - // Process the type 3 NTLM message - Type3NTLMMessage type3Msg = new Type3NTLMMessage(ntlmByts); - return processType3(type3Msg, context, sreq, sresp); - } - else - { - if (getLogger().isDebugEnabled()) - getLogger().debug("NTLM blob not handled, redirecting to login page."); - - if ( hasLoginPage()) - redirectToLoginPage(sreq, sresp); - else - restartLoginChallenge(context, sreq, sresp); - return false; - } - } - } - - - /** - * Process a type 1 NTLM message - * - * @param type1Msg Type1NTLMMessage - * @param req HttpServletRequest - * @param res HttpServletResponse - * @exception IOException - */ - protected void processType1(Type1NTLMMessage type1Msg, HttpServletRequest req, - HttpServletResponse res) throws IOException - { - if (getLogger().isDebugEnabled()) - getLogger().debug("Received type1 " + type1Msg); - - // Get the existing NTLM details - NTLMLogonDetails ntlmDetails = null; - HttpSession session = req.getSession(); - ntlmDetails = (NTLMLogonDetails)session.getAttribute(NTLM_AUTH_DETAILS); - - // Check if cached logon details are available - if (ntlmDetails != null && ntlmDetails.hasType2Message() && - ntlmDetails.hasNTLMHashedPassword() && ntlmDetails.hasAuthenticationToken()) - { - // Get the authentication server type2 response - Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message(); - - byte[] type2Bytes = cachedType2.getBytes(); - String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes)); - - if (getLogger().isDebugEnabled()) - getLogger().debug("Sending cached NTLM type2 to client - " + cachedType2); - - // Send back a request for NTLM authentication - res.setHeader(WWW_AUTHENTICATE, ntlmBlob); - res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - res.flushBuffer(); - } - else - { - // Clear any cached logon details - session.removeAttribute(NTLM_AUTH_DETAILS); - - // Set the 8 byte challenge for the new logon request - byte[] challenge = null; - NTLMPassthruToken authToken = null; - - if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) - { - // Generate a random 8 byte challenge - - challenge = new byte[8]; - DataPacker.putIntelLong(m_random.nextLong(), challenge, 0); - } - else - { - // Get the client domain - String domain = type1Msg.getDomain(); - if (domain == null || domain.length() == 0) - { - domain = mapClientAddressToDomain(req.getRemoteAddr()); - } - - if (getLogger().isDebugEnabled()) - getLogger().debug("Client domain " + domain); - - // Create an authentication token for the new logon - authToken = new NTLMPassthruToken(domain); - - // Run the first stage of the passthru authentication to get the challenge - nltmAuthenticator.authenticate(authToken); - - // Get the challenge from the token - if (authToken.getChallenge() != null) - { - challenge = authToken.getChallenge().getBytes(); - } - } - - // Get the flags from the client request and mask out unsupported features - int ntlmFlags = type1Msg.getFlags() & m_ntlmFlags; - - // Build a type2 message to send back to the client, containing the challenge - List tList = new ArrayList(); - String srvName = getServerName(); - tList.add(new TargetInfo(NTLM.TargetServer, srvName)); - - Type2NTLMMessage type2Msg = new Type2NTLMMessage(); - type2Msg.buildType2(ntlmFlags, srvName, challenge, null, tList); - - // Store the NTLM logon details, cache the type2 message, and token if using passthru - ntlmDetails = new NTLMLogonDetails(); - ntlmDetails.setType2Message(type2Msg); - ntlmDetails.setAuthenticationToken(authToken); - - session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails); - - if (getLogger().isDebugEnabled()) - getLogger().debug("Sending NTLM type2 to client - " + type2Msg); - - // Send back a request for NTLM authentication - byte[] type2Bytes = type2Msg.getBytes(); - String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes)); - - res.setHeader(WWW_AUTHENTICATE, ntlmBlob); - res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - res.flushBuffer(); - } - } - - /** - * Process a type 3 NTLM message - * - * @param type3Msg Type3NTLMMessage - * @param req HttpServletRequest - * @param res HttpServletResponse - * - * @exception IOException - * @exception ServletException - */ - protected boolean processType3(Type3NTLMMessage type3Msg, ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException - { - Log logger = getLogger(); - - if (logger.isDebugEnabled()) - logger.debug("Received type3 " + type3Msg); - - // Get the existing NTLM details - NTLMLogonDetails ntlmDetails = null; - SessionUser user = null; - - user = getSessionUser(context, req, res, true); - HttpSession session = req.getSession(); - ntlmDetails = (NTLMLogonDetails)session.getAttribute(NTLM_AUTH_DETAILS); - - // Get the NTLM logon details - String userName = type3Msg.getUserName(); - String workstation = type3Msg.getWorkstation(); - String domain = type3Msg.getDomain(); - - // ALF-10997 fix, normalize the userName - //the system runAs is acceptable because we are resolving a username i.e. it's a system-wide operation that does not need permission checks - - final String userName_f = userName; - String normalized = transactionService.getRetryingTransactionHelper().doInTransaction( - new RetryingTransactionHelper.RetryingTransactionCallback() - { - public String execute() throws Throwable - { - return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() - { - public String doWork() throws Exception - { - String normalized = personService.getUserIdentifier(userName_f); - return normalized; - } - }, AuthenticationUtil.SYSTEM_USER_NAME); - } - }, true); - - if (normalized != null) - { - userName = normalized; - } - - boolean authenticated = false; - - // Check if we are using cached details for the authentication - if (user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword()) - { - // Check if the received NTLM hashed password matches the cached password - byte[] ntlmPwd = type3Msg.getNTLMHash(); - byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword(); - - if (ntlmPwd != null) - { - authenticated = Arrays.equals( cachedPwd, ntlmPwd); - } - - if (logger.isDebugEnabled()) - logger.debug("Using cached NTLM hash, authenticated = " + authenticated); - - onValidate(context, req, res, new NTLMCredentials(userName, ntlmPwd)); - - // Allow the user to access the requested page - return true; - } - else - { - WebCredentials credentials; - // Check if we are using local MD4 password hashes or passthru authentication - if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) - { - // Check if guest logons are allowed and this is a guest logon - if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName())) - { - credentials = new GuestCredentials(); - // Indicate that the user has been authenticated - authenticated = true; - - if (getLogger().isDebugEnabled()) - getLogger().debug("Guest logon"); - } - else - { - // Get the stored MD4 hashed password for the user, or null if the user does not exist - String md4hash = getMD4Hash(userName); - - if (md4hash != null) - { - authenticated = validateLocalHashedPassword(type3Msg, ntlmDetails, authenticated, md4hash); - credentials = new NTLMCredentials(ntlmDetails.getUserName(), ntlmDetails.getNTLMHashedPassword()); - } - else - { - // Check if unknown users should be logged on as guest - if (m_mapUnknownUserToGuest) - { - // Reset the user name to be the guest user - userName = authenticationComponent.getGuestUserName(); - authenticated = true; - credentials = new GuestCredentials(); - - if (logger.isDebugEnabled()) - logger.debug("User " + userName + " logged on as guest, no Alfresco account"); - } - else - { - if (logger.isDebugEnabled()) - logger.debug("User " + userName + " does not have Alfresco account"); - - // Bypass NTLM authentication and display the logon screen, - // as user account does not exist in Alfresco - credentials = new UnknownCredentials(); - authenticated = false; - } - } - } - } - else - { - credentials = new NTLMCredentials(type3Msg.getUserName(), type3Msg.getNTLMHash()); - // Determine if the client sent us NTLMv1 or NTLMv2 - if (type3Msg.hasFlag(NTLM.Flag128Bit) && type3Msg.hasFlag(NTLM.FlagNTLM2Key) || - (type3Msg.getNTLMHash() != null && type3Msg.getNTLMHash().length > 24)) - { - // Cannot accept NTLMv2 if we are using passthru auth - if (logger.isErrorEnabled()) - logger.error("Client " + workstation + " using NTLMv2 logon, not valid with passthru authentication"); - } - else - { - if (ntlmDetails == null) - { - if (logger.isWarnEnabled()) - logger.warn("Authentication failed: NTLM details can not be retrieved from session. Client must support cookies."); - restartLoginChallenge(context, req, res); - return false; - } - // Passthru mode, send the hashed password details to the passthru authentication server - NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken(); - authToken.setUserAndPassword(type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1); - try - { - // Run the second stage of the passthru authentication - nltmAuthenticator.authenticate(authToken); - authenticated = true; - - // Check if the user has been logged on as guest - if (authToken.isGuestLogon()) - { - userName = authenticationComponent.getGuestUserName(); - } - - // Set the authentication context - authenticationComponent.setCurrentUser(userName); - } - catch (BadCredentialsException ex) - { - if (logger.isDebugEnabled()) - logger.debug("Authentication failed, " + ex.getMessage()); - } - catch (AuthenticationException ex) - { - if (logger.isDebugEnabled()) - logger.debug("Authentication failed, " + ex.getMessage()); - } - finally - { - // Clear the authentication token from the NTLM details - ntlmDetails.setAuthenticationToken(null); - } - } - } - - // Check if the user has been authenticated, if so then setup the user environment - if (authenticated == true) - { - boolean userInit = false; - if (user == null) - { - try - { - user = createUserEnvironment(session, userName); - userInit = true; - } - catch (AuthenticationException ex) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to validate user " + userName, ex); - - onValidateFailed(context, req, res, session, credentials); - return false; - } - } - - onValidate(context, req, res, credentials); - - // Update the NTLM logon details in the session - String srvName = getServerName(); - if (ntlmDetails == null) - { - // No cached NTLM details - ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, srvName); - ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash()); - session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails); - - if (logger.isDebugEnabled()) - logger.debug("No cached NTLM details, created"); - } - else - { - // Update the cached NTLM details - ntlmDetails.setDetails(userName, workstation, domain, false, srvName); - ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash()); - - if (logger.isDebugEnabled()) - logger.debug("Updated cached NTLM details"); - } - - if (logger.isDebugEnabled()) - logger.debug("User logged on via NTLM, " + ntlmDetails); - - if (onLoginComplete(context, req, res, userInit)) - { - // Allow the user to access the requested page - return true; - } - } - else - { - restartLoginChallenge(context, req, res); - } - } - return false; - } - - /** - * Validate the MD4 hash against local password - * - * @param type3Msg Type3NTLMMessage - * @param ntlmDetails NTLMLogonDetails - * @param authenticated boolean - * @param md4hash String - * - * @return true if password hash is valid, false otherwise - */ - protected boolean validateLocalHashedPassword(Type3NTLMMessage type3Msg, NTLMLogonDetails ntlmDetails, boolean authenticated, String md4hash) - { - // Make sure we have hte cached NTLM details, including the type2 message with the server challenge - - if ( ntlmDetails == null || ntlmDetails.getType2Message() == null) - { - // DEBUG - - if ( getLogger().isDebugEnabled()) - getLogger().debug("No cached Type2, ntlmDetails=" + ntlmDetails); - - // Not authenticated - - return false; - } - - // Determine if the client sent us NTLMv1 or NTLMv2 - if (type3Msg.hasFlag(NTLM.FlagNTLM2Key)) - { - // Determine if the client sent us an NTLMv2 blob or an NTLMv2 session key - if (type3Msg.getNTLMHashLength() > 24) - { - // Looks like an NTLMv2 blob - authenticated = checkNTLMv2(md4hash, ntlmDetails.getChallengeKey(), type3Msg); - - if (getLogger().isDebugEnabled()) - getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv2"); - - // If the NTlmv2 autentication failed then check if the client has sent an NTLMv1 hash - - if ( authenticated == false && type3Msg.hasFlag(NTLM.Flag56Bit) && type3Msg.getLMHashLength() == 24) - { - // Check the LM hash field - - authenticated = checkNTLMv1(md4hash, ntlmDetails.getChallengeKey(), type3Msg, true); - - // DEBUG - - if (getLogger().isDebugEnabled()) - getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv1 (via fallback)"); - } - } - else - { - // Looks like an NTLMv2 session key - authenticated = checkNTLMv2SessionKey(md4hash, ntlmDetails.getChallengeKey(), type3Msg); - - if (getLogger().isDebugEnabled()) - getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv2SessKey"); - } - } - else - { - // Looks like an NTLMv1 blob - authenticated = checkNTLMv1(md4hash, ntlmDetails.getChallengeKey(), type3Msg, false); - - if (getLogger().isDebugEnabled()) - getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv1"); - } - return authenticated; - } - - /** - * Perform an NTLMv1 hashed password check - * - * @param md4hash String - * @param challenge byte[] - * @param type3Msg Type3NTLMMessage - * @param checkLMHash boolean - * @return boolean - */ - protected final boolean checkNTLMv1(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg, boolean checkLMHash) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("Perform an NTLMv1 hashed password check.")); - - // Generate the local encrypted password using the challenge that was sent to the client - byte[] p21 = new byte[21]; - byte[] md4byts = m_md4Encoder.decodeHash(md4hash); - System.arraycopy(md4byts, 0, p21, 0, 16); - - // Generate the local hash of the password using the same challenge - byte[] localHash = null; - - try - { - localHash = m_encryptor.doNTLM1Encryption(p21, challenge); - } - catch (NoSuchAlgorithmException ex) - { - } - - // Validate the password - byte[] clientHash = checkLMHash ? type3Msg.getLMHash() : type3Msg.getNTLMHash(); - - if (clientHash != null && localHash != null && clientHash.length == localHash.length) - { - int i = 0; - - while (i < clientHash.length && clientHash[i] == localHash[i]) - { - i++; - } - - if (i == clientHash.length) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("Hashed passwords match.")); - return true; - } - } - - if (getLogger().isDebugEnabled()) - getLogger().debug(("Hashed passwords do not match.")); - return false; - } - - /** - * Perform an NTLMv2 check - * - * @param md4hash String - * @param challenge byte[] - * @param type3Msg Type3NTLMMessage - * @return boolean - */ - protected final boolean checkNTLMv2(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("Perform an NTLMv2 check.")); - boolean ntlmv2OK = false; - boolean lmv2OK = false; - - try - { - // Generate the v2 hash using the challenge that was sent to the client - byte[] v2hash = m_encryptor.doNTLM2Encryption(m_md4Encoder.decodeHash(md4hash), type3Msg.getUserName(), type3Msg.getDomain()); - - // Get the NTLMv2 blob sent by the client and the challenge that was sent by the server - NTLMv2Blob v2blob = new NTLMv2Blob(type3Msg.getNTLMHash()); - - // Calculate the HMAC of the received blob and compare - byte[] srvHmac = v2blob.calculateHMAC(challenge, v2hash); - byte[] clientHmac = v2blob.getHMAC(); - - if (clientHmac != null && srvHmac != null && clientHmac.length == srvHmac.length) - { - int i = 0; - - while (i < clientHmac.length && clientHmac[i] == srvHmac[i]) - { - i++; - } - - if (i == clientHmac.length) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("HMAC matches the client, user authenticated.")); - ntlmv2OK = true; - } - } - - // NTLMv2 check failed, try the LMv2 value - - if ( ntlmv2OK == false) - { - byte[] lmv2 = type3Msg.getLMHash(); - byte[] clChallenge = v2blob.getClientChallenge(); - - if ( lmv2 != null && lmv2.length == 24 && clChallenge != null && clChallenge.length == 8) - { - // Check that the LM hash contains the client challenge as the last 8 bytes - - int i = 0; - - while ( i < clChallenge.length && lmv2[ i + 16] == clChallenge[ i]) - i++; - - if ( i == clChallenge.length) - { - // Calculate the LMv2 value - - byte[] lmv2Hmac = v2blob.calculateLMv2HMAC(v2hash, challenge, clChallenge); - - // Check if the LMv2 HMAC matches - - i = 0; - - while (i < lmv2Hmac.length && lmv2[i] == lmv2Hmac[i]) - i++; - - if (i == lmv2Hmac.length) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("LMv2 HMAC matches the client, user authenticated.")); - - //return true; - lmv2OK = true; - } - - } - } - } - } - catch (Exception ex) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(ex); - } - - // Check if either of the NTLMv2 checks passed - - if ( ntlmv2OK || lmv2OK) - return true; - return false; - } - - /** - * Perform an NTLMv2 session key check - * - * @param md4hash String - * @param challenge byte[] - * @param type3Msg Type3NTLMMessage - * @return boolean - */ - protected final boolean checkNTLMv2SessionKey(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("Perform an NTLMv2 session key check.")); - // Create the value to be encrypted by appending the server challenge and client challenge - // and applying an MD5 digest - byte[] nonce = new byte[16]; - System.arraycopy(challenge, 0, nonce, 0, 8); - System.arraycopy(type3Msg.getLMHash(), 0, nonce, 8, 8); - - MessageDigest md5 = null; - byte[] v2challenge = new byte[8]; - - try - { - // Create the MD5 digest - md5 = MessageDigest.getInstance("MD5"); - - // Apply the MD5 digest to the nonce - md5.update(nonce); - byte[] md5nonce = md5.digest(); - - // We only want the first 8 bytes - System.arraycopy(md5nonce, 0, v2challenge, 0, 8); - } - catch (NoSuchAlgorithmException ex) - { - // Log the error - getLogger().error(ex); - } - - // Generate the local encrypted password using the MD5 generated challenge - byte[] p21 = new byte[21]; - byte[] md4byts = m_md4Encoder.decodeHash(md4hash); - System.arraycopy(md4byts, 0, p21, 0, 16); - - // Generate the local hash of the password - byte[] localHash = null; - - try - { - localHash = m_encryptor.doNTLM1Encryption(p21, v2challenge); - } - catch (NoSuchAlgorithmException ex) - { - // Log the error - getLogger().error(ex); - } - - // Validate the password - byte[] clientHash = type3Msg.getNTLMHash(); - - if (clientHash != null && localHash != null && clientHash.length == localHash.length) - { - int i = 0; - - while (i < clientHash.length && clientHash[i] == localHash[i]) - { - i++; - } - - if (i == clientHash.length) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(("Hashed password check successful.")); - return true; - } - } - if (getLogger().isDebugEnabled()) - getLogger().debug(("Password check failed.")); - return false; - } - - /** - * Get the stored MD4 hashed password for the user, or null if the user does not exist - * - * @param userName String - * - * @return MD4 hash or null - */ - protected String getMD4Hash(String userName) - { - String md4hash = null; - - // Wrap the auth component calls in a transaction - UserTransaction tx = transactionService.getUserTransaction(); - try - { - tx.begin(); - - // Get the stored MD4 hashed password for the user, or null if the user does not exist - md4hash = nltmAuthenticator.getMD4HashedPassword(userName); - } - catch (Throwable ex) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(ex); - } - finally - { - // Rollback/commit the transaction if still valid - if (tx != null) - { - try - { - // Commit or rollback the transaction - if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK || - tx.getStatus() == Status.STATUS_ROLLEDBACK || - tx.getStatus() == Status.STATUS_ROLLING_BACK) - { - // Transaction is marked for rollback - tx.rollback(); - } - else - { - // Commit the transaction - tx.commit(); - } - } - catch (Throwable ex) - { - if (getLogger().isDebugEnabled()) - getLogger().debug(ex); - } - } - } - - return md4hash; - } - - /** - * Restart the NTLM logon process - * - * @param context ServletContext - * @param req HttpServletRequest - * @param res SessHttpServletResponse - * @throws IOException - */ - public void restartLoginChallenge(ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException - { - if (getLogger().isDebugEnabled()) - getLogger().debug("restartLoginChallenge..."); - - // Remove any existing session and NTLM details from the session - HttpSession session = req.getSession(false); - if (session != null) - { - clearSession(session); - } - - // check for "chrome" since Chrome user-agent contains a Safari version - String userAgent = req.getHeader("user-agent"); - if (userAgent != null && userAgent.indexOf("Safari") != -1 && userAgent.indexOf("Chrome") == -1) - { - final PrintWriter out = res.getWriter(); - out.println(""); - out.println("

Login authentication failed. Please close and re-open Safari to try again.

"); - out.println(""); - out.close(); - } - else - { - // Force the logon to start again - res.setHeader(WWW_AUTHENTICATE, AUTH_NTLM); - res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - writeLoginPageLink(context, req, res); - } - - if (isFallbackEnabled()) - { - includeFallbackAuth(context, req, res); - } - - res.flushBuffer(); - } - - /** - * Removes all attributes stored in session - * - * @param session Session - */ - @SuppressWarnings("unchecked") - private void clearSession(HttpSession session) - { - Enumeration names = (Enumeration) session.getAttributeNames(); - while (names.hasMoreElements()) - { - session.removeAttribute(names.nextElement()); - } - } - - - /** - * Disable NTLMv2 support, must be called from the implementation constructor - */ - protected final void disableNTLMv2() - { - m_disableNTLMv2 = true; - } -} +package org.alfresco.repo.webdav.auth; + +import java.io.IOException; +import java.io.PrintWriter; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.Random; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +import net.sf.acegisecurity.BadCredentialsException; + +import org.alfresco.jlan.server.auth.PasswordEncryptor; +import org.alfresco.jlan.server.auth.ntlm.NTLM; +import org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails; +import org.alfresco.jlan.server.auth.ntlm.NTLMMessage; +import org.alfresco.jlan.server.auth.ntlm.NTLMv2Blob; +import org.alfresco.jlan.server.auth.ntlm.TargetInfo; +import org.alfresco.jlan.server.auth.ntlm.Type1NTLMMessage; +import org.alfresco.jlan.server.auth.ntlm.Type2NTLMMessage; +import org.alfresco.jlan.server.auth.ntlm.Type3NTLMMessage; +import org.alfresco.jlan.util.DataPacker; +import org.alfresco.repo.SessionUser; +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.MD4PasswordEncoder; +import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl; +import org.alfresco.repo.security.authentication.NTLMMode; +import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator; +import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.web.auth.GuestCredentials; +import org.alfresco.repo.web.auth.NTLMCredentials; +import org.alfresco.repo.web.auth.TicketCredentials; +import org.alfresco.repo.web.auth.UnknownCredentials; +import org.alfresco.repo.web.auth.WebCredentials; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.logging.Log; + +/** + * Base class with common code and initialisation for NTLM authentication filters. + */ +public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthenticationFilter +{ + // NTLM authentication session object names + public static final String NTLM_AUTH_SESSION = "_alfNTLMAuthSess"; + public static final String NTLM_AUTH_DETAILS = "_alfNTLMDetails"; + + protected static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + protected static final String AUTHORIZATION = "Authorization"; + protected static final String AUTH_NTLM = "NTLM"; + + // NTLM flags mask for use with an authentication component that supports MD4 hashed password + // Enable NTLMv1 and NTLMv2 + private static final int NTLM_FLAGS_NTLM2 = NTLM.Flag56Bit + + NTLM.Flag128Bit + + NTLM.FlagLanManKey + + NTLM.FlagNegotiateNTLM + + NTLM.FlagNTLM2Key + + NTLM.FlagNegotiateUnicode; + + // NTLM flags mask for use with an authentication component that uses passthru auth + // Enable NTLMv1 only + private static final int NTLM_FLAGS_NTLM1 = NTLM.Flag56Bit + + NTLM.FlagLanManKey + + NTLM.FlagNegotiateNTLM + + NTLM.FlagNegotiateOEM + + NTLM.FlagNegotiateUnicode; + + // NTLM flags to send to the client with the allowed logon types + private int m_ntlmFlags; + + // Password encryptor + private PasswordEncryptor m_encryptor = new PasswordEncryptor(); + + // Random number generator used to generate challenge keys + private Random m_random = new Random(System.currentTimeMillis()); + + // MD4 hash decoder + private MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl(); + + // Allow guest access + private boolean m_allowGuest = false; + + // Allow guest access, map unknown users to the guest account + private boolean m_mapUnknownUserToGuest = false; + + // Disable NTLMv2 support + private boolean m_disableNTLMv2 = false; + + // SSO enabled authentication component (required) + private NLTMAuthenticator nltmAuthenticator; + + + /** + * @param mapUnknownUserToGuest should an unknown user be mapped to guest? + */ + public void setMapUnknownUserToGuest(boolean mapUnknownUserToGuest) + { + m_mapUnknownUserToGuest = mapUnknownUserToGuest; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.webdav.auth.BaseSSOAuthenticationFilter#init() + */ + @Override + protected void init() throws ServletException + { + // Call the base SSO filter initialization + super.init(); + + // Check that the authentication component supports the required mode + + if (!(authenticationComponent instanceof NLTMAuthenticator)) + { + throw new ServletException("Authentication component does not support NTLM"); + } + this.nltmAuthenticator = (NLTMAuthenticator)this.authenticationComponent; + if (nltmAuthenticator.getNTLMMode() != NTLMMode.MD4_PROVIDER && + nltmAuthenticator.getNTLMMode() != NTLMMode.PASS_THROUGH) + { + throw new ServletException("Required authentication mode not available"); + } + + // Check if guest access is to be allowed + m_allowGuest = this.authenticationComponent.guestUserAuthenticationAllowed(); + + if (getLogger().isDebugEnabled() && m_allowGuest) + getLogger().debug("NTLM filter guest access allowed"); + + // Check if unknown users should be mapped to guest access + if (getLogger().isDebugEnabled() && m_mapUnknownUserToGuest) + getLogger().debug("NTLM filter map unknown users to guest"); + + // Set the NTLM flags depending on the authentication component supporting MD4 passwords, + // or is using passthru auth + + if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER && m_disableNTLMv2 == false) + { + // Allow the client to use an NTLMv2 logon + + m_ntlmFlags = NTLM_FLAGS_NTLM2; + } + else + { + // Only allows NTLMv1 type logons as passthru authentication is being used + + m_ntlmFlags = NTLM_FLAGS_NTLM1; + } + } + + public boolean authenticateRequest(ServletContext context, HttpServletRequest sreq, HttpServletResponse sresp) throws IOException, ServletException + { + // Check if there is an authorization header with an NTLM security blob + String authHdr = sreq.getHeader(AUTHORIZATION); + boolean reqAuth = false; + + // Check if an NTLM authorization header was received + + if ( authHdr != null) + { + // Check for an NTLM authorization header + + if ( authHdr.startsWith(AUTH_NTLM)) + reqAuth = true; + else if ( authHdr.startsWith( "Negotiate")) + { + if ( getLogger().isDebugEnabled()) + getLogger().debug("Received 'Negotiate' from client, may be SPNEGO/Kerberos logon"); + + // Restart the authentication + + restartLoginChallenge(context, sreq, sresp); + return false; + } + else if (isFallbackEnabled()) + { + return performFallbackAuthentication(context, sreq, sresp); + } + } + + // Check if the user is already authenticated + SessionUser user = getSessionUser(context, sreq, sresp, true); + + // If the user has been validated and we do not require re-authentication then continue to + // the next filter + if (user != null && reqAuth == false) + { + // Filter validate hook + onValidate( context, sreq, sresp, new TicketCredentials(user.getTicket())); + + if (getLogger().isDebugEnabled()) + getLogger().debug("Authentication not required (user), chaining ..."); + + // Chain to the next filter + return true; + } + + // Check if the login page is being accessed, do not intercept the login page + if (hasLoginPage() && sreq.getRequestURI().endsWith(getLoginPage()) == true) + { + if (getLogger().isDebugEnabled()) + getLogger().debug("Login page requested, chaining ..."); + + // Chain to the next filter + return true; + } + + // Check if the browser is Opera, if so then display the login page as Opera does not + // support NTLM and displays an error page if a request to use NTLM is sent to it + String userAgent = sreq.getHeader("user-agent"); + if (userAgent != null && userAgent.indexOf("Opera ") != -1) + { + if (getLogger().isDebugEnabled()) + getLogger().debug("Opera detected, redirecting to login page"); + + // If there is no login page configured (WebDAV) then just keep requesting the user details from the client + + if ( hasLoginPage()) + redirectToLoginPage(sreq, sresp); + else + restartLoginChallenge(context, sreq, sresp); + return false; + } + + // Check the authorization header + if (authHdr == null) + { + // Check for a ticket based logon, if enabled + + if ( allowsTicketLogons()) + { + // Check if the request includes an authentication ticket + + if (checkForTicketParameter(context, sreq, sresp)) + { + + // Authentication was bypassed using a ticket parameter + return true; + } + } + + // DEBUG + + if (getLogger().isDebugEnabled()) + getLogger().debug("New NTLM auth request from " + sreq.getRemoteHost() + " (" + + sreq.getRemoteAddr() + ":" + sreq.getRemotePort() + ") SID:" + sreq.getSession().getId()); + + // Send back a request for NTLM authentication + restartLoginChallenge(context, sreq, sresp); + return false; + } + else + { + // Decode the received NTLM blob and validate + final byte[] ntlmByts = Base64.decodeBase64(authHdr.substring(5).getBytes()); + int ntlmTyp = NTLMMessage.isNTLMType(ntlmByts); + if (ntlmTyp == NTLM.Type1) + { + // Process the type 1 NTLM message + Type1NTLMMessage type1Msg = new Type1NTLMMessage(ntlmByts); + processType1(type1Msg, sreq, sresp); + return false; + } + else if (ntlmTyp == NTLM.Type3) + { + // Process the type 3 NTLM message + Type3NTLMMessage type3Msg = new Type3NTLMMessage(ntlmByts); + return processType3(type3Msg, context, sreq, sresp); + } + else + { + if (getLogger().isDebugEnabled()) + getLogger().debug("NTLM blob not handled, redirecting to login page."); + + if ( hasLoginPage()) + redirectToLoginPage(sreq, sresp); + else + restartLoginChallenge(context, sreq, sresp); + return false; + } + } + } + + + /** + * Process a type 1 NTLM message + * + * @param type1Msg Type1NTLMMessage + * @param req HttpServletRequest + * @param res HttpServletResponse + * @exception IOException + */ + protected void processType1(Type1NTLMMessage type1Msg, HttpServletRequest req, + HttpServletResponse res) throws IOException + { + if (getLogger().isDebugEnabled()) + getLogger().debug("Received type1 " + type1Msg); + + // Get the existing NTLM details + NTLMLogonDetails ntlmDetails = null; + HttpSession session = req.getSession(); + ntlmDetails = (NTLMLogonDetails)session.getAttribute(NTLM_AUTH_DETAILS); + + // Check if cached logon details are available + if (ntlmDetails != null && ntlmDetails.hasType2Message() && + ntlmDetails.hasNTLMHashedPassword() && ntlmDetails.hasAuthenticationToken()) + { + // Get the authentication server type2 response + Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message(); + + byte[] type2Bytes = cachedType2.getBytes(); + String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes)); + + if (getLogger().isDebugEnabled()) + getLogger().debug("Sending cached NTLM type2 to client - " + cachedType2); + + // Send back a request for NTLM authentication + res.setHeader(WWW_AUTHENTICATE, ntlmBlob); + res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + res.flushBuffer(); + } + else + { + // Clear any cached logon details + session.removeAttribute(NTLM_AUTH_DETAILS); + + // Set the 8 byte challenge for the new logon request + byte[] challenge = null; + NTLMPassthruToken authToken = null; + + if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) + { + // Generate a random 8 byte challenge + + challenge = new byte[8]; + DataPacker.putIntelLong(m_random.nextLong(), challenge, 0); + } + else + { + // Get the client domain + String domain = type1Msg.getDomain(); + if (domain == null || domain.length() == 0) + { + domain = mapClientAddressToDomain(req.getRemoteAddr()); + } + + if (getLogger().isDebugEnabled()) + getLogger().debug("Client domain " + domain); + + // Create an authentication token for the new logon + authToken = new NTLMPassthruToken(domain); + + // Run the first stage of the passthru authentication to get the challenge + nltmAuthenticator.authenticate(authToken); + + // Get the challenge from the token + if (authToken.getChallenge() != null) + { + challenge = authToken.getChallenge().getBytes(); + } + } + + // Get the flags from the client request and mask out unsupported features + int ntlmFlags = type1Msg.getFlags() & m_ntlmFlags; + + // Build a type2 message to send back to the client, containing the challenge + List tList = new ArrayList(); + String srvName = getServerName(); + tList.add(new TargetInfo(NTLM.TargetServer, srvName)); + + Type2NTLMMessage type2Msg = new Type2NTLMMessage(); + type2Msg.buildType2(ntlmFlags, srvName, challenge, null, tList); + + // Store the NTLM logon details, cache the type2 message, and token if using passthru + ntlmDetails = new NTLMLogonDetails(); + ntlmDetails.setType2Message(type2Msg); + ntlmDetails.setAuthenticationToken(authToken); + + session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails); + + if (getLogger().isDebugEnabled()) + getLogger().debug("Sending NTLM type2 to client - " + type2Msg); + + // Send back a request for NTLM authentication + byte[] type2Bytes = type2Msg.getBytes(); + String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes)); + + res.setHeader(WWW_AUTHENTICATE, ntlmBlob); + res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + res.flushBuffer(); + } + } + + /** + * Process a type 3 NTLM message + * + * @param type3Msg Type3NTLMMessage + * @param req HttpServletRequest + * @param res HttpServletResponse + * + * @exception IOException + * @exception ServletException + */ + protected boolean processType3(Type3NTLMMessage type3Msg, ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException + { + Log logger = getLogger(); + + if (logger.isDebugEnabled()) + logger.debug("Received type3 " + type3Msg); + + // Get the existing NTLM details + NTLMLogonDetails ntlmDetails = null; + SessionUser user = null; + + user = getSessionUser(context, req, res, true); + HttpSession session = req.getSession(); + ntlmDetails = (NTLMLogonDetails)session.getAttribute(NTLM_AUTH_DETAILS); + + // Get the NTLM logon details + String userName = type3Msg.getUserName(); + String workstation = type3Msg.getWorkstation(); + String domain = type3Msg.getDomain(); + + // ALF-10997 fix, normalize the userName + //the system runAs is acceptable because we are resolving a username i.e. it's a system-wide operation that does not need permission checks + + final String userName_f = userName; + String normalized = transactionService.getRetryingTransactionHelper().doInTransaction( + new RetryingTransactionHelper.RetryingTransactionCallback() + { + public String execute() throws Throwable + { + return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + public String doWork() throws Exception + { + String normalized = personService.getUserIdentifier(userName_f); + return normalized; + } + }, AuthenticationUtil.SYSTEM_USER_NAME); + } + }, true); + + if (normalized != null) + { + userName = normalized; + } + + boolean authenticated = false; + + // Check if we are using cached details for the authentication + if (user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword()) + { + // Check if the received NTLM hashed password matches the cached password + byte[] ntlmPwd = type3Msg.getNTLMHash(); + byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword(); + + if (ntlmPwd != null) + { + authenticated = Arrays.equals( cachedPwd, ntlmPwd); + } + + if (logger.isDebugEnabled()) + logger.debug("Using cached NTLM hash, authenticated = " + authenticated); + + onValidate(context, req, res, new NTLMCredentials(userName, ntlmPwd)); + + // Allow the user to access the requested page + return true; + } + else + { + WebCredentials credentials; + // Check if we are using local MD4 password hashes or passthru authentication + if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) + { + // Check if guest logons are allowed and this is a guest logon + if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName())) + { + credentials = new GuestCredentials(); + // Indicate that the user has been authenticated + authenticated = true; + + if (getLogger().isDebugEnabled()) + getLogger().debug("Guest logon"); + } + else + { + // Get the stored MD4 hashed password for the user, or null if the user does not exist + String md4hash = getMD4Hash(userName); + + if (md4hash != null) + { + authenticated = validateLocalHashedPassword(type3Msg, ntlmDetails, authenticated, md4hash); + credentials = new NTLMCredentials(ntlmDetails.getUserName(), ntlmDetails.getNTLMHashedPassword()); + } + else + { + // Check if unknown users should be logged on as guest + if (m_mapUnknownUserToGuest) + { + // Reset the user name to be the guest user + userName = authenticationComponent.getGuestUserName(); + authenticated = true; + credentials = new GuestCredentials(); + + if (logger.isDebugEnabled()) + logger.debug("User " + userName + " logged on as guest, no Alfresco account"); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("User " + userName + " does not have Alfresco account"); + + // Bypass NTLM authentication and display the logon screen, + // as user account does not exist in Alfresco + credentials = new UnknownCredentials(); + authenticated = false; + } + } + } + } + else + { + credentials = new NTLMCredentials(type3Msg.getUserName(), type3Msg.getNTLMHash()); + // Determine if the client sent us NTLMv1 or NTLMv2 + if (type3Msg.hasFlag(NTLM.Flag128Bit) && type3Msg.hasFlag(NTLM.FlagNTLM2Key) || + (type3Msg.getNTLMHash() != null && type3Msg.getNTLMHash().length > 24)) + { + // Cannot accept NTLMv2 if we are using passthru auth + if (logger.isErrorEnabled()) + logger.error("Client " + workstation + " using NTLMv2 logon, not valid with passthru authentication"); + } + else + { + if (ntlmDetails == null) + { + if (logger.isWarnEnabled()) + logger.warn("Authentication failed: NTLM details can not be retrieved from session. Client must support cookies."); + restartLoginChallenge(context, req, res); + return false; + } + // Passthru mode, send the hashed password details to the passthru authentication server + NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken(); + authToken.setUserAndPassword(type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1); + try + { + // Run the second stage of the passthru authentication + nltmAuthenticator.authenticate(authToken); + authenticated = true; + + // Check if the user has been logged on as guest + if (authToken.isGuestLogon()) + { + userName = authenticationComponent.getGuestUserName(); + } + + // Set the authentication context + authenticationComponent.setCurrentUser(userName); + } + catch (BadCredentialsException ex) + { + if (logger.isDebugEnabled()) + logger.debug("Authentication failed, " + ex.getMessage()); + } + catch (AuthenticationException ex) + { + if (logger.isDebugEnabled()) + logger.debug("Authentication failed, " + ex.getMessage()); + } + finally + { + // Clear the authentication token from the NTLM details + ntlmDetails.setAuthenticationToken(null); + } + } + } + + // Check if the user has been authenticated, if so then setup the user environment + if (authenticated == true) + { + boolean userInit = false; + if (user == null) + { + try + { + user = createUserEnvironment(session, userName); + userInit = true; + } + catch (AuthenticationException ex) + { + if (logger.isDebugEnabled()) + logger.debug("Failed to validate user " + userName, ex); + + onValidateFailed(context, req, res, session, credentials); + return false; + } + } + + onValidate(context, req, res, credentials); + + // Update the NTLM logon details in the session + String srvName = getServerName(); + if (ntlmDetails == null) + { + // No cached NTLM details + ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, srvName); + ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash()); + session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails); + + if (logger.isDebugEnabled()) + logger.debug("No cached NTLM details, created"); + } + else + { + // Update the cached NTLM details + ntlmDetails.setDetails(userName, workstation, domain, false, srvName); + ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash()); + + if (logger.isDebugEnabled()) + logger.debug("Updated cached NTLM details"); + } + + if (logger.isDebugEnabled()) + logger.debug("User logged on via NTLM, " + ntlmDetails); + + if (onLoginComplete(context, req, res, userInit)) + { + // Allow the user to access the requested page + return true; + } + } + else + { + restartLoginChallenge(context, req, res); + } + } + return false; + } + + /** + * Validate the MD4 hash against local password + * + * @param type3Msg Type3NTLMMessage + * @param ntlmDetails NTLMLogonDetails + * @param authenticated boolean + * @param md4hash String + * + * @return true if password hash is valid, false otherwise + */ + protected boolean validateLocalHashedPassword(Type3NTLMMessage type3Msg, NTLMLogonDetails ntlmDetails, boolean authenticated, String md4hash) + { + // Make sure we have hte cached NTLM details, including the type2 message with the server challenge + + if ( ntlmDetails == null || ntlmDetails.getType2Message() == null) + { + // DEBUG + + if ( getLogger().isDebugEnabled()) + getLogger().debug("No cached Type2, ntlmDetails=" + ntlmDetails); + + // Not authenticated + + return false; + } + + // Determine if the client sent us NTLMv1 or NTLMv2 + if (type3Msg.hasFlag(NTLM.FlagNTLM2Key)) + { + // Determine if the client sent us an NTLMv2 blob or an NTLMv2 session key + if (type3Msg.getNTLMHashLength() > 24) + { + // Looks like an NTLMv2 blob + authenticated = checkNTLMv2(md4hash, ntlmDetails.getChallengeKey(), type3Msg); + + if (getLogger().isDebugEnabled()) + getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv2"); + + // If the NTlmv2 autentication failed then check if the client has sent an NTLMv1 hash + + if ( authenticated == false && type3Msg.hasFlag(NTLM.Flag56Bit) && type3Msg.getLMHashLength() == 24) + { + // Check the LM hash field + + authenticated = checkNTLMv1(md4hash, ntlmDetails.getChallengeKey(), type3Msg, true); + + // DEBUG + + if (getLogger().isDebugEnabled()) + getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv1 (via fallback)"); + } + } + else + { + // Looks like an NTLMv2 session key + authenticated = checkNTLMv2SessionKey(md4hash, ntlmDetails.getChallengeKey(), type3Msg); + + if (getLogger().isDebugEnabled()) + getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv2SessKey"); + } + } + else + { + // Looks like an NTLMv1 blob + authenticated = checkNTLMv1(md4hash, ntlmDetails.getChallengeKey(), type3Msg, false); + + if (getLogger().isDebugEnabled()) + getLogger().debug((authenticated ? "Logged on" : "Logon failed") + " using NTLMSSP/NTLMv1"); + } + return authenticated; + } + + /** + * Perform an NTLMv1 hashed password check + * + * @param md4hash String + * @param challenge byte[] + * @param type3Msg Type3NTLMMessage + * @param checkLMHash boolean + * @return boolean + */ + protected final boolean checkNTLMv1(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg, boolean checkLMHash) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("Perform an NTLMv1 hashed password check.")); + + // Generate the local encrypted password using the challenge that was sent to the client + byte[] p21 = new byte[21]; + byte[] md4byts = m_md4Encoder.decodeHash(md4hash); + System.arraycopy(md4byts, 0, p21, 0, 16); + + // Generate the local hash of the password using the same challenge + byte[] localHash = null; + + try + { + localHash = m_encryptor.doNTLM1Encryption(p21, challenge); + } + catch (NoSuchAlgorithmException ex) + { + } + + // Validate the password + byte[] clientHash = checkLMHash ? type3Msg.getLMHash() : type3Msg.getNTLMHash(); + + if (clientHash != null && localHash != null && clientHash.length == localHash.length) + { + int i = 0; + + while (i < clientHash.length && clientHash[i] == localHash[i]) + { + i++; + } + + if (i == clientHash.length) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("Hashed passwords match.")); + return true; + } + } + + if (getLogger().isDebugEnabled()) + getLogger().debug(("Hashed passwords do not match.")); + return false; + } + + /** + * Perform an NTLMv2 check + * + * @param md4hash String + * @param challenge byte[] + * @param type3Msg Type3NTLMMessage + * @return boolean + */ + protected final boolean checkNTLMv2(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("Perform an NTLMv2 check.")); + boolean ntlmv2OK = false; + boolean lmv2OK = false; + + try + { + // Generate the v2 hash using the challenge that was sent to the client + byte[] v2hash = m_encryptor.doNTLM2Encryption(m_md4Encoder.decodeHash(md4hash), type3Msg.getUserName(), type3Msg.getDomain()); + + // Get the NTLMv2 blob sent by the client and the challenge that was sent by the server + NTLMv2Blob v2blob = new NTLMv2Blob(type3Msg.getNTLMHash()); + + // Calculate the HMAC of the received blob and compare + byte[] srvHmac = v2blob.calculateHMAC(challenge, v2hash); + byte[] clientHmac = v2blob.getHMAC(); + + if (clientHmac != null && srvHmac != null && clientHmac.length == srvHmac.length) + { + int i = 0; + + while (i < clientHmac.length && clientHmac[i] == srvHmac[i]) + { + i++; + } + + if (i == clientHmac.length) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("HMAC matches the client, user authenticated.")); + ntlmv2OK = true; + } + } + + // NTLMv2 check failed, try the LMv2 value + + if ( ntlmv2OK == false) + { + byte[] lmv2 = type3Msg.getLMHash(); + byte[] clChallenge = v2blob.getClientChallenge(); + + if ( lmv2 != null && lmv2.length == 24 && clChallenge != null && clChallenge.length == 8) + { + // Check that the LM hash contains the client challenge as the last 8 bytes + + int i = 0; + + while ( i < clChallenge.length && lmv2[ i + 16] == clChallenge[ i]) + i++; + + if ( i == clChallenge.length) + { + // Calculate the LMv2 value + + byte[] lmv2Hmac = v2blob.calculateLMv2HMAC(v2hash, challenge, clChallenge); + + // Check if the LMv2 HMAC matches + + i = 0; + + while (i < lmv2Hmac.length && lmv2[i] == lmv2Hmac[i]) + i++; + + if (i == lmv2Hmac.length) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("LMv2 HMAC matches the client, user authenticated.")); + + //return true; + lmv2OK = true; + } + + } + } + } + } + catch (Exception ex) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(ex); + } + + // Check if either of the NTLMv2 checks passed + + if ( ntlmv2OK || lmv2OK) + return true; + return false; + } + + /** + * Perform an NTLMv2 session key check + * + * @param md4hash String + * @param challenge byte[] + * @param type3Msg Type3NTLMMessage + * @return boolean + */ + protected final boolean checkNTLMv2SessionKey(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("Perform an NTLMv2 session key check.")); + // Create the value to be encrypted by appending the server challenge and client challenge + // and applying an MD5 digest + byte[] nonce = new byte[16]; + System.arraycopy(challenge, 0, nonce, 0, 8); + System.arraycopy(type3Msg.getLMHash(), 0, nonce, 8, 8); + + MessageDigest md5 = null; + byte[] v2challenge = new byte[8]; + + try + { + // Create the MD5 digest + md5 = MessageDigest.getInstance("MD5"); + + // Apply the MD5 digest to the nonce + md5.update(nonce); + byte[] md5nonce = md5.digest(); + + // We only want the first 8 bytes + System.arraycopy(md5nonce, 0, v2challenge, 0, 8); + } + catch (NoSuchAlgorithmException ex) + { + // Log the error + getLogger().error(ex); + } + + // Generate the local encrypted password using the MD5 generated challenge + byte[] p21 = new byte[21]; + byte[] md4byts = m_md4Encoder.decodeHash(md4hash); + System.arraycopy(md4byts, 0, p21, 0, 16); + + // Generate the local hash of the password + byte[] localHash = null; + + try + { + localHash = m_encryptor.doNTLM1Encryption(p21, v2challenge); + } + catch (NoSuchAlgorithmException ex) + { + // Log the error + getLogger().error(ex); + } + + // Validate the password + byte[] clientHash = type3Msg.getNTLMHash(); + + if (clientHash != null && localHash != null && clientHash.length == localHash.length) + { + int i = 0; + + while (i < clientHash.length && clientHash[i] == localHash[i]) + { + i++; + } + + if (i == clientHash.length) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(("Hashed password check successful.")); + return true; + } + } + if (getLogger().isDebugEnabled()) + getLogger().debug(("Password check failed.")); + return false; + } + + /** + * Get the stored MD4 hashed password for the user, or null if the user does not exist + * + * @param userName String + * + * @return MD4 hash or null + */ + protected String getMD4Hash(String userName) + { + String md4hash = null; + + // Wrap the auth component calls in a transaction + UserTransaction tx = transactionService.getUserTransaction(); + try + { + tx.begin(); + + // Get the stored MD4 hashed password for the user, or null if the user does not exist + md4hash = nltmAuthenticator.getMD4HashedPassword(userName); + } + catch (Throwable ex) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(ex); + } + finally + { + // Rollback/commit the transaction if still valid + if (tx != null) + { + try + { + // Commit or rollback the transaction + if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK || + tx.getStatus() == Status.STATUS_ROLLEDBACK || + tx.getStatus() == Status.STATUS_ROLLING_BACK) + { + // Transaction is marked for rollback + tx.rollback(); + } + else + { + // Commit the transaction + tx.commit(); + } + } + catch (Throwable ex) + { + if (getLogger().isDebugEnabled()) + getLogger().debug(ex); + } + } + } + + return md4hash; + } + + /** + * Restart the NTLM logon process + * + * @param context ServletContext + * @param req HttpServletRequest + * @param res SessHttpServletResponse + * @throws IOException + */ + public void restartLoginChallenge(ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException + { + if (getLogger().isDebugEnabled()) + getLogger().debug("restartLoginChallenge..."); + + // Remove any existing session and NTLM details from the session + HttpSession session = req.getSession(false); + if (session != null) + { + clearSession(session); + } + + // check for "chrome" since Chrome user-agent contains a Safari version + String userAgent = req.getHeader("user-agent"); + if (userAgent != null && userAgent.indexOf("Safari") != -1 && userAgent.indexOf("Chrome") == -1) + { + final PrintWriter out = res.getWriter(); + out.println(""); + out.println("

Login authentication failed. Please close and re-open Safari to try again.

"); + out.println(""); + out.close(); + } + else + { + // Force the logon to start again + res.setHeader(WWW_AUTHENTICATE, AUTH_NTLM); + res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + writeLoginPageLink(context, req, res); + } + + if (isFallbackEnabled()) + { + includeFallbackAuth(context, req, res); + } + + res.flushBuffer(); + } + + /** + * Removes all attributes stored in session + * + * @param session Session + */ + @SuppressWarnings("unchecked") + private void clearSession(HttpSession session) + { + Enumeration names = (Enumeration) session.getAttributeNames(); + while (names.hasMoreElements()) + { + session.removeAttribute(names.nextElement()); + } + } + + + /** + * Disable NTLMv2 support, must be called from the implementation constructor + */ + protected final void disableNTLMv2() + { + m_disableNTLMv2 = true; + } +} diff --git a/source/java/org/alfresco/rest/api/Activities.java b/source/java/org/alfresco/rest/api/Activities.java index 32f417a655..a739b2788c 100644 --- a/source/java/org/alfresco/rest/api/Activities.java +++ b/source/java/org/alfresco/rest/api/Activities.java @@ -1,24 +1,24 @@ -package org.alfresco.rest.api; - -import java.util.Map; - -import org.alfresco.repo.Client; -import org.alfresco.repo.domain.activities.ActivityFeedEntity; -import org.alfresco.rest.api.model.Activity; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.json.JSONException; - -public interface Activities -{ - static final String APP_TOOL = "restapi"; - static final Client RESTAPI_CLIENT = Client.asType(Client.ClientType.restapi); - - public static enum ActivityWho - { - me, others; - }; - - public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException; - public CollectionWithPagingInfo getUserActivities(String personId, final Parameters parameters); -} +package org.alfresco.rest.api; + +import java.util.Map; + +import org.alfresco.repo.Client; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.rest.api.model.Activity; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.json.JSONException; + +public interface Activities +{ + static final String APP_TOOL = "restapi"; + static final Client RESTAPI_CLIENT = Client.asType(Client.ClientType.restapi); + + public static enum ActivityWho + { + me, others; + }; + + public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException; + public CollectionWithPagingInfo getUserActivities(String personId, final Parameters parameters); +} diff --git a/source/java/org/alfresco/rest/api/Comments.java b/source/java/org/alfresco/rest/api/Comments.java index 553da3b615..2830cefc94 100644 --- a/source/java/org/alfresco/rest/api/Comments.java +++ b/source/java/org/alfresco/rest/api/Comments.java @@ -1,18 +1,18 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.Comment; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -/** - * - * @author steveglover - * @since publicapi1.0 - */ -public interface Comments -{ - public Comment createComment(String nodeId, Comment comment); - public Comment updateComment(String nodeId, Comment comment); - public void deleteComment(String nodeId, String commentNodeId); - public CollectionWithPagingInfo getComments(String nodeId, Paging paging); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.Comment; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +/** + * + * @author steveglover + * @since publicapi1.0 + */ +public interface Comments +{ + public Comment createComment(String nodeId, Comment comment); + public Comment updateComment(String nodeId, Comment comment); + public void deleteComment(String nodeId, String commentNodeId); + public CollectionWithPagingInfo getComments(String nodeId, Paging paging); +} diff --git a/source/java/org/alfresco/rest/api/Favourites.java b/source/java/org/alfresco/rest/api/Favourites.java index f7c8e17d1c..2ab6fb47ac 100644 --- a/source/java/org/alfresco/rest/api/Favourites.java +++ b/source/java/org/alfresco/rest/api/Favourites.java @@ -1,48 +1,48 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.Favourite; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; - -/** - * Centralises access to favourites functionality and maps between representations repository and api representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public interface Favourites -{ - /** - * Add a favourite for user personId - * - * @param personId the personId for which the favourite is to be added - * @param favourite the favourite to add - */ - Favourite addFavourite(String personId, Favourite favourite); - - /** - * Add a favourite for user personId - * - * @param personId the personId for which the favourite is to be removed - * @param id the id of the favourite to remove (id is a uuid) - */ - void removeFavourite(String personId, String id); - - /** - * Get a paged list of favourites for user personId - * - * @param personId the personId for which the favourite is to be removed - * @param parameters Parameters - * @return paged favourites - */ - CollectionWithPagingInfo getFavourites(String personId, final Parameters parameters); - - /** - * Get a specific favourite for user personId - * - * @param personId the personId for which the favourite is to be removed - * @param favouriteId the favourite id - * @return the favourite - */ - Favourite getFavourite(String personId, String favouriteId); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.Favourite; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; + +/** + * Centralises access to favourites functionality and maps between representations repository and api representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public interface Favourites +{ + /** + * Add a favourite for user personId + * + * @param personId the personId for which the favourite is to be added + * @param favourite the favourite to add + */ + Favourite addFavourite(String personId, Favourite favourite); + + /** + * Add a favourite for user personId + * + * @param personId the personId for which the favourite is to be removed + * @param id the id of the favourite to remove (id is a uuid) + */ + void removeFavourite(String personId, String id); + + /** + * Get a paged list of favourites for user personId + * + * @param personId the personId for which the favourite is to be removed + * @param parameters Parameters + * @return paged favourites + */ + CollectionWithPagingInfo getFavourites(String personId, final Parameters parameters); + + /** + * Get a specific favourite for user personId + * + * @param personId the personId for which the favourite is to be removed + * @param favouriteId the favourite id + * @return the favourite + */ + Favourite getFavourite(String personId, String favouriteId); +} diff --git a/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java b/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java index f00ef9a304..3440419ab3 100644 --- a/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java +++ b/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java @@ -1,93 +1,93 @@ -package org.alfresco.rest.api; - -import java.io.IOException; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.rest.api.model.PersonNetwork; -import org.alfresco.rest.api.networks.NetworksEntityResource; -import org.alfresco.rest.framework.Api; -import org.alfresco.rest.framework.core.exceptions.ApiException; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; -import org.alfresco.rest.framework.resource.parameters.Params; -import org.alfresco.rest.framework.webscripts.ApiWebScript; -import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.springframework.extensions.webscripts.Format; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -public class NetworkWebScriptGet extends ApiWebScript -{ - private Networks networks; - private ResourceWebScriptHelper helper; - - public void setHelper(ResourceWebScriptHelper helper) - { - this.helper = helper; - } - - public void setNetworks(Networks networks) - { - this.networks = networks; - } - - @Override - public void execute(final Api api, final WebScriptRequest req, final WebScriptResponse res) throws IOException - { - try - { - transactionService.getRetryingTransactionHelper().doInTransaction( - new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - // apply content type - res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); - - assistant.getJsonHelper().withWriter(res.getOutputStream(), new Writer() - { - @Override - public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) - throws JsonGenerationException, JsonMappingException, IOException - { - String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - String networkId = TenantUtil.getCurrentDomain(); - - PersonNetwork networkMembership = networks.getNetwork(personId, networkId); - if(networkMembership != null) - { - // TODO this is not ideal, but the only way to populate the embedded network entities (this would normally be - // done automatically by the api framework). - Object wrapped = helper.processAdditionsToTheResponse(res, Api.ALFRESCO_PUBLIC, NetworksEntityResource.NAME, Params.valueOf(personId, null, req), networkMembership); - - objectMapper.writeValue(generator, wrapped); - } - else - { - throw new EntityNotFoundException(networkId); - } - } - }); - - return null; - } - }, true, true); - } - catch (ApiException | WebScriptException apiException) - { - assistant.renderException(apiException, res); - } - catch (RuntimeException runtimeException) - { - assistant.renderException(runtimeException, res); - } - } -} +package org.alfresco.rest.api; + +import java.io.IOException; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.rest.api.model.PersonNetwork; +import org.alfresco.rest.api.networks.NetworksEntityResource; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.core.exceptions.ApiException; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.webscripts.ApiWebScript; +import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.springframework.extensions.webscripts.Format; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +public class NetworkWebScriptGet extends ApiWebScript +{ + private Networks networks; + private ResourceWebScriptHelper helper; + + public void setHelper(ResourceWebScriptHelper helper) + { + this.helper = helper; + } + + public void setNetworks(Networks networks) + { + this.networks = networks; + } + + @Override + public void execute(final Api api, final WebScriptRequest req, final WebScriptResponse res) throws IOException + { + try + { + transactionService.getRetryingTransactionHelper().doInTransaction( + new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // apply content type + res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); + + assistant.getJsonHelper().withWriter(res.getOutputStream(), new Writer() + { + @Override + public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) + throws JsonGenerationException, JsonMappingException, IOException + { + String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + String networkId = TenantUtil.getCurrentDomain(); + + PersonNetwork networkMembership = networks.getNetwork(personId, networkId); + if(networkMembership != null) + { + // TODO this is not ideal, but the only way to populate the embedded network entities (this would normally be + // done automatically by the api framework). + Object wrapped = helper.processAdditionsToTheResponse(res, Api.ALFRESCO_PUBLIC, NetworksEntityResource.NAME, Params.valueOf(personId, null, req), networkMembership); + + objectMapper.writeValue(generator, wrapped); + } + else + { + throw new EntityNotFoundException(networkId); + } + } + }); + + return null; + } + }, true, true); + } + catch (ApiException | WebScriptException apiException) + { + assistant.renderException(apiException, res); + } + catch (RuntimeException runtimeException) + { + assistant.renderException(runtimeException, res); + } + } +} diff --git a/source/java/org/alfresco/rest/api/Networks.java b/source/java/org/alfresco/rest/api/Networks.java index a490966127..73c5987489 100644 --- a/source/java/org/alfresco/rest/api/Networks.java +++ b/source/java/org/alfresco/rest/api/Networks.java @@ -1,14 +1,14 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.Network; -import org.alfresco.rest.api.model.PersonNetwork; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -public interface Networks -{ - public Network validateNetwork(String networkId); - public Network getNetwork(String networkId); - public PersonNetwork getNetwork(String personId, String networkId); - public CollectionWithPagingInfo getNetworks(String personId, Paging paging); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.Network; +import org.alfresco.rest.api.model.PersonNetwork; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +public interface Networks +{ + public Network validateNetwork(String networkId); + public Network getNetwork(String networkId); + public PersonNetwork getNetwork(String personId, String networkId); + public CollectionWithPagingInfo getNetworks(String personId, Paging paging); +} diff --git a/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java b/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java index 740a2723fe..0a00a55771 100644 --- a/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java +++ b/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java @@ -1,101 +1,101 @@ -package org.alfresco.rest.api; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.rest.api.model.PersonNetwork; -import org.alfresco.rest.api.networks.NetworksEntityResource; -import org.alfresco.rest.framework.Api; -import org.alfresco.rest.framework.core.exceptions.ApiException; -import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Params; -import org.alfresco.rest.framework.webscripts.ApiWebScript; -import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.springframework.extensions.webscripts.Format; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * A webscript that returns the authenticated user's network memberships. - * - * @author steveglover - * - */ -public class NetworksWebScriptGet extends ApiWebScript -{ - private Networks networks; - private ResourceWebScriptHelper helper; - - public void setHelper(ResourceWebScriptHelper helper) - { - this.helper = helper; - } - - public void setNetworks(Networks networks) - { - this.networks = networks; - } - - @Override - public void execute(final Api api, final WebScriptRequest req, final WebScriptResponse res) throws IOException - { - try - { - transactionService.getRetryingTransactionHelper().doInTransaction( - new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - final Paging paging = ResourceWebScriptHelper.findPaging(req); - - // apply content type - res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); - - assistant.getJsonHelper().withWriter(res.getOutputStream(), new Writer() - { - @Override - public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) - throws JsonGenerationException, JsonMappingException, IOException - { - List entities = new ArrayList(); - - String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - - CollectionWithPagingInfo networkMemberships = networks.getNetworks(personId, paging); - for (PersonNetwork networkMember : networkMemberships.getCollection()) - { - // TODO this is not ideal, but the only way to populate the embedded network entities (this would normally be - // done automatically by the api framework). - Object wrapped = helper.processAdditionsToTheResponse(res, Api.ALFRESCO_PUBLIC, NetworksEntityResource.NAME, Params.valueOf(personId, null, req), networkMember); - entities.add(wrapped); - } - - objectMapper.writeValue(generator, CollectionWithPagingInfo.asPaged(paging, entities)); - } - }); - - return null; - } - }, true, true); - } - catch (ApiException | WebScriptException apiException) - { - assistant.renderException(apiException, res); - } - catch (RuntimeException runtimeException) - { - assistant.renderException(runtimeException, res); - } - } +package org.alfresco.rest.api; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.rest.api.model.PersonNetwork; +import org.alfresco.rest.api.networks.NetworksEntityResource; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.core.exceptions.ApiException; +import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.webscripts.ApiWebScript; +import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.springframework.extensions.webscripts.Format; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * A webscript that returns the authenticated user's network memberships. + * + * @author steveglover + * + */ +public class NetworksWebScriptGet extends ApiWebScript +{ + private Networks networks; + private ResourceWebScriptHelper helper; + + public void setHelper(ResourceWebScriptHelper helper) + { + this.helper = helper; + } + + public void setNetworks(Networks networks) + { + this.networks = networks; + } + + @Override + public void execute(final Api api, final WebScriptRequest req, final WebScriptResponse res) throws IOException + { + try + { + transactionService.getRetryingTransactionHelper().doInTransaction( + new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + final Paging paging = ResourceWebScriptHelper.findPaging(req); + + // apply content type + res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); + + assistant.getJsonHelper().withWriter(res.getOutputStream(), new Writer() + { + @Override + public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) + throws JsonGenerationException, JsonMappingException, IOException + { + List entities = new ArrayList(); + + String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + + CollectionWithPagingInfo networkMemberships = networks.getNetworks(personId, paging); + for (PersonNetwork networkMember : networkMemberships.getCollection()) + { + // TODO this is not ideal, but the only way to populate the embedded network entities (this would normally be + // done automatically by the api framework). + Object wrapped = helper.processAdditionsToTheResponse(res, Api.ALFRESCO_PUBLIC, NetworksEntityResource.NAME, Params.valueOf(personId, null, req), networkMember); + entities.add(wrapped); + } + + objectMapper.writeValue(generator, CollectionWithPagingInfo.asPaged(paging, entities)); + } + }); + + return null; + } + }, true, true); + } + catch (ApiException | WebScriptException apiException) + { + assistant.renderException(apiException, res); + } + catch (RuntimeException runtimeException) + { + assistant.renderException(runtimeException, res); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/NodeRatings.java b/source/java/org/alfresco/rest/api/NodeRatings.java index 02f3ad96e7..12f668139d 100644 --- a/source/java/org/alfresco/rest/api/NodeRatings.java +++ b/source/java/org/alfresco/rest/api/NodeRatings.java @@ -1,15 +1,15 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.impl.node.ratings.RatingScheme; -import org.alfresco.rest.api.model.NodeRating; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -public interface NodeRatings -{ - public RatingScheme validateRatingScheme(String ratingSchemeId); - public NodeRating getNodeRating(String nodeId, String ratingSchemeId); - public CollectionWithPagingInfo getNodeRatings(String nodeId, Paging paging); - public void addRating(String nodeId, String ratingSchemeId, Object rating); - public void removeRating(String nodeId, String ratingSchemeId); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.impl.node.ratings.RatingScheme; +import org.alfresco.rest.api.model.NodeRating; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +public interface NodeRatings +{ + public RatingScheme validateRatingScheme(String ratingSchemeId); + public NodeRating getNodeRating(String nodeId, String ratingSchemeId); + public CollectionWithPagingInfo getNodeRatings(String nodeId, Paging paging); + public void addRating(String nodeId, String ratingSchemeId, Object rating); + public void removeRating(String nodeId, String ratingSchemeId); +} diff --git a/source/java/org/alfresco/rest/api/Nodes.java b/source/java/org/alfresco/rest/api/Nodes.java index 5ed09073e2..5443e7b4ca 100644 --- a/source/java/org/alfresco/rest/api/Nodes.java +++ b/source/java/org/alfresco/rest/api/Nodes.java @@ -1,267 +1,267 @@ -package org.alfresco.rest.api; - -import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.rest.api.model.AssocChild; -import org.alfresco.rest.api.model.AssocTarget; -import org.alfresco.rest.api.model.Document; -import org.alfresco.rest.api.model.Folder; -import org.alfresco.rest.api.model.Node; -import org.alfresco.rest.api.model.UserInfo; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.namespace.QName; -import org.springframework.extensions.webscripts.servlet.FormData; - -/** - * File Folder (Nodes) API - * - * @author janv - * @author Jamal Kaabi-Mofrad - * @author Gethin James - * @author steveglover - */ -public interface Nodes -{ - /** - * Get the node representation for the given node. - * - * @param nodeId String - * @return Node - */ - Node getNode(String nodeId); - - /** - * Get the document representation for the given node. - * - * @param nodeRef NodeRef - * @return Document - */ - Document getDocument(NodeRef nodeRef); - - /** - * Get the folder representation for the given node. - * - * @param nodeRef NodeRef - * @return Folder - */ - Folder getFolder(NodeRef nodeRef); - - /** - * Get the folder or document representation (as appropriate) for the given node. - * - * @param nodeId String nodeId or well-known alias, eg. "-root-" or "-my-" - * @param parameters the {@link Parameters} object to get the parameters passed into the request - * including: - * - incPrimaryParent - * @return - */ - Node getFolderOrDocument(String nodeId, Parameters parameters); - - Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters, Map mapUserInfo); - - /** - * Get the folder or document representation (as appropriate) for the given node. - * - * @param nodeRef A real Node - * @param parentNodeRef - * @param nodeTypeQName - * @param includeParam - * @param mapUserInfo - * @return - */ - Node getFolderOrDocument(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, List includeParam, Map mapUserInfo); - - /** - * Get list of children of a parent folder. - * - * @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-" - * @param parameters the {@link Parameters} object to get the parameters passed into the request - * including: - * - filter, sort & paging params (where, orderBy, skipCount, maxItems) - * - incFiles, incFolders (both true by default) - * @return a paged list of {@code org.alfresco.rest.api.model.Node} objects - */ - CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters); - - /** - * Delete the given node. Note: will cascade delete for a folder. - * - * @param nodeId String id of node (folder or document) - * @param parameters the {@link Parameters} object to get the parameters passed into the request - * - permanent (default false) - */ - void deleteNode(String nodeId, Parameters parameters); - - /** - * Create node - folder or (empty) file. - * - * @param parentFolderNodeId - * @param nodeInfo - * @param parameters - * @return - */ - Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters); - - /** - * Move or Copy node - * - * @param sourceNodeId - * @param parentFolderNodeId - * @param name - * @param parameters - * @return - */ - Node moveOrCopyNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters, boolean isCopy); - - /** - * Update node meta-data. - * - * @param nodeId - * @param entity - * @param parameters - * @return - */ - Node updateNode(String nodeId, Node entity, Parameters parameters); - - /** - * Download file content. - * - * @param fileNodeId - * @param parameters - * @param recordActivity true, if an activity post is required. - * @return - */ - BinaryResource getContent(String fileNodeId, Parameters parameters, boolean recordActivity); - - /** - * Download file content. - * - * @param nodeRef the content nodeRef - * @param parameters - * @param recordActivity true, if an activity post is required. - * @return - */ - BinaryResource getContent(NodeRef nodeRef, Parameters parameters, boolean recordActivity); - - /** - * Uploads file content (updates existing node with new content). - * - * Note: may create a new version, depending on versioning behaviour. - * - * @param fileNodeId - * @param contentInfo - * @param stream - * @param parameters - * @return - */ - Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters); - - /** - * Uploads file content and meta-data into the repository. - * - * @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-" - * @param formData the {@link FormData} - * @param parameters the {@link Parameters} object to get the parameters passed into the request - * @return {@code Node} if successful - */ - Node upload(String parentFolderNodeId, FormData formData, Parameters parameters); - - - NodeRef validateNode(StoreRef storeRef, String nodeId); - NodeRef validateNode(String nodeId); - NodeRef validateNode(NodeRef nodeRef); - NodeRef validateOrLookupNode(String nodeId, String path); - - boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes); - - /** - * Determines whether the type of the given nodeRef is a sub-class of another class or not. - * - * @param nodeRef source nodeRef - * @param ofClassQName the class to test against - * @param validateNodeRef whether to validate the given source node or not - * @return true if the type of the given nodeRef is a sub-class of another class, otherwise false - */ - boolean isSubClass(NodeRef nodeRef, QName ofClassQName, boolean validateNodeRef); - - /** - * Helper to create a QName from either a fully qualified or short-name QName string - * - * @param qnameStr Fully qualified or short-name QName string - * @return QName - */ - QName createQName(String qnameStr); - - QName getAssocType(String assocTypeQNameStr); - - QName getAssocType(String assocTypeQNameStr, boolean mandatory); - - /** - * - * @param parentNodeId - * @param entities - * @return - */ - List addChildren(String parentNodeId, List entities); - - /** - * - * @param sourceNodeId - * @param entities - * @return - */ - List addTargets(String sourceNodeId, List entities); - - /** - * API Constants - query parameters, etc - */ - - String PATH_ROOT = "-root-"; - String PATH_MY = "-my-"; - String PATH_SHARED = "-shared-"; - - String OP_CREATE = "create"; - String OP_DELETE = "delete"; - String OP_UPDATE = "update"; - - String PARAM_RELATIVE_PATH = "relativePath"; - String PARAM_AUTO_RENAME = "autoRename"; - String PARAM_PERMANENT = "permanent"; - - String PARAM_INCLUDE_PROPERTIES = "properties"; - String PARAM_INCLUDE_PATH = "path"; - String PARAM_INCLUDE_ASPECTNAMES = "aspectNames"; - String PARAM_INCLUDE_ISLINK = "isLink"; - String PARAM_INCLUDE_ALLOWABLEOPERATIONS = "allowableOperations"; - - String PARAM_INCLUDE_ASSOCIATION = "association"; - - String PARAM_ISFOLDER = "isFolder"; - String PARAM_ISFILE = "isFile"; - - String PARAM_INCLUDE_SUBTYPES = "INCLUDESUBTYPES"; - - String PARAM_NAME = "name"; - String PARAM_CREATEDAT = "createdAt"; - String PARAM_MODIFIEDAT = "modifiedAt"; - String PARAM_CREATEBYUSER = "createdByUser"; - String PARAM_MODIFIEDBYUSER = "modifiedByUser"; - String PARAM_MIMETYPE = "mimeType"; - String PARAM_SIZEINBYTES = "sizeInBytes"; - String PARAM_NODETYPE = "nodeType"; - - String PARAM_VERSION_MAJOR = "majorVersion"; // true if major, false if minor - String PARAM_VERSION_COMMENT = "comment"; - - String PARAM_ISPRIMARY = "isPrimary"; - String PARAM_ASSOC_TYPE = "assocType"; -} - +package org.alfresco.rest.api; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.rest.api.model.AssocChild; +import org.alfresco.rest.api.model.AssocTarget; +import org.alfresco.rest.api.model.Document; +import org.alfresco.rest.api.model.Folder; +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.api.model.UserInfo; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.webscripts.servlet.FormData; + +/** + * File Folder (Nodes) API + * + * @author janv + * @author Jamal Kaabi-Mofrad + * @author Gethin James + * @author steveglover + */ +public interface Nodes +{ + /** + * Get the node representation for the given node. + * + * @param nodeId String + * @return Node + */ + Node getNode(String nodeId); + + /** + * Get the document representation for the given node. + * + * @param nodeRef NodeRef + * @return Document + */ + Document getDocument(NodeRef nodeRef); + + /** + * Get the folder representation for the given node. + * + * @param nodeRef NodeRef + * @return Folder + */ + Folder getFolder(NodeRef nodeRef); + + /** + * Get the folder or document representation (as appropriate) for the given node. + * + * @param nodeId String nodeId or well-known alias, eg. "-root-" or "-my-" + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * including: + * - incPrimaryParent + * @return + */ + Node getFolderOrDocument(String nodeId, Parameters parameters); + + Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters, Map mapUserInfo); + + /** + * Get the folder or document representation (as appropriate) for the given node. + * + * @param nodeRef A real Node + * @param parentNodeRef + * @param nodeTypeQName + * @param includeParam + * @param mapUserInfo + * @return + */ + Node getFolderOrDocument(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, List includeParam, Map mapUserInfo); + + /** + * Get list of children of a parent folder. + * + * @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-" + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * including: + * - filter, sort & paging params (where, orderBy, skipCount, maxItems) + * - incFiles, incFolders (both true by default) + * @return a paged list of {@code org.alfresco.rest.api.model.Node} objects + */ + CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters); + + /** + * Delete the given node. Note: will cascade delete for a folder. + * + * @param nodeId String id of node (folder or document) + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * - permanent (default false) + */ + void deleteNode(String nodeId, Parameters parameters); + + /** + * Create node - folder or (empty) file. + * + * @param parentFolderNodeId + * @param nodeInfo + * @param parameters + * @return + */ + Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters); + + /** + * Move or Copy node + * + * @param sourceNodeId + * @param parentFolderNodeId + * @param name + * @param parameters + * @return + */ + Node moveOrCopyNode(String sourceNodeId, String parentFolderNodeId, String name, Parameters parameters, boolean isCopy); + + /** + * Update node meta-data. + * + * @param nodeId + * @param entity + * @param parameters + * @return + */ + Node updateNode(String nodeId, Node entity, Parameters parameters); + + /** + * Download file content. + * + * @param fileNodeId + * @param parameters + * @param recordActivity true, if an activity post is required. + * @return + */ + BinaryResource getContent(String fileNodeId, Parameters parameters, boolean recordActivity); + + /** + * Download file content. + * + * @param nodeRef the content nodeRef + * @param parameters + * @param recordActivity true, if an activity post is required. + * @return + */ + BinaryResource getContent(NodeRef nodeRef, Parameters parameters, boolean recordActivity); + + /** + * Uploads file content (updates existing node with new content). + * + * Note: may create a new version, depending on versioning behaviour. + * + * @param fileNodeId + * @param contentInfo + * @param stream + * @param parameters + * @return + */ + Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters); + + /** + * Uploads file content and meta-data into the repository. + * + * @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-" + * @param formData the {@link FormData} + * @param parameters the {@link Parameters} object to get the parameters passed into the request + * @return {@code Node} if successful + */ + Node upload(String parentFolderNodeId, FormData formData, Parameters parameters); + + + NodeRef validateNode(StoreRef storeRef, String nodeId); + NodeRef validateNode(String nodeId); + NodeRef validateNode(NodeRef nodeRef); + NodeRef validateOrLookupNode(String nodeId, String path); + + boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes); + + /** + * Determines whether the type of the given nodeRef is a sub-class of another class or not. + * + * @param nodeRef source nodeRef + * @param ofClassQName the class to test against + * @param validateNodeRef whether to validate the given source node or not + * @return true if the type of the given nodeRef is a sub-class of another class, otherwise false + */ + boolean isSubClass(NodeRef nodeRef, QName ofClassQName, boolean validateNodeRef); + + /** + * Helper to create a QName from either a fully qualified or short-name QName string + * + * @param qnameStr Fully qualified or short-name QName string + * @return QName + */ + QName createQName(String qnameStr); + + QName getAssocType(String assocTypeQNameStr); + + QName getAssocType(String assocTypeQNameStr, boolean mandatory); + + /** + * + * @param parentNodeId + * @param entities + * @return + */ + List addChildren(String parentNodeId, List entities); + + /** + * + * @param sourceNodeId + * @param entities + * @return + */ + List addTargets(String sourceNodeId, List entities); + + /** + * API Constants - query parameters, etc + */ + + String PATH_ROOT = "-root-"; + String PATH_MY = "-my-"; + String PATH_SHARED = "-shared-"; + + String OP_CREATE = "create"; + String OP_DELETE = "delete"; + String OP_UPDATE = "update"; + + String PARAM_RELATIVE_PATH = "relativePath"; + String PARAM_AUTO_RENAME = "autoRename"; + String PARAM_PERMANENT = "permanent"; + + String PARAM_INCLUDE_PROPERTIES = "properties"; + String PARAM_INCLUDE_PATH = "path"; + String PARAM_INCLUDE_ASPECTNAMES = "aspectNames"; + String PARAM_INCLUDE_ISLINK = "isLink"; + String PARAM_INCLUDE_ALLOWABLEOPERATIONS = "allowableOperations"; + + String PARAM_INCLUDE_ASSOCIATION = "association"; + + String PARAM_ISFOLDER = "isFolder"; + String PARAM_ISFILE = "isFile"; + + String PARAM_INCLUDE_SUBTYPES = "INCLUDESUBTYPES"; + + String PARAM_NAME = "name"; + String PARAM_CREATEDAT = "createdAt"; + String PARAM_MODIFIEDAT = "modifiedAt"; + String PARAM_CREATEBYUSER = "createdByUser"; + String PARAM_MODIFIEDBYUSER = "modifiedByUser"; + String PARAM_MIMETYPE = "mimeType"; + String PARAM_SIZEINBYTES = "sizeInBytes"; + String PARAM_NODETYPE = "nodeType"; + + String PARAM_VERSION_MAJOR = "majorVersion"; // true if major, false if minor + String PARAM_VERSION_COMMENT = "comment"; + + String PARAM_ISPRIMARY = "isPrimary"; + String PARAM_ASSOC_TYPE = "assocType"; +} + diff --git a/source/java/org/alfresco/rest/api/People.java b/source/java/org/alfresco/rest/api/People.java index 479787e6fd..69de3ecb51 100644 --- a/source/java/org/alfresco/rest/api/People.java +++ b/source/java/org/alfresco/rest/api/People.java @@ -1,21 +1,21 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.Person; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.NoSuchPersonException; - -public interface People -{ - String DEFAULT_USER = "-me-"; - - String validatePerson(String personId); - String validatePerson(String personId, boolean validateIsCurrentUser); - NodeRef getAvatar(String personId); - - /** - * - * @throws NoSuchPersonException if personId does not exist - */ - Person getPerson(final String personId); - //Person updatePerson(String personId, Person person); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.Person; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.NoSuchPersonException; + +public interface People +{ + String DEFAULT_USER = "-me-"; + + String validatePerson(String personId); + String validatePerson(String personId, boolean validateIsCurrentUser); + NodeRef getAvatar(String personId); + + /** + * + * @throws NoSuchPersonException if personId does not exist + */ + Person getPerson(final String personId); + //Person updatePerson(String personId, Person person); +} diff --git a/source/java/org/alfresco/rest/api/Preferences.java b/source/java/org/alfresco/rest/api/Preferences.java index 188ca9b413..aac334f0b7 100644 --- a/source/java/org/alfresco/rest/api/Preferences.java +++ b/source/java/org/alfresco/rest/api/Preferences.java @@ -1,11 +1,11 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.Preference; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -public interface Preferences -{ - public Preference getPreference(String personId, String preferenceName); - public CollectionWithPagingInfo getPreferences(String personId, Paging paging); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.Preference; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +public interface Preferences +{ + public Preference getPreference(String personId, String preferenceName); + public CollectionWithPagingInfo getPreferences(String personId, Paging paging); +} diff --git a/source/java/org/alfresco/rest/api/PublicApiAuthenticatorFactory.java b/source/java/org/alfresco/rest/api/PublicApiAuthenticatorFactory.java index e0de913e6e..cfa530b50f 100644 --- a/source/java/org/alfresco/rest/api/PublicApiAuthenticatorFactory.java +++ b/source/java/org/alfresco/rest/api/PublicApiAuthenticatorFactory.java @@ -1,261 +1,261 @@ -package org.alfresco.rest.api; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.web.auth.AuthenticationListener; -import org.alfresco.repo.web.auth.TenantAuthentication; -import org.alfresco.repo.web.auth.WebCredentials; -import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; -import org.alfresco.repo.web.scripts.servlet.RemoteUserAuthenticatorFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.Authenticator; -import org.springframework.extensions.webscripts.Description.RequiredAuthentication; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; -import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse; - -/** - * HTTP Basic Authentication for Public Api. - * - * Adapted from org.alfresco.module.org_alfresco_module_cloud.webscripts.TenantBasicHTTPAuthenticatorFactory. - * - * @author sglover - */ -public class PublicApiAuthenticatorFactory extends RemoteUserAuthenticatorFactory -{ - private static Log logger = LogFactory.getLog(PublicApiAuthenticatorFactory.class); - - public static final String DEFAULT_AUTHENTICATOR_KEY_HEADER = "X-Alfresco-Authenticator-Key"; - - private String authenticatorKeyHeader = DEFAULT_AUTHENTICATOR_KEY_HEADER; - private RetryingTransactionHelper retryingTransactionHelper; - private TenantAuthentication tenantAuthentication; - private Set validAuthenticatorKeys = Collections.emptySet(); - private Set outboundHeaderNames; - - public void setAuthenticatorKeyHeader(String authenticatorKeyHeader) - { - this.authenticatorKeyHeader = authenticatorKeyHeader; - } - - /** - * Set the headers passed to the gateway for authentication. - * - * @param outboundHeaders Set - */ - public void setOutboundHeaders(Set outboundHeaders) - { - if (outboundHeaders != null) - { - Set trimmed = new HashSet(); - for (String value : outboundHeaders) - { - trimmed.add(value.toLowerCase(Locale.ENGLISH).trim()); - } - outboundHeaders = trimmed; - } - - this.outboundHeaderNames = outboundHeaders; - } - - public void setTenantAuthentication(TenantAuthentication service) - { - this.tenantAuthentication = service; - } - - public void setTransactionHelper(RetryingTransactionHelper service) - { - this.retryingTransactionHelper = service; - } - - public void setValidAuthentictorKeys(Set validKeys) - { - if (validKeys != null) - { - Set trimmedKeys = new HashSet(); - for (String key : validKeys) - { - trimmedKeys.add(key.trim()); - } - validKeys = trimmedKeys; - } - this.validAuthenticatorKeys = validKeys; - } - - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(org.alfresco.web.scripts.servlet.WebScriptServletRequest, org.alfresco.web.scripts.servlet.WebScriptServletResponse) - */ - public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res) - { - return new PublicApiAuthenticator(req, res, new ProxyListener()); - } - - private Map getOutboundHeaders(TenantWebScriptServletRequest req) - { - Map outboundHeaders = new HashMap(); - for (String headerName : outboundHeaderNames) - { - String[] headerValues = req.getHeaderValues(headerName); - if (headerValues != null && headerValues.length > 0) - { - outboundHeaders.put(headerName, headerValues); - } - } - return outboundHeaders; - } - - /** - * Public api authentication with additional tenant applicability check - */ - public class PublicApiAuthenticator extends RemoteUserAuthenticator - { - // dependencies - private TenantWebScriptServletRequest servletReq; - - // Proxy listener used to receive initial authentication events from the base BasicHttpAuthenticator - private ProxyListener proxyListener; - - /** - * Construct - * - * @param req WebScriptServletRequest - * @param res WebScriptServletResponse - * @param proxyListener ProxyListener - */ - public PublicApiAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res, ProxyListener proxyListener) - { - super(req, res, proxyListener); - if (!(req instanceof TenantWebScriptServletRequest)) - { - throw new WebScriptException("Request is not a tenant aware request"); - } - servletReq = (TenantWebScriptServletRequest)req; - this.proxyListener = proxyListener; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean) - */ - public boolean authenticate(RequiredAuthentication required, boolean isGuest) - { - boolean authorized = false; - try - { - String authenticatorKey = servletReq.getHeader(authenticatorKeyHeader); - String remoteUser = getRemoteUser(); - if (authenticatorKey != null && remoteUser != null) - { - // Trusted auth. Validate key and setup authentication context. - authorized = authenticateViaGateway(required, isGuest, authenticatorKey, remoteUser); - } - else - { - // Fallback to parent authenticator - try - { - authorized = super.authenticate(required, isGuest); - } - catch (AuthenticationException ae) - { - // e.g. guest - if (logger.isDebugEnabled()) - logger.debug("TenantBasicHttpAuthenticator: required="+required+", isGuest="+isGuest+" - "+ae.getMessage()); - } - } - if (authorized) - { - // check tenant validity - final String tenant = servletReq.getTenant(); - final String email = AuthenticationUtil.getFullyAuthenticatedUser(); - try - { - authorized = retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() - { - public Boolean execute() throws Exception - { - return tenantAuthentication.authenticateTenant(email, tenant); - } - }, true, false); - } - finally - { - if (!authorized) - { - listener.authenticationFailed(new TenantCredentials(tenant, email, proxyListener.getOrignalCredentials())); - AuthenticationUtil.clearCurrentSecurityContext(); - } - else - { - listener.userAuthenticated(new TenantCredentials(tenant, email, proxyListener.getOrignalCredentials())); - } - } - } - return authorized; - } - finally - { - if (!authorized) - { - servletRes.setStatus(401); - servletRes.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco " + servletReq.getTenant() + " tenant\""); - } - } - } - - private boolean authenticateViaGateway(RequiredAuthentication required, boolean isGuest, String authenticatorKey, String remoteUser) - { - // Validate the authenticator key, and if valid set the fully authenticated user. - if (validAuthenticatorKeys.contains(authenticatorKey)) - { - AuthenticationUtil.setFullyAuthenticatedUser(remoteUser); - proxyListener.userAuthenticated(new PublicApiCredentials(authenticatorKey, remoteUser, getOutboundHeaders(servletReq))); - return true; - } - else - { - logger.error("Invalid authenticator key:- " + authenticatorKey); - proxyListener.authenticationFailed(new PublicApiCredentials(authenticatorKey, remoteUser, getOutboundHeaders(servletReq))); - return false; - } - } - } - - private class ProxyListener implements AuthenticationListener - { - private WebCredentials originalCredentials; - - @Override - public void userAuthenticated(WebCredentials credentials) - { - this.originalCredentials = credentials; - } - - @Override - public void authenticationFailed(WebCredentials credentials) - { - listener.authenticationFailed(credentials); - } - - @Override - public void authenticationFailed(WebCredentials credentials, Exception ex) - { - listener.authenticationFailed(credentials, ex); - } - - public WebCredentials getOrignalCredentials() - { - return this.originalCredentials; - } - } -} +package org.alfresco.rest.api; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.web.auth.AuthenticationListener; +import org.alfresco.repo.web.auth.TenantAuthentication; +import org.alfresco.repo.web.auth.WebCredentials; +import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; +import org.alfresco.repo.web.scripts.servlet.RemoteUserAuthenticatorFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Authenticator; +import org.springframework.extensions.webscripts.Description.RequiredAuthentication; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; +import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse; + +/** + * HTTP Basic Authentication for Public Api. + * + * Adapted from org.alfresco.module.org_alfresco_module_cloud.webscripts.TenantBasicHTTPAuthenticatorFactory. + * + * @author sglover + */ +public class PublicApiAuthenticatorFactory extends RemoteUserAuthenticatorFactory +{ + private static Log logger = LogFactory.getLog(PublicApiAuthenticatorFactory.class); + + public static final String DEFAULT_AUTHENTICATOR_KEY_HEADER = "X-Alfresco-Authenticator-Key"; + + private String authenticatorKeyHeader = DEFAULT_AUTHENTICATOR_KEY_HEADER; + private RetryingTransactionHelper retryingTransactionHelper; + private TenantAuthentication tenantAuthentication; + private Set validAuthenticatorKeys = Collections.emptySet(); + private Set outboundHeaderNames; + + public void setAuthenticatorKeyHeader(String authenticatorKeyHeader) + { + this.authenticatorKeyHeader = authenticatorKeyHeader; + } + + /** + * Set the headers passed to the gateway for authentication. + * + * @param outboundHeaders Set + */ + public void setOutboundHeaders(Set outboundHeaders) + { + if (outboundHeaders != null) + { + Set trimmed = new HashSet(); + for (String value : outboundHeaders) + { + trimmed.add(value.toLowerCase(Locale.ENGLISH).trim()); + } + outboundHeaders = trimmed; + } + + this.outboundHeaderNames = outboundHeaders; + } + + public void setTenantAuthentication(TenantAuthentication service) + { + this.tenantAuthentication = service; + } + + public void setTransactionHelper(RetryingTransactionHelper service) + { + this.retryingTransactionHelper = service; + } + + public void setValidAuthentictorKeys(Set validKeys) + { + if (validKeys != null) + { + Set trimmedKeys = new HashSet(); + for (String key : validKeys) + { + trimmedKeys.add(key.trim()); + } + validKeys = trimmedKeys; + } + this.validAuthenticatorKeys = validKeys; + } + + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(org.alfresco.web.scripts.servlet.WebScriptServletRequest, org.alfresco.web.scripts.servlet.WebScriptServletResponse) + */ + public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res) + { + return new PublicApiAuthenticator(req, res, new ProxyListener()); + } + + private Map getOutboundHeaders(TenantWebScriptServletRequest req) + { + Map outboundHeaders = new HashMap(); + for (String headerName : outboundHeaderNames) + { + String[] headerValues = req.getHeaderValues(headerName); + if (headerValues != null && headerValues.length > 0) + { + outboundHeaders.put(headerName, headerValues); + } + } + return outboundHeaders; + } + + /** + * Public api authentication with additional tenant applicability check + */ + public class PublicApiAuthenticator extends RemoteUserAuthenticator + { + // dependencies + private TenantWebScriptServletRequest servletReq; + + // Proxy listener used to receive initial authentication events from the base BasicHttpAuthenticator + private ProxyListener proxyListener; + + /** + * Construct + * + * @param req WebScriptServletRequest + * @param res WebScriptServletResponse + * @param proxyListener ProxyListener + */ + public PublicApiAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res, ProxyListener proxyListener) + { + super(req, res, proxyListener); + if (!(req instanceof TenantWebScriptServletRequest)) + { + throw new WebScriptException("Request is not a tenant aware request"); + } + servletReq = (TenantWebScriptServletRequest)req; + this.proxyListener = proxyListener; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean) + */ + public boolean authenticate(RequiredAuthentication required, boolean isGuest) + { + boolean authorized = false; + try + { + String authenticatorKey = servletReq.getHeader(authenticatorKeyHeader); + String remoteUser = getRemoteUser(); + if (authenticatorKey != null && remoteUser != null) + { + // Trusted auth. Validate key and setup authentication context. + authorized = authenticateViaGateway(required, isGuest, authenticatorKey, remoteUser); + } + else + { + // Fallback to parent authenticator + try + { + authorized = super.authenticate(required, isGuest); + } + catch (AuthenticationException ae) + { + // e.g. guest + if (logger.isDebugEnabled()) + logger.debug("TenantBasicHttpAuthenticator: required="+required+", isGuest="+isGuest+" - "+ae.getMessage()); + } + } + if (authorized) + { + // check tenant validity + final String tenant = servletReq.getTenant(); + final String email = AuthenticationUtil.getFullyAuthenticatedUser(); + try + { + authorized = retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public Boolean execute() throws Exception + { + return tenantAuthentication.authenticateTenant(email, tenant); + } + }, true, false); + } + finally + { + if (!authorized) + { + listener.authenticationFailed(new TenantCredentials(tenant, email, proxyListener.getOrignalCredentials())); + AuthenticationUtil.clearCurrentSecurityContext(); + } + else + { + listener.userAuthenticated(new TenantCredentials(tenant, email, proxyListener.getOrignalCredentials())); + } + } + } + return authorized; + } + finally + { + if (!authorized) + { + servletRes.setStatus(401); + servletRes.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco " + servletReq.getTenant() + " tenant\""); + } + } + } + + private boolean authenticateViaGateway(RequiredAuthentication required, boolean isGuest, String authenticatorKey, String remoteUser) + { + // Validate the authenticator key, and if valid set the fully authenticated user. + if (validAuthenticatorKeys.contains(authenticatorKey)) + { + AuthenticationUtil.setFullyAuthenticatedUser(remoteUser); + proxyListener.userAuthenticated(new PublicApiCredentials(authenticatorKey, remoteUser, getOutboundHeaders(servletReq))); + return true; + } + else + { + logger.error("Invalid authenticator key:- " + authenticatorKey); + proxyListener.authenticationFailed(new PublicApiCredentials(authenticatorKey, remoteUser, getOutboundHeaders(servletReq))); + return false; + } + } + } + + private class ProxyListener implements AuthenticationListener + { + private WebCredentials originalCredentials; + + @Override + public void userAuthenticated(WebCredentials credentials) + { + this.originalCredentials = credentials; + } + + @Override + public void authenticationFailed(WebCredentials credentials) + { + listener.authenticationFailed(credentials); + } + + @Override + public void authenticationFailed(WebCredentials credentials, Exception ex) + { + listener.authenticationFailed(credentials, ex); + } + + public WebCredentials getOrignalCredentials() + { + return this.originalCredentials; + } + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiDeclarativeRegistry.java b/source/java/org/alfresco/rest/api/PublicApiDeclarativeRegistry.java index 9d55099e5d..3989e29ba0 100644 --- a/source/java/org/alfresco/rest/api/PublicApiDeclarativeRegistry.java +++ b/source/java/org/alfresco/rest/api/PublicApiDeclarativeRegistry.java @@ -1,436 +1,436 @@ -package org.alfresco.rest.api; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.util.*; - -import org.alfresco.rest.api.authentications.AuthenticationTicketsEntityResource; -import org.alfresco.rest.framework.Api; -import org.alfresco.rest.framework.core.ResourceLocator; -import org.alfresco.rest.framework.core.ResourceWithMetadata; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; -import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction; -import org.alfresco.rest.framework.resource.actions.interfaces.ResourceAction; -import org.alfresco.rest.framework.tools.ApiAssistant; -import org.apache.commons.lang.StringUtils; -import org.springframework.extensions.webscripts.*; -import org.springframework.extensions.webscripts.Description.FormatStyle; -import org.springframework.extensions.webscripts.Description.RequiredAuthentication; -import org.springframework.extensions.webscripts.Description.RequiredTransaction; -import org.springframework.extensions.webscripts.Description.TransactionCapability; -import org.springframework.http.HttpMethod; - -/** - * - * @author steveglover - * @author janv - * @since PublicApi1.0 - */ -public class PublicApiDeclarativeRegistry extends DeclarativeRegistry -{ - private WebScript getNetworksWebScript; - private WebScript getNetworkWebScript; - private Container container; - - private ResourceLocator locator; - - public void setLocator(ResourceLocator locator) - { - this.locator = locator; - } - - public void setGetNetworksWebScript(WebScript getNetworksWebScript) - { - this.getNetworksWebScript = getNetworksWebScript; - } - - public void setGetNetworkWebScript(WebScript getNetworkWebScript) - { - this.getNetworkWebScript = getNetworkWebScript; - } - - public void setContainer(Container container) - { - super.setContainer(container); - this.container = container; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.Registry#findWebScript(java.lang.String, java.lang.String) - */ - public Match findWebScript(String method, String uri) - { - Match match; - - HttpMethod httpMethod = HttpMethod.valueOf(method); - if (HttpMethod.GET.equals(httpMethod)) - { - if (uri.equals(PublicApiTenantWebScriptServletRequest.NETWORKS_PATH)) - { - Map templateVars = new HashMap<>(); - templateVars.put("apiScope", "public"); - templateVars.put("apiVersion", "1"); - templateVars.put("apiName", "networks"); - match = new Match("", templateVars, "", getNetworksWebScript); - } - else if (uri.equals(PublicApiTenantWebScriptServletRequest.NETWORK_PATH)) - { - Map templateVars = new HashMap<>(); - templateVars.put("apiScope", "public"); - templateVars.put("apiVersion", "1"); - templateVars.put("apiName", "network"); - match = new Match("", templateVars, "", getNetworkWebScript); - } - else - { - match = super.findWebScript(method, uri); - if (match == null) - { - return null; - } - Map templateVars = match.getTemplateVars(); - ResourceWithMetadata rwm = getResourceWithMetadataOrNull(templateVars, httpMethod); - if (rwm != null) - { - Class resAction = null; - - String entityId = templateVars.get(ResourceLocator.ENTITY_ID); - String relationshipId = templateVars.get(ResourceLocator.RELATIONSHIP_ID); - - switch (rwm.getMetaData().getType()) - { - case ENTITY: - if (StringUtils.isNotBlank(entityId)) - { - if (EntityResourceAction.ReadById.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = EntityResourceAction.ReadById.class; - } - } - else - { - if (EntityResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = EntityResourceAction.Read.class; - } - } - break; - case PROPERTY: - if (StringUtils.isNotBlank(entityId)) - { - if (BinaryResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = BinaryResourceAction.Read.class; - } - else if (RelationshipResourceBinaryAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = RelationshipResourceBinaryAction.Read.class; - } - } - break; - case RELATIONSHIP: - if (StringUtils.isNotBlank(relationshipId)) - { - if (RelationshipResourceAction.ReadById.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = RelationshipResourceAction.ReadById.class; - } - } - else - { - if (RelationshipResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = RelationshipResourceAction.Read.class; - } - } - break; - default: - break; - } - - final boolean noAuth = (resAction != null && rwm.getMetaData().isNoAuth(resAction)); - if (noAuth) - { - // override match with noAuth - match = overrideMatch(match); - } - } - } - } - else if (HttpMethod.POST.equals(httpMethod)) - { - match = super.findWebScript(method, uri); - if (match != null && uri.endsWith(AuthenticationTicketsEntityResource.COLLECTION_RESOURCE_NAME)) - { - ResourceWithMetadata rwm = getResourceWithMetadataOrNull(match.getTemplateVars(), httpMethod); - if (rwm != null && AuthenticationTicketsEntityResource.class.equals(rwm.getResource().getClass())) - { - Class resAction = null; - if (EntityResourceAction.Create.class.isAssignableFrom(rwm.getResource().getClass())) - { - resAction = EntityResourceAction.Create.class; - } - final boolean noAuth = (resAction != null && rwm.getMetaData().isNoAuth(resAction)); - if (noAuth) - { - // override match with noAuth - match = overrideMatch(match); - } - } - } - } - else - { - match = super.findWebScript(method, uri); - } - - if (match == null) - { - throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[] {uri}); - } - return match; - } - - private ResourceWithMetadata getResourceWithMetadataOrNull(Map templateVars, HttpMethod method) - { - if (templateVars.get("apiName") != null) - { - // NOTE: noAuth currently only exposed for GET or Create Ticket (login) - Api api = ApiAssistant.determineApi(templateVars); - - // TODO can we avoid locating resource more than once (or at least provide a common code to determine the GET resourceAction) ? - return locator.locateResource(api, templateVars, method); - } - return null; - } - - private Match overrideMatch(final Match match) - { - // TODO is there a better way (to dynamically override "requiredAuthentication") or handle noAuth check earlier ? - WebScript noAuthWebScriptWrapper = new WebScript() - { - @Override - public void init(Container container, Description description) - { - match.getWebScript().init(container, description); - } - - @Override - public Description getDescription() - { - final Description d = match.getWebScript().getDescription(); - return new Description() - { - @Override - public String getStorePath() - { - return d.getStorePath(); - } - - @Override - public String getScriptPath() - { - return d.getScriptPath(); - } - - @Override - public Path getPackage() - { - return d.getPackage(); - } - - @Override - public String getDescPath() - { - return d.getDescPath(); - } - - @Override - public InputStream getDescDocument() throws IOException - { - return d.getDescDocument(); - } - - @Override - public String getKind() - { - return d.getKind(); - } - - @Override - public Set getFamilys() - { - return d.getFamilys(); - } - - @Override - public RequiredAuthentication getRequiredAuthentication() - { - return RequiredAuthentication.none; - } - - @Override - public String getRunAs() - { - return d.getRunAs(); - } - - @Override - public RequiredTransaction getRequiredTransaction() - { - return d.getRequiredTransaction(); - } - - @Override - public RequiredTransactionParameters getRequiredTransactionParameters() - { - return d.getRequiredTransactionParameters(); - } - - @Override - public RequiredCache getRequiredCache() - { - return d.getRequiredCache(); - } - - @Override - public String getMethod() - { - return d.getMethod(); - } - - @Override - public String[] getURIs() - { - return d.getURIs(); - } - - @Override - public FormatStyle getFormatStyle() - { - return d.getFormatStyle(); - } - - @Override - public String getDefaultFormat() - { - return d.getDefaultFormat(); - } - - @Override - public NegotiatedFormat[] getNegotiatedFormats() - { - return d.getNegotiatedFormats(); - } - - @Override - public Map getExtensions() - { - return d.getExtensions(); - } - - @Override - public Lifecycle getLifecycle() - { - return d.getLifecycle(); - } - - @Override - public boolean getMultipartProcessing() - { - return d.getMultipartProcessing(); - } - - @Override - public void setMultipartProcessing(boolean b) - { - d.setMultipartProcessing(b); - } - - @Override - public ArgumentTypeDescription[] getArguments() - { - return d.getArguments(); - } - - @Override - public TypeDescription[] getRequestTypes() - { - return d.getRequestTypes(); - } - - @Override - public TypeDescription[] getResponseTypes() - { - return d.getResponseTypes(); - } - - @Override - public String getId() - { - return d.getId(); - } - - @Override - public String getShortName() - { - return d.getShortName(); - } - - @Override - public String getDescription() - { - return d.getDescription(); - } - }; - } - - @Override - public ResourceBundle getResources() - { - return match.getWebScript().getResources(); - } - - @Override - public void execute(WebScriptRequest webScriptRequest, WebScriptResponse webScriptResponse) throws IOException - { - match.getWebScript().execute(webScriptRequest, webScriptResponse); - } - - @Override - public void setURLModelFactory(URLModelFactory urlModelFactory) - { - match.getWebScript().setURLModelFactory(urlModelFactory); - } - }; - - // override match with noAuth - return new Match(match.getTemplate(), match.getTemplateVars(), match.getPath(), noAuthWebScriptWrapper); - } - - private void initWebScript(WebScript webScript, String name) - { - DescriptionImpl serviceDesc = new DescriptionImpl(name, name, name, name); - serviceDesc.setRequiredAuthentication(RequiredAuthentication.user); - TransactionParameters transactionParameters = new TransactionParameters(); - transactionParameters.setRequired(RequiredTransaction.required); - transactionParameters.setCapability(TransactionCapability.readonly); - serviceDesc.setRequiredTransactionParameters(transactionParameters); - serviceDesc.setFormatStyle(FormatStyle.argument); - serviceDesc.setDefaultFormat("json"); - serviceDesc.setUris(new String[] { name }); - webScript.init(container, serviceDesc); - } - - public void reset() - { - super.reset(); - initWebScript(getNetworksWebScript, "networks"); - initWebScript(getNetworkWebScript, "network"); - } -} - +package org.alfresco.rest.api; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.*; + +import org.alfresco.rest.api.authentications.AuthenticationTicketsEntityResource; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.core.ResourceLocator; +import org.alfresco.rest.framework.core.ResourceWithMetadata; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction; +import org.alfresco.rest.framework.resource.actions.interfaces.ResourceAction; +import org.alfresco.rest.framework.tools.ApiAssistant; +import org.apache.commons.lang.StringUtils; +import org.springframework.extensions.webscripts.*; +import org.springframework.extensions.webscripts.Description.FormatStyle; +import org.springframework.extensions.webscripts.Description.RequiredAuthentication; +import org.springframework.extensions.webscripts.Description.RequiredTransaction; +import org.springframework.extensions.webscripts.Description.TransactionCapability; +import org.springframework.http.HttpMethod; + +/** + * + * @author steveglover + * @author janv + * @since PublicApi1.0 + */ +public class PublicApiDeclarativeRegistry extends DeclarativeRegistry +{ + private WebScript getNetworksWebScript; + private WebScript getNetworkWebScript; + private Container container; + + private ResourceLocator locator; + + public void setLocator(ResourceLocator locator) + { + this.locator = locator; + } + + public void setGetNetworksWebScript(WebScript getNetworksWebScript) + { + this.getNetworksWebScript = getNetworksWebScript; + } + + public void setGetNetworkWebScript(WebScript getNetworkWebScript) + { + this.getNetworkWebScript = getNetworkWebScript; + } + + public void setContainer(Container container) + { + super.setContainer(container); + this.container = container; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.Registry#findWebScript(java.lang.String, java.lang.String) + */ + public Match findWebScript(String method, String uri) + { + Match match; + + HttpMethod httpMethod = HttpMethod.valueOf(method); + if (HttpMethod.GET.equals(httpMethod)) + { + if (uri.equals(PublicApiTenantWebScriptServletRequest.NETWORKS_PATH)) + { + Map templateVars = new HashMap<>(); + templateVars.put("apiScope", "public"); + templateVars.put("apiVersion", "1"); + templateVars.put("apiName", "networks"); + match = new Match("", templateVars, "", getNetworksWebScript); + } + else if (uri.equals(PublicApiTenantWebScriptServletRequest.NETWORK_PATH)) + { + Map templateVars = new HashMap<>(); + templateVars.put("apiScope", "public"); + templateVars.put("apiVersion", "1"); + templateVars.put("apiName", "network"); + match = new Match("", templateVars, "", getNetworkWebScript); + } + else + { + match = super.findWebScript(method, uri); + if (match == null) + { + return null; + } + Map templateVars = match.getTemplateVars(); + ResourceWithMetadata rwm = getResourceWithMetadataOrNull(templateVars, httpMethod); + if (rwm != null) + { + Class resAction = null; + + String entityId = templateVars.get(ResourceLocator.ENTITY_ID); + String relationshipId = templateVars.get(ResourceLocator.RELATIONSHIP_ID); + + switch (rwm.getMetaData().getType()) + { + case ENTITY: + if (StringUtils.isNotBlank(entityId)) + { + if (EntityResourceAction.ReadById.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = EntityResourceAction.ReadById.class; + } + } + else + { + if (EntityResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = EntityResourceAction.Read.class; + } + } + break; + case PROPERTY: + if (StringUtils.isNotBlank(entityId)) + { + if (BinaryResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = BinaryResourceAction.Read.class; + } + else if (RelationshipResourceBinaryAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = RelationshipResourceBinaryAction.Read.class; + } + } + break; + case RELATIONSHIP: + if (StringUtils.isNotBlank(relationshipId)) + { + if (RelationshipResourceAction.ReadById.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = RelationshipResourceAction.ReadById.class; + } + } + else + { + if (RelationshipResourceAction.Read.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = RelationshipResourceAction.Read.class; + } + } + break; + default: + break; + } + + final boolean noAuth = (resAction != null && rwm.getMetaData().isNoAuth(resAction)); + if (noAuth) + { + // override match with noAuth + match = overrideMatch(match); + } + } + } + } + else if (HttpMethod.POST.equals(httpMethod)) + { + match = super.findWebScript(method, uri); + if (match != null && uri.endsWith(AuthenticationTicketsEntityResource.COLLECTION_RESOURCE_NAME)) + { + ResourceWithMetadata rwm = getResourceWithMetadataOrNull(match.getTemplateVars(), httpMethod); + if (rwm != null && AuthenticationTicketsEntityResource.class.equals(rwm.getResource().getClass())) + { + Class resAction = null; + if (EntityResourceAction.Create.class.isAssignableFrom(rwm.getResource().getClass())) + { + resAction = EntityResourceAction.Create.class; + } + final boolean noAuth = (resAction != null && rwm.getMetaData().isNoAuth(resAction)); + if (noAuth) + { + // override match with noAuth + match = overrideMatch(match); + } + } + } + } + else + { + match = super.findWebScript(method, uri); + } + + if (match == null) + { + throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[] {uri}); + } + return match; + } + + private ResourceWithMetadata getResourceWithMetadataOrNull(Map templateVars, HttpMethod method) + { + if (templateVars.get("apiName") != null) + { + // NOTE: noAuth currently only exposed for GET or Create Ticket (login) + Api api = ApiAssistant.determineApi(templateVars); + + // TODO can we avoid locating resource more than once (or at least provide a common code to determine the GET resourceAction) ? + return locator.locateResource(api, templateVars, method); + } + return null; + } + + private Match overrideMatch(final Match match) + { + // TODO is there a better way (to dynamically override "requiredAuthentication") or handle noAuth check earlier ? + WebScript noAuthWebScriptWrapper = new WebScript() + { + @Override + public void init(Container container, Description description) + { + match.getWebScript().init(container, description); + } + + @Override + public Description getDescription() + { + final Description d = match.getWebScript().getDescription(); + return new Description() + { + @Override + public String getStorePath() + { + return d.getStorePath(); + } + + @Override + public String getScriptPath() + { + return d.getScriptPath(); + } + + @Override + public Path getPackage() + { + return d.getPackage(); + } + + @Override + public String getDescPath() + { + return d.getDescPath(); + } + + @Override + public InputStream getDescDocument() throws IOException + { + return d.getDescDocument(); + } + + @Override + public String getKind() + { + return d.getKind(); + } + + @Override + public Set getFamilys() + { + return d.getFamilys(); + } + + @Override + public RequiredAuthentication getRequiredAuthentication() + { + return RequiredAuthentication.none; + } + + @Override + public String getRunAs() + { + return d.getRunAs(); + } + + @Override + public RequiredTransaction getRequiredTransaction() + { + return d.getRequiredTransaction(); + } + + @Override + public RequiredTransactionParameters getRequiredTransactionParameters() + { + return d.getRequiredTransactionParameters(); + } + + @Override + public RequiredCache getRequiredCache() + { + return d.getRequiredCache(); + } + + @Override + public String getMethod() + { + return d.getMethod(); + } + + @Override + public String[] getURIs() + { + return d.getURIs(); + } + + @Override + public FormatStyle getFormatStyle() + { + return d.getFormatStyle(); + } + + @Override + public String getDefaultFormat() + { + return d.getDefaultFormat(); + } + + @Override + public NegotiatedFormat[] getNegotiatedFormats() + { + return d.getNegotiatedFormats(); + } + + @Override + public Map getExtensions() + { + return d.getExtensions(); + } + + @Override + public Lifecycle getLifecycle() + { + return d.getLifecycle(); + } + + @Override + public boolean getMultipartProcessing() + { + return d.getMultipartProcessing(); + } + + @Override + public void setMultipartProcessing(boolean b) + { + d.setMultipartProcessing(b); + } + + @Override + public ArgumentTypeDescription[] getArguments() + { + return d.getArguments(); + } + + @Override + public TypeDescription[] getRequestTypes() + { + return d.getRequestTypes(); + } + + @Override + public TypeDescription[] getResponseTypes() + { + return d.getResponseTypes(); + } + + @Override + public String getId() + { + return d.getId(); + } + + @Override + public String getShortName() + { + return d.getShortName(); + } + + @Override + public String getDescription() + { + return d.getDescription(); + } + }; + } + + @Override + public ResourceBundle getResources() + { + return match.getWebScript().getResources(); + } + + @Override + public void execute(WebScriptRequest webScriptRequest, WebScriptResponse webScriptResponse) throws IOException + { + match.getWebScript().execute(webScriptRequest, webScriptResponse); + } + + @Override + public void setURLModelFactory(URLModelFactory urlModelFactory) + { + match.getWebScript().setURLModelFactory(urlModelFactory); + } + }; + + // override match with noAuth + return new Match(match.getTemplate(), match.getTemplateVars(), match.getPath(), noAuthWebScriptWrapper); + } + + private void initWebScript(WebScript webScript, String name) + { + DescriptionImpl serviceDesc = new DescriptionImpl(name, name, name, name); + serviceDesc.setRequiredAuthentication(RequiredAuthentication.user); + TransactionParameters transactionParameters = new TransactionParameters(); + transactionParameters.setRequired(RequiredTransaction.required); + transactionParameters.setCapability(TransactionCapability.readonly); + serviceDesc.setRequiredTransactionParameters(transactionParameters); + serviceDesc.setFormatStyle(FormatStyle.argument); + serviceDesc.setDefaultFormat("json"); + serviceDesc.setUris(new String[] { name }); + webScript.init(container, serviceDesc); + } + + public void reset() + { + super.reset(); + initWebScript(getNetworksWebScript, "networks"); + initWebScript(getNetworkWebScript, "network"); + } +} + diff --git a/source/java/org/alfresco/rest/api/PublicApiHttpServletRequest.java b/source/java/org/alfresco/rest/api/PublicApiHttpServletRequest.java index ff2fcd6628..99f865f6dd 100644 --- a/source/java/org/alfresco/rest/api/PublicApiHttpServletRequest.java +++ b/source/java/org/alfresco/rest/api/PublicApiHttpServletRequest.java @@ -1,90 +1,90 @@ - -package org.alfresco.rest.api; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - -public class PublicApiHttpServletRequest extends HttpServletRequestWrapper -{ - private static final String HEADER_CONTENT_TYPE = "Content-Type"; - public static final String MULTIPART_FORM_DATA = "multipart/form-data"; - - public PublicApiHttpServletRequest(HttpServletRequest request) throws IOException - { - super(getWrappedHttpServletRequest(request)); - } - - public void resetInputStream() throws IOException - { - ServletInputStream stream = getInputStream(); - if (stream.markSupported()) - { - stream.reset(); - } - } - - private static HttpServletRequest getWrappedHttpServletRequest(HttpServletRequest request) throws IOException - { - //TODO is it really necessary to wrap the request into a BufferedInputStream? - // If not, then we could remove the check for multipart upload. - // The check is needed as we get an IOException (Resetting to invalid mark) for files more than 8193 bytes. - boolean resetSupported = true; - String contentType = request.getHeader(HEADER_CONTENT_TYPE); - if (contentType != null && contentType.startsWith(MULTIPART_FORM_DATA)) - { - resetSupported = false; - } - final PublicApiServletInputStream sis = new PublicApiServletInputStream(request.getInputStream(), resetSupported); - HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) - { - public ServletInputStream getInputStream() throws java.io.IOException - { - return sis; - } - }; - return wrapper; - } - - private static class PublicApiServletInputStream extends ServletInputStream - { - private final InputStream in; - private final boolean resetSupported; - - PublicApiServletInputStream(InputStream in, boolean resetSupported) - { - this.resetSupported = resetSupported; - if (resetSupported) - { - this.in = new BufferedInputStream(in); - this.in.mark(8096); - } - else - { - this.in = in; - } - } - - @Override - public int read() throws IOException - { - return in.read(); - } - - @Override - public void reset() throws IOException - { - in.reset(); - } - - @Override - public boolean markSupported() - { - return resetSupported; - } - } -} + +package org.alfresco.rest.api; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class PublicApiHttpServletRequest extends HttpServletRequestWrapper +{ + private static final String HEADER_CONTENT_TYPE = "Content-Type"; + public static final String MULTIPART_FORM_DATA = "multipart/form-data"; + + public PublicApiHttpServletRequest(HttpServletRequest request) throws IOException + { + super(getWrappedHttpServletRequest(request)); + } + + public void resetInputStream() throws IOException + { + ServletInputStream stream = getInputStream(); + if (stream.markSupported()) + { + stream.reset(); + } + } + + private static HttpServletRequest getWrappedHttpServletRequest(HttpServletRequest request) throws IOException + { + //TODO is it really necessary to wrap the request into a BufferedInputStream? + // If not, then we could remove the check for multipart upload. + // The check is needed as we get an IOException (Resetting to invalid mark) for files more than 8193 bytes. + boolean resetSupported = true; + String contentType = request.getHeader(HEADER_CONTENT_TYPE); + if (contentType != null && contentType.startsWith(MULTIPART_FORM_DATA)) + { + resetSupported = false; + } + final PublicApiServletInputStream sis = new PublicApiServletInputStream(request.getInputStream(), resetSupported); + HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) + { + public ServletInputStream getInputStream() throws java.io.IOException + { + return sis; + } + }; + return wrapper; + } + + private static class PublicApiServletInputStream extends ServletInputStream + { + private final InputStream in; + private final boolean resetSupported; + + PublicApiServletInputStream(InputStream in, boolean resetSupported) + { + this.resetSupported = resetSupported; + if (resetSupported) + { + this.in = new BufferedInputStream(in); + this.in.mark(8096); + } + else + { + this.in = in; + } + } + + @Override + public int read() throws IOException + { + return in.read(); + } + + @Override + public void reset() throws IOException + { + in.reset(); + } + + @Override + public boolean markSupported() + { + return resetSupported; + } + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiRepositoryContainer.java b/source/java/org/alfresco/rest/api/PublicApiRepositoryContainer.java index 543a39ac0b..0cae16c230 100644 --- a/source/java/org/alfresco/rest/api/PublicApiRepositoryContainer.java +++ b/source/java/org/alfresco/rest/api/PublicApiRepositoryContainer.java @@ -1,106 +1,106 @@ -package org.alfresco.rest.api; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.web.scripts.TenantRepositoryContainer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.Authenticator; -import org.springframework.extensions.webscripts.WebScript; -import org.springframework.extensions.webscripts.WebScriptRequest; -import org.springframework.extensions.webscripts.WebScriptResponse; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; - -/** - * Repository (server-tier) container for public api - * - * @author steveglover - * @author davidc - */ -public class PublicApiRepositoryContainer extends TenantRepositoryContainer -{ - protected static final Log logger = LogFactory.getLog(PublicApiRepositoryContainer.class); - - /** - * Execute script within required level of transaction - */ - @Override - protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes) - throws IOException - { - final HttpServletRequest httpServletRequest = WebScriptServletRuntime.getHttpServletRequest(scriptReq); - if(httpServletRequest instanceof PublicApiHttpServletRequest) - { - // reset the request input stream if it has been read e.g. by getParameter - PublicApiHttpServletRequest publicApiRequest = (PublicApiHttpServletRequest)httpServletRequest; - publicApiRequest.resetInputStream(); - } - - super.transactionedExecute(script, scriptReq, scriptRes); - } - - @Override - public void executeScript(final WebScriptRequest scriptReq, final WebScriptResponse scriptRes, final Authenticator auth) - throws IOException - { - String tenant = ((PublicApiTenantWebScriptServletRequest)scriptReq).getTenant(); - if (tenant != null) - { - // handle special tenant keys - // -super- => run as system tenant - // -default- => run as user's default tenant - String user = null; - if (tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) - { - // switch from default to super tenant, if not authenticated - user = AuthenticationUtil.getFullyAuthenticatedUser(); - if (user == null) - { - tenant = TenantUtil.SYSTEM_TENANT; - } - } - - // run as super tenant - if (tenant.equalsIgnoreCase(TenantUtil.SYSTEM_TENANT)) - { - if (logger.isDebugEnabled()) - { - logger.debug("executeScript (-system-): ["+user+","+tenant+"] "+scriptReq.getServicePath()); - } - - TenantUtil.runAsTenant(new TenantRunAsWork() - { - public Object doWork() throws Exception - { - PublicApiRepositoryContainer.super.executeScript(scriptReq, scriptRes, auth); - return null; - - } - }, TenantService.DEFAULT_DOMAIN); - } - else - { - if (tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) - { - tenant = tenantAdminService.getUserDomain(user); - } - - // run as explicit tenant - TenantUtil.runAsTenant(new TenantRunAsWork() - { - public Object doWork() throws Exception - { - PublicApiRepositoryContainer.super.executeScript(scriptReq, scriptRes, auth); - return null; - } - }, tenant); - } - } - } -} +package org.alfresco.rest.api; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.web.scripts.TenantRepositoryContainer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Authenticator; +import org.springframework.extensions.webscripts.WebScript; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + +/** + * Repository (server-tier) container for public api + * + * @author steveglover + * @author davidc + */ +public class PublicApiRepositoryContainer extends TenantRepositoryContainer +{ + protected static final Log logger = LogFactory.getLog(PublicApiRepositoryContainer.class); + + /** + * Execute script within required level of transaction + */ + @Override + protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes) + throws IOException + { + final HttpServletRequest httpServletRequest = WebScriptServletRuntime.getHttpServletRequest(scriptReq); + if(httpServletRequest instanceof PublicApiHttpServletRequest) + { + // reset the request input stream if it has been read e.g. by getParameter + PublicApiHttpServletRequest publicApiRequest = (PublicApiHttpServletRequest)httpServletRequest; + publicApiRequest.resetInputStream(); + } + + super.transactionedExecute(script, scriptReq, scriptRes); + } + + @Override + public void executeScript(final WebScriptRequest scriptReq, final WebScriptResponse scriptRes, final Authenticator auth) + throws IOException + { + String tenant = ((PublicApiTenantWebScriptServletRequest)scriptReq).getTenant(); + if (tenant != null) + { + // handle special tenant keys + // -super- => run as system tenant + // -default- => run as user's default tenant + String user = null; + if (tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) + { + // switch from default to super tenant, if not authenticated + user = AuthenticationUtil.getFullyAuthenticatedUser(); + if (user == null) + { + tenant = TenantUtil.SYSTEM_TENANT; + } + } + + // run as super tenant + if (tenant.equalsIgnoreCase(TenantUtil.SYSTEM_TENANT)) + { + if (logger.isDebugEnabled()) + { + logger.debug("executeScript (-system-): ["+user+","+tenant+"] "+scriptReq.getServicePath()); + } + + TenantUtil.runAsTenant(new TenantRunAsWork() + { + public Object doWork() throws Exception + { + PublicApiRepositoryContainer.super.executeScript(scriptReq, scriptRes, auth); + return null; + + } + }, TenantService.DEFAULT_DOMAIN); + } + else + { + if (tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) + { + tenant = tenantAdminService.getUserDomain(user); + } + + // run as explicit tenant + TenantUtil.runAsTenant(new TenantRunAsWork() + { + public Object doWork() throws Exception + { + PublicApiRepositoryContainer.super.executeScript(scriptReq, scriptRes, auth); + return null; + } + }, tenant); + } + } + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiTenantAuthentication.java b/source/java/org/alfresco/rest/api/PublicApiTenantAuthentication.java index 29b5a4369c..5dd7e3326d 100644 --- a/source/java/org/alfresco/rest/api/PublicApiTenantAuthentication.java +++ b/source/java/org/alfresco/rest/api/PublicApiTenantAuthentication.java @@ -1,80 +1,80 @@ -package org.alfresco.rest.api; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.web.auth.TenantAuthentication; - -/** - * Authenticate current user against specified tenant (Enterprise) - * - * @author steveglover - */ -public class PublicApiTenantAuthentication implements TenantAuthentication -{ - private TenantAdminService tenantAdminService; - - public void setTenantAdminService(TenantAdminService service) - { - this.tenantAdminService = service; - } - - /** - * Determine whether tenant exists and enabled - * - * @param tenant String - * @return true => it exists, no it doesn't - */ - public boolean tenantExists(final String tenant) - { - if (tenant == null || TenantService.DEFAULT_DOMAIN.equalsIgnoreCase(tenant)) - { - return true; - } - - return AuthenticationUtil.runAsSystem(new RunAsWork() - { - public Boolean doWork() throws Exception - { - return tenantAdminService.existsTenant(tenant) && tenantAdminService.isEnabled(); - } - }); - } - - /** - * Authenticate user against network/tenant. - * - * @param username String - * @param networkId String - * @return true => authenticated, false => not authenticated - */ - public boolean authenticateTenant(String username, String networkId) - { - boolean authenticated = false; - - String userNetworkId = tenantAdminService.getUserDomain(username); - if(userNetworkId == null || userNetworkId.equals(TenantService.DEFAULT_DOMAIN)) - { - if(networkId.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT) || networkId.equalsIgnoreCase(TenantUtil.SYSTEM_TENANT)) - { - authenticated = true; - } - } - else - { - if(networkId.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) - { - networkId = userNetworkId; - } - - if(userNetworkId.equalsIgnoreCase(networkId)) - { - authenticated = tenantAdminService.isEnabledTenant(networkId); - } - } - - return authenticated; - } -} +package org.alfresco.rest.api; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.web.auth.TenantAuthentication; + +/** + * Authenticate current user against specified tenant (Enterprise) + * + * @author steveglover + */ +public class PublicApiTenantAuthentication implements TenantAuthentication +{ + private TenantAdminService tenantAdminService; + + public void setTenantAdminService(TenantAdminService service) + { + this.tenantAdminService = service; + } + + /** + * Determine whether tenant exists and enabled + * + * @param tenant String + * @return true => it exists, no it doesn't + */ + public boolean tenantExists(final String tenant) + { + if (tenant == null || TenantService.DEFAULT_DOMAIN.equalsIgnoreCase(tenant)) + { + return true; + } + + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + public Boolean doWork() throws Exception + { + return tenantAdminService.existsTenant(tenant) && tenantAdminService.isEnabled(); + } + }); + } + + /** + * Authenticate user against network/tenant. + * + * @param username String + * @param networkId String + * @return true => authenticated, false => not authenticated + */ + public boolean authenticateTenant(String username, String networkId) + { + boolean authenticated = false; + + String userNetworkId = tenantAdminService.getUserDomain(username); + if(userNetworkId == null || userNetworkId.equals(TenantService.DEFAULT_DOMAIN)) + { + if(networkId.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT) || networkId.equalsIgnoreCase(TenantUtil.SYSTEM_TENANT)) + { + authenticated = true; + } + } + else + { + if(networkId.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT)) + { + networkId = userNetworkId; + } + + if(userNetworkId.equalsIgnoreCase(networkId)) + { + authenticated = tenantAdminService.isEnabledTenant(networkId); + } + } + + return authenticated; + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java index ed103bd850..f97e4e804a 100644 --- a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java +++ b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java @@ -1,51 +1,51 @@ -package org.alfresco.rest.api; - -import javax.servlet.http.HttpServletRequest; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; -import org.springframework.extensions.config.ServerProperties; -import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.Runtime; - -public class PublicApiTenantWebScriptServletRequest extends TenantWebScriptServletRequest -{ - public static final String NETWORKS_PATH = "networks"; - public static final String NETWORK_PATH = "network"; - - public PublicApiTenantWebScriptServletRequest(Runtime container, HttpServletRequest req, Match serviceMatch, ServerProperties serverProperties) - { - super(container, req, serviceMatch, serverProperties); - } - - @Override - protected void parse() - { - String realPathInfo = getRealPathInfo(); - - if(realPathInfo.equals("") || realPathInfo.equals("/")) - { - // no tenant - "index" request - tenant = TenantUtil.DEFAULT_TENANT; - pathInfo = NETWORKS_PATH; - } - else - { - // optimisation - don't need to lowercase the whole path - if(realPathInfo.substring(0, 5).toLowerCase().equals("/cmis")) - { - // cmis service document, pass through as is and set tenant to "-default-". - tenant = TenantUtil.DEFAULT_TENANT; - pathInfo = realPathInfo; - } - else - { - int idx = realPathInfo.indexOf('/', 1); - - // remove tenant - tenant = realPathInfo.substring(1, idx == -1 ? realPathInfo.length() : idx); - pathInfo = realPathInfo.substring(tenant.length() + 1); - } - } - } -} +package org.alfresco.rest.api; + +import javax.servlet.http.HttpServletRequest; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest; +import org.springframework.extensions.config.ServerProperties; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.Runtime; + +public class PublicApiTenantWebScriptServletRequest extends TenantWebScriptServletRequest +{ + public static final String NETWORKS_PATH = "networks"; + public static final String NETWORK_PATH = "network"; + + public PublicApiTenantWebScriptServletRequest(Runtime container, HttpServletRequest req, Match serviceMatch, ServerProperties serverProperties) + { + super(container, req, serviceMatch, serverProperties); + } + + @Override + protected void parse() + { + String realPathInfo = getRealPathInfo(); + + if(realPathInfo.equals("") || realPathInfo.equals("/")) + { + // no tenant - "index" request + tenant = TenantUtil.DEFAULT_TENANT; + pathInfo = NETWORKS_PATH; + } + else + { + // optimisation - don't need to lowercase the whole path + if(realPathInfo.substring(0, 5).toLowerCase().equals("/cmis")) + { + // cmis service document, pass through as is and set tenant to "-default-". + tenant = TenantUtil.DEFAULT_TENANT; + pathInfo = realPathInfo; + } + else + { + int idx = realPathInfo.indexOf('/', 1); + + // remove tenant + tenant = realPathInfo.substring(1, idx == -1 ? realPathInfo.length() : idx); + pathInfo = realPathInfo.substring(tenant.length() + 1); + } + } + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java index 64025a4725..cdc8684495 100644 --- a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java +++ b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java @@ -1,128 +1,128 @@ -package org.alfresco.rest.api; - -import java.io.IOException; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.repo.web.scripts.TenantWebScriptServletRuntime; -import org.alfresco.rest.framework.tools.ApiAssistant; -import org.springframework.extensions.config.ServerProperties; -import org.springframework.extensions.surf.util.URLDecoder; -import org.springframework.extensions.webscripts.*; -import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory; - -public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServletRuntime -{ - private static final Pattern CMIS_URI_PATTERN = Pattern.compile(".*/cmis/versions/[0-9]+\\.[0-9]+/.*"); - private ApiAssistant apiAssistant; - - public PublicApiTenantWebScriptServletRuntime(RuntimeContainer container, ServletAuthenticatorFactory authFactory, HttpServletRequest req, - HttpServletResponse res, ServerProperties serverProperties, ApiAssistant apiAssistant) - { - super(container, authFactory, req, res, serverProperties); - this.apiAssistant = apiAssistant; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl() - */ - @Override - protected String getScriptUrl() - { - // NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat - final String requestURI = req.getRequestURI(); - final String serviceContextPath = req.getContextPath() + req.getServletPath(); - String pathInfo; - - if (serviceContextPath.length() > requestURI.length()) - { - // NOTE: assume a redirect has taken place e.g. tomcat welcome-page - // NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon - pathInfo = req.getPathInfo(); - } - // MNT-13057 fix, do not decode CMIS uris. - else if (CMIS_URI_PATTERN.matcher(requestURI).matches()) - { - pathInfo = requestURI.substring(serviceContextPath.length()); - } - else - { - pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length())); - } - - // NOTE: must contain at least root / and single character for tenant name - if (pathInfo.length() < 2 || pathInfo.equals("/")) - { - // url path has no tenant id -> get networks request - pathInfo = PublicApiTenantWebScriptServletRequest.NETWORKS_PATH; - } - else - { - if(!pathInfo.substring(0, 6).toLowerCase().equals("/cmis/")) - { - // remove tenant - int idx = pathInfo.indexOf('/', 1); - pathInfo = pathInfo.substring(idx == -1 ? pathInfo.length() : idx); - if(pathInfo.equals("") || pathInfo.equals("/")) - { - // url path is just a tenant id -> get network request - pathInfo = PublicApiTenantWebScriptServletRequest.NETWORK_PATH; - } - } - } - - return pathInfo; - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch) - */ - @Override - protected WebScriptRequest createRequest(Match match) - { -// try -// { - // make the request input stream a BufferedInputStream so that the first x bytes can be reused. -// PublicApiHttpServletRequest wrapped = new PublicApiHttpServletRequest(req); - - // TODO: construct org.springframework.extensions.webscripts.servlet.WebScriptServletResponse when - // org.alfresco.web.scripts.WebScriptServletResponse (deprecated) is removed - servletReq = new PublicApiTenantWebScriptServletRequest(this, req, match, serverProperties); - return servletReq; -// } -// catch(IOException e) -// { -// throw new AlfrescoRuntimeException("", e); -// } - } - - /* (non-Javadoc) - * @see org.alfresco.web.scripts.WebScriptContainer#getName() - */ - public String getName() - { - return "PublicApiTenantServletRuntime"; - } - - @Override - protected void renderErrorResponse(Match match, Throwable exception, WebScriptRequest request, WebScriptResponse response) { - - //If its cmis or not an exception then use the default behaviour - if (CMIS_URI_PATTERN.matcher(req.getRequestURI()).matches() || !(exception instanceof Exception)) - { - super.renderErrorResponse(match, exception, request, response); - } - else - { - try { - apiAssistant.renderException((Exception)exception, response); - } catch (IOException e) { - logger.error("Internal error", e); - throw new WebScriptException("Internal error", e); - } - } - - } -} +package org.alfresco.rest.api; + +import java.io.IOException; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.web.scripts.TenantWebScriptServletRuntime; +import org.alfresco.rest.framework.tools.ApiAssistant; +import org.springframework.extensions.config.ServerProperties; +import org.springframework.extensions.surf.util.URLDecoder; +import org.springframework.extensions.webscripts.*; +import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory; + +public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServletRuntime +{ + private static final Pattern CMIS_URI_PATTERN = Pattern.compile(".*/cmis/versions/[0-9]+\\.[0-9]+/.*"); + private ApiAssistant apiAssistant; + + public PublicApiTenantWebScriptServletRuntime(RuntimeContainer container, ServletAuthenticatorFactory authFactory, HttpServletRequest req, + HttpServletResponse res, ServerProperties serverProperties, ApiAssistant apiAssistant) + { + super(container, authFactory, req, res, serverProperties); + this.apiAssistant = apiAssistant; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl() + */ + @Override + protected String getScriptUrl() + { + // NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat + final String requestURI = req.getRequestURI(); + final String serviceContextPath = req.getContextPath() + req.getServletPath(); + String pathInfo; + + if (serviceContextPath.length() > requestURI.length()) + { + // NOTE: assume a redirect has taken place e.g. tomcat welcome-page + // NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon + pathInfo = req.getPathInfo(); + } + // MNT-13057 fix, do not decode CMIS uris. + else if (CMIS_URI_PATTERN.matcher(requestURI).matches()) + { + pathInfo = requestURI.substring(serviceContextPath.length()); + } + else + { + pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length())); + } + + // NOTE: must contain at least root / and single character for tenant name + if (pathInfo.length() < 2 || pathInfo.equals("/")) + { + // url path has no tenant id -> get networks request + pathInfo = PublicApiTenantWebScriptServletRequest.NETWORKS_PATH; + } + else + { + if(!pathInfo.substring(0, 6).toLowerCase().equals("/cmis/")) + { + // remove tenant + int idx = pathInfo.indexOf('/', 1); + pathInfo = pathInfo.substring(idx == -1 ? pathInfo.length() : idx); + if(pathInfo.equals("") || pathInfo.equals("/")) + { + // url path is just a tenant id -> get network request + pathInfo = PublicApiTenantWebScriptServletRequest.NETWORK_PATH; + } + } + } + + return pathInfo; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch) + */ + @Override + protected WebScriptRequest createRequest(Match match) + { +// try +// { + // make the request input stream a BufferedInputStream so that the first x bytes can be reused. +// PublicApiHttpServletRequest wrapped = new PublicApiHttpServletRequest(req); + + // TODO: construct org.springframework.extensions.webscripts.servlet.WebScriptServletResponse when + // org.alfresco.web.scripts.WebScriptServletResponse (deprecated) is removed + servletReq = new PublicApiTenantWebScriptServletRequest(this, req, match, serverProperties); + return servletReq; +// } +// catch(IOException e) +// { +// throw new AlfrescoRuntimeException("", e); +// } + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptContainer#getName() + */ + public String getName() + { + return "PublicApiTenantServletRuntime"; + } + + @Override + protected void renderErrorResponse(Match match, Throwable exception, WebScriptRequest request, WebScriptResponse response) { + + //If its cmis or not an exception then use the default behaviour + if (CMIS_URI_PATTERN.matcher(req.getRequestURI()).matches() || !(exception instanceof Exception)) + { + super.renderErrorResponse(match, exception, request, response); + } + else + { + try { + apiAssistant.renderException((Exception)exception, response); + } catch (IOException e) { + logger.error("Internal error", e); + throw new WebScriptException("Internal error", e); + } + } + + } +} diff --git a/source/java/org/alfresco/rest/api/PublicApiWebScriptServlet.java b/source/java/org/alfresco/rest/api/PublicApiWebScriptServlet.java index be11bedf8f..709bdc0903 100644 --- a/source/java/org/alfresco/rest/api/PublicApiWebScriptServlet.java +++ b/source/java/org/alfresco/rest/api/PublicApiWebScriptServlet.java @@ -1,45 +1,45 @@ -package org.alfresco.rest.api; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.repo.web.scripts.TenantWebScriptServlet; -import org.alfresco.rest.framework.tools.ApiAssistant; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.webscripts.RuntimeContainer; -import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; -import org.springframework.web.context.support.WebApplicationContextUtils; - -public class PublicApiWebScriptServlet extends TenantWebScriptServlet -{ - private static final long serialVersionUID = 726730674397482039L; - private ApiAssistant apiAssistant; - @Override - public void init() throws ServletException - { - super.init(); - - ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); - container = (RuntimeContainer)context.getBean("publicapi.container"); - apiAssistant = (ApiAssistant) context.getBean("apiAssistant"); - } - - /* (non-Javadoc) - * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException - { - // make the request input stream a BufferedInputStream so that the first x bytes can be reused. - PublicApiHttpServletRequest wrapped = new PublicApiHttpServletRequest(req); - super.service(wrapped, res); - } - - protected WebScriptServletRuntime getRuntime(HttpServletRequest req, HttpServletResponse res) - { - WebScriptServletRuntime runtime = new PublicApiTenantWebScriptServletRuntime(container, authenticatorFactory, req, res, serverProperties, apiAssistant); - return runtime; - } -} +package org.alfresco.rest.api; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.web.scripts.TenantWebScriptServlet; +import org.alfresco.rest.framework.tools.ApiAssistant; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.webscripts.RuntimeContainer; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; +import org.springframework.web.context.support.WebApplicationContextUtils; + +public class PublicApiWebScriptServlet extends TenantWebScriptServlet +{ + private static final long serialVersionUID = 726730674397482039L; + private ApiAssistant apiAssistant; + @Override + public void init() throws ServletException + { + super.init(); + + ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); + container = (RuntimeContainer)context.getBean("publicapi.container"); + apiAssistant = (ApiAssistant) context.getBean("apiAssistant"); + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + // make the request input stream a BufferedInputStream so that the first x bytes can be reused. + PublicApiHttpServletRequest wrapped = new PublicApiHttpServletRequest(req); + super.service(wrapped, res); + } + + protected WebScriptServletRuntime getRuntime(HttpServletRequest req, HttpServletResponse res) + { + WebScriptServletRuntime runtime = new PublicApiTenantWebScriptServletRuntime(container, authenticatorFactory, req, res, serverProperties, apiAssistant); + return runtime; + } +} diff --git a/source/java/org/alfresco/rest/api/SiteMembershipRequests.java b/source/java/org/alfresco/rest/api/SiteMembershipRequests.java index 65dc4f0fbe..4ca0f63ca3 100644 --- a/source/java/org/alfresco/rest/api/SiteMembershipRequests.java +++ b/source/java/org/alfresco/rest/api/SiteMembershipRequests.java @@ -1,56 +1,56 @@ -package org.alfresco.rest.api; - -import org.alfresco.rest.api.model.SiteMembershipRequest; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -/** - * Public REST API: centralises access to site membership requests and maps between representations. - * - * @author steveglover - * - */ -public interface SiteMembershipRequests -{ - /** - * Create a site membership request for the user 'inviteeId' - * @param inviteeId the site inviteee id - * @param siteInvite the site invite - * @return SiteMembershipRequest - */ - SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); - - /** - * Update the site membership request for inviteeId and site - * @param inviteeId the site inviteee id - * @param siteInvite the site invite - * @return the updated siteMembershipRequest - */ - SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); - - /** - * Cancel site membership request for invitee and site. - * - * @param inviteeId the site inviteee id - * @param siteId the site id - */ - void cancelSiteMembershipRequest(String inviteeId, String siteId); - - /** - * Get the site membership request for inviteeId and siteId, if it exists. - * - * @param inviteeId the site inviteee id - * @param siteId the site id - * @return the site membership request - */ - SiteMembershipRequest getSiteMembershipRequest(String inviteeId, String siteId); - - /** - * Get a paged list of site membership requests for inviteeId. - * - * @param inviteeId the site inviteee id - * @param paging paging information - * @return a paged list of site membership requests - */ - CollectionWithPagingInfo getPagedSiteMembershipRequests(String inviteeId, Paging paging); -} +package org.alfresco.rest.api; + +import org.alfresco.rest.api.model.SiteMembershipRequest; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +/** + * Public REST API: centralises access to site membership requests and maps between representations. + * + * @author steveglover + * + */ +public interface SiteMembershipRequests +{ + /** + * Create a site membership request for the user 'inviteeId' + * @param inviteeId the site inviteee id + * @param siteInvite the site invite + * @return SiteMembershipRequest + */ + SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); + + /** + * Update the site membership request for inviteeId and site + * @param inviteeId the site inviteee id + * @param siteInvite the site invite + * @return the updated siteMembershipRequest + */ + SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite); + + /** + * Cancel site membership request for invitee and site. + * + * @param inviteeId the site inviteee id + * @param siteId the site id + */ + void cancelSiteMembershipRequest(String inviteeId, String siteId); + + /** + * Get the site membership request for inviteeId and siteId, if it exists. + * + * @param inviteeId the site inviteee id + * @param siteId the site id + * @return the site membership request + */ + SiteMembershipRequest getSiteMembershipRequest(String inviteeId, String siteId); + + /** + * Get a paged list of site membership requests for inviteeId. + * + * @param inviteeId the site inviteee id + * @param paging paging information + * @return a paged list of site membership requests + */ + CollectionWithPagingInfo getPagedSiteMembershipRequests(String inviteeId, Paging paging); +} diff --git a/source/java/org/alfresco/rest/api/Sites.java b/source/java/org/alfresco/rest/api/Sites.java index 4899ceeb52..01c588bcbe 100644 --- a/source/java/org/alfresco/rest/api/Sites.java +++ b/source/java/org/alfresco/rest/api/Sites.java @@ -1,51 +1,51 @@ -package org.alfresco.rest.api; - -import org.alfresco.query.PagingResults; -import org.alfresco.rest.api.model.FavouriteSite; -import org.alfresco.rest.api.model.MemberOfSite; -import org.alfresco.rest.api.model.Site; -import org.alfresco.rest.api.model.SiteContainer; -import org.alfresco.rest.api.model.SiteMember; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteInfo; - -public interface Sites -{ - SiteInfo validateSite(String siteShortName); - SiteInfo validateSite(NodeRef nodeRef); - CollectionWithPagingInfo getSiteMembers(String siteShortName, Parameters parameters); - Site getSite(String siteId); - void deleteSite(String siteId, Parameters parameters); - Site createSite(Site site, Parameters parameters); - - /** - * people//sites/ - * - * @param personId String - * @param siteShortName String - * @return MemberOfSite - */ - MemberOfSite getMemberOfSite(String personId, String siteShortName); - SiteMember getSiteMember(String personId, String siteShortName); - SiteMember addSiteMember(String siteShortName, SiteMember siteMember); - void removeSiteMember(String personId, String siteId); - SiteMember updateSiteMember(String siteShortName, SiteMember siteMember); - CollectionWithPagingInfo getSites(String personId, Parameters parameters); - SiteContainer getSiteContainer(String siteShortName, String containerId); - PagingResults getSiteContainers(String siteShortName, Paging paging); - CollectionWithPagingInfo getSites(Parameters parameters); - FavouriteSite getFavouriteSite(String personId, String siteShortName); - void addFavouriteSite(String personId, FavouriteSite favouriteSite); - void removeFavouriteSite(String personId, String siteId); - CollectionWithPagingInfo getFavouriteSites(String personId, Parameters parameters); - - String getSiteRole(String siteId); - String getSiteRole(String siteId, String personId); - - String PARAM_PERMANENT = "permanent"; - String PARAM_SKIP_ADDTOFAVORITES = "skipAddToFavorites"; - String PARAM_SKIP_SURF_CONFIGURATION = "skipConfiguration"; -} +package org.alfresco.rest.api; + +import org.alfresco.query.PagingResults; +import org.alfresco.rest.api.model.FavouriteSite; +import org.alfresco.rest.api.model.MemberOfSite; +import org.alfresco.rest.api.model.Site; +import org.alfresco.rest.api.model.SiteContainer; +import org.alfresco.rest.api.model.SiteMember; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteInfo; + +public interface Sites +{ + SiteInfo validateSite(String siteShortName); + SiteInfo validateSite(NodeRef nodeRef); + CollectionWithPagingInfo getSiteMembers(String siteShortName, Parameters parameters); + Site getSite(String siteId); + void deleteSite(String siteId, Parameters parameters); + Site createSite(Site site, Parameters parameters); + + /** + * people//sites/ + * + * @param personId String + * @param siteShortName String + * @return MemberOfSite + */ + MemberOfSite getMemberOfSite(String personId, String siteShortName); + SiteMember getSiteMember(String personId, String siteShortName); + SiteMember addSiteMember(String siteShortName, SiteMember siteMember); + void removeSiteMember(String personId, String siteId); + SiteMember updateSiteMember(String siteShortName, SiteMember siteMember); + CollectionWithPagingInfo getSites(String personId, Parameters parameters); + SiteContainer getSiteContainer(String siteShortName, String containerId); + PagingResults getSiteContainers(String siteShortName, Paging paging); + CollectionWithPagingInfo getSites(Parameters parameters); + FavouriteSite getFavouriteSite(String personId, String siteShortName); + void addFavouriteSite(String personId, FavouriteSite favouriteSite); + void removeFavouriteSite(String personId, String siteId); + CollectionWithPagingInfo getFavouriteSites(String personId, Parameters parameters); + + String getSiteRole(String siteId); + String getSiteRole(String siteId, String personId); + + String PARAM_PERMANENT = "permanent"; + String PARAM_SKIP_ADDTOFAVORITES = "skipAddToFavorites"; + String PARAM_SKIP_SURF_CONFIGURATION = "skipConfiguration"; +} diff --git a/source/java/org/alfresco/rest/api/Tags.java b/source/java/org/alfresco/rest/api/Tags.java index b1ce1848b2..efadfb89a9 100644 --- a/source/java/org/alfresco/rest/api/Tags.java +++ b/source/java/org/alfresco/rest/api/Tags.java @@ -1,19 +1,19 @@ -package org.alfresco.rest.api; - -import java.util.List; - -import org.alfresco.rest.api.model.Tag; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.repository.StoreRef; - -public interface Tags -{ - public List addTags(String nodeId, List tags); - public Tag getTag(StoreRef storeRef, String tagId); - public void deleteTag(String nodeId, String tagId); - public CollectionWithPagingInfo getTags(StoreRef storeRef, Paging paging); - public Tag changeTag(StoreRef storeRef, String tagId, Tag tag); - public CollectionWithPagingInfo getTags(String nodeId, Parameters params); -} +package org.alfresco.rest.api; + +import java.util.List; + +import org.alfresco.rest.api.model.Tag; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.repository.StoreRef; + +public interface Tags +{ + public List addTags(String nodeId, List tags); + public Tag getTag(StoreRef storeRef, String tagId); + public void deleteTag(String nodeId, String tagId); + public CollectionWithPagingInfo getTags(StoreRef storeRef, Paging paging); + public Tag changeTag(StoreRef storeRef, String tagId, Tag tag); + public CollectionWithPagingInfo getTags(String nodeId, Parameters params); +} diff --git a/source/java/org/alfresco/rest/api/impl/ActivitiesImpl.java b/source/java/org/alfresco/rest/api/impl/ActivitiesImpl.java index 4547027afa..8d26022101 100644 --- a/source/java/org/alfresco/rest/api/impl/ActivitiesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/ActivitiesImpl.java @@ -1,157 +1,157 @@ -package org.alfresco.rest.api.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.domain.activities.ActivityFeedEntity; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.rest.api.Activities; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.impl.activities.ActivitySummaryParser; -import org.alfresco.rest.api.model.Activity; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.activities.ActivityService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.json.JSONException; - -/** - * Centralises access to activities services and maps between representations. - * - * @author steveglover - * - */ -public class ActivitiesImpl implements Activities -{ - private static final String ACTIVITIES_FORMAT = "json"; - - private People people; - private ActivityService activityService; - private ActivitySummaryParser activitySummaryParser; - private TenantService tenantService; - private Sites sites; - - public void setSites(Sites sites) - { - this.sites = sites; - } - - public void setPeople(People people) - { - this.people = people; - } - - public void setTenantService(TenantService tenantService) - { - this.tenantService = tenantService; - } - - public void setActivityService(ActivityService activityService) - { - this.activityService = activityService; - } - - public void setActivitySummaryParser(ActivitySummaryParser activitySummaryParser) - { - this.activitySummaryParser = activitySummaryParser; - } - - public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException - { - Map activitySummary = activitySummaryParser.parse(entity.getActivityType(), entity.getActivitySummary()); - return activitySummary; - } - - private String getSiteId(String siteNetwork) - { - String siteId = siteNetwork; - - int idx = siteNetwork.lastIndexOf(TenantService.SEPARATOR); - if(idx != -1) - { - siteId = siteNetwork.substring(idx + 1); - } - - return siteId; - } - - public CollectionWithPagingInfo getUserActivities(String personId, final Parameters parameters) - { - personId = people.validatePerson(personId); - - Paging paging = parameters.getPaging(); - String siteId = parameters.getParameter("siteId"); - String who = parameters.getParameter("who"); - ActivityWho activityWho = null; - if(who != null) - { - try - { - activityWho = ActivityWho.valueOf(who); - } - catch(IllegalArgumentException e) - { - throw new InvalidArgumentException("Parameter who should be one of " + Arrays.toString(ActivityWho.values())); - } - } - - if(siteId != null && !siteId.equals("")) - { - SiteInfo siteInfo = sites.validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - } - - try - { - PagingResults activities = null; - - if(activityWho == null) - { - activities = activityService.getPagedUserFeedEntries(personId, siteId, false, false, -1, Util.getPagingRequest(paging)); - } - else if(activityWho.equals(ActivityWho.me)) - { - activities = activityService.getPagedUserFeedEntries(personId, siteId, false, true, -1, Util.getPagingRequest(paging)); - } - else if(activityWho.equals(ActivityWho.others)) - { - activities = activityService.getPagedUserFeedEntries(personId, siteId, true, false, -1, Util.getPagingRequest(paging)); - } - else - { - throw new InvalidArgumentException("Who argument is invalid."); - } - - List feedEntities = activities.getPage(); - List ret = new ArrayList(feedEntities.size()); - for(ActivityFeedEntity entity : feedEntities) - { - String feedSiteId = getSiteId(entity.getSiteNetwork()); - String networkId = tenantService.getDomain(entity.getSiteNetwork()); - Activity activity = new Activity(entity.getId(), networkId, feedSiteId, entity.getFeedUserId(), entity.getPostUserId(), - entity.getPostDate(), entity.getActivityType(), getActivitySummary(entity)); - ret.add(activity); - } - - return CollectionWithPagingInfo.asPaged(paging, ret, activities.hasMoreItems(), activities.getTotalResultCount().getFirst()); - } - catch(JSONException e) - { - throw new AlfrescoRuntimeException("", e); - } - } -} +package org.alfresco.rest.api.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.rest.api.Activities; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.impl.activities.ActivitySummaryParser; +import org.alfresco.rest.api.model.Activity; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.json.JSONException; + +/** + * Centralises access to activities services and maps between representations. + * + * @author steveglover + * + */ +public class ActivitiesImpl implements Activities +{ + private static final String ACTIVITIES_FORMAT = "json"; + + private People people; + private ActivityService activityService; + private ActivitySummaryParser activitySummaryParser; + private TenantService tenantService; + private Sites sites; + + public void setSites(Sites sites) + { + this.sites = sites; + } + + public void setPeople(People people) + { + this.people = people; + } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + public void setActivityService(ActivityService activityService) + { + this.activityService = activityService; + } + + public void setActivitySummaryParser(ActivitySummaryParser activitySummaryParser) + { + this.activitySummaryParser = activitySummaryParser; + } + + public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException + { + Map activitySummary = activitySummaryParser.parse(entity.getActivityType(), entity.getActivitySummary()); + return activitySummary; + } + + private String getSiteId(String siteNetwork) + { + String siteId = siteNetwork; + + int idx = siteNetwork.lastIndexOf(TenantService.SEPARATOR); + if(idx != -1) + { + siteId = siteNetwork.substring(idx + 1); + } + + return siteId; + } + + public CollectionWithPagingInfo getUserActivities(String personId, final Parameters parameters) + { + personId = people.validatePerson(personId); + + Paging paging = parameters.getPaging(); + String siteId = parameters.getParameter("siteId"); + String who = parameters.getParameter("who"); + ActivityWho activityWho = null; + if(who != null) + { + try + { + activityWho = ActivityWho.valueOf(who); + } + catch(IllegalArgumentException e) + { + throw new InvalidArgumentException("Parameter who should be one of " + Arrays.toString(ActivityWho.values())); + } + } + + if(siteId != null && !siteId.equals("")) + { + SiteInfo siteInfo = sites.validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + } + + try + { + PagingResults activities = null; + + if(activityWho == null) + { + activities = activityService.getPagedUserFeedEntries(personId, siteId, false, false, -1, Util.getPagingRequest(paging)); + } + else if(activityWho.equals(ActivityWho.me)) + { + activities = activityService.getPagedUserFeedEntries(personId, siteId, false, true, -1, Util.getPagingRequest(paging)); + } + else if(activityWho.equals(ActivityWho.others)) + { + activities = activityService.getPagedUserFeedEntries(personId, siteId, true, false, -1, Util.getPagingRequest(paging)); + } + else + { + throw new InvalidArgumentException("Who argument is invalid."); + } + + List feedEntities = activities.getPage(); + List ret = new ArrayList(feedEntities.size()); + for(ActivityFeedEntity entity : feedEntities) + { + String feedSiteId = getSiteId(entity.getSiteNetwork()); + String networkId = tenantService.getDomain(entity.getSiteNetwork()); + Activity activity = new Activity(entity.getId(), networkId, feedSiteId, entity.getFeedUserId(), entity.getPostUserId(), + entity.getPostDate(), entity.getActivityType(), getActivitySummary(entity)); + ret.add(activity); + } + + return CollectionWithPagingInfo.asPaged(paging, ret, activities.hasMoreItems(), activities.getTotalResultCount().getFirst()); + } + catch(JSONException e) + { + throw new AlfrescoRuntimeException("", e); + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/CommentsImpl.java b/source/java/org/alfresco/rest/api/impl/CommentsImpl.java index 6bc6e4a987..c928a807e4 100644 --- a/source/java/org/alfresco/rest/api/impl/CommentsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/CommentsImpl.java @@ -1,230 +1,230 @@ -package org.alfresco.rest.api.impl; - -import java.io.Serializable; -import java.util.AbstractList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.model.ContentModel; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.forum.CommentService; -import org.alfresco.rest.api.Comments; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.model.Comment; -import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockStatus; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.TypeConstraint; - -/** - * Centralises access to comment services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class CommentsImpl implements Comments -{ - private Nodes nodes; - private NodeService nodeService; - private CommentService commentService; - private ContentService contentService; - private LockService lockService; - private PermissionService permissionService; - private TypeConstraint typeConstraint; - - public void setTypeConstraint(TypeConstraint typeConstraint) - { - this.typeConstraint = typeConstraint; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setLockService(LockService lockService) - { - this.lockService = lockService; - } - - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setCommentService(CommentService commentService) - { - this.commentService = commentService; - } - - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - - private Comment toComment(NodeRef nodeRef, NodeRef commentNodeRef) - { - Map nodeProps = nodeService.getProperties(commentNodeRef); - - ContentReader reader = contentService.getReader(commentNodeRef, ContentModel.PROP_CONTENT); - if(reader != null) - { - String content = reader.getContentString(); - nodeProps.put(Comment.PROP_COMMENT_CONTENT, content); - nodeProps.remove(ContentModel.PROP_CONTENT); - } - - boolean canEdit = true; - boolean canDelete = true; - - boolean isNodeLocked = false; - boolean isWorkingCopy = false; - - if(nodeRef != null) - { - Set aspects = nodeService.getAspects(nodeRef); - - isWorkingCopy = aspects.contains(ContentModel.ASPECT_WORKING_COPY); - if(!isWorkingCopy) - { - if(aspects.contains(ContentModel.ASPECT_LOCKABLE)) - { - LockStatus lockStatus = lockService.getLockStatus(nodeRef); - if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER) - { - isNodeLocked = true; - } - } - } - } - - if(isNodeLocked || isWorkingCopy) - { - canEdit = false; - canDelete = false; - } - else - { - canEdit = permissionService.hasPermission(commentNodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED; - canDelete = permissionService.hasPermission(commentNodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED; - } - - Comment comment = new Comment(commentNodeRef.getId(), nodeProps, canEdit, canDelete); - return comment; - } - - public Comment createComment(String nodeId, Comment comment) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - - if(!typeConstraint.matches(nodeRef)) - { - throw new UnsupportedResourceOperationException("Cannot comment on this node"); - } - - try - { - NodeRef commentNode = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false); - return toComment(nodeRef, commentNode); - } - catch(IllegalArgumentException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - public Comment updateComment(String nodeId, Comment comment) - { - try - { - NodeRef nodeRef = nodes.validateNode(nodeId); - String commentNodeId = comment.getId(); - NodeRef commentNodeRef = nodes.validateNode(commentNodeId); - - String title = comment.getTitle(); - String content = comment.getContent(); - - if(content == null) - { - throw new InvalidArgumentException(); - } - - commentService.updateComment(commentNodeRef, title, content); - return toComment(nodeRef, commentNodeRef); - } - catch(IllegalArgumentException e) - { - throw new ConstraintViolatedException(e.getMessage()); - } - } - - public CollectionWithPagingInfo getComments(String nodeId, Paging paging) - { - final NodeRef nodeRef = nodes.validateNode(nodeId); - - /* MNT-10536 : fix */ - final Set contentAndFolders = - new HashSet(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT)); - if (!nodes.nodeMatches(nodeRef, contentAndFolders, null)) - { - throw new InvalidArgumentException("NodeId of folder or content is expected"); - } - - PagingRequest pagingRequest = Util.getPagingRequest(paging); - final PagingResults pagingResults = commentService.listComments(nodeRef, pagingRequest); - - final List page = pagingResults.getPage(); - List comments = new AbstractList() - { - @Override - public Comment get(int index) - { - return toComment(nodeRef, page.get(index)); - } - - @Override - public int size() - { - return page.size(); - } - }; - - return CollectionWithPagingInfo.asPaged(paging, comments, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst()); - } - - @Override - // TODO validate that it is a comment of the node - public void deleteComment(String nodeId, String commentNodeId) - { - try - { - nodes.validateNode(nodeId); - NodeRef commentNodeRef = nodes.validateNode(commentNodeId); - commentService.deleteComment(commentNodeRef); - } - catch(IllegalArgumentException e) - { - throw new ConstraintViolatedException(e.getMessage()); - } - } -} +package org.alfresco.rest.api.impl; + +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.forum.CommentService; +import org.alfresco.rest.api.Comments; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.model.Comment; +import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockStatus; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.TypeConstraint; + +/** + * Centralises access to comment services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class CommentsImpl implements Comments +{ + private Nodes nodes; + private NodeService nodeService; + private CommentService commentService; + private ContentService contentService; + private LockService lockService; + private PermissionService permissionService; + private TypeConstraint typeConstraint; + + public void setTypeConstraint(TypeConstraint typeConstraint) + { + this.typeConstraint = typeConstraint; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setLockService(LockService lockService) + { + this.lockService = lockService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setCommentService(CommentService commentService) + { + this.commentService = commentService; + } + + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + private Comment toComment(NodeRef nodeRef, NodeRef commentNodeRef) + { + Map nodeProps = nodeService.getProperties(commentNodeRef); + + ContentReader reader = contentService.getReader(commentNodeRef, ContentModel.PROP_CONTENT); + if(reader != null) + { + String content = reader.getContentString(); + nodeProps.put(Comment.PROP_COMMENT_CONTENT, content); + nodeProps.remove(ContentModel.PROP_CONTENT); + } + + boolean canEdit = true; + boolean canDelete = true; + + boolean isNodeLocked = false; + boolean isWorkingCopy = false; + + if(nodeRef != null) + { + Set aspects = nodeService.getAspects(nodeRef); + + isWorkingCopy = aspects.contains(ContentModel.ASPECT_WORKING_COPY); + if(!isWorkingCopy) + { + if(aspects.contains(ContentModel.ASPECT_LOCKABLE)) + { + LockStatus lockStatus = lockService.getLockStatus(nodeRef); + if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER) + { + isNodeLocked = true; + } + } + } + } + + if(isNodeLocked || isWorkingCopy) + { + canEdit = false; + canDelete = false; + } + else + { + canEdit = permissionService.hasPermission(commentNodeRef, PermissionService.WRITE) == AccessStatus.ALLOWED; + canDelete = permissionService.hasPermission(commentNodeRef, PermissionService.DELETE) == AccessStatus.ALLOWED; + } + + Comment comment = new Comment(commentNodeRef.getId(), nodeProps, canEdit, canDelete); + return comment; + } + + public Comment createComment(String nodeId, Comment comment) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + + if(!typeConstraint.matches(nodeRef)) + { + throw new UnsupportedResourceOperationException("Cannot comment on this node"); + } + + try + { + NodeRef commentNode = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false); + return toComment(nodeRef, commentNode); + } + catch(IllegalArgumentException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + public Comment updateComment(String nodeId, Comment comment) + { + try + { + NodeRef nodeRef = nodes.validateNode(nodeId); + String commentNodeId = comment.getId(); + NodeRef commentNodeRef = nodes.validateNode(commentNodeId); + + String title = comment.getTitle(); + String content = comment.getContent(); + + if(content == null) + { + throw new InvalidArgumentException(); + } + + commentService.updateComment(commentNodeRef, title, content); + return toComment(nodeRef, commentNodeRef); + } + catch(IllegalArgumentException e) + { + throw new ConstraintViolatedException(e.getMessage()); + } + } + + public CollectionWithPagingInfo getComments(String nodeId, Paging paging) + { + final NodeRef nodeRef = nodes.validateNode(nodeId); + + /* MNT-10536 : fix */ + final Set contentAndFolders = + new HashSet(Arrays.asList(ContentModel.TYPE_FOLDER, ContentModel.TYPE_CONTENT)); + if (!nodes.nodeMatches(nodeRef, contentAndFolders, null)) + { + throw new InvalidArgumentException("NodeId of folder or content is expected"); + } + + PagingRequest pagingRequest = Util.getPagingRequest(paging); + final PagingResults pagingResults = commentService.listComments(nodeRef, pagingRequest); + + final List page = pagingResults.getPage(); + List comments = new AbstractList() + { + @Override + public Comment get(int index) + { + return toComment(nodeRef, page.get(index)); + } + + @Override + public int size() + { + return page.size(); + } + }; + + return CollectionWithPagingInfo.asPaged(paging, comments, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst()); + } + + @Override + // TODO validate that it is a comment of the node + public void deleteComment(String nodeId, String commentNodeId) + { + try + { + nodes.validateNode(nodeId); + NodeRef commentNodeRef = nodes.validateNode(commentNodeId); + commentService.deleteComment(commentNodeRef); + } + catch(IllegalArgumentException e) + { + throw new ConstraintViolatedException(e.getMessage()); + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/DefaultExceptionHandler.java b/source/java/org/alfresco/rest/api/impl/DefaultExceptionHandler.java index 553d304973..b018ef3322 100644 --- a/source/java/org/alfresco/rest/api/impl/DefaultExceptionHandler.java +++ b/source/java/org/alfresco/rest/api/impl/DefaultExceptionHandler.java @@ -1,30 +1,30 @@ -package org.alfresco.rest.api.impl; - -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; - -/** - * Translates access denied exceptions from the service layer to API not found exception. - * - * @author steveglover - * - */ -public class DefaultExceptionHandler implements ExceptionHandler -{ - @Override - public boolean handle(Throwable t) - { - if(t instanceof AccessDeniedException) - { - // Note: security, no message to indicate why - throw new NotFoundException(); - } - else if(t instanceof PermissionDeniedException) - { - // Note: security, no message to indicate why - throw new NotFoundException(); - } - return false; - } -} +package org.alfresco.rest.api.impl; + +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; + +/** + * Translates access denied exceptions from the service layer to API not found exception. + * + * @author steveglover + * + */ +public class DefaultExceptionHandler implements ExceptionHandler +{ + @Override + public boolean handle(Throwable t) + { + if(t instanceof AccessDeniedException) + { + // Note: security, no message to indicate why + throw new NotFoundException(); + } + else if(t instanceof PermissionDeniedException) + { + // Note: security, no message to indicate why + throw new NotFoundException(); + } + return false; + } +} diff --git a/source/java/org/alfresco/rest/api/impl/ExceptionHandler.java b/source/java/org/alfresco/rest/api/impl/ExceptionHandler.java index 178db3f821..59144a373c 100644 --- a/source/java/org/alfresco/rest/api/impl/ExceptionHandler.java +++ b/source/java/org/alfresco/rest/api/impl/ExceptionHandler.java @@ -1,6 +1,6 @@ -package org.alfresco.rest.api.impl; - -public interface ExceptionHandler -{ - boolean handle(Throwable t); -} +package org.alfresco.rest.api.impl; + +public interface ExceptionHandler +{ + boolean handle(Throwable t); +} diff --git a/source/java/org/alfresco/rest/api/impl/ExceptionInterceptor.java b/source/java/org/alfresco/rest/api/impl/ExceptionInterceptor.java index d3c74da8ff..dd6090121f 100644 --- a/source/java/org/alfresco/rest/api/impl/ExceptionInterceptor.java +++ b/source/java/org/alfresco/rest/api/impl/ExceptionInterceptor.java @@ -1,46 +1,46 @@ -package org.alfresco.rest.api.impl; - -import java.util.List; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -/** - * An interceptor that catches exceptions and handlers them in some way, possibly by re-throwing as a different exception. - * - * @author steveglover - * - */ -public class ExceptionInterceptor implements MethodInterceptor -{ - private List exceptionHandlers; - - public void setExceptionHandlers(List exceptionHandlers) - { - this.exceptionHandlers = exceptionHandlers; - } - - public ExceptionInterceptor() - { - super(); - } - - public Object invoke(MethodInvocation mi) throws Throwable - { - try - { - return mi.proceed(); - } - catch(Throwable t) - { - for(ExceptionHandler handler : exceptionHandlers) - { - if(handler.handle(t)) - { - break; - } - } - throw t; - } - } -} +package org.alfresco.rest.api.impl; + +import java.util.List; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * An interceptor that catches exceptions and handlers them in some way, possibly by re-throwing as a different exception. + * + * @author steveglover + * + */ +public class ExceptionInterceptor implements MethodInterceptor +{ + private List exceptionHandlers; + + public void setExceptionHandlers(List exceptionHandlers) + { + this.exceptionHandlers = exceptionHandlers; + } + + public ExceptionInterceptor() + { + super(); + } + + public Object invoke(MethodInvocation mi) throws Throwable + { + try + { + return mi.proceed(); + } + catch(Throwable t) + { + for(ExceptionHandler handler : exceptionHandlers) + { + if(handler.handle(t)) + { + break; + } + } + throw t; + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/ExcludedTypes.java b/source/java/org/alfresco/rest/api/impl/ExcludedTypes.java index b8b3834efd..3f4ce849cd 100644 --- a/source/java/org/alfresco/rest/api/impl/ExcludedTypes.java +++ b/source/java/org/alfresco/rest/api/impl/ExcludedTypes.java @@ -1,91 +1,91 @@ -package org.alfresco.rest.api.impl; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.alfresco.opencmis.dictionary.QNameFilter; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.namespace.QName; - -/** - * Stores a set of excluded types, by full type name. The localName can be a wildcard (*) to indicate that the - * whole namespace should be excluded. - * - * @author steveglover - * - */ -public class ExcludedTypes -{ - private List expectedTypes; - private QNameFilter excludedTypes; - private NodeService nodeService; - - public void setExpectedTypes(List expectedTypes) - { - if(expectedTypes != null && expectedTypes.size() > 0) - { - this.expectedTypes = new ArrayList(expectedTypes.size()); - - for(String type : expectedTypes) - { - final QName typeDef = QName.createQName(type); - this.expectedTypes.add(typeDef); - } - } - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setExcludedTypes(QNameFilter excludedTypes) - { - this.excludedTypes = excludedTypes; - } - - public boolean isExcluded(final NodeRef nodeRef) - { - boolean excluded = false; - - QName nodeType = nodeService.getType(nodeRef); - if(expectedTypes != null && !expectedTypes.contains(nodeType)) - { - excluded = true; - } - - if(!excluded) - { - // need to run as system - caller may not be able to read the node's aspects - // but we need to know what they are in order to determine exclusion. - excluded = TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Boolean doWork() throws Exception - { - boolean excluded = false; - - // the node is a content node. Make sure it doesn't have an aspect in the excluded list. - Set aspects = new HashSet(nodeService.getAspects(nodeRef)); - for(QName aspect : aspects) - { - if(excludedTypes.isExcluded(aspect)) - { - excluded = true; - break; - } - } - - return excluded; - } - }, TenantUtil.getCurrentDomain()); - } - - return excluded; - } -} +package org.alfresco.rest.api.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.opencmis.dictionary.QNameFilter; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; + +/** + * Stores a set of excluded types, by full type name. The localName can be a wildcard (*) to indicate that the + * whole namespace should be excluded. + * + * @author steveglover + * + */ +public class ExcludedTypes +{ + private List expectedTypes; + private QNameFilter excludedTypes; + private NodeService nodeService; + + public void setExpectedTypes(List expectedTypes) + { + if(expectedTypes != null && expectedTypes.size() > 0) + { + this.expectedTypes = new ArrayList(expectedTypes.size()); + + for(String type : expectedTypes) + { + final QName typeDef = QName.createQName(type); + this.expectedTypes.add(typeDef); + } + } + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setExcludedTypes(QNameFilter excludedTypes) + { + this.excludedTypes = excludedTypes; + } + + public boolean isExcluded(final NodeRef nodeRef) + { + boolean excluded = false; + + QName nodeType = nodeService.getType(nodeRef); + if(expectedTypes != null && !expectedTypes.contains(nodeType)) + { + excluded = true; + } + + if(!excluded) + { + // need to run as system - caller may not be able to read the node's aspects + // but we need to know what they are in order to determine exclusion. + excluded = TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + boolean excluded = false; + + // the node is a content node. Make sure it doesn't have an aspect in the excluded list. + Set aspects = new HashSet(nodeService.getAspects(nodeRef)); + for(QName aspect : aspects) + { + if(excludedTypes.isExcluded(aspect)) + { + excluded = true; + break; + } + } + + return excluded; + } + }, TenantUtil.getCurrentDomain()); + } + + return excluded; + } +} diff --git a/source/java/org/alfresco/rest/api/impl/FavouritesImpl.java b/source/java/org/alfresco/rest/api/impl/FavouritesImpl.java index 6e8e29277f..a37142110f 100644 --- a/source/java/org/alfresco/rest/api/impl/FavouritesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/FavouritesImpl.java @@ -1,325 +1,325 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.impl; - -import java.util.AbstractList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.favourites.PersonFavourite; -import org.alfresco.repo.site.SiteDoesNotExistException; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.rest.api.Favourites; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.Document; -import org.alfresco.rest.api.model.DocumentTarget; -import org.alfresco.rest.api.model.Favourite; -import org.alfresco.rest.api.model.Folder; -import org.alfresco.rest.api.model.FolderTarget; -import org.alfresco.rest.api.model.Site; -import org.alfresco.rest.api.model.SiteTarget; -import org.alfresco.rest.api.model.Target; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; -import org.alfresco.rest.framework.resource.parameters.where.QueryHelper.WalkerCallbackAdapter; -import org.alfresco.service.cmr.favourites.FavouritesService; -import org.alfresco.service.cmr.favourites.FavouritesService.Type; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.util.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Public REST API: Centralises access to favourites functionality and maps between representations repository and api representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class FavouritesImpl implements Favourites -{ - private static final Log logger = LogFactory.getLog(FavouritesImpl.class); - - private People people; - private Sites sites; - private Nodes nodes; - private FavouritesService favouritesService; - private SiteService siteService; - - public void setPeople(People people) - { - this.people = people; - } - - public void setSites(Sites sites) - { - this.sites = sites; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setFavouritesService(FavouritesService favouritesService) - { - this.favouritesService = favouritesService; - } - - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - private Target getTarget(PersonFavourite personFavourite) - { - Target target = null; - NodeRef nodeRef = personFavourite.getNodeRef(); - Type type = personFavourite.getType(); - if(type.equals(Type.FILE)) - { - Document document = nodes.getDocument(nodeRef); - target = new DocumentTarget(document); - } - else if(type.equals(Type.FOLDER)) - { - Folder folder = nodes.getFolder(nodeRef); - target = new FolderTarget(folder); - } - else if(type.equals(Type.SITE)) - { - SiteInfo siteInfo = siteService.getSite(nodeRef); - String role = sites.getSiteRole(siteInfo.getShortName()); - Site site = new Site(siteInfo, role); - target = new SiteTarget(site); - } - else - { - throw new AlfrescoRuntimeException("Unexpected favourite target type: " + type); - } - - return target; - } - - private Favourite getFavourite(PersonFavourite personFavourite) - { - Favourite fav = new Favourite(); - fav.setTargetGuid(personFavourite.getNodeRef().getId()); - fav.setCreatedAt(personFavourite.getCreatedAt()); - Target target = getTarget(personFavourite); - fav.setTarget(target); - return fav; - } - - private CollectionWithPagingInfo wrap(Paging paging, PagingResults personFavourites) - { - final List page = personFavourites.getPage(); - final List list = new AbstractList() - { - @Override - public Favourite get(int index) - { - PersonFavourite personFavourite = page.get(index); - Favourite fav = getFavourite(personFavourite); - return fav; - } - - @Override - public int size() - { - return page.size(); - } - }; - Pair pair = personFavourites.getTotalResultCount(); - Integer total = null; - if(pair.getFirst().equals(pair.getSecond())) - { - total = pair.getFirst(); - } - return CollectionWithPagingInfo.asPaged(paging, list, personFavourites.hasMoreItems(), total); - } - - @Override - public Favourite addFavourite(String personId, Favourite favourite) - { - Favourite ret = null; - - personId = people.validatePerson(personId, true); - Target target = favourite.getTarget(); - if(target == null) - { - throw new InvalidArgumentException("target is missing"); - } - else if(target instanceof SiteTarget) - { - SiteTarget siteTarget = (SiteTarget)target; - String guid = siteTarget.getSite().getGuid(); - SiteInfo siteInfo = sites.validateSite(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, guid)); - NodeRef siteNodeRef = siteInfo.getNodeRef(); - String siteId = siteInfo.getShortName(); - - try - { - PersonFavourite personFavourite = favouritesService.addFavourite(personId, siteNodeRef); - ret = getFavourite(personFavourite); - } - catch(SiteDoesNotExistException e) - { - throw new RelationshipResourceNotFoundException(personId, siteId); - } - } - else if(target instanceof DocumentTarget) - { - DocumentTarget documentTarget = (DocumentTarget)target; - NodeRef nodeRef = documentTarget.getFile().getGuid(); - if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) - { - throw new RelationshipResourceNotFoundException(personId, nodeRef.getId()); - } - - PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef); - ret = getFavourite(personFavourite); - } - else if(target instanceof FolderTarget) - { - FolderTarget folderTarget = (FolderTarget)target; - NodeRef nodeRef = folderTarget.getFolder().getGuid(); - if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE))) - { - throw new RelationshipResourceNotFoundException(personId, nodeRef.getId()); - } - - PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef); - ret = getFavourite(personFavourite); - } - - return ret; - } - - @Override - public void removeFavourite(String personId, String id) - { - personId = people.validatePerson(personId, true); - NodeRef nodeRef = nodes.validateNode(id); - boolean exists = false; - - Type type = favouritesService.getType(nodeRef); - if(type.equals(Type.SITE)) - { - SiteInfo siteInfo = siteService.getSite(nodeRef); - if(siteInfo == null) - { - // shouldn't happen because the type implies it's a site - throw new AlfrescoRuntimeException("Unable to find site with nodeRef " + nodeRef); - } - exists = favouritesService.removeFavourite(personId, siteInfo.getNodeRef()); - } - else if(type.equals(Type.FILE)) - { - exists = favouritesService.removeFavourite(personId, nodeRef); - } - else if(type.equals(Type.FOLDER)) - { - exists = favouritesService.removeFavourite(personId, nodeRef); - } - if(!exists) - { - throw new RelationshipResourceNotFoundException(personId, id); - } - } - - public Favourite getFavourite(String personId, String favouriteId) - { - NodeRef nodeRef = nodes.validateNode(favouriteId); - personId = people.validatePerson(personId, true); - - PersonFavourite personFavourite = favouritesService.getFavourite(personId, nodeRef); - if(personFavourite != null) - { - Favourite favourite = getFavourite(personFavourite); - return favourite; - } - else - { - throw new RelationshipResourceNotFoundException(personId, favouriteId); - } - } - - @Override - public CollectionWithPagingInfo getFavourites(String personId, final Parameters parameters) - { - personId = people.validatePerson(personId, true); - - Paging paging = parameters.getPaging(); - - final Set filteredByClientQuery = new HashSet(); - Set filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; //Default all - - // filterType is of the form 'target.' - QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter() - { - @Override - public void or() { - //OR is supported but exists() will be called for each EXISTS so we don't - //need to do anything here. If we don't override it then it will be assumed - //that OR in the grammar is not supported. - } - - @Override - public void exists(String filteredByClient, boolean negated) { - if(filteredByClient != null) - { - int idx = filteredByClient.lastIndexOf("/"); - if(idx == -1 || idx == filteredByClient.length()) - { - throw new InvalidArgumentException(); - } - else - { - String filtertype = filteredByClient.substring(idx + 1).toUpperCase(); - filteredByClientQuery.add(Type.valueOf(filtertype)); - } - } - - } - }); - - if (filteredByClientQuery.size() > 0) - { - filterTypes = filteredByClientQuery; - } - - final PagingResults favourites = favouritesService.getPagedFavourites(personId, filterTypes, FavouritesService.DEFAULT_SORT_PROPS, - Util.getPagingRequest(paging)); - return wrap(paging, favourites); - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.impl; + +import java.util.AbstractList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.favourites.PersonFavourite; +import org.alfresco.repo.site.SiteDoesNotExistException; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.rest.api.Favourites; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.Document; +import org.alfresco.rest.api.model.DocumentTarget; +import org.alfresco.rest.api.model.Favourite; +import org.alfresco.rest.api.model.Folder; +import org.alfresco.rest.api.model.FolderTarget; +import org.alfresco.rest.api.model.Site; +import org.alfresco.rest.api.model.SiteTarget; +import org.alfresco.rest.api.model.Target; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; +import org.alfresco.rest.framework.resource.parameters.where.QueryHelper.WalkerCallbackAdapter; +import org.alfresco.service.cmr.favourites.FavouritesService; +import org.alfresco.service.cmr.favourites.FavouritesService.Type; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Public REST API: Centralises access to favourites functionality and maps between representations repository and api representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class FavouritesImpl implements Favourites +{ + private static final Log logger = LogFactory.getLog(FavouritesImpl.class); + + private People people; + private Sites sites; + private Nodes nodes; + private FavouritesService favouritesService; + private SiteService siteService; + + public void setPeople(People people) + { + this.people = people; + } + + public void setSites(Sites sites) + { + this.sites = sites; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setFavouritesService(FavouritesService favouritesService) + { + this.favouritesService = favouritesService; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + private Target getTarget(PersonFavourite personFavourite) + { + Target target = null; + NodeRef nodeRef = personFavourite.getNodeRef(); + Type type = personFavourite.getType(); + if(type.equals(Type.FILE)) + { + Document document = nodes.getDocument(nodeRef); + target = new DocumentTarget(document); + } + else if(type.equals(Type.FOLDER)) + { + Folder folder = nodes.getFolder(nodeRef); + target = new FolderTarget(folder); + } + else if(type.equals(Type.SITE)) + { + SiteInfo siteInfo = siteService.getSite(nodeRef); + String role = sites.getSiteRole(siteInfo.getShortName()); + Site site = new Site(siteInfo, role); + target = new SiteTarget(site); + } + else + { + throw new AlfrescoRuntimeException("Unexpected favourite target type: " + type); + } + + return target; + } + + private Favourite getFavourite(PersonFavourite personFavourite) + { + Favourite fav = new Favourite(); + fav.setTargetGuid(personFavourite.getNodeRef().getId()); + fav.setCreatedAt(personFavourite.getCreatedAt()); + Target target = getTarget(personFavourite); + fav.setTarget(target); + return fav; + } + + private CollectionWithPagingInfo wrap(Paging paging, PagingResults personFavourites) + { + final List page = personFavourites.getPage(); + final List list = new AbstractList() + { + @Override + public Favourite get(int index) + { + PersonFavourite personFavourite = page.get(index); + Favourite fav = getFavourite(personFavourite); + return fav; + } + + @Override + public int size() + { + return page.size(); + } + }; + Pair pair = personFavourites.getTotalResultCount(); + Integer total = null; + if(pair.getFirst().equals(pair.getSecond())) + { + total = pair.getFirst(); + } + return CollectionWithPagingInfo.asPaged(paging, list, personFavourites.hasMoreItems(), total); + } + + @Override + public Favourite addFavourite(String personId, Favourite favourite) + { + Favourite ret = null; + + personId = people.validatePerson(personId, true); + Target target = favourite.getTarget(); + if(target == null) + { + throw new InvalidArgumentException("target is missing"); + } + else if(target instanceof SiteTarget) + { + SiteTarget siteTarget = (SiteTarget)target; + String guid = siteTarget.getSite().getGuid(); + SiteInfo siteInfo = sites.validateSite(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, guid)); + NodeRef siteNodeRef = siteInfo.getNodeRef(); + String siteId = siteInfo.getShortName(); + + try + { + PersonFavourite personFavourite = favouritesService.addFavourite(personId, siteNodeRef); + ret = getFavourite(personFavourite); + } + catch(SiteDoesNotExistException e) + { + throw new RelationshipResourceNotFoundException(personId, siteId); + } + } + else if(target instanceof DocumentTarget) + { + DocumentTarget documentTarget = (DocumentTarget)target; + NodeRef nodeRef = documentTarget.getFile().getGuid(); + if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) + { + throw new RelationshipResourceNotFoundException(personId, nodeRef.getId()); + } + + PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef); + ret = getFavourite(personFavourite); + } + else if(target instanceof FolderTarget) + { + FolderTarget folderTarget = (FolderTarget)target; + NodeRef nodeRef = folderTarget.getFolder().getGuid(); + if(!nodes.nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), Collections.singleton(SiteModel.TYPE_SITE))) + { + throw new RelationshipResourceNotFoundException(personId, nodeRef.getId()); + } + + PersonFavourite personFavourite = favouritesService.addFavourite(personId, nodeRef); + ret = getFavourite(personFavourite); + } + + return ret; + } + + @Override + public void removeFavourite(String personId, String id) + { + personId = people.validatePerson(personId, true); + NodeRef nodeRef = nodes.validateNode(id); + boolean exists = false; + + Type type = favouritesService.getType(nodeRef); + if(type.equals(Type.SITE)) + { + SiteInfo siteInfo = siteService.getSite(nodeRef); + if(siteInfo == null) + { + // shouldn't happen because the type implies it's a site + throw new AlfrescoRuntimeException("Unable to find site with nodeRef " + nodeRef); + } + exists = favouritesService.removeFavourite(personId, siteInfo.getNodeRef()); + } + else if(type.equals(Type.FILE)) + { + exists = favouritesService.removeFavourite(personId, nodeRef); + } + else if(type.equals(Type.FOLDER)) + { + exists = favouritesService.removeFavourite(personId, nodeRef); + } + if(!exists) + { + throw new RelationshipResourceNotFoundException(personId, id); + } + } + + public Favourite getFavourite(String personId, String favouriteId) + { + NodeRef nodeRef = nodes.validateNode(favouriteId); + personId = people.validatePerson(personId, true); + + PersonFavourite personFavourite = favouritesService.getFavourite(personId, nodeRef); + if(personFavourite != null) + { + Favourite favourite = getFavourite(personFavourite); + return favourite; + } + else + { + throw new RelationshipResourceNotFoundException(personId, favouriteId); + } + } + + @Override + public CollectionWithPagingInfo getFavourites(String personId, final Parameters parameters) + { + personId = people.validatePerson(personId, true); + + Paging paging = parameters.getPaging(); + + final Set filteredByClientQuery = new HashSet(); + Set filterTypes = FavouritesService.Type.ALL_FILTER_TYPES; //Default all + + // filterType is of the form 'target.' + QueryHelper.walk(parameters.getQuery(), new WalkerCallbackAdapter() + { + @Override + public void or() { + //OR is supported but exists() will be called for each EXISTS so we don't + //need to do anything here. If we don't override it then it will be assumed + //that OR in the grammar is not supported. + } + + @Override + public void exists(String filteredByClient, boolean negated) { + if(filteredByClient != null) + { + int idx = filteredByClient.lastIndexOf("/"); + if(idx == -1 || idx == filteredByClient.length()) + { + throw new InvalidArgumentException(); + } + else + { + String filtertype = filteredByClient.substring(idx + 1).toUpperCase(); + filteredByClientQuery.add(Type.valueOf(filtertype)); + } + } + + } + }); + + if (filteredByClientQuery.size() > 0) + { + filterTypes = filteredByClientQuery; + } + + final PagingResults favourites = favouritesService.getPagedFavourites(personId, filterTypes, FavouritesService.DEFAULT_SORT_PROPS, + Util.getPagingRequest(paging)); + return wrap(paging, favourites); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/LegacyExceptionHandler.java b/source/java/org/alfresco/rest/api/impl/LegacyExceptionHandler.java index 10dd6c6855..f24d3dc8f7 100644 --- a/source/java/org/alfresco/rest/api/impl/LegacyExceptionHandler.java +++ b/source/java/org/alfresco/rest/api/impl/LegacyExceptionHandler.java @@ -1,24 +1,24 @@ -package org.alfresco.rest.api.impl; - -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; - -/** - * Translates access denied exceptions from the service layer to API permission denied exception. - * - * @author steveglover - * - */ -public class LegacyExceptionHandler implements ExceptionHandler -{ - @Override - public boolean handle(Throwable t) - { - if(t instanceof AccessDeniedException) - { - // Note: security, no message to indicate why - throw new PermissionDeniedException(); - } - return false; - } -} +package org.alfresco.rest.api.impl; + +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; + +/** + * Translates access denied exceptions from the service layer to API permission denied exception. + * + * @author steveglover + * + */ +public class LegacyExceptionHandler implements ExceptionHandler +{ + @Override + public boolean handle(Throwable t) + { + if(t instanceof AccessDeniedException) + { + // Note: security, no message to indicate why + throw new PermissionDeniedException(); + } + return false; + } +} diff --git a/source/java/org/alfresco/rest/api/impl/NetworksImpl.java b/source/java/org/alfresco/rest/api/impl/NetworksImpl.java index 3102bdb003..245dd38033 100644 --- a/source/java/org/alfresco/rest/api/impl/NetworksImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NetworksImpl.java @@ -1,87 +1,87 @@ -package org.alfresco.rest.api.impl; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.query.PagingResults; -import org.alfresco.repo.tenant.NetworksService; -import org.alfresco.rest.api.Networks; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.model.Network; -import org.alfresco.rest.api.model.NetworkImpl; -import org.alfresco.rest.api.model.PersonNetwork; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; - -/** - * Centralises access to network services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class NetworksImpl implements Networks -{ - private People people; - private NetworksService networksService; - - public void setPeople(People people) - { - this.people = people; - } - - public void setNetworksService(NetworksService networksService) - { - this.networksService = networksService; - } - - public Network validateNetwork(String networkId) - { - org.alfresco.repo.tenant.Network network = networksService.getNetwork(networkId); - if(network == null) - { - throw new EntityNotFoundException(networkId); - } - Network restNetwork = new NetworkImpl(network); - return restNetwork; - } - - private PersonNetwork getPersonNetwork(org.alfresco.repo.tenant.Network network) - { - Network restNetwork = new NetworkImpl(network); - PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork); - return personNetwork; - } - - public Network getNetwork(String networkId) - { - Network network = validateNetwork(networkId); - return network; - } - - public PersonNetwork getNetwork(String personId, String networkId) - { - // check that personId is the current user - personId = people.validatePerson(personId, true); - Network network = validateNetwork(networkId); - - org.alfresco.repo.tenant.Network tenantNetwork = networksService.getNetwork(network.getId()); - PersonNetwork personNetwork = getPersonNetwork(tenantNetwork); - return personNetwork; - } - - public CollectionWithPagingInfo getNetworks(String personId, Paging paging) - { - // check that personId is the current user - personId = people.validatePerson(personId, true); - - PagingResults networks = networksService.getNetworks(Util.getPagingRequest(paging)); - List ret = new ArrayList(networks.getPage().size()); - for(org.alfresco.repo.tenant.Network network : networks.getPage()) - { - PersonNetwork personNetwork = getPersonNetwork(network); - ret.add(personNetwork); - } - return CollectionWithPagingInfo.asPaged(paging, ret, networks.hasMoreItems(), networks.getTotalResultCount().getFirst()); - } -} +package org.alfresco.rest.api.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.query.PagingResults; +import org.alfresco.repo.tenant.NetworksService; +import org.alfresco.rest.api.Networks; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.model.Network; +import org.alfresco.rest.api.model.NetworkImpl; +import org.alfresco.rest.api.model.PersonNetwork; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; + +/** + * Centralises access to network services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class NetworksImpl implements Networks +{ + private People people; + private NetworksService networksService; + + public void setPeople(People people) + { + this.people = people; + } + + public void setNetworksService(NetworksService networksService) + { + this.networksService = networksService; + } + + public Network validateNetwork(String networkId) + { + org.alfresco.repo.tenant.Network network = networksService.getNetwork(networkId); + if(network == null) + { + throw new EntityNotFoundException(networkId); + } + Network restNetwork = new NetworkImpl(network); + return restNetwork; + } + + private PersonNetwork getPersonNetwork(org.alfresco.repo.tenant.Network network) + { + Network restNetwork = new NetworkImpl(network); + PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork); + return personNetwork; + } + + public Network getNetwork(String networkId) + { + Network network = validateNetwork(networkId); + return network; + } + + public PersonNetwork getNetwork(String personId, String networkId) + { + // check that personId is the current user + personId = people.validatePerson(personId, true); + Network network = validateNetwork(networkId); + + org.alfresco.repo.tenant.Network tenantNetwork = networksService.getNetwork(network.getId()); + PersonNetwork personNetwork = getPersonNetwork(tenantNetwork); + return personNetwork; + } + + public CollectionWithPagingInfo getNetworks(String personId, Paging paging) + { + // check that personId is the current user + personId = people.validatePerson(personId, true); + + PagingResults networks = networksService.getNetworks(Util.getPagingRequest(paging)); + List ret = new ArrayList(networks.getPage().size()); + for(org.alfresco.repo.tenant.Network network : networks.getPage()) + { + PersonNetwork personNetwork = getPersonNetwork(network); + ret.add(personNetwork); + } + return CollectionWithPagingInfo.asPaged(paging, ret, networks.hasMoreItems(), networks.getTotalResultCount().getFirst()); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/NodeRatingsImpl.java b/source/java/org/alfresco/rest/api/impl/NodeRatingsImpl.java index 32258a9a44..d9b4172b69 100644 --- a/source/java/org/alfresco/rest/api/impl/NodeRatingsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodeRatingsImpl.java @@ -1,134 +1,134 @@ -package org.alfresco.rest.api.impl; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import org.alfresco.rest.api.NodeRatings; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.impl.node.ratings.RatingScheme; -import org.alfresco.rest.api.model.NodeRating; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.service.cmr.rating.RatingService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.util.TypeConstraint; -import org.alfresco.util.registry.NamedObjectRegistry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Centralises access to node ratings services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class NodeRatingsImpl implements NodeRatings -{ - private static Log logger = LogFactory.getLog(NodeRatingsImpl.class); - - private Nodes nodes; - private RatingService ratingService; - private NamedObjectRegistry nodeRatingSchemeRegistry; - private TypeConstraint typeConstraint; - - public void setTypeConstraint(TypeConstraint typeConstraint) - { - this.typeConstraint = typeConstraint; - } - - public void setRatingService(RatingService ratingService) - { - this.ratingService = ratingService; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setNodeRatingSchemeRegistry(NamedObjectRegistry nodeRatingSchemeRegistry) - { - this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry; - } - - public RatingScheme validateRatingScheme(String ratingSchemeId) - { - RatingScheme ratingScheme = nodeRatingSchemeRegistry.getNamedObject(ratingSchemeId); - if(ratingScheme == null) - { - throw new InvalidArgumentException("Invalid ratingSchemeId " + ratingSchemeId); - } - - return ratingScheme; - } - - // TODO deal with fractional ratings - InvalidArgumentException - public NodeRating getNodeRating(String nodeId, String ratingSchemeId) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); - return ratingScheme.getNodeRating(nodeRef); - } - - public CollectionWithPagingInfo getNodeRatings(String nodeId, Paging paging) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - Set schemes = new TreeSet(ratingService.getRatingSchemes().keySet()); - Iterator it = schemes.iterator(); - - int skipCount = paging.getSkipCount(); - int maxItems = paging.getMaxItems(); - int end = skipCount + maxItems; - if(end < 0) - { - // overflow - end = Integer.MAX_VALUE; - } - int count = Math.min(maxItems, schemes.size() - skipCount); - List ratings = new ArrayList(count); - - for(int i = 0; i < end && it.hasNext(); i++) - { - String schemeName = it.next(); - if(i < skipCount) - { - continue; - } - - RatingScheme ratingScheme = validateRatingScheme(schemeName); - NodeRating nodeRating = ratingScheme.getNodeRating(nodeRef); - ratings.add(nodeRating); - } - - int totalSize = schemes.size(); - boolean hasMoreItems = (skipCount + count < totalSize); - - return CollectionWithPagingInfo.asPaged(paging, ratings, hasMoreItems, totalSize); - } - - public void addRating(String nodeId, String ratingSchemeId, Object rating) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - - RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); - - if(!typeConstraint.matches(nodeRef)) - { - throw new UnsupportedResourceOperationException("Cannot rate this node"); - } - - ratingScheme.applyRating(nodeRef, rating); - } - - public void removeRating(String nodeId, String ratingSchemeId) - { - RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); - NodeRef nodeRef = nodes.validateNode(nodeId); - ratingScheme.removeRating(nodeRef); - } -} +package org.alfresco.rest.api.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.alfresco.rest.api.NodeRatings; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.impl.node.ratings.RatingScheme; +import org.alfresco.rest.api.model.NodeRating; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.service.cmr.rating.RatingService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.TypeConstraint; +import org.alfresco.util.registry.NamedObjectRegistry; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Centralises access to node ratings services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class NodeRatingsImpl implements NodeRatings +{ + private static Log logger = LogFactory.getLog(NodeRatingsImpl.class); + + private Nodes nodes; + private RatingService ratingService; + private NamedObjectRegistry nodeRatingSchemeRegistry; + private TypeConstraint typeConstraint; + + public void setTypeConstraint(TypeConstraint typeConstraint) + { + this.typeConstraint = typeConstraint; + } + + public void setRatingService(RatingService ratingService) + { + this.ratingService = ratingService; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setNodeRatingSchemeRegistry(NamedObjectRegistry nodeRatingSchemeRegistry) + { + this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry; + } + + public RatingScheme validateRatingScheme(String ratingSchemeId) + { + RatingScheme ratingScheme = nodeRatingSchemeRegistry.getNamedObject(ratingSchemeId); + if(ratingScheme == null) + { + throw new InvalidArgumentException("Invalid ratingSchemeId " + ratingSchemeId); + } + + return ratingScheme; + } + + // TODO deal with fractional ratings - InvalidArgumentException + public NodeRating getNodeRating(String nodeId, String ratingSchemeId) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); + return ratingScheme.getNodeRating(nodeRef); + } + + public CollectionWithPagingInfo getNodeRatings(String nodeId, Paging paging) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + Set schemes = new TreeSet(ratingService.getRatingSchemes().keySet()); + Iterator it = schemes.iterator(); + + int skipCount = paging.getSkipCount(); + int maxItems = paging.getMaxItems(); + int end = skipCount + maxItems; + if(end < 0) + { + // overflow + end = Integer.MAX_VALUE; + } + int count = Math.min(maxItems, schemes.size() - skipCount); + List ratings = new ArrayList(count); + + for(int i = 0; i < end && it.hasNext(); i++) + { + String schemeName = it.next(); + if(i < skipCount) + { + continue; + } + + RatingScheme ratingScheme = validateRatingScheme(schemeName); + NodeRating nodeRating = ratingScheme.getNodeRating(nodeRef); + ratings.add(nodeRating); + } + + int totalSize = schemes.size(); + boolean hasMoreItems = (skipCount + count < totalSize); + + return CollectionWithPagingInfo.asPaged(paging, ratings, hasMoreItems, totalSize); + } + + public void addRating(String nodeId, String ratingSchemeId, Object rating) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + + RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); + + if(!typeConstraint.matches(nodeRef)) + { + throw new UnsupportedResourceOperationException("Cannot rate this node"); + } + + ratingScheme.applyRating(nodeRef, rating); + } + + public void removeRating(String nodeId, String ratingSchemeId) + { + RatingScheme ratingScheme = validateRatingScheme(ratingSchemeId); + NodeRef nodeRef = nodes.validateNode(nodeId); + ratingScheme.removeRating(nodeRef); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index 8201edc7ea..a6c55a03ec 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -1,2830 +1,2830 @@ -package org.alfresco.rest.api.impl; - -import org.alfresco.model.ApplicationModel; -import org.alfresco.model.ContentModel; -import org.alfresco.model.QuickShareModel; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.action.executer.ContentMetadataExtracter; -import org.alfresco.repo.activities.ActivityType; -import org.alfresco.repo.content.ContentLimitViolationException; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.model.Repository; -import org.alfresco.repo.model.filefolder.FileFolderServiceImpl; -import org.alfresco.repo.node.getchildren.FilterProp; -import org.alfresco.repo.node.getchildren.FilterPropBoolean; -import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; -import org.alfresco.repo.policy.BehaviourFilter; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.thumbnail.ThumbnailDefinition; -import org.alfresco.repo.thumbnail.ThumbnailHelper; -import org.alfresco.repo.thumbnail.ThumbnailRegistry; -import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.version.VersionModel; -import org.alfresco.rest.antlr.WhereClauseParser; -import org.alfresco.rest.api.Activities; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.QuickShareLinks; -import org.alfresco.rest.api.model.AssocChild; -import org.alfresco.rest.api.model.AssocTarget; -import org.alfresco.rest.api.model.ContentInfo; -import org.alfresco.rest.api.model.Document; -import org.alfresco.rest.api.model.Folder; -import org.alfresco.rest.api.model.Node; -import org.alfresco.rest.api.model.PathInfo; -import org.alfresco.rest.api.model.PathInfo.ElementInfo; -import org.alfresco.rest.api.model.QuickShareLink; -import org.alfresco.rest.api.model.UserInfo; -import org.alfresco.rest.api.nodes.NodeAssocService; -import org.alfresco.rest.framework.core.exceptions.ApiException; -import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; -import org.alfresco.rest.framework.core.exceptions.DisabledServiceException; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; -import org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException; -import org.alfresco.rest.framework.core.exceptions.UnsupportedMediaTypeException; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.content.ContentInfoImpl; -import org.alfresco.rest.framework.resource.content.NodeBinaryResource; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.rest.framework.resource.parameters.SortColumn; -import org.alfresco.rest.framework.resource.parameters.where.Query; -import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; -import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.action.ActionDefinition; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.activities.ActivitiesTransactionListener; -import org.alfresco.service.cmr.activities.ActivityInfo; -import org.alfresco.service.cmr.activities.ActivityPoster; -import org.alfresco.service.cmr.dictionary.AspectDefinition; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -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.AssociationExistsException; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.CyclicChildRelationshipException; -import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.MimetypeService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.cmr.repository.Path.Element; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.security.OwnableService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.thumbnail.ThumbnailService; -import org.alfresco.service.cmr.usage.ContentQuotaException; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.version.VersionType; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.Pair; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.dao.ConcurrencyFailureException; -import org.springframework.extensions.surf.util.Content; -import org.springframework.extensions.webscripts.servlet.FormData; -import org.springframework.http.InvalidMediaTypeException; -import org.springframework.http.MediaType; - -import java.io.InputStream; -import java.io.Serializable; -import java.math.BigInteger; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Centralises access to file/folder/node services and maps between representations. - * - * Note: - * This class was originally used for returning some basic node info when listing Favourites. - * - * It has now been re-purposed and extended to implement the new Nodes (RESTful) API for - * managing files & folders, as well as custom node types. - * - * @author steveglover - * @author janv - * @author Jamal Kaabi-Mofrad - * - * @since publicapi1.0 - */ -public class NodesImpl implements Nodes -{ - private static final Log logger = LogFactory.getLog(NodesImpl.class); - - - private enum Type - { - // Note: ordered - DOCUMENT, FOLDER - } - - private static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_BINARY; - - private NodeService nodeService; - private DictionaryService dictionaryService; - private FileFolderService fileFolderService; - private NamespaceService namespaceService; - private PermissionService permissionService; - private MimetypeService mimetypeService; - private ContentService contentService; - private ActionService actionService; - private VersionService versionService; - private PersonService personService; - private OwnableService ownableService; - private AuthorityService authorityService; - private ThumbnailService thumbnailService; - private SiteService siteService; - private ActivityPoster poster; - private RetryingTransactionHelper retryingTransactionHelper; - private NodeAssocService nodeAssocService; - - private enum Activity_Type - { - ADDED, UPDATED, DELETED, DOWNLOADED - } - - private BehaviourFilter behaviourFilter; - - // note: circular - Nodes/QuickShareLinks currently use each other (albeit for different methods) - private QuickShareLinks quickShareLinks; - - private Repository repositoryHelper; - private ServiceRegistry sr; - private Set defaultIgnoreTypesAndAspects; - - // ignore types/aspects - private Set ignoreQNames; - - private ConcurrentHashMap ddCache = new ConcurrentHashMap<>(); - - private Set nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf - - public void setNonAttachContentTypes(Set nonAttachWhiteList) - { - this.nonAttachContentTypes = nonAttachWhiteList; - } - - public void init() - { - PropertyCheck.mandatory(this, "serviceRegistry", sr); - PropertyCheck.mandatory(this, "behaviourFilter", behaviourFilter); - PropertyCheck.mandatory(this, "repositoryHelper", repositoryHelper); - PropertyCheck.mandatory(this, "quickShareLinks", quickShareLinks); - PropertyCheck.mandatory(this, "poster", poster); - - this.namespaceService = sr.getNamespaceService(); - this.fileFolderService = sr.getFileFolderService(); - this.nodeService = sr.getNodeService(); - this.permissionService = sr.getPermissionService(); - this.dictionaryService = sr.getDictionaryService(); - this.mimetypeService = sr.getMimetypeService(); - this.contentService = sr.getContentService(); - this.actionService = sr.getActionService(); - this.versionService = sr.getVersionService(); - this.personService = sr.getPersonService(); - this.ownableService = sr.getOwnableService(); - this.authorityService = sr.getAuthorityService(); - this.thumbnailService = sr.getThumbnailService(); - this.siteService = sr.getSiteService(); - this.retryingTransactionHelper = sr.getRetryingTransactionHelper(); - - if (defaultIgnoreTypesAndAspects != null) - { - ignoreQNames = new HashSet<>(defaultIgnoreTypesAndAspects.size()); - for (String type : defaultIgnoreTypesAndAspects) - { - ignoreQNames.add(createQName(type)); - } - } - } - - public void setServiceRegistry(ServiceRegistry sr) - { - this.sr = sr; - } - - public void setBehaviourFilter(BehaviourFilter behaviourFilter) - { - this.behaviourFilter = behaviourFilter; - } - - public void setRepositoryHelper(Repository repositoryHelper) - { - this.repositoryHelper = repositoryHelper; - } - - public void setQuickShareLinks(QuickShareLinks quickShareLinks) - { - this.quickShareLinks = quickShareLinks; - } - - public void setIgnoreTypes(Set ignoreTypesAndAspects) - { - this.defaultIgnoreTypesAndAspects = ignoreTypesAndAspects; - } - - public void setPoster(ActivityPoster poster) - { - this.poster = poster; - } - - // Introduces permissions for Node Assoc (see public-rest-context.xml) - public void setNodeAssocService(NodeAssocService nodeAssocService) - { - this.nodeAssocService = nodeAssocService; - } - - - // excluded namespaces (aspects, properties, assoc types) - private static final List EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI); - - // excluded aspects - private static final List EXCLUDED_ASPECTS = Arrays.asList(); - - // excluded properties - private static final List EXCLUDED_PROPS = Arrays.asList( - // top-level minimal info - ContentModel.PROP_NAME, - ContentModel.PROP_MODIFIER, - ContentModel.PROP_MODIFIED, - ContentModel.PROP_CREATOR, - ContentModel.PROP_CREATED, - ContentModel.PROP_CONTENT, - // other - TBC - ContentModel.PROP_INITIAL_VERSION, - ContentModel.PROP_AUTO_VERSION_PROPS, - ContentModel.PROP_AUTO_VERSION); - - private static final List PROPS_USERLOOKUP = Arrays.asList( - ContentModel.PROP_CREATOR, - ContentModel.PROP_MODIFIER, - ContentModel.PROP_OWNER, - ContentModel.PROP_LOCK_OWNER, - ContentModel.PROP_WORKING_COPY_OWNER); - - private final static Map MAP_PARAM_QNAME; - static - { - Map aMap = new HashMap<>(9); - - aMap.put(PARAM_ISFOLDER, GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER); - aMap.put(PARAM_NAME, ContentModel.PROP_NAME); - aMap.put(PARAM_CREATEDAT, ContentModel.PROP_CREATED); - aMap.put(PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED); - aMap.put(PARAM_CREATEBYUSER, ContentModel.PROP_CREATOR); - aMap.put(PARAM_MODIFIEDBYUSER, ContentModel.PROP_MODIFIER); - aMap.put(PARAM_MIMETYPE, GetChildrenCannedQuery.SORT_QNAME_CONTENT_MIMETYPE); - aMap.put(PARAM_SIZEINBYTES, GetChildrenCannedQuery.SORT_QNAME_CONTENT_SIZE); - aMap.put(PARAM_NODETYPE, GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE); - - MAP_PARAM_QNAME = Collections.unmodifiableMap(aMap); - } - - // list children filtering (via where clause) - private final static Set LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES = - new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY, PARAM_ASSOC_TYPE})); - - /* - * Validates that node exists. - * - * Note: assumes workspace://SpacesStore - */ - @Override - public NodeRef validateNode(String nodeId) - { - return validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); - } - - @Override - public NodeRef validateNode(StoreRef storeRef, String nodeId) - { - String versionLabel = null; - - int idx = nodeId.indexOf(";"); - if (idx != -1) - { - versionLabel = nodeId.substring(idx + 1); - nodeId = nodeId.substring(0, idx); - if (versionLabel.equals("pwc")) - { - // TODO correct exception? - throw new EntityNotFoundException(nodeId); - } - } - - NodeRef nodeRef = new NodeRef(storeRef, nodeId); - return validateNode(nodeRef); - } - - @Override - public NodeRef validateNode(NodeRef nodeRef) - { - if (!nodeService.exists(nodeRef)) - { - throw new EntityNotFoundException(nodeRef.getId()); - } - - return nodeRef; - } - - /* - * Check that nodes exists and matches given expected/excluded type(s). - */ - @Override - public boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes) - { - return nodeMatches(nodeRef, expectedTypes, excludedTypes, true); - } - - @Override - public boolean isSubClass(NodeRef nodeRef, QName ofClassQName, boolean validateNodeRef) - { - if (validateNodeRef) - { - nodeRef = validateNode(nodeRef); - } - return isSubClass(getNodeType(nodeRef), ofClassQName); - } - - private boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes, boolean existsCheck) - { - if (existsCheck && (! nodeService.exists(nodeRef))) - { - throw new EntityNotFoundException(nodeRef.getId()); - } - - return typeMatches(getNodeType(nodeRef), expectedTypes, excludedTypes); - } - - private QName getNodeType(NodeRef nodeRef) - { - return nodeService.getType(nodeRef); - } - - private boolean isSubClass(QName className, QName ofClassQName) - { - return dictionaryService.isSubClass(className, ofClassQName); - } - - protected boolean typeMatches(QName type, Set expectedTypes, Set excludedTypes) - { - if (((expectedTypes != null) && (expectedTypes.size() == 1)) && - ((excludedTypes == null) || (excludedTypes.size() == 0))) - { - // use isSubClass if checking against single expected type (and no excluded types) - return isSubClass(type, expectedTypes.iterator().next()); - } - - Set allExpectedTypes = new HashSet<>(); - if (expectedTypes != null) - { - for (QName expectedType : expectedTypes) - { - allExpectedTypes.addAll(dictionaryService.getSubTypes(expectedType, true)); - } - } - - Set allExcludedTypes = new HashSet<>(); - if (excludedTypes != null) - { - for (QName excludedType : excludedTypes) - { - allExcludedTypes.addAll(dictionaryService.getSubTypes(excludedType, true)); - } - } - - boolean inExpected = allExpectedTypes.contains(type); - boolean excluded = allExcludedTypes.contains(type); - return (inExpected && !excluded); - } - - /** - * @deprecated review usage (backward compat') - */ - @Override - public Node getNode(String nodeId) - { - NodeRef nodeRef = validateNode(nodeId); - - return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); - } - - /** - * @deprecated review usage (backward compat') - */ - public Node getNode(NodeRef nodeRef) - { - return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); - } - - private Type getType(NodeRef nodeRef) - { - return getType(getNodeType(nodeRef), nodeRef); - } - - private Type getType(QName typeQName, NodeRef nodeRef) - { - // quick check for common types - if (typeQName.equals(ContentModel.TYPE_FOLDER) || typeQName.equals(ApplicationModel.TYPE_FOLDERLINK)) - { - return Type.FOLDER; - } - else if (typeQName.equals(ContentModel.TYPE_CONTENT) || typeQName.equals(ApplicationModel.TYPE_FILELINK)) - { - return Type.DOCUMENT; - } - - // further checks - - if (isSubClass(typeQName, ContentModel.TYPE_LINK)) - { - if (isSubClass(typeQName, ApplicationModel.TYPE_FOLDERLINK)) - { - return Type.FOLDER; - } - else if (isSubClass(typeQName, ApplicationModel.TYPE_FILELINK)) - { - return Type.DOCUMENT; - } - - NodeRef linkNodeRef = (NodeRef)nodeService.getProperty(nodeRef, ContentModel.PROP_LINK_DESTINATION); - if (linkNodeRef != null) - { - try - { - typeQName = getNodeType(linkNodeRef); - // drop-through to check type of destination - // note: edge-case - if link points to another link then we will return null - } - catch (InvalidNodeRefException inre) - { - // ignore - } - } - } - - if (isSubClass(typeQName, ContentModel.TYPE_FOLDER)) - { - if (! isSubClass(typeQName, ContentModel.TYPE_SYSTEM_FOLDER)) - { - return Type.FOLDER; - } - return null; // unknown - } - else if (isSubClass(typeQName, ContentModel.TYPE_CONTENT)) - { - return Type.DOCUMENT; - } - - return null; // unknown - } - - /** - * @deprecated note: currently required for backwards compat' (Favourites API) - */ - @Override - public Document getDocument(NodeRef nodeRef) - { - Type type = getType(nodeRef); - if ((type != null) && type.equals(Type.DOCUMENT)) - { - Map properties = nodeService.getProperties(nodeRef); - - Document doc = new Document(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); - - doc.setVersionLabel((String) properties.get(ContentModel.PROP_VERSION_LABEL)); - ContentData cd = (ContentData) properties.get(ContentModel.PROP_CONTENT); - if (cd != null) - { - doc.setSizeInBytes(BigInteger.valueOf(cd.getSize())); - doc.setMimeType((cd.getMimetype())); - } - - setCommonProps(doc, nodeRef, properties); - return doc; - } - else - { - throw new InvalidArgumentException("Node is not a file: "+nodeRef.getId()); - } - } - - private void setCommonProps(Node node, NodeRef nodeRef, Map properties) - { - node.setGuid(nodeRef); - node.setTitle((String)properties.get(ContentModel.PROP_TITLE)); - node.setDescription((String)properties.get(ContentModel.PROP_TITLE)); - node.setModifiedBy((String)properties.get(ContentModel.PROP_MODIFIER)); - node.setCreatedBy((String)properties.get(ContentModel.PROP_CREATOR)); - } - - /** - * @deprecated note: currently required for backwards compat' (Favourites API) - */ - @Override - public Folder getFolder(NodeRef nodeRef) - { - Type type = getType(nodeRef); - if ((type != null) && type.equals(Type.FOLDER)) - { - Map properties = nodeService.getProperties(nodeRef); - - Folder folder = new Folder(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); - setCommonProps(folder, nodeRef, properties); - return folder; - } - else - { - throw new InvalidArgumentException("Node is not a folder: "+nodeRef.getId()); - } - } - - private NodeRef getParentNodeRef(NodeRef nodeRef) - { - if (repositoryHelper.getCompanyHome().equals(nodeRef)) - { - return null; // note: does not make sense to return parent above C/H - } - - return nodeService.getPrimaryParent(nodeRef).getParentRef(); - } - - public NodeRef validateOrLookupNode(String nodeId, String path) - { - NodeRef parentNodeRef; - - if ((nodeId == null) || (nodeId.isEmpty())) - { - throw new InvalidArgumentException("Missing nodeId"); - } - - if (nodeId.equals(PATH_ROOT)) - { - parentNodeRef = repositoryHelper.getCompanyHome(); - } - else if (nodeId.equals(PATH_SHARED)) - { - parentNodeRef = repositoryHelper.getSharedHome(); - } - else if (nodeId.equals(PATH_MY)) - { - NodeRef person = repositoryHelper.getPerson(); - if (person == null) - { - throw new InvalidArgumentException("Unexpected - cannot use: " + PATH_MY); - } - parentNodeRef = repositoryHelper.getUserHome(person); - if (parentNodeRef == null) - { - throw new EntityNotFoundException(nodeId); - } - } - else - { - parentNodeRef = validateNode(nodeId); - } - - if (path != null) - { - // check that parent is a folder before resolving relative path - if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) - { - throw new InvalidArgumentException("NodeId of folder is expected: "+parentNodeRef.getId()); - } - - // resolve path relative to current nodeId - parentNodeRef = resolveNodeByPath(parentNodeRef, path, true); - } - - return parentNodeRef; - } - - protected NodeRef resolveNodeByPath(final NodeRef parentNodeRef, String path, boolean checkForCompanyHome) - { - final List pathElements = getPathElements(path); - - if (!pathElements.isEmpty() && checkForCompanyHome) - { - /* - if (nodeService.getRootNode(parentNodeRef.getStoreRef()).equals(parentNodeRef)) - { - // special case - NodeRef chNodeRef = repositoryHelper.getCompanyHome(); - String chName = (String) nodeService.getProperty(chNodeRef, ContentModel.PROP_NAME); - if (chName.equals(pathElements.get(0))) - { - pathElements = pathElements.subList(1, pathElements.size()); - parentNodeRef = chNodeRef; - } - } - */ - } - - FileInfo fileInfo = null; - try - { - if (!pathElements.isEmpty()) - { - fileInfo = fileFolderService.resolveNamePath(parentNodeRef, pathElements); - } - else - { - fileInfo = fileFolderService.getFileInfo(parentNodeRef); - if (fileInfo == null) - { - throw new EntityNotFoundException(parentNodeRef.getId()); - } - } - } - catch (FileNotFoundException fnfe) - { - // convert checked exception - throw new NotFoundException("The entity with relativePath: " + path + " was not found."); - } - catch (AccessDeniedException ade) - { - // return 404 instead of 403 (as per security review - uuid vs path) - throw new NotFoundException("The entity with relativePath: " + path + " was not found."); - } - - return fileInfo.getNodeRef(); - } - - private List getPathElements(String path) - { - final List pathElements = new ArrayList<>(); - if (path != null && path.trim().length() > 0) - { - // There is no need to check for leading and trailing "/" - final StringTokenizer tokenizer = new StringTokenizer(path, "/"); - while (tokenizer.hasMoreTokens()) - { - pathElements.add(tokenizer.nextToken().trim()); - } - } - return pathElements; - } - - private NodeRef makeFolders(NodeRef parentNodeRef, List pathElements) - { - NodeRef currentParentRef = parentNodeRef; - // just loop and create if necessary - for (final String element : pathElements) - { - final NodeRef contextNodeRef = currentParentRef; - // does it exist? - // Navigation should not check permissions - NodeRef nodeRef = AuthenticationUtil.runAs(new RunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - return nodeService.getChildByName(contextNodeRef, ContentModel.ASSOC_CONTAINS, element); - } - }, AuthenticationUtil.getSystemUserName()); - - if (nodeRef == null) - { - try - { - // Checks for create permissions as the fileFolderService is a public service. - FileInfo createdFileInfo = fileFolderService.create(currentParentRef, element, ContentModel.TYPE_FOLDER); - currentParentRef = createdFileInfo.getNodeRef(); - } - catch (AccessDeniedException ade) - { - throw new PermissionDeniedException(ade.getMessage()); - } - catch (FileExistsException fex) - { - // Assume concurrency failure, so retry - throw new ConcurrencyFailureException(fex.getMessage()); - } - } - else if (!isSubClass(nodeRef, ContentModel.TYPE_FOLDER, false)) - { - String parentName = (String) nodeService.getProperty(contextNodeRef, ContentModel.PROP_NAME); - throw new ConstraintViolatedException("Name [" + element + "] already exists in the target parent: " + parentName); - } - else - { - // it exists - currentParentRef = nodeRef; - } - } - return currentParentRef; - } - - @Override - public Node getFolderOrDocument(String nodeId, Parameters parameters) - { - String path = parameters.getParameter(PARAM_RELATIVE_PATH); - NodeRef nodeRef = validateOrLookupNode(nodeId, path); - - return getFolderOrDocumentFullInfo(nodeRef, null, null, parameters); - } - - private Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters) - { - return getFolderOrDocumentFullInfo(nodeRef, parentNodeRef, nodeTypeQName, parameters, null); - } - - @Override - public Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters, Map mapUserInfo) - { - List includeParam = new ArrayList<>(); - if (parameters != null) - { - includeParam.addAll(parameters.getInclude()); - } - - // Add basic info for single get (above & beyond minimal that is used for listing collections) - includeParam.add(PARAM_INCLUDE_ASPECTNAMES); - includeParam.add(PARAM_INCLUDE_PROPERTIES); - - return getFolderOrDocument(nodeRef, parentNodeRef, nodeTypeQName, includeParam, mapUserInfo); - } - - @Override - public Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, List includeParam, Map mapUserInfo) - { - if (mapUserInfo == null) - { - mapUserInfo = new HashMap<>(2); - } - - if (includeParam == null) - { - includeParam = Collections.emptyList(); - } - - Node node; - Map properties = nodeService.getProperties(nodeRef); - - PathInfo pathInfo = null; - if (includeParam.contains(PARAM_INCLUDE_PATH)) - { - ChildAssociationRef archivedParentAssoc = (ChildAssociationRef) properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC); - pathInfo = lookupPathInfo(nodeRef, archivedParentAssoc); - } - - if (nodeTypeQName == null) - { - nodeTypeQName = getNodeType(nodeRef); - } - - if (parentNodeRef == null) - { - parentNodeRef = getParentNodeRef(nodeRef); - } - - Type type = getType(nodeTypeQName, nodeRef); - - if (type == null) - { - // not direct folder (or file) ... - // might be sub-type of cm:cmobject (or a cm:link pointing to cm:cmobject or possibly even another cm:link) - node = new Node(nodeRef, parentNodeRef, properties, mapUserInfo, sr); - node.setIsFolder(false); - node.setIsFile(false); - } - else if (type.equals(Type.DOCUMENT)) - { - node = new Document(nodeRef, parentNodeRef, properties, mapUserInfo, sr); - } - else if (type.equals(Type.FOLDER)) - { - node = new Folder(nodeRef, parentNodeRef, properties, mapUserInfo, sr); - } - else - { - throw new RuntimeException("Unexpected - should not reach here: "+type); - } - - if (includeParam.size() > 0) - { - node.setProperties(mapFromNodeProperties(properties, includeParam, mapUserInfo)); - } - - if (includeParam.contains(PARAM_INCLUDE_ASPECTNAMES)) - { - node.setAspectNames(mapFromNodeAspects(nodeService.getAspects(nodeRef))); - } - - if (includeParam.contains(PARAM_INCLUDE_ISLINK)) - { - boolean isLink = isSubClass(nodeTypeQName, ContentModel.TYPE_LINK); - node.setIsLink(isLink); - } - - if (includeParam.contains(PARAM_INCLUDE_ALLOWABLEOPERATIONS)) - { - // note: refactor when requirements change - Map mapPermsToOps = new HashMap<>(3); - mapPermsToOps.put(PermissionService.DELETE, OP_DELETE); - mapPermsToOps.put(PermissionService.ADD_CHILDREN, OP_CREATE); - mapPermsToOps.put(PermissionService.WRITE, OP_UPDATE); - - List allowableOperations = new ArrayList<>(3); - for (Entry kv : mapPermsToOps.entrySet()) - { - String perm = kv.getKey(); - String op = kv.getValue(); - - if (perm.equals(PermissionService.ADD_CHILDREN) && type.equals(Type.DOCUMENT)) - { - // special case: do not return "create" (as an allowable op) for file/content types - continue; - } - else if (perm.equals(PermissionService.DELETE) && (isSpecialNodeDoNotDelete(nodeRef, nodeTypeQName))) - { - // special case: do not return "delete" (as an allowable op) for specific system nodes - continue; - } - else if (permissionService.hasPermission(nodeRef, perm) == AccessStatus.ALLOWED) - { - allowableOperations.add(op); - } - } - - node.setAllowableOperations((allowableOperations.size() > 0 )? allowableOperations : null); - } - - if (includeParam.contains(PARAM_INCLUDE_ASSOCIATION)) - { - // Ugh ... can we optimise this and return the actual assoc directly (via FileFolderService/GetChildrenCQ) ? - ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef); - - // note: parentAssocRef.parentRef can be null for -root- node ! - if ((parentAssocRef == null) || (parentAssocRef.getParentRef() == null) || (! parentAssocRef.getParentRef().equals(parentNodeRef))) - { - List parentAssocRefs = nodeService.getParentAssocs(nodeRef); - for (ChildAssociationRef pAssocRef : parentAssocRefs) - { - if (pAssocRef.getParentRef().equals(parentNodeRef)) - { - // for now, assume same parent/child cannot appear more than once (due to unique name) - parentAssocRef = pAssocRef; - break; - } - } - } - - if (parentAssocRef != null) - { - QName assocTypeQName = parentAssocRef.getTypeQName(); - if ((assocTypeQName != null) && (! EXCLUDED_NS.contains(assocTypeQName.getNamespaceURI()))) - { - AssocChild childAssoc = new AssocChild( - assocTypeQName.toPrefixString(namespaceService), - parentAssocRef.isPrimary()); - - node.setAssociation(childAssoc); - } - } - } - - node.setNodeType(nodeTypeQName.toPrefixString(namespaceService)); - node.setPath(pathInfo); - - return node; - } - - protected PathInfo lookupPathInfo(NodeRef nodeRefIn, ChildAssociationRef archivedParentAssoc) - { - - List pathElements = new ArrayList<>(); - Boolean isComplete = Boolean.TRUE; - final Path nodePath; - final int pathIndex; - - if (archivedParentAssoc != null) - { - if (permissionService.hasPermission(archivedParentAssoc.getParentRef(), PermissionService.READ).equals(AccessStatus.ALLOWED) - && nodeService.exists(archivedParentAssoc.getParentRef())) - { - nodePath = nodeService.getPath(archivedParentAssoc.getParentRef()); - pathIndex = 1;// 1 => we want to include the given node in the path as well. - } - else - { - //We can't return a valid path - return null; - } - } - else - { - nodePath = nodeService.getPath(nodeRefIn); - pathIndex = 2; // 2 => as we don't want to include the given node in the path as well. - } - - for (int i = nodePath.size() - pathIndex; i >= 0; i--) - { - Element element = nodePath.get(i); - if (element instanceof Path.ChildAssocElement) - { - ChildAssociationRef elementRef = ((Path.ChildAssocElement) element).getRef(); - if (elementRef.getParentRef() != null) - { - NodeRef childNodeRef = elementRef.getChildRef(); - if (permissionService.hasPermission(childNodeRef, PermissionService.READ) == AccessStatus.ALLOWED) - { - Serializable nameProp = nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); - pathElements.add(0, new ElementInfo(childNodeRef.getId(), nameProp.toString())); - } - else - { - // Just return the pathInfo up to the location where the user has access - isComplete = Boolean.FALSE; - break; - } - } - } - } - - String pathStr = null; - if (pathElements.size() > 0) - { - StringBuilder sb = new StringBuilder(120); - for (PathInfo.ElementInfo e : pathElements) - { - sb.append("/").append(e.getName()); - } - pathStr = sb.toString(); - } - else - { - // There is no path element, so set it to null in order to be - // ignored by Jackson during serialisation - isComplete = null; - } - return new PathInfo(pathStr, isComplete, pathElements); - } - - protected Set mapToNodeAspects(List aspectNames) - { - Set nodeAspects = new HashSet<>(aspectNames.size()); - - for (String aspectName : aspectNames) - { - QName aspectQName = createQName(aspectName); - - AspectDefinition ad = dictionaryService.getAspect(aspectQName); - if (ad != null) - { - nodeAspects.add(aspectQName); - } - else - { - throw new InvalidArgumentException("Unknown aspect: " + aspectName); - } - } - - return nodeAspects; - } - - protected Map mapToNodeProperties(Map props) - { - Map nodeProps = new HashMap<>(props.size()); - - for (Entry entry : props.entrySet()) - { - String propName = entry.getKey(); - QName propQName = createQName(propName); - - PropertyDefinition pd = dictionaryService.getProperty(propQName); - if (pd != null) - { - Serializable value; - if (pd.getDataType().getName().equals(DataTypeDefinition.NODE_REF)) - { - String nodeRefString = (String) entry.getValue(); - if (! NodeRef.isNodeRef(nodeRefString)) - { - value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRefString); - } - else - { - value = new NodeRef(nodeRefString); - } - } - else - { - value = (Serializable)entry.getValue(); - } - nodeProps.put(propQName, value); - } - else - { - throw new InvalidArgumentException("Unknown property: " + propName); - } - } - - return nodeProps; - } - - protected Map mapFromNodeProperties(Map nodeProps, List selectParam, Map mapUserInfo) - { - List selectedProperties; - - if ((selectParam.size() == 0) || selectParam.contains(PARAM_INCLUDE_PROPERTIES)) - { - // return all properties - selectedProperties = new ArrayList<>(nodeProps.size()); - for (QName propQName : nodeProps.keySet()) - { - if ((! EXCLUDED_NS.contains(propQName.getNamespaceURI())) && (! EXCLUDED_PROPS.contains(propQName))) - { - selectedProperties.add(propQName); - } - } - } - else - { - // return selected properties - selectedProperties = createQNames(selectParam); - } - - Map props = null; - if (!selectedProperties.isEmpty()) - { - props = new HashMap<>(selectedProperties.size()); - - for (QName qName : selectedProperties) - { - Serializable value = nodeProps.get(qName); - if (value != null) - { - if (PROPS_USERLOOKUP.contains(qName)) - { - value = Node.lookupUserInfo((String)value, mapUserInfo, sr.getPersonService()); - } - props.put(qName.toPrefixString(namespaceService), value); - } - } - if (props.isEmpty()) - { - props = null; // set to null so it doesn't show up as an empty object in the JSON response. - } - } - - return props; - } - - protected List mapFromNodeAspects(Set nodeAspects) - { - List aspectNames = new ArrayList<>(nodeAspects.size()); - - for (QName aspectQName : nodeAspects) - { - if ((! EXCLUDED_NS.contains(aspectQName.getNamespaceURI())) && (! EXCLUDED_ASPECTS.contains(aspectQName))) - { - aspectNames.add(aspectQName.toPrefixString(namespaceService)); - } - } - - if (aspectNames.size() == 0) - { - aspectNames = null; // no aspects to return - } - - return aspectNames; - } - - @Override - public CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters) - { - String path = parameters.getParameter(PARAM_RELATIVE_PATH); - - final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path); - - final List includeParam = parameters.getInclude(); - - // filters - Boolean includeFolders = null; - Boolean includeFiles = null; - Boolean isPrimary = null; - QName assocTypeQNameParam = null; - QName filterNodeTypeQName = null; - - // note: for files/folders, include subtypes by default (unless filtering by a specific nodeType - see below) - boolean filterIncludeSubTypes = true; - - Query q = parameters.getQuery(); - - if (q != null) - { - // filtering via "where" clause - MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES, null); - QueryHelper.walk(q, propertyWalker); - - isPrimary = propertyWalker.getProperty(PARAM_ISPRIMARY, WhereClauseParser.EQUALS, Boolean.class); - - String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class); - if (assocTypeQNameStr != null) - { - assocTypeQNameParam = getAssocType(assocTypeQNameStr); - } - - Boolean isFolder = propertyWalker.getProperty(PARAM_ISFOLDER, WhereClauseParser.EQUALS, Boolean.class); - Boolean isFile = propertyWalker.getProperty(PARAM_ISFILE, WhereClauseParser.EQUALS, Boolean.class); - - if (isFolder != null) - { - includeFolders = isFolder; - } - - if (isFile != null) - { - includeFiles = isFile; - } - - if (Boolean.TRUE.equals(includeFiles) && Boolean.TRUE.equals(includeFolders)) - { - throw new InvalidArgumentException("Invalid filter (isFile=true and isFolder=true) - a node cannot be both a file and a folder"); - } - - String nodeTypeStr = propertyWalker.getProperty(PARAM_NODETYPE, WhereClauseParser.EQUALS, String.class); - if ((nodeTypeStr != null) && (! nodeTypeStr.isEmpty())) - { - if ((isFile != null) || (isFolder != null)) - { - throw new InvalidArgumentException("Invalid filter - nodeType and isFile/isFolder are mutually exclusive"); - } - - Pair pair = parseNodeTypeFilter(nodeTypeStr); - filterNodeTypeQName = pair.getFirst(); - filterIncludeSubTypes = pair.getSecond(); - } - } - - List sortCols = parameters.getSorting(); - List> sortProps = null; - if ((sortCols != null) && (sortCols.size() > 0)) - { - // TODO should we allow isFile in sort (and map to reverse of isFolder) ? - sortProps = new ArrayList<>(sortCols.size()); - for (SortColumn sortCol : sortCols) - { - QName propQname = MAP_PARAM_QNAME.get(sortCol.column); - if (propQname == null) - { - propQname = createQName(sortCol.column); - } - - if (propQname != null) - { - sortProps.add(new Pair<>(propQname, sortCol.asc)); - } - } - } - else - { - // default sort order - sortProps = new ArrayList<>(Arrays.asList( - new Pair<>(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, Boolean.FALSE), - new Pair<>(ContentModel.PROP_NAME, true))); - } - - List filterProps = null; - if (isPrimary != null) - { - filterProps = new ArrayList<>(1); - filterProps.add(new FilterPropBoolean(GetChildrenCannedQuery.FILTER_QNAME_NODE_IS_PRIMARY, isPrimary)); - } - - Paging paging = parameters.getPaging(); - - PagingRequest pagingRequest = Util.getPagingRequest(paging); - - final PagingResults pagingResults; - - // notes (see also earlier validation checks): - // - no filtering means any types/sub-types (well, apart from hidden &/or default ignored types - eg. systemfolder, fm types) - // - node type filtering is mutually exclusive from isFile/isFolder, can optionally also include sub-types - // - isFile & isFolder cannot both be true - // - (isFile=false) means any other types/sub-types (other than files) - // - (isFolder=false) means any other types/sub-types (other than folders) - // - (isFile=false and isFolder=false) means any other types/sub-types (other than files or folders) - - if (filterNodeTypeQName == null) - { - if ((includeFiles == null) && (includeFolders == null)) - { - // no additional filtering - filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; - } - else if ((includeFiles != null) && (includeFolders != null)) - { - if ((! includeFiles) && (! includeFolders)) - { - // no files or folders - filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; - } - } - else if ((includeFiles != null) && (! includeFiles)) - { - // no files - filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; - } - else if ((includeFolders != null) && (! includeFolders)) - { - // no folders - filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; - } - } - - Pair, Set> pair = buildSearchTypesAndIgnoreAspects(filterNodeTypeQName, filterIncludeSubTypes, ignoreQNames, includeFiles, includeFolders); - Set searchTypeQNames = pair.getFirst(); - Set ignoreAspectQNames = pair.getSecond(); - - Set assocTypeQNames = buildAssocTypes(assocTypeQNameParam); - - // call GetChildrenCannedQuery (via FileFolderService) - pagingResults = fileFolderService.list(parentNodeRef, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest); - - - final Map mapUserInfo = new HashMap<>(10); - - final List page = pagingResults.getPage(); - List nodes = new AbstractList() - { - @Override - public Node get(int index) - { - FileInfo fInfo = page.get(index); - - // minimal info by default (unless "include"d otherwise) - return getFolderOrDocument(fInfo.getNodeRef(), parentNodeRef, fInfo.getType(), includeParam, mapUserInfo); - } - - @Override - public int size() - { - return page.size(); - } - }; - - Node sourceEntity = null; - if (parameters.includeSource()) - { - sourceEntity = getFolderOrDocumentFullInfo(parentNodeRef, null, null, null, mapUserInfo); - } - - return CollectionWithPagingInfo.asPaged(paging, nodes, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst(), sourceEntity); - } - - private Pair parseNodeTypeFilter(String nodeTypeStr) - { - boolean filterIncludeSubTypes = false; // default nodeType filtering is without subTypes (unless nodeType value is suffixed with ' INCLUDESUBTYPES') - - int idx = nodeTypeStr.lastIndexOf(' '); - if (idx > 0) - { - String suffix = nodeTypeStr.substring(idx); - if (suffix.equalsIgnoreCase(" "+PARAM_INCLUDE_SUBTYPES)) - { - filterIncludeSubTypes = true; - nodeTypeStr = nodeTypeStr.substring(0, idx); - } - } - - QName filterNodeTypeQName = createQName(nodeTypeStr); - if (dictionaryService.getType(filterNodeTypeQName) == null) - { - throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr); - } - - return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes); - } - - protected Set buildAssocTypes(QName assocTypeQName) - { - Set assocTypeQNames = null; - if (assocTypeQName != null) - { - assocTypeQNames = Collections.singleton(assocTypeQName); - } - /* - // TODO review - this works, but reduces from ~100 to ~96 (OOTB) - // maybe we could post filter (rather than join) - examples: sys:children, sys:lost_found, sys:archivedLink, sys:archiveUserLink - else - { - Collection qnames = dictionaryService.getAllAssociations(); - assocTypeQNames = new HashSet<>(qnames.size()); - - // remove system assoc types - for (QName qname : qnames) - { - if ((!EXCLUDED_NS.contains(qname.getNamespaceURI()))) - { - assocTypeQNames.add(qname); - } - } - } - */ - return assocTypeQNames; - } - - protected Pair, Set> buildSearchTypesAndIgnoreAspects(QName nodeTypeQName, boolean includeSubTypes, Set ignoreQNameTypes, Boolean includeFiles, Boolean includeFolders) - { - Set searchTypeQNames = new HashSet<>(100); - Set ignoreAspectQNames = null; - - if (nodeTypeQName != null) - { - // Build a list of (sub-)types - if (includeSubTypes) - { - Collection qnames = dictionaryService.getSubTypes(nodeTypeQName, true); - searchTypeQNames.addAll(qnames); - } - searchTypeQNames.add(nodeTypeQName); - - // Remove 'system' folders - if (includeSubTypes) - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_SYSTEM_FOLDER, true); - searchTypeQNames.removeAll(qnames); - } - searchTypeQNames.remove(ContentModel.TYPE_SYSTEM_FOLDER); - } - - if (includeFiles != null) - { - if (includeFiles) - { - if (includeSubTypes) - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true); - searchTypeQNames.addAll(qnames); - } - searchTypeQNames.add(ContentModel.TYPE_CONTENT); - } - else - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true); - searchTypeQNames.removeAll(qnames); - searchTypeQNames.remove(ContentModel.TYPE_CONTENT); - } - } - - if (includeFolders != null) - { - if (includeFolders) - { - if (includeSubTypes) - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_FOLDER, true); - searchTypeQNames.addAll(qnames); - } - searchTypeQNames.add(ContentModel.TYPE_FOLDER); - - // Remove 'system' folders - if (includeSubTypes) - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_SYSTEM_FOLDER, true); - searchTypeQNames.removeAll(qnames); - } - searchTypeQNames.remove(ContentModel.TYPE_SYSTEM_FOLDER); - } - else - { - Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_FOLDER, true); - searchTypeQNames.removeAll(qnames); - searchTypeQNames.remove(ContentModel.TYPE_FOLDER); - } - } - - if (ignoreQNameTypes != null) - { - Set ignoreQNamesNotSearchTypes = new HashSet<>(ignoreQNameTypes); - ignoreQNamesNotSearchTypes.removeAll(searchTypeQNames); - ignoreQNamesNotSearchTypes.remove(ContentModel.TYPE_SYSTEM_FOLDER); - - if (ignoreQNamesNotSearchTypes.size() > 0) - { - ignoreAspectQNames = getAspectsToIgnore(ignoreQNamesNotSearchTypes); - } - - searchTypeQNames.removeAll(ignoreQNameTypes); - } - - return new Pair<>(searchTypeQNames, ignoreAspectQNames); - } - - private Set getAspectsToIgnore(Set ignoreQNames) - { - Set ignoreQNameAspects = new HashSet<>(ignoreQNames.size()); - for (QName qname : ignoreQNames) - { - if (dictionaryService.getAspect(qname) != null) - { - ignoreQNameAspects.add(qname); - } - } - return ignoreQNameAspects; - } - - @Override - public void deleteNode(String nodeId, Parameters parameters) - { - NodeRef nodeRef = validateOrLookupNode(nodeId, null); - - if (isSpecialNodeDoNotDelete(nodeRef, getNodeType(nodeRef))) - { - throw new PermissionDeniedException("Cannot delete: " + nodeId); - } - - // default false (if not provided) - boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT)); - - if (permanentDelete == true) - { - boolean isAdmin = authorityService.hasAdminAuthority(); - if (! isAdmin) - { - String owner = ownableService.getOwner(nodeRef); - if (! AuthenticationUtil.getRunAsUser().equals(owner)) - { - // non-owner/non-admin cannot permanently delete (even if they have delete permission) - throw new PermissionDeniedException("Non-owner/non-admin cannot permanently delete: " + nodeId); - } - } - - // Set as temporary to delete node instead of archiving. - nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); - } - - final ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); - postActivity(Activity_Type.DELETED, activityInfo, true); - - fileFolderService.delete(nodeRef); - } - - @Override - public Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters) - { - if (nodeInfo.getNodeRef() != null) - { - throw new InvalidArgumentException("Unexpected id when trying to create a new node: "+nodeInfo.getNodeRef().getId()); - } - - // check that requested parent node exists and it's type is a (sub-)type of folder - NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); - - // node name - mandatory - String nodeName = nodeInfo.getName(); - if ((nodeName == null) || nodeName.isEmpty()) - { - throw new InvalidArgumentException("Node name is expected: "+parentNodeRef.getId()); - } - - // node type - check that requested type is a (sub-) type of cm:object - String nodeType = nodeInfo.getNodeType(); - if ((nodeType == null) || nodeType.isEmpty()) - { - throw new InvalidArgumentException("Node type is expected: "+parentNodeRef.getId()+","+nodeName); - } - - QName nodeTypeQName = createQName(nodeType); - - boolean isContent = isSubClass(nodeTypeQName, ContentModel.TYPE_CONTENT); - if (! isContent) - { - validateCmObject(nodeTypeQName); - } - - /* RA-834: commented-out since not currently applicable for empty file - List thumbnailDefs = null; - String renditionsParam = parameters.getParameter(PARAM_RENDITIONS); - if (renditionsParam != null) - { - if (!isContent) - { - throw new InvalidArgumentException("Renditions ['"+renditionsParam+"'] only apply to content types: "+parentNodeRef.getId()+","+nodeName); - } - - thumbnailDefs = getThumbnailDefs(renditionsParam); - } - */ - - Map props = new HashMap<>(1); - - if (nodeInfo.getProperties() != null) - { - // node properties - set any additional properties - props = mapToNodeProperties(nodeInfo.getProperties()); - } - - // Existing file/folder name handling - boolean autoRename = Boolean.valueOf(parameters.getParameter(PARAM_AUTO_RENAME)); - if (autoRename && (isContent || isSubClass(nodeTypeQName, ContentModel.TYPE_FOLDER))) - { - NodeRef existingNode = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, nodeName); - if (existingNode != null) - { - // File already exists, find a unique name - nodeName = findUniqueName(parentNodeRef, nodeName); - } - } - - String relativePath = nodeInfo.getRelativePath(); - parentNodeRef = getOrCreatePath(parentNodeRef, relativePath); - - QName assocTypeQName = ContentModel.ASSOC_CONTAINS; - if ((nodeInfo.getAssociation() != null) && (nodeInfo.getAssociation().getAssocType() != null)) - { - assocTypeQName = getAssocType(nodeInfo.getAssociation().getAssocType()); - } - - // Create the node - NodeRef nodeRef = createNodeImpl(parentNodeRef, nodeName, nodeTypeQName, props, assocTypeQName); - - List aspectNames = nodeInfo.getAspectNames(); - if (aspectNames != null) - { - // node aspects - set any additional aspects - Set aspectQNames = mapToNodeAspects(aspectNames); - for (QName aspectQName : aspectQNames) - { - if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) - { - continue; // ignore - } - - nodeService.addAspect(nodeRef, aspectQName, null); - } - } - - if (isContent) - { - // add empty file - ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - setWriterContentType(writer, new ContentInfoWrapper(nodeInfo.getContent()), nodeRef, false); - writer.putContent(""); - } - - // eg. to create mandatory assoc(s) - - if (nodeInfo.getTargets() != null) - { - addTargets(nodeRef.getId(), nodeInfo.getTargets()); - } - - if (nodeInfo.getSecondaryChildren() != null) - { - addChildren(nodeRef.getId(), nodeInfo.getSecondaryChildren()); - } - - Node newNode = getFolderOrDocument(nodeRef.getId(), parameters); - - /* RA-834: commented-out since not currently applicable for empty file - requestRenditions(thumbnailDefs, newNode); // note: noop for folder - */ - - return newNode; - } - - private NodeRef getOrCreatePath(NodeRef parentNodeRef, String relativePath) - { - if (relativePath != null) - { - List pathElements = getPathElements(relativePath); - - // Checks for the presence of, and creates as necessary, - // the folder structure in the provided path elements list. - if (!pathElements.isEmpty()) - { - parentNodeRef = makeFolders(parentNodeRef, pathElements); - } - } - - return parentNodeRef; - } - - public List addChildren(String parentNodeId, List entities) - { - NodeRef parentNodeRef = validateNode(parentNodeId); - - List result = new ArrayList<>(entities.size()); - - for (AssocChild assoc : entities) - { - QName assocTypeQName = getAssocType(assoc.getAssocType()); - - try - { - NodeRef childNodeRef = validateNode(assoc.getChildId()); - - String nodeName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); - QName assocChildQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)); - - nodeService.addChild(parentNodeRef, childNodeRef, assocTypeQName, assocChildQName); - } - catch (AssociationExistsException aee) - { - throw new ConstraintViolatedException(aee.getMessage()); - } - catch (DuplicateChildNodeNameException dcne) - { - throw new ConstraintViolatedException(dcne.getMessage()); - } - - result.add(assoc); - } - - return result; - } - - public List addTargets(String sourceNodeId, List entities) - { - List result = new ArrayList<>(entities.size()); - - NodeRef srcNodeRef = validateNode(sourceNodeId); - - for (AssocTarget assoc : entities) - { - String assocTypeStr = assoc.getAssocType(); - QName assocTypeQName = getAssocType(assocTypeStr); - - String targetNodeId = assoc.getTargetId(); - - try - { - NodeRef tgtNodeRef = validateNode(targetNodeId); - nodeAssocService.createAssociation(srcNodeRef, tgtNodeRef, assocTypeQName); - } - catch (AssociationExistsException aee) - { - throw new ConstraintViolatedException("Node association '"+assocTypeStr+"' already exists from "+sourceNodeId+" to "+targetNodeId); - } - catch (IllegalArgumentException iae) - { - // note: for now, we assume it is invalid assocType - alternatively, we could attempt to pre-validate via dictionary.getAssociation - throw new InvalidArgumentException(sourceNodeId+","+assocTypeStr+","+targetNodeId); - } - - result.add(assoc); - } - return result; - } - - public QName getAssocType(String assocTypeQNameStr) - { - return getAssocType(assocTypeQNameStr, true); - } - - public QName getAssocType(String assocTypeQNameStr, boolean mandatory) - { - QName assocType = null; - - if ((assocTypeQNameStr != null) && (! assocTypeQNameStr.isEmpty())) - { - assocType = createQName(assocTypeQNameStr); - if (dictionaryService.getAssociation(assocType) == null) - { - throw new InvalidArgumentException("Unknown assocType: " + assocTypeQNameStr); - } - - if (EXCLUDED_NS.contains(assocType.getNamespaceURI())) - { - throw new InvalidArgumentException("Invalid assocType: " + assocTypeQNameStr); - } - } - - if (mandatory && (assocType == null)) - { - throw new InvalidArgumentException("Missing assocType"); - } - - return assocType; - } - - - private NodeRef createNodeImpl(NodeRef parentNodeRef, String nodeName, QName nodeTypeQName, Map props, QName assocTypeQName) - { - NodeRef newNode = null; - if (props == null) - { - props = new HashMap<>(1); - } - props.put(ContentModel.PROP_NAME, nodeName); - - validatePropValues(props); - - QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)); - try - { - newNode = nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, props).getChildRef(); - } - catch (DuplicateChildNodeNameException dcne) - { - // duplicate - name clash - throw new ConstraintViolatedException(dcne.getMessage()); - } - - ActivityInfo activityInfo = getActivityInfo(parentNodeRef, newNode); - postActivity(Activity_Type.ADDED, activityInfo, false); - return newNode; - } - - /** - * Posts activites based on the activity_type. - * If the method is called with aSync=true then a TransactionListener is used post the activity - * afterCommit. Otherwise the activity posting is done synchronously. - * @param activity_type - * @param activityInfo - * @param aSync - */ - protected void postActivity(Activity_Type activity_type, ActivityInfo activityInfo, boolean aSync) - { - if (activityInfo == null) return; //Nothing to do. - - String activityType = determineActivityType(activity_type, activityInfo.getFileInfo().isFolder()); - if (activityType != null) - { - if (aSync) - { - ActivitiesTransactionListener txListener = new ActivitiesTransactionListener(activityType, activityInfo, - TenantUtil.getCurrentDomain(), Activities.APP_TOOL, Activities.RESTAPI_CLIENT, - poster, retryingTransactionHelper); - AlfrescoTransactionSupport.bindListener(txListener); - } - else - { - poster.postFileFolderActivity(activityType, null, TenantUtil.getCurrentDomain(), - activityInfo.getSiteId(), activityInfo.getParentNodeRef(), activityInfo.getNodeRef(), - activityInfo.getFileName(), Activities.APP_TOOL, Activities.RESTAPI_CLIENT, - activityInfo.getFileInfo()); - } - } - } - - protected ActivityInfo getActivityInfo(NodeRef parentNodeRef, NodeRef nodeRef) - { - SiteInfo siteInfo = siteService.getSite(nodeRef); - String siteId = (siteInfo != null ? siteInfo.getShortName() : null); - if(siteId != null && !siteId.equals("")) - { - FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef); - if (fileInfo != null) - { - boolean isContent = isSubClass(fileInfo.getType(), ContentModel.TYPE_CONTENT); - - if (fileInfo.isFolder() || isContent) - { - return new ActivityInfo(null, parentNodeRef, siteId, fileInfo); - } - } - } - else - { - if (logger.isDebugEnabled()) - { - logger.debug("Non-site activity, so ignored " + nodeRef); - } - } - return null; - } - - protected static String determineActivityType(Activity_Type activity_type, boolean isFolder) - { - switch (activity_type) - { - case DELETED: - return isFolder ? ActivityType.FOLDER_DELETED:ActivityType.FILE_DELETED; - case ADDED: - return isFolder ? ActivityType.FOLDER_ADDED:ActivityType.FILE_ADDED; - case UPDATED: - if (!isFolder) return ActivityType.FILE_UPDATED; - break; - case DOWNLOADED: - if (!isFolder) return ActivityPoster.DOWNLOADED; - break; - } - return null; - } - - // check cm:cmobject (but *not* cm:systemfolder) - private void validateCmObject(QName nodeTypeQName) - { - if (! isSubClass(nodeTypeQName, ContentModel.TYPE_CMOBJECT)) - { - throw new InvalidArgumentException("Invalid type: " + nodeTypeQName + " - expected (sub-)type of cm:cmobject"); - } - - if (isSubClass(nodeTypeQName, ContentModel.TYPE_SYSTEM_FOLDER)) - { - throw new InvalidArgumentException("Invalid type: " + nodeTypeQName + " - cannot be (sub-)type of cm:systemfolder"); - } - } - - // special cases: additional validation of property values (if not done by underlying foundation services) - private void validatePropValues(Map props) - { - String newOwner = (String)props.get(ContentModel.PROP_OWNER); - if (newOwner != null) - { - // validate that user exists - if (! personService.personExists(newOwner)) - { - throw new InvalidArgumentException("Unknown owner: "+newOwner); - } - } - } - - // special case: additional delete validation (pending common lower-level service support) - // for blacklist of system nodes that should not be deleted, eg. Company Home, Sites, Data Dictionary - private boolean isSpecialNodeDoNotDelete(NodeRef nodeRef, QName type) - { - // Check for Company Home, Sites and Data Dictionary (note: must be tenant-aware) - - if (nodeRef.equals(repositoryHelper.getCompanyHome())) - { - return true; - } - else if (type.equals(SiteModel.TYPE_SITES) || type.equals(SiteModel.TYPE_SITE)) - { - // note: alternatively, we could inject SiteServiceInternal and use getSitesRoot (or indirectly via node locator) - return true; - } - else - { - String tenantDomain = TenantUtil.getCurrentDomain(); - NodeRef ddNodeRef = ddCache.get(tenantDomain); - if (ddNodeRef == null) - { - List ddAssocs = nodeService.getChildAssocs( - repositoryHelper.getCompanyHome(), - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "dictionary")); - if (ddAssocs.size() == 1) - { - ddNodeRef = ddAssocs.get(0).getChildRef(); - ddCache.put(tenantDomain, ddNodeRef); - } - } - - if (nodeRef.equals(ddNodeRef)) - { - return true; - } - } - - return false; - } - - @Override - public Node updateNode(String nodeId, Node nodeInfo, Parameters parameters) - { - final NodeRef nodeRef = validateNode(nodeId); - - QName nodeTypeQName = getNodeType(nodeRef); - - validateCmObject(nodeTypeQName); - - Map props = new HashMap<>(0); - - if (nodeInfo.getProperties() != null) - { - props = mapToNodeProperties(nodeInfo.getProperties()); - } - - String name = nodeInfo.getName(); - if ((name != null) && (! name.isEmpty())) - { - // update node name if needed - note: if the name is different than existing then this is equivalent of a rename (within parent folder) - props.put(ContentModel.PROP_NAME, name); - } - - String nodeType = nodeInfo.getNodeType(); - if ((nodeType != null) && (! nodeType.isEmpty())) - { - // update node type - ensure that we are performing a specialise (we do not support generalise) - QName destNodeTypeQName = createQName(nodeType); - - if ((! destNodeTypeQName.equals(nodeTypeQName)) && - isSubClass(destNodeTypeQName, nodeTypeQName) && - (! isSubClass(destNodeTypeQName, ContentModel.TYPE_SYSTEM_FOLDER))) - { - nodeService.setType(nodeRef, destNodeTypeQName); - } - else - { - throw new InvalidArgumentException("Failed to change (specialise) node type - from "+nodeTypeQName+" to "+destNodeTypeQName); - } - } - - NodeRef parentNodeRef = nodeInfo.getParentId(); - if (parentNodeRef != null) - { - NodeRef currentParentNodeRef = getParentNodeRef(nodeRef); - if (currentParentNodeRef == null) - { - // implies root (Company Home) hence return 403 here - throw new PermissionDeniedException(); - } - - if (! currentParentNodeRef.equals(parentNodeRef)) - { - //moveOrCopy(nodeRef, parentNodeRef, name, false); // not currently supported - client should use explicit POST /move operation instead - throw new InvalidArgumentException("Cannot update parentId of "+nodeId+" via PUT /nodes/{nodeId}. Please use explicit POST /nodes/{nodeId}/move operation instead"); - } - } - - List aspectNames = nodeInfo.getAspectNames(); - if (aspectNames != null) - { - // update aspects - note: can be empty (eg. to remove existing aspects+properties) but not cm:auditable, sys:referencable, sys:localized - - Set aspectQNames = mapToNodeAspects(aspectNames); - - Set existingAspects = nodeService.getAspects(nodeRef); - - Set aspectsToAdd = new HashSet<>(3); - Set aspectsToRemove = new HashSet<>(3); - - for (QName aspectQName : aspectQNames) - { - if (EXCLUDED_NS.contains(aspectQName.getNamespaceURI()) || EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) - { - continue; // ignore - } - - if (! existingAspects.contains(aspectQName)) - { - aspectsToAdd.add(aspectQName); - } - } - - for (QName existingAspect : existingAspects) - { - if (EXCLUDED_NS.contains(existingAspect.getNamespaceURI()) || EXCLUDED_ASPECTS.contains(existingAspect) || existingAspect.equals(ContentModel.ASPECT_AUDITABLE)) - { - continue; // ignore - } - - if (! aspectQNames.contains(existingAspect)) - { - aspectsToRemove.add(existingAspect); - } - } - - // Note: for now, if aspectNames are sent then all that are required should be sent (to avoid properties from other existing aspects being removed) - // TODO: optional PATCH mechanism to add one new new aspect (with some related aspect properties) without affecting existing aspects/properties - for (QName aQName : aspectsToRemove) - { - if (aQName.equals(QuickShareModel.ASPECT_QSHARE)) - { - String qSharedId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID); - if (qSharedId != null) - { - // note: for now, go via QuickShareLinks (rather than QuickShareService) to ensure consistent permission checks - // alternatively we could disallow (or ignore) "qshare:shared" aspect removal - quickShareLinks.delete(qSharedId, null); - } - } - - nodeService.removeAspect(nodeRef, aQName); - } - - for (QName aQName : aspectsToAdd) - { - if (aQName.equals(QuickShareModel.ASPECT_QSHARE)) - { - // note: for now, go via QuickShareLinks (rather than QuickShareService) to ensure consistent permission checks - // alternatively we could disallow (or ignore) "qshare:shared" aspect addition - QuickShareLink qs = new QuickShareLink(); - qs.setNodeId(nodeRef.getId()); - quickShareLinks.create(Collections.singletonList(qs), null); - } - - nodeService.addAspect(nodeRef, aQName, null); - } - } - - if (props.size() > 0) - { - validatePropValues(props); - - try - { - // update node properties - note: null will unset the specified property - nodeService.addProperties(nodeRef, props); - } - catch (DuplicateChildNodeNameException dcne) - { - throw new ConstraintViolatedException(dcne.getMessage()); - } - } - - ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); - postActivity(Activity_Type.UPDATED, activityInfo, false); - - return getFolderOrDocument(nodeRef.getId(), parameters); - } - - @Override - public Node moveOrCopyNode(String sourceNodeId, String targetParentId, String name, Parameters parameters, boolean isCopy) - { - if ((sourceNodeId == null) || (sourceNodeId.isEmpty())) - { - throw new InvalidArgumentException("Missing sourceNodeId"); - } - - if ((targetParentId == null) || (targetParentId.isEmpty())) - { - throw new InvalidArgumentException("Missing targetParentId"); - } - - final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null); - final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null); - - FileInfo fi = moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy); - return getFolderOrDocument(fi.getNodeRef().getId(), parameters); - } - - protected FileInfo moveOrCopyImpl(NodeRef nodeRef, NodeRef parentNodeRef, String name, boolean isCopy) - { - String targetParentId = parentNodeRef.getId(); - - try - { - if (isCopy) - { - // copy - FileInfo newFileInfo = fileFolderService.copy(nodeRef, parentNodeRef, name); - if (newFileInfo.getNodeRef().equals(nodeRef)) - { - // copy did not happen - eg. same parent folder and name (name can be null or same) - throw new FileExistsException(nodeRef, ""); - } - return newFileInfo; - } - else - { - // move - if ((! nodeRef.equals(parentNodeRef)) && isSpecialNodeDoNotDelete(nodeRef, getNodeType(nodeRef))) - { - throw new PermissionDeniedException("Cannot move: "+nodeRef.getId()); - } - - // updating "parentId" means moving primary parent ! - // note: in the future (as and when we support secondary parent/child assocs) we may also - // wish to select which parent to "move from" (in case where the node resides in multiple locations) - return fileFolderService.move(nodeRef, parentNodeRef, name); - } - } - catch (InvalidNodeRefException inre) - { - throw new EntityNotFoundException(targetParentId); - } - catch (FileNotFoundException fnfe) - { - // convert checked exception - throw new EntityNotFoundException(targetParentId); - } - catch (FileExistsException fee) - { - // duplicate - name clash - throw new ConstraintViolatedException("Name already exists in target parent: "+name); - } - catch (FileFolderServiceImpl.InvalidTypeException ite) - { - throw new InvalidArgumentException("Invalid type of target parent: "+targetParentId); - } - catch (CyclicChildRelationshipException ccre) - { - throw new InvalidArgumentException("Parent/child cycle detected: "+targetParentId); - } - } - - @Override - public BinaryResource getContent(String fileNodeId, Parameters parameters, boolean recordActivity) - { - final NodeRef nodeRef = validateNode(fileNodeId); - return getContent(nodeRef, parameters, recordActivity); - } - - @Override - public BinaryResource getContent(NodeRef nodeRef, Parameters parameters, boolean recordActivity) - { - if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) - { - throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef.getId()); - } - - Map nodeProps = nodeService.getProperties(nodeRef); - ContentData cd = (ContentData) nodeProps.get(ContentModel.PROP_CONTENT); - String name = (String) nodeProps.get(ContentModel.PROP_NAME); - - org.alfresco.rest.framework.resource.content.ContentInfo ci = null; - String mimeType = null; - if (cd != null) - { - mimeType = cd.getMimetype(); - ci = new org.alfresco.rest.framework.resource.content.ContentInfoImpl(mimeType, cd.getEncoding(), cd.getSize(), cd.getLocale()); - } - - // By default set attachment header (with filename) unless attachment=false *and* content type is pre-configured as non-attach - boolean attach = true; - String attachment = parameters.getParameter("attachment"); - if (attachment != null) - { - Boolean a = Boolean.valueOf(attachment); - if (!a) - { - if (nonAttachContentTypes.contains(mimeType)) - { - attach = false; - } - else - { - logger.warn("Ignored attachment=false for "+nodeRef.getId()+" since "+mimeType+" is not in the whitelist for non-attach content types"); - } - } - } - String attachFileName = (attach ? name : null); - - if (recordActivity) - { - final ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); - postActivity(Activity_Type.DOWNLOADED, activityInfo, true); - } - - return new NodeBinaryResource(nodeRef, ContentModel.PROP_CONTENT, ci, attachFileName); - } - - @Override - public Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) - { - if (contentInfo.getMimeType().toLowerCase().startsWith("multipart")) - { - throw new UnsupportedMediaTypeException("Cannot update using "+contentInfo.getMimeType()); - } - - final NodeRef nodeRef = validateNode(fileNodeId); - - if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) - { - throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef.getId()); - } - - Boolean versionMajor = null; - String str = parameters.getParameter(PARAM_VERSION_MAJOR); - if (str != null) - { - versionMajor = new Boolean(str); - } - String versionComment = parameters.getParameter(PARAM_VERSION_COMMENT); - - final String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); - return updateExistingFile(null, nodeRef, fileName, contentInfo, stream, parameters, versionMajor, versionComment); - } - - private Node updateExistingFile(NodeRef parentNodeRef, NodeRef nodeRef, String fileName, BasicContentInfo contentInfo, InputStream stream, Parameters parameters, Boolean versionMajor, String versionComment) - { - boolean isVersioned = versionService.isVersioned(nodeRef); - - behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); - try - { - writeContent(nodeRef, contentInfo, stream); - - if ((isVersioned) || (versionMajor != null) || (versionComment != null) ) - { - VersionType versionType = VersionType.MINOR; - if ((versionMajor != null) && (versionMajor == true)) - { - versionType = VersionType.MAJOR; - } - createVersion(nodeRef, isVersioned, versionType, versionComment); - } - - ActivityInfo activityInfo = getActivityInfo(parentNodeRef, nodeRef); - postActivity(Activity_Type.UPDATED, activityInfo, false); - - extractMetadata(nodeRef); - } - finally - { - behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); - } - - return getFolderOrDocumentFullInfo(nodeRef, null, null, parameters); - } - - private void writeContent(NodeRef nodeRef, BasicContentInfo contentInfo, InputStream stream) - { - ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - setWriterContentType(writer, new ContentInfoWrapper(contentInfo), nodeRef, true); - writer.putContent(stream); - } - - protected void createVersion(NodeRef nodeRef, boolean isVersioned, VersionType versionType, String reason) - { - if (! isVersioned) - { - // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) - ensureVersioningEnabled(nodeRef, true, false); - } - else - { - Map versionProperties = new HashMap<>(2); - versionProperties.put(VersionModel.PROP_VERSION_TYPE, versionType); - if (reason != null) - { - versionProperties.put(VersionModel.PROP_DESCRIPTION, reason); - } - - versionService.createVersion(nodeRef, versionProperties); - } - } - - private void setWriterContentType(ContentWriter writer, ContentInfoWrapper contentInfo, NodeRef nodeRef, boolean guessEncodingIfNull) - { - String mimeType = contentInfo.mimeType; - // Manage MimeType - if ((mimeType == null) || mimeType.equals(DEFAULT_MIMETYPE)) - { - // the mimeType was not provided (or was the default binary mimeType) via the contentInfo, so try to guess - final String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); - mimeType = mimetypeService.guessMimetype(fileName); - } - writer.setMimetype(mimeType); - - // Manage Encoding - if (contentInfo.encoding == null) - { - if (guessEncodingIfNull) - { - // the encoding was not provided, so try to guess - writer.guessEncoding(); - } - } - else - { - writer.setEncoding(contentInfo.encoding); - } - } - - - @Override - public Node upload(String parentFolderNodeId, FormData formData, Parameters parameters) - { - if (formData == null || !formData.getIsMultiPart()) - { - throw new InvalidArgumentException("The request content-type is not multipart: "+parentFolderNodeId); - } - - NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); - if (!nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) - { - throw new InvalidArgumentException("NodeId of folder is expected: " + parentNodeRef.getId()); - } - - String fileName = null; - Content content = null; - boolean autoRename = false; - QName nodeTypeQName = null; - boolean overwrite = false; // If a fileName clashes for a versionable file - Boolean majorVersion = null; - String versionComment = null; - String relativePath = null; - String renditionNames = null; - - Map qnameStrProps = new HashMap<>(); - Map properties = null; - - for (FormData.FormField field : formData.getFields()) - { - switch (field.getName().toLowerCase()) - { - case "name": - String str = getStringOrNull(field.getValue()); - if ((str != null) && (! str.isEmpty())) - { - fileName = str; - } - break; - - case "filedata": - if (field.getIsFile()) - { - fileName = (fileName != null ? fileName : field.getFilename()); - content = field.getContent(); - } - break; - - case "autorename": - autoRename = Boolean.valueOf(field.getValue()); - break; - - case "nodetype": - nodeTypeQName = createQName(getStringOrNull(field.getValue())); - if (! isSubClass(nodeTypeQName, ContentModel.TYPE_CONTENT)) - { - throw new InvalidArgumentException("Can only upload type of cm:content: " + nodeTypeQName); - } - break; - - case "overwrite": - overwrite = Boolean.valueOf(field.getValue()); - break; - - case "majorversion": - majorVersion = Boolean.valueOf(field.getValue()); - break; - - case "comment": - versionComment = getStringOrNull(field.getValue()); - break; - - case "relativepath": - relativePath = getStringOrNull(field.getValue()); - break; - - case "renditions": - renditionNames = getStringOrNull(field.getValue()); - break; - - default: - { - final String propName = field.getName(); - if (propName.indexOf(QName.NAMESPACE_PREFIX) > -1) - { - qnameStrProps.put(propName, field.getValue()); - } - } - } - } - - // MNT-7213 When alf_data runs out of disk space, Share uploads - // result in a success message, but the files do not appear. - if (formData.getFields().length == 0) - { - throw new ConstraintViolatedException("No disk space available"); - } - // Ensure mandatory file attributes have been located. Need either - // destination, or site + container or updateNodeRef - if ((fileName == null) || fileName.isEmpty() || (content == null)) - { - throw new InvalidArgumentException("Required parameters are missing"); - } - - if (autoRename && overwrite) - { - throw new InvalidArgumentException("Both 'overwrite' and 'autoRename' should not be true when uploading a file"); - } - - // if requested, make (get or create) path - parentNodeRef = getOrCreatePath(parentNodeRef, relativePath); - final QName assocTypeQName = ContentModel.ASSOC_CONTAINS; - final Set renditions = getRequestedRenditions(renditionNames); - - try - { - // Map the given properties, if any. - if (qnameStrProps.size() > 0) - { - properties = mapToNodeProperties(qnameStrProps); - } - - /* - * Existing file handling - */ - NodeRef existingFile = nodeService.getChildByName(parentNodeRef, assocTypeQName, fileName); - if (existingFile != null) - { - // File already exists, decide what to do - if (autoRename) - { - // attempt to find a unique name - fileName = findUniqueName(parentNodeRef, fileName); - - // drop-through ! - } - else if (overwrite && nodeService.hasAspect(existingFile, ContentModel.ASPECT_VERSIONABLE)) - { - // overwrite existing (versionable) file - BasicContentInfo contentInfo = new ContentInfoImpl(content.getMimetype(), content.getEncoding(), -1, null); - return updateExistingFile(parentNodeRef, existingFile, fileName, contentInfo, content.getInputStream(), parameters, majorVersion, versionComment); - } - else - { - // name clash (and no autoRename or overwrite) - throw new ConstraintViolatedException(fileName + " already exists."); - } - } - - // Create a new file. - final Node fileNode = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, assocTypeQName, parameters); - - // RA-1052 - try - { - List thumbnailDefs = getThumbnailDefs(renditions); - requestRenditions(thumbnailDefs, fileNode); - } - catch (Exception ex) - { - // Note: The log level is not 'error' as it could easily fill out the log file, especially in the Cloud. - if (logger.isDebugEnabled()) - { - // Don't throw the exception as we don't want the the upload to fail, just log it. - logger.debug("Asynchronous request to create a rendition upon upload failed: " + ex.getMessage()); - } - } - - return fileNode; - - // Do not clean formData temp files to allow for retries. - // Temp files will be deleted later when GC call DiskFileItem#finalize() method or by temp file cleaner. - } - catch (ApiException apiEx) - { - // As this is an public API fwk exception, there is no need to convert it, so just throw it. - throw apiEx; - } - catch (AccessDeniedException ade) - { - throw new PermissionDeniedException(ade.getMessage()); - } - catch (ContentQuotaException cqe) - { - throw new InsufficientStorageException(); - } - catch (ContentLimitViolationException clv) - { - throw new RequestEntityTooLargeException(clv.getMessage()); - } - catch (Exception ex) - { - /* - * NOTE: Do not clean formData temp files to allow for retries. It's - * possible for a temp file to remain if max retry attempts are - * made, but this is rare, so leave to usual temp file cleanup. - */ - - throw new ApiException("Unexpected error occurred during upload of new content.", ex); - } - } - - private Node createNewFile(NodeRef parentNodeRef, String fileName, QName nodeType, Content content, Map props, QName assocTypeQName, Parameters params) - { - if (nodeType == null) - { - nodeType = ContentModel.TYPE_CONTENT; - } - NodeRef newFile = createNodeImpl(parentNodeRef, fileName, nodeType, props, assocTypeQName); - - // Write content - write(newFile, content); - - // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) - ensureVersioningEnabled(newFile, true, false); - - // Extract the metadata - extractMetadata(newFile); - - // Create the response - return getFolderOrDocumentFullInfo(newFile, parentNodeRef, nodeType, params); - } - - private String getStringOrNull(String value) - { - if (StringUtils.isNotEmpty(value)) - { - return value.equalsIgnoreCase("null") ? null : value; - } - return null; - } - - private List getThumbnailDefs(Set renditionNames) - { - List thumbnailDefs = null; - - if (renditionNames != null) - { - // If thumbnail generation has been configured off, then don't bother. - if (!thumbnailService.getThumbnailsEnabled()) - { - throw new DisabledServiceException("Thumbnail generation has been disabled."); - } - - thumbnailDefs = new ArrayList<>(renditionNames.size()); - ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry(); - for (String renditionName : renditionNames) - { - // Use the thumbnail registry to get the details of the thumbnail - ThumbnailDefinition thumbnailDef = registry.getThumbnailDefinition(renditionName); - if (thumbnailDef == null) - { - throw new NotFoundException(renditionName + " is not registered."); - } - - thumbnailDefs.add(thumbnailDef); - - } - } - - return thumbnailDefs; - } - - private Set getRequestedRenditions(String renditionsParam) - { - if (renditionsParam == null) - { - return null; - } - - String[] renditionNames = renditionsParam.split(","); - - // Temporary - pending future improvements to thumbnail service to minimise chance of - // missing/failed thumbnails (when requested/generated 'concurrently') - if (renditionNames.length > 1) - { - throw new InvalidArgumentException("Please specify one rendition entity id only"); - } - - Set renditions = new LinkedHashSet<>(renditionNames.length); - for (String name : renditionNames) - { - name = name.trim(); - if (!name.isEmpty()) - { - renditions.add(name.trim()); - } - } - return renditions; - } - - private void requestRenditions(List thumbnailDefs, Node fileNode) - { - if (thumbnailDefs != null) - { - ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry(); - for (ThumbnailDefinition thumbnailDef : thumbnailDefs) - { - NodeRef sourceNodeRef = fileNode.getNodeRef(); - String mimeType = fileNode.getContent().getMimeType(); - long size = fileNode.getContent().getSizeInBytes(); - - // Check if anything is currently available to generate thumbnails for the specified mimeType - if (! registry.isThumbnailDefinitionAvailable(null, mimeType, size, sourceNodeRef, thumbnailDef)) - { - throw new InvalidArgumentException("Unable to create thumbnail '" + thumbnailDef.getName() + "' for " + - mimeType + " as no transformer is currently available."); - } - - Action action = ThumbnailHelper.createCreateThumbnailAction(thumbnailDef, sr); - - // Queue async creation of thumbnail - actionService.executeAction(action, sourceNodeRef, true, true); - } - } - } - - - - /** - * Writes the content to the repository. - * - * @param nodeRef the reference to the node having a content property - * @param content the content - */ - protected void write(NodeRef nodeRef, Content content) - { - ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - // Per RA-637 & RA-885 requirement the mimeType provided by the client takes precedence, however, - // if the mimeType is null (or default binary mimeType) then it will be guessed. - setWriterContentType(writer, new ContentInfoWrapper(content), nodeRef, true); - writer.putContent(content.getInputStream()); - } - - /** - * Ensures the given node has the {@code cm:versionable} aspect applied to it, and - * that it has the initial version in the version store. - * - * @param nodeRef the reference to the node to be checked - * @param autoVersion If the {@code cm:versionable} aspect is applied, should auto - * versioning be requested? - * @param autoVersionProps If the {@code cm:versionable} aspect is applied, should - * auto versioning of properties be requested? - */ - protected void ensureVersioningEnabled(NodeRef nodeRef, boolean autoVersion, boolean autoVersionProps) - { - Map props = new HashMap<>(2); - props.put(ContentModel.PROP_AUTO_VERSION, autoVersion); - props.put(ContentModel.PROP_AUTO_VERSION_PROPS, autoVersionProps); - - versionService.ensureVersioningEnabled(nodeRef, props); - } - - /** - * Extracts the given node metadata asynchronously. - * - * The overwrite policy controls which if any parts of the document's properties are updated from this. - */ - private void extractMetadata(NodeRef nodeRef) - { - final String actionName = ContentMetadataExtracter.EXECUTOR_NAME; - ActionDefinition actionDef = actionService.getActionDefinition(actionName); - if (actionDef != null) - { - Action action = actionService.createAction(actionName); - actionService.executeAction(action, nodeRef); - } - } - - /** - * Creates a unique file name, if the upload component was configured to - * find a new unique name for clashing filenames. - * - * @param parentNodeRef the parent node - * @param fileName the original fileName - * @return a new file name - */ - private String findUniqueName(NodeRef parentNodeRef, String fileName) - { - int counter = 1; - String tmpFilename; - NodeRef existingFile; - do - { - int dotIndex = fileName.lastIndexOf('.'); - if (dotIndex == 0) - { - // File didn't have a proper 'name' instead it - // had just a suffix and started with a ".", create "1.txt" - tmpFilename = counter + fileName; - } - else if (dotIndex > 0) - { - // Filename contained ".", create "fileName-1.txt" - tmpFilename = fileName.substring(0, dotIndex) + "-" + counter + fileName.substring(dotIndex); - } - else - { - // Filename didn't contain a dot at all, create "fileName-1" - tmpFilename = fileName + "-" + counter; - } - existingFile = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, tmpFilename); - counter++; - - } while (existingFile != null); - - return tmpFilename; - } - - /** - * Helper to create a QName from either a fully qualified or short-name QName string - * - * @param qnameStr Fully qualified or short-name QName string - * @return QName - */ - public QName createQName(String qnameStr) - { - try - { - QName qname; - if (qnameStr.indexOf(QName.NAMESPACE_BEGIN) != -1) - { - qname = QName.createQName(qnameStr); - } - else - { - qname = QName.createQName(qnameStr, namespaceService); - } - return qname; - } - catch (Exception ex) - { - String msg = ex.getMessage(); - if (msg == null) - { - msg = ""; - } - throw new InvalidArgumentException(qnameStr + " isn't a valid QName. " + msg); - } - } - - /** - * Helper to create a QName from either a fully qualified or short-name QName string - * - * @param qnameStrList list of fully qualified or short-name QName string - * @return a list of {@code QName} objects - */ - protected List createQNames(List qnameStrList) - { - String PREFIX = PARAM_INCLUDE_PROPERTIES +"/"; - - List result = new ArrayList<>(qnameStrList.size()); - for (String str : qnameStrList) - { - if (str.startsWith(PREFIX)) - { - str = str.substring(PREFIX.length()); - } - - QName name = createQName(str); - if (!EXCLUDED_PROPS.contains(name)) - { - result.add(name); - } - } - return result; - } - - /** - * @author Jamal Kaabi-Mofrad - */ - private static class ContentInfoWrapper - { - private String mimeType; - private String encoding; - - ContentInfoWrapper(BasicContentInfo basicContentInfo) - { - if (basicContentInfo != null) - { - this.mimeType = basicContentInfo.getMimeType(); - this.encoding = basicContentInfo.getEncoding(); - } - } - - ContentInfoWrapper(ContentInfo contentInfo) - { - if (contentInfo != null) - { - this.mimeType = contentInfo.getMimeType(); - this.encoding = contentInfo.getEncoding(); - } - } - - ContentInfoWrapper(Content content) - { - if (content != null && StringUtils.isNotEmpty(content.getMimetype())) - { - try - { - // TODO I think it makes sense to push contentType parsing into org.springframework.extensions.webscripts.servlet.FormData - MediaType media = MediaType.parseMediaType(content.getMimetype()); - this.mimeType = media.getType() + '/' + media.getSubtype(); - - if (media.getCharSet() != null) - { - this.encoding = media.getCharSet().name(); - } - } - catch (InvalidMediaTypeException ime) - { - throw new InvalidArgumentException(ime.getMessage()); - } - } - } - } -} - +package org.alfresco.rest.api.impl; + +import org.alfresco.model.ApplicationModel; +import org.alfresco.model.ContentModel; +import org.alfresco.model.QuickShareModel; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.action.executer.ContentMetadataExtracter; +import org.alfresco.repo.activities.ActivityType; +import org.alfresco.repo.content.ContentLimitViolationException; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.model.filefolder.FileFolderServiceImpl; +import org.alfresco.repo.node.getchildren.FilterProp; +import org.alfresco.repo.node.getchildren.FilterPropBoolean; +import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.thumbnail.ThumbnailDefinition; +import org.alfresco.repo.thumbnail.ThumbnailHelper; +import org.alfresco.repo.thumbnail.ThumbnailRegistry; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.version.VersionModel; +import org.alfresco.rest.antlr.WhereClauseParser; +import org.alfresco.rest.api.Activities; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.QuickShareLinks; +import org.alfresco.rest.api.model.AssocChild; +import org.alfresco.rest.api.model.AssocTarget; +import org.alfresco.rest.api.model.ContentInfo; +import org.alfresco.rest.api.model.Document; +import org.alfresco.rest.api.model.Folder; +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.api.model.PathInfo; +import org.alfresco.rest.api.model.PathInfo.ElementInfo; +import org.alfresco.rest.api.model.QuickShareLink; +import org.alfresco.rest.api.model.UserInfo; +import org.alfresco.rest.api.nodes.NodeAssocService; +import org.alfresco.rest.framework.core.exceptions.ApiException; +import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; +import org.alfresco.rest.framework.core.exceptions.DisabledServiceException; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; +import org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException; +import org.alfresco.rest.framework.core.exceptions.UnsupportedMediaTypeException; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.content.ContentInfoImpl; +import org.alfresco.rest.framework.resource.content.NodeBinaryResource; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.resource.parameters.SortColumn; +import org.alfresco.rest.framework.resource.parameters.where.Query; +import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; +import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionDefinition; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.activities.ActivitiesTransactionListener; +import org.alfresco.service.cmr.activities.ActivityInfo; +import org.alfresco.service.cmr.activities.ActivityPoster; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +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.AssociationExistsException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.CyclicChildRelationshipException; +import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Path.Element; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.cmr.usage.ContentQuotaException; +import org.alfresco.service.cmr.version.VersionService; +import org.alfresco.service.cmr.version.VersionType; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.alfresco.util.PropertyCheck; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.servlet.FormData; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; + +import java.io.InputStream; +import java.io.Serializable; +import java.math.BigInteger; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Centralises access to file/folder/node services and maps between representations. + * + * Note: + * This class was originally used for returning some basic node info when listing Favourites. + * + * It has now been re-purposed and extended to implement the new Nodes (RESTful) API for + * managing files & folders, as well as custom node types. + * + * @author steveglover + * @author janv + * @author Jamal Kaabi-Mofrad + * + * @since publicapi1.0 + */ +public class NodesImpl implements Nodes +{ + private static final Log logger = LogFactory.getLog(NodesImpl.class); + + + private enum Type + { + // Note: ordered + DOCUMENT, FOLDER + } + + private static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_BINARY; + + private NodeService nodeService; + private DictionaryService dictionaryService; + private FileFolderService fileFolderService; + private NamespaceService namespaceService; + private PermissionService permissionService; + private MimetypeService mimetypeService; + private ContentService contentService; + private ActionService actionService; + private VersionService versionService; + private PersonService personService; + private OwnableService ownableService; + private AuthorityService authorityService; + private ThumbnailService thumbnailService; + private SiteService siteService; + private ActivityPoster poster; + private RetryingTransactionHelper retryingTransactionHelper; + private NodeAssocService nodeAssocService; + + private enum Activity_Type + { + ADDED, UPDATED, DELETED, DOWNLOADED + } + + private BehaviourFilter behaviourFilter; + + // note: circular - Nodes/QuickShareLinks currently use each other (albeit for different methods) + private QuickShareLinks quickShareLinks; + + private Repository repositoryHelper; + private ServiceRegistry sr; + private Set defaultIgnoreTypesAndAspects; + + // ignore types/aspects + private Set ignoreQNames; + + private ConcurrentHashMap ddCache = new ConcurrentHashMap<>(); + + private Set nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf + + public void setNonAttachContentTypes(Set nonAttachWhiteList) + { + this.nonAttachContentTypes = nonAttachWhiteList; + } + + public void init() + { + PropertyCheck.mandatory(this, "serviceRegistry", sr); + PropertyCheck.mandatory(this, "behaviourFilter", behaviourFilter); + PropertyCheck.mandatory(this, "repositoryHelper", repositoryHelper); + PropertyCheck.mandatory(this, "quickShareLinks", quickShareLinks); + PropertyCheck.mandatory(this, "poster", poster); + + this.namespaceService = sr.getNamespaceService(); + this.fileFolderService = sr.getFileFolderService(); + this.nodeService = sr.getNodeService(); + this.permissionService = sr.getPermissionService(); + this.dictionaryService = sr.getDictionaryService(); + this.mimetypeService = sr.getMimetypeService(); + this.contentService = sr.getContentService(); + this.actionService = sr.getActionService(); + this.versionService = sr.getVersionService(); + this.personService = sr.getPersonService(); + this.ownableService = sr.getOwnableService(); + this.authorityService = sr.getAuthorityService(); + this.thumbnailService = sr.getThumbnailService(); + this.siteService = sr.getSiteService(); + this.retryingTransactionHelper = sr.getRetryingTransactionHelper(); + + if (defaultIgnoreTypesAndAspects != null) + { + ignoreQNames = new HashSet<>(defaultIgnoreTypesAndAspects.size()); + for (String type : defaultIgnoreTypesAndAspects) + { + ignoreQNames.add(createQName(type)); + } + } + } + + public void setServiceRegistry(ServiceRegistry sr) + { + this.sr = sr; + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + public void setRepositoryHelper(Repository repositoryHelper) + { + this.repositoryHelper = repositoryHelper; + } + + public void setQuickShareLinks(QuickShareLinks quickShareLinks) + { + this.quickShareLinks = quickShareLinks; + } + + public void setIgnoreTypes(Set ignoreTypesAndAspects) + { + this.defaultIgnoreTypesAndAspects = ignoreTypesAndAspects; + } + + public void setPoster(ActivityPoster poster) + { + this.poster = poster; + } + + // Introduces permissions for Node Assoc (see public-rest-context.xml) + public void setNodeAssocService(NodeAssocService nodeAssocService) + { + this.nodeAssocService = nodeAssocService; + } + + + // excluded namespaces (aspects, properties, assoc types) + private static final List EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI); + + // excluded aspects + private static final List EXCLUDED_ASPECTS = Arrays.asList(); + + // excluded properties + private static final List EXCLUDED_PROPS = Arrays.asList( + // top-level minimal info + ContentModel.PROP_NAME, + ContentModel.PROP_MODIFIER, + ContentModel.PROP_MODIFIED, + ContentModel.PROP_CREATOR, + ContentModel.PROP_CREATED, + ContentModel.PROP_CONTENT, + // other - TBC + ContentModel.PROP_INITIAL_VERSION, + ContentModel.PROP_AUTO_VERSION_PROPS, + ContentModel.PROP_AUTO_VERSION); + + private static final List PROPS_USERLOOKUP = Arrays.asList( + ContentModel.PROP_CREATOR, + ContentModel.PROP_MODIFIER, + ContentModel.PROP_OWNER, + ContentModel.PROP_LOCK_OWNER, + ContentModel.PROP_WORKING_COPY_OWNER); + + private final static Map MAP_PARAM_QNAME; + static + { + Map aMap = new HashMap<>(9); + + aMap.put(PARAM_ISFOLDER, GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER); + aMap.put(PARAM_NAME, ContentModel.PROP_NAME); + aMap.put(PARAM_CREATEDAT, ContentModel.PROP_CREATED); + aMap.put(PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED); + aMap.put(PARAM_CREATEBYUSER, ContentModel.PROP_CREATOR); + aMap.put(PARAM_MODIFIEDBYUSER, ContentModel.PROP_MODIFIER); + aMap.put(PARAM_MIMETYPE, GetChildrenCannedQuery.SORT_QNAME_CONTENT_MIMETYPE); + aMap.put(PARAM_SIZEINBYTES, GetChildrenCannedQuery.SORT_QNAME_CONTENT_SIZE); + aMap.put(PARAM_NODETYPE, GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE); + + MAP_PARAM_QNAME = Collections.unmodifiableMap(aMap); + } + + // list children filtering (via where clause) + private final static Set LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES = + new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY, PARAM_ASSOC_TYPE})); + + /* + * Validates that node exists. + * + * Note: assumes workspace://SpacesStore + */ + @Override + public NodeRef validateNode(String nodeId) + { + return validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); + } + + @Override + public NodeRef validateNode(StoreRef storeRef, String nodeId) + { + String versionLabel = null; + + int idx = nodeId.indexOf(";"); + if (idx != -1) + { + versionLabel = nodeId.substring(idx + 1); + nodeId = nodeId.substring(0, idx); + if (versionLabel.equals("pwc")) + { + // TODO correct exception? + throw new EntityNotFoundException(nodeId); + } + } + + NodeRef nodeRef = new NodeRef(storeRef, nodeId); + return validateNode(nodeRef); + } + + @Override + public NodeRef validateNode(NodeRef nodeRef) + { + if (!nodeService.exists(nodeRef)) + { + throw new EntityNotFoundException(nodeRef.getId()); + } + + return nodeRef; + } + + /* + * Check that nodes exists and matches given expected/excluded type(s). + */ + @Override + public boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes) + { + return nodeMatches(nodeRef, expectedTypes, excludedTypes, true); + } + + @Override + public boolean isSubClass(NodeRef nodeRef, QName ofClassQName, boolean validateNodeRef) + { + if (validateNodeRef) + { + nodeRef = validateNode(nodeRef); + } + return isSubClass(getNodeType(nodeRef), ofClassQName); + } + + private boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes, boolean existsCheck) + { + if (existsCheck && (! nodeService.exists(nodeRef))) + { + throw new EntityNotFoundException(nodeRef.getId()); + } + + return typeMatches(getNodeType(nodeRef), expectedTypes, excludedTypes); + } + + private QName getNodeType(NodeRef nodeRef) + { + return nodeService.getType(nodeRef); + } + + private boolean isSubClass(QName className, QName ofClassQName) + { + return dictionaryService.isSubClass(className, ofClassQName); + } + + protected boolean typeMatches(QName type, Set expectedTypes, Set excludedTypes) + { + if (((expectedTypes != null) && (expectedTypes.size() == 1)) && + ((excludedTypes == null) || (excludedTypes.size() == 0))) + { + // use isSubClass if checking against single expected type (and no excluded types) + return isSubClass(type, expectedTypes.iterator().next()); + } + + Set allExpectedTypes = new HashSet<>(); + if (expectedTypes != null) + { + for (QName expectedType : expectedTypes) + { + allExpectedTypes.addAll(dictionaryService.getSubTypes(expectedType, true)); + } + } + + Set allExcludedTypes = new HashSet<>(); + if (excludedTypes != null) + { + for (QName excludedType : excludedTypes) + { + allExcludedTypes.addAll(dictionaryService.getSubTypes(excludedType, true)); + } + } + + boolean inExpected = allExpectedTypes.contains(type); + boolean excluded = allExcludedTypes.contains(type); + return (inExpected && !excluded); + } + + /** + * @deprecated review usage (backward compat') + */ + @Override + public Node getNode(String nodeId) + { + NodeRef nodeRef = validateNode(nodeId); + + return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); + } + + /** + * @deprecated review usage (backward compat') + */ + public Node getNode(NodeRef nodeRef) + { + return new Node(nodeRef, null, nodeService.getProperties(nodeRef), null, sr); + } + + private Type getType(NodeRef nodeRef) + { + return getType(getNodeType(nodeRef), nodeRef); + } + + private Type getType(QName typeQName, NodeRef nodeRef) + { + // quick check for common types + if (typeQName.equals(ContentModel.TYPE_FOLDER) || typeQName.equals(ApplicationModel.TYPE_FOLDERLINK)) + { + return Type.FOLDER; + } + else if (typeQName.equals(ContentModel.TYPE_CONTENT) || typeQName.equals(ApplicationModel.TYPE_FILELINK)) + { + return Type.DOCUMENT; + } + + // further checks + + if (isSubClass(typeQName, ContentModel.TYPE_LINK)) + { + if (isSubClass(typeQName, ApplicationModel.TYPE_FOLDERLINK)) + { + return Type.FOLDER; + } + else if (isSubClass(typeQName, ApplicationModel.TYPE_FILELINK)) + { + return Type.DOCUMENT; + } + + NodeRef linkNodeRef = (NodeRef)nodeService.getProperty(nodeRef, ContentModel.PROP_LINK_DESTINATION); + if (linkNodeRef != null) + { + try + { + typeQName = getNodeType(linkNodeRef); + // drop-through to check type of destination + // note: edge-case - if link points to another link then we will return null + } + catch (InvalidNodeRefException inre) + { + // ignore + } + } + } + + if (isSubClass(typeQName, ContentModel.TYPE_FOLDER)) + { + if (! isSubClass(typeQName, ContentModel.TYPE_SYSTEM_FOLDER)) + { + return Type.FOLDER; + } + return null; // unknown + } + else if (isSubClass(typeQName, ContentModel.TYPE_CONTENT)) + { + return Type.DOCUMENT; + } + + return null; // unknown + } + + /** + * @deprecated note: currently required for backwards compat' (Favourites API) + */ + @Override + public Document getDocument(NodeRef nodeRef) + { + Type type = getType(nodeRef); + if ((type != null) && type.equals(Type.DOCUMENT)) + { + Map properties = nodeService.getProperties(nodeRef); + + Document doc = new Document(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); + + doc.setVersionLabel((String) properties.get(ContentModel.PROP_VERSION_LABEL)); + ContentData cd = (ContentData) properties.get(ContentModel.PROP_CONTENT); + if (cd != null) + { + doc.setSizeInBytes(BigInteger.valueOf(cd.getSize())); + doc.setMimeType((cd.getMimetype())); + } + + setCommonProps(doc, nodeRef, properties); + return doc; + } + else + { + throw new InvalidArgumentException("Node is not a file: "+nodeRef.getId()); + } + } + + private void setCommonProps(Node node, NodeRef nodeRef, Map properties) + { + node.setGuid(nodeRef); + node.setTitle((String)properties.get(ContentModel.PROP_TITLE)); + node.setDescription((String)properties.get(ContentModel.PROP_TITLE)); + node.setModifiedBy((String)properties.get(ContentModel.PROP_MODIFIER)); + node.setCreatedBy((String)properties.get(ContentModel.PROP_CREATOR)); + } + + /** + * @deprecated note: currently required for backwards compat' (Favourites API) + */ + @Override + public Folder getFolder(NodeRef nodeRef) + { + Type type = getType(nodeRef); + if ((type != null) && type.equals(Type.FOLDER)) + { + Map properties = nodeService.getProperties(nodeRef); + + Folder folder = new Folder(nodeRef, getParentNodeRef(nodeRef), properties, null, sr); + setCommonProps(folder, nodeRef, properties); + return folder; + } + else + { + throw new InvalidArgumentException("Node is not a folder: "+nodeRef.getId()); + } + } + + private NodeRef getParentNodeRef(NodeRef nodeRef) + { + if (repositoryHelper.getCompanyHome().equals(nodeRef)) + { + return null; // note: does not make sense to return parent above C/H + } + + return nodeService.getPrimaryParent(nodeRef).getParentRef(); + } + + public NodeRef validateOrLookupNode(String nodeId, String path) + { + NodeRef parentNodeRef; + + if ((nodeId == null) || (nodeId.isEmpty())) + { + throw new InvalidArgumentException("Missing nodeId"); + } + + if (nodeId.equals(PATH_ROOT)) + { + parentNodeRef = repositoryHelper.getCompanyHome(); + } + else if (nodeId.equals(PATH_SHARED)) + { + parentNodeRef = repositoryHelper.getSharedHome(); + } + else if (nodeId.equals(PATH_MY)) + { + NodeRef person = repositoryHelper.getPerson(); + if (person == null) + { + throw new InvalidArgumentException("Unexpected - cannot use: " + PATH_MY); + } + parentNodeRef = repositoryHelper.getUserHome(person); + if (parentNodeRef == null) + { + throw new EntityNotFoundException(nodeId); + } + } + else + { + parentNodeRef = validateNode(nodeId); + } + + if (path != null) + { + // check that parent is a folder before resolving relative path + if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) + { + throw new InvalidArgumentException("NodeId of folder is expected: "+parentNodeRef.getId()); + } + + // resolve path relative to current nodeId + parentNodeRef = resolveNodeByPath(parentNodeRef, path, true); + } + + return parentNodeRef; + } + + protected NodeRef resolveNodeByPath(final NodeRef parentNodeRef, String path, boolean checkForCompanyHome) + { + final List pathElements = getPathElements(path); + + if (!pathElements.isEmpty() && checkForCompanyHome) + { + /* + if (nodeService.getRootNode(parentNodeRef.getStoreRef()).equals(parentNodeRef)) + { + // special case + NodeRef chNodeRef = repositoryHelper.getCompanyHome(); + String chName = (String) nodeService.getProperty(chNodeRef, ContentModel.PROP_NAME); + if (chName.equals(pathElements.get(0))) + { + pathElements = pathElements.subList(1, pathElements.size()); + parentNodeRef = chNodeRef; + } + } + */ + } + + FileInfo fileInfo = null; + try + { + if (!pathElements.isEmpty()) + { + fileInfo = fileFolderService.resolveNamePath(parentNodeRef, pathElements); + } + else + { + fileInfo = fileFolderService.getFileInfo(parentNodeRef); + if (fileInfo == null) + { + throw new EntityNotFoundException(parentNodeRef.getId()); + } + } + } + catch (FileNotFoundException fnfe) + { + // convert checked exception + throw new NotFoundException("The entity with relativePath: " + path + " was not found."); + } + catch (AccessDeniedException ade) + { + // return 404 instead of 403 (as per security review - uuid vs path) + throw new NotFoundException("The entity with relativePath: " + path + " was not found."); + } + + return fileInfo.getNodeRef(); + } + + private List getPathElements(String path) + { + final List pathElements = new ArrayList<>(); + if (path != null && path.trim().length() > 0) + { + // There is no need to check for leading and trailing "/" + final StringTokenizer tokenizer = new StringTokenizer(path, "/"); + while (tokenizer.hasMoreTokens()) + { + pathElements.add(tokenizer.nextToken().trim()); + } + } + return pathElements; + } + + private NodeRef makeFolders(NodeRef parentNodeRef, List pathElements) + { + NodeRef currentParentRef = parentNodeRef; + // just loop and create if necessary + for (final String element : pathElements) + { + final NodeRef contextNodeRef = currentParentRef; + // does it exist? + // Navigation should not check permissions + NodeRef nodeRef = AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + return nodeService.getChildByName(contextNodeRef, ContentModel.ASSOC_CONTAINS, element); + } + }, AuthenticationUtil.getSystemUserName()); + + if (nodeRef == null) + { + try + { + // Checks for create permissions as the fileFolderService is a public service. + FileInfo createdFileInfo = fileFolderService.create(currentParentRef, element, ContentModel.TYPE_FOLDER); + currentParentRef = createdFileInfo.getNodeRef(); + } + catch (AccessDeniedException ade) + { + throw new PermissionDeniedException(ade.getMessage()); + } + catch (FileExistsException fex) + { + // Assume concurrency failure, so retry + throw new ConcurrencyFailureException(fex.getMessage()); + } + } + else if (!isSubClass(nodeRef, ContentModel.TYPE_FOLDER, false)) + { + String parentName = (String) nodeService.getProperty(contextNodeRef, ContentModel.PROP_NAME); + throw new ConstraintViolatedException("Name [" + element + "] already exists in the target parent: " + parentName); + } + else + { + // it exists + currentParentRef = nodeRef; + } + } + return currentParentRef; + } + + @Override + public Node getFolderOrDocument(String nodeId, Parameters parameters) + { + String path = parameters.getParameter(PARAM_RELATIVE_PATH); + NodeRef nodeRef = validateOrLookupNode(nodeId, path); + + return getFolderOrDocumentFullInfo(nodeRef, null, null, parameters); + } + + private Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters) + { + return getFolderOrDocumentFullInfo(nodeRef, parentNodeRef, nodeTypeQName, parameters, null); + } + + @Override + public Node getFolderOrDocumentFullInfo(NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, Parameters parameters, Map mapUserInfo) + { + List includeParam = new ArrayList<>(); + if (parameters != null) + { + includeParam.addAll(parameters.getInclude()); + } + + // Add basic info for single get (above & beyond minimal that is used for listing collections) + includeParam.add(PARAM_INCLUDE_ASPECTNAMES); + includeParam.add(PARAM_INCLUDE_PROPERTIES); + + return getFolderOrDocument(nodeRef, parentNodeRef, nodeTypeQName, includeParam, mapUserInfo); + } + + @Override + public Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, List includeParam, Map mapUserInfo) + { + if (mapUserInfo == null) + { + mapUserInfo = new HashMap<>(2); + } + + if (includeParam == null) + { + includeParam = Collections.emptyList(); + } + + Node node; + Map properties = nodeService.getProperties(nodeRef); + + PathInfo pathInfo = null; + if (includeParam.contains(PARAM_INCLUDE_PATH)) + { + ChildAssociationRef archivedParentAssoc = (ChildAssociationRef) properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC); + pathInfo = lookupPathInfo(nodeRef, archivedParentAssoc); + } + + if (nodeTypeQName == null) + { + nodeTypeQName = getNodeType(nodeRef); + } + + if (parentNodeRef == null) + { + parentNodeRef = getParentNodeRef(nodeRef); + } + + Type type = getType(nodeTypeQName, nodeRef); + + if (type == null) + { + // not direct folder (or file) ... + // might be sub-type of cm:cmobject (or a cm:link pointing to cm:cmobject or possibly even another cm:link) + node = new Node(nodeRef, parentNodeRef, properties, mapUserInfo, sr); + node.setIsFolder(false); + node.setIsFile(false); + } + else if (type.equals(Type.DOCUMENT)) + { + node = new Document(nodeRef, parentNodeRef, properties, mapUserInfo, sr); + } + else if (type.equals(Type.FOLDER)) + { + node = new Folder(nodeRef, parentNodeRef, properties, mapUserInfo, sr); + } + else + { + throw new RuntimeException("Unexpected - should not reach here: "+type); + } + + if (includeParam.size() > 0) + { + node.setProperties(mapFromNodeProperties(properties, includeParam, mapUserInfo)); + } + + if (includeParam.contains(PARAM_INCLUDE_ASPECTNAMES)) + { + node.setAspectNames(mapFromNodeAspects(nodeService.getAspects(nodeRef))); + } + + if (includeParam.contains(PARAM_INCLUDE_ISLINK)) + { + boolean isLink = isSubClass(nodeTypeQName, ContentModel.TYPE_LINK); + node.setIsLink(isLink); + } + + if (includeParam.contains(PARAM_INCLUDE_ALLOWABLEOPERATIONS)) + { + // note: refactor when requirements change + Map mapPermsToOps = new HashMap<>(3); + mapPermsToOps.put(PermissionService.DELETE, OP_DELETE); + mapPermsToOps.put(PermissionService.ADD_CHILDREN, OP_CREATE); + mapPermsToOps.put(PermissionService.WRITE, OP_UPDATE); + + List allowableOperations = new ArrayList<>(3); + for (Entry kv : mapPermsToOps.entrySet()) + { + String perm = kv.getKey(); + String op = kv.getValue(); + + if (perm.equals(PermissionService.ADD_CHILDREN) && type.equals(Type.DOCUMENT)) + { + // special case: do not return "create" (as an allowable op) for file/content types + continue; + } + else if (perm.equals(PermissionService.DELETE) && (isSpecialNodeDoNotDelete(nodeRef, nodeTypeQName))) + { + // special case: do not return "delete" (as an allowable op) for specific system nodes + continue; + } + else if (permissionService.hasPermission(nodeRef, perm) == AccessStatus.ALLOWED) + { + allowableOperations.add(op); + } + } + + node.setAllowableOperations((allowableOperations.size() > 0 )? allowableOperations : null); + } + + if (includeParam.contains(PARAM_INCLUDE_ASSOCIATION)) + { + // Ugh ... can we optimise this and return the actual assoc directly (via FileFolderService/GetChildrenCQ) ? + ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef); + + // note: parentAssocRef.parentRef can be null for -root- node ! + if ((parentAssocRef == null) || (parentAssocRef.getParentRef() == null) || (! parentAssocRef.getParentRef().equals(parentNodeRef))) + { + List parentAssocRefs = nodeService.getParentAssocs(nodeRef); + for (ChildAssociationRef pAssocRef : parentAssocRefs) + { + if (pAssocRef.getParentRef().equals(parentNodeRef)) + { + // for now, assume same parent/child cannot appear more than once (due to unique name) + parentAssocRef = pAssocRef; + break; + } + } + } + + if (parentAssocRef != null) + { + QName assocTypeQName = parentAssocRef.getTypeQName(); + if ((assocTypeQName != null) && (! EXCLUDED_NS.contains(assocTypeQName.getNamespaceURI()))) + { + AssocChild childAssoc = new AssocChild( + assocTypeQName.toPrefixString(namespaceService), + parentAssocRef.isPrimary()); + + node.setAssociation(childAssoc); + } + } + } + + node.setNodeType(nodeTypeQName.toPrefixString(namespaceService)); + node.setPath(pathInfo); + + return node; + } + + protected PathInfo lookupPathInfo(NodeRef nodeRefIn, ChildAssociationRef archivedParentAssoc) + { + + List pathElements = new ArrayList<>(); + Boolean isComplete = Boolean.TRUE; + final Path nodePath; + final int pathIndex; + + if (archivedParentAssoc != null) + { + if (permissionService.hasPermission(archivedParentAssoc.getParentRef(), PermissionService.READ).equals(AccessStatus.ALLOWED) + && nodeService.exists(archivedParentAssoc.getParentRef())) + { + nodePath = nodeService.getPath(archivedParentAssoc.getParentRef()); + pathIndex = 1;// 1 => we want to include the given node in the path as well. + } + else + { + //We can't return a valid path + return null; + } + } + else + { + nodePath = nodeService.getPath(nodeRefIn); + pathIndex = 2; // 2 => as we don't want to include the given node in the path as well. + } + + for (int i = nodePath.size() - pathIndex; i >= 0; i--) + { + Element element = nodePath.get(i); + if (element instanceof Path.ChildAssocElement) + { + ChildAssociationRef elementRef = ((Path.ChildAssocElement) element).getRef(); + if (elementRef.getParentRef() != null) + { + NodeRef childNodeRef = elementRef.getChildRef(); + if (permissionService.hasPermission(childNodeRef, PermissionService.READ) == AccessStatus.ALLOWED) + { + Serializable nameProp = nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); + pathElements.add(0, new ElementInfo(childNodeRef.getId(), nameProp.toString())); + } + else + { + // Just return the pathInfo up to the location where the user has access + isComplete = Boolean.FALSE; + break; + } + } + } + } + + String pathStr = null; + if (pathElements.size() > 0) + { + StringBuilder sb = new StringBuilder(120); + for (PathInfo.ElementInfo e : pathElements) + { + sb.append("/").append(e.getName()); + } + pathStr = sb.toString(); + } + else + { + // There is no path element, so set it to null in order to be + // ignored by Jackson during serialisation + isComplete = null; + } + return new PathInfo(pathStr, isComplete, pathElements); + } + + protected Set mapToNodeAspects(List aspectNames) + { + Set nodeAspects = new HashSet<>(aspectNames.size()); + + for (String aspectName : aspectNames) + { + QName aspectQName = createQName(aspectName); + + AspectDefinition ad = dictionaryService.getAspect(aspectQName); + if (ad != null) + { + nodeAspects.add(aspectQName); + } + else + { + throw new InvalidArgumentException("Unknown aspect: " + aspectName); + } + } + + return nodeAspects; + } + + protected Map mapToNodeProperties(Map props) + { + Map nodeProps = new HashMap<>(props.size()); + + for (Entry entry : props.entrySet()) + { + String propName = entry.getKey(); + QName propQName = createQName(propName); + + PropertyDefinition pd = dictionaryService.getProperty(propQName); + if (pd != null) + { + Serializable value; + if (pd.getDataType().getName().equals(DataTypeDefinition.NODE_REF)) + { + String nodeRefString = (String) entry.getValue(); + if (! NodeRef.isNodeRef(nodeRefString)) + { + value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRefString); + } + else + { + value = new NodeRef(nodeRefString); + } + } + else + { + value = (Serializable)entry.getValue(); + } + nodeProps.put(propQName, value); + } + else + { + throw new InvalidArgumentException("Unknown property: " + propName); + } + } + + return nodeProps; + } + + protected Map mapFromNodeProperties(Map nodeProps, List selectParam, Map mapUserInfo) + { + List selectedProperties; + + if ((selectParam.size() == 0) || selectParam.contains(PARAM_INCLUDE_PROPERTIES)) + { + // return all properties + selectedProperties = new ArrayList<>(nodeProps.size()); + for (QName propQName : nodeProps.keySet()) + { + if ((! EXCLUDED_NS.contains(propQName.getNamespaceURI())) && (! EXCLUDED_PROPS.contains(propQName))) + { + selectedProperties.add(propQName); + } + } + } + else + { + // return selected properties + selectedProperties = createQNames(selectParam); + } + + Map props = null; + if (!selectedProperties.isEmpty()) + { + props = new HashMap<>(selectedProperties.size()); + + for (QName qName : selectedProperties) + { + Serializable value = nodeProps.get(qName); + if (value != null) + { + if (PROPS_USERLOOKUP.contains(qName)) + { + value = Node.lookupUserInfo((String)value, mapUserInfo, sr.getPersonService()); + } + props.put(qName.toPrefixString(namespaceService), value); + } + } + if (props.isEmpty()) + { + props = null; // set to null so it doesn't show up as an empty object in the JSON response. + } + } + + return props; + } + + protected List mapFromNodeAspects(Set nodeAspects) + { + List aspectNames = new ArrayList<>(nodeAspects.size()); + + for (QName aspectQName : nodeAspects) + { + if ((! EXCLUDED_NS.contains(aspectQName.getNamespaceURI())) && (! EXCLUDED_ASPECTS.contains(aspectQName))) + { + aspectNames.add(aspectQName.toPrefixString(namespaceService)); + } + } + + if (aspectNames.size() == 0) + { + aspectNames = null; // no aspects to return + } + + return aspectNames; + } + + @Override + public CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters) + { + String path = parameters.getParameter(PARAM_RELATIVE_PATH); + + final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path); + + final List includeParam = parameters.getInclude(); + + // filters + Boolean includeFolders = null; + Boolean includeFiles = null; + Boolean isPrimary = null; + QName assocTypeQNameParam = null; + QName filterNodeTypeQName = null; + + // note: for files/folders, include subtypes by default (unless filtering by a specific nodeType - see below) + boolean filterIncludeSubTypes = true; + + Query q = parameters.getQuery(); + + if (q != null) + { + // filtering via "where" clause + MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES, null); + QueryHelper.walk(q, propertyWalker); + + isPrimary = propertyWalker.getProperty(PARAM_ISPRIMARY, WhereClauseParser.EQUALS, Boolean.class); + + String assocTypeQNameStr = propertyWalker.getProperty(PARAM_ASSOC_TYPE, WhereClauseParser.EQUALS, String.class); + if (assocTypeQNameStr != null) + { + assocTypeQNameParam = getAssocType(assocTypeQNameStr); + } + + Boolean isFolder = propertyWalker.getProperty(PARAM_ISFOLDER, WhereClauseParser.EQUALS, Boolean.class); + Boolean isFile = propertyWalker.getProperty(PARAM_ISFILE, WhereClauseParser.EQUALS, Boolean.class); + + if (isFolder != null) + { + includeFolders = isFolder; + } + + if (isFile != null) + { + includeFiles = isFile; + } + + if (Boolean.TRUE.equals(includeFiles) && Boolean.TRUE.equals(includeFolders)) + { + throw new InvalidArgumentException("Invalid filter (isFile=true and isFolder=true) - a node cannot be both a file and a folder"); + } + + String nodeTypeStr = propertyWalker.getProperty(PARAM_NODETYPE, WhereClauseParser.EQUALS, String.class); + if ((nodeTypeStr != null) && (! nodeTypeStr.isEmpty())) + { + if ((isFile != null) || (isFolder != null)) + { + throw new InvalidArgumentException("Invalid filter - nodeType and isFile/isFolder are mutually exclusive"); + } + + Pair pair = parseNodeTypeFilter(nodeTypeStr); + filterNodeTypeQName = pair.getFirst(); + filterIncludeSubTypes = pair.getSecond(); + } + } + + List sortCols = parameters.getSorting(); + List> sortProps = null; + if ((sortCols != null) && (sortCols.size() > 0)) + { + // TODO should we allow isFile in sort (and map to reverse of isFolder) ? + sortProps = new ArrayList<>(sortCols.size()); + for (SortColumn sortCol : sortCols) + { + QName propQname = MAP_PARAM_QNAME.get(sortCol.column); + if (propQname == null) + { + propQname = createQName(sortCol.column); + } + + if (propQname != null) + { + sortProps.add(new Pair<>(propQname, sortCol.asc)); + } + } + } + else + { + // default sort order + sortProps = new ArrayList<>(Arrays.asList( + new Pair<>(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, Boolean.FALSE), + new Pair<>(ContentModel.PROP_NAME, true))); + } + + List filterProps = null; + if (isPrimary != null) + { + filterProps = new ArrayList<>(1); + filterProps.add(new FilterPropBoolean(GetChildrenCannedQuery.FILTER_QNAME_NODE_IS_PRIMARY, isPrimary)); + } + + Paging paging = parameters.getPaging(); + + PagingRequest pagingRequest = Util.getPagingRequest(paging); + + final PagingResults pagingResults; + + // notes (see also earlier validation checks): + // - no filtering means any types/sub-types (well, apart from hidden &/or default ignored types - eg. systemfolder, fm types) + // - node type filtering is mutually exclusive from isFile/isFolder, can optionally also include sub-types + // - isFile & isFolder cannot both be true + // - (isFile=false) means any other types/sub-types (other than files) + // - (isFolder=false) means any other types/sub-types (other than folders) + // - (isFile=false and isFolder=false) means any other types/sub-types (other than files or folders) + + if (filterNodeTypeQName == null) + { + if ((includeFiles == null) && (includeFolders == null)) + { + // no additional filtering + filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; + } + else if ((includeFiles != null) && (includeFolders != null)) + { + if ((! includeFiles) && (! includeFolders)) + { + // no files or folders + filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; + } + } + else if ((includeFiles != null) && (! includeFiles)) + { + // no files + filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; + } + else if ((includeFolders != null) && (! includeFolders)) + { + // no folders + filterNodeTypeQName = ContentModel.TYPE_CMOBJECT; + } + } + + Pair, Set> pair = buildSearchTypesAndIgnoreAspects(filterNodeTypeQName, filterIncludeSubTypes, ignoreQNames, includeFiles, includeFolders); + Set searchTypeQNames = pair.getFirst(); + Set ignoreAspectQNames = pair.getSecond(); + + Set assocTypeQNames = buildAssocTypes(assocTypeQNameParam); + + // call GetChildrenCannedQuery (via FileFolderService) + pagingResults = fileFolderService.list(parentNodeRef, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest); + + + final Map mapUserInfo = new HashMap<>(10); + + final List page = pagingResults.getPage(); + List nodes = new AbstractList() + { + @Override + public Node get(int index) + { + FileInfo fInfo = page.get(index); + + // minimal info by default (unless "include"d otherwise) + return getFolderOrDocument(fInfo.getNodeRef(), parentNodeRef, fInfo.getType(), includeParam, mapUserInfo); + } + + @Override + public int size() + { + return page.size(); + } + }; + + Node sourceEntity = null; + if (parameters.includeSource()) + { + sourceEntity = getFolderOrDocumentFullInfo(parentNodeRef, null, null, null, mapUserInfo); + } + + return CollectionWithPagingInfo.asPaged(paging, nodes, pagingResults.hasMoreItems(), pagingResults.getTotalResultCount().getFirst(), sourceEntity); + } + + private Pair parseNodeTypeFilter(String nodeTypeStr) + { + boolean filterIncludeSubTypes = false; // default nodeType filtering is without subTypes (unless nodeType value is suffixed with ' INCLUDESUBTYPES') + + int idx = nodeTypeStr.lastIndexOf(' '); + if (idx > 0) + { + String suffix = nodeTypeStr.substring(idx); + if (suffix.equalsIgnoreCase(" "+PARAM_INCLUDE_SUBTYPES)) + { + filterIncludeSubTypes = true; + nodeTypeStr = nodeTypeStr.substring(0, idx); + } + } + + QName filterNodeTypeQName = createQName(nodeTypeStr); + if (dictionaryService.getType(filterNodeTypeQName) == null) + { + throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr); + } + + return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes); + } + + protected Set buildAssocTypes(QName assocTypeQName) + { + Set assocTypeQNames = null; + if (assocTypeQName != null) + { + assocTypeQNames = Collections.singleton(assocTypeQName); + } + /* + // TODO review - this works, but reduces from ~100 to ~96 (OOTB) + // maybe we could post filter (rather than join) - examples: sys:children, sys:lost_found, sys:archivedLink, sys:archiveUserLink + else + { + Collection qnames = dictionaryService.getAllAssociations(); + assocTypeQNames = new HashSet<>(qnames.size()); + + // remove system assoc types + for (QName qname : qnames) + { + if ((!EXCLUDED_NS.contains(qname.getNamespaceURI()))) + { + assocTypeQNames.add(qname); + } + } + } + */ + return assocTypeQNames; + } + + protected Pair, Set> buildSearchTypesAndIgnoreAspects(QName nodeTypeQName, boolean includeSubTypes, Set ignoreQNameTypes, Boolean includeFiles, Boolean includeFolders) + { + Set searchTypeQNames = new HashSet<>(100); + Set ignoreAspectQNames = null; + + if (nodeTypeQName != null) + { + // Build a list of (sub-)types + if (includeSubTypes) + { + Collection qnames = dictionaryService.getSubTypes(nodeTypeQName, true); + searchTypeQNames.addAll(qnames); + } + searchTypeQNames.add(nodeTypeQName); + + // Remove 'system' folders + if (includeSubTypes) + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_SYSTEM_FOLDER, true); + searchTypeQNames.removeAll(qnames); + } + searchTypeQNames.remove(ContentModel.TYPE_SYSTEM_FOLDER); + } + + if (includeFiles != null) + { + if (includeFiles) + { + if (includeSubTypes) + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true); + searchTypeQNames.addAll(qnames); + } + searchTypeQNames.add(ContentModel.TYPE_CONTENT); + } + else + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true); + searchTypeQNames.removeAll(qnames); + searchTypeQNames.remove(ContentModel.TYPE_CONTENT); + } + } + + if (includeFolders != null) + { + if (includeFolders) + { + if (includeSubTypes) + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_FOLDER, true); + searchTypeQNames.addAll(qnames); + } + searchTypeQNames.add(ContentModel.TYPE_FOLDER); + + // Remove 'system' folders + if (includeSubTypes) + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_SYSTEM_FOLDER, true); + searchTypeQNames.removeAll(qnames); + } + searchTypeQNames.remove(ContentModel.TYPE_SYSTEM_FOLDER); + } + else + { + Collection qnames = dictionaryService.getSubTypes(ContentModel.TYPE_FOLDER, true); + searchTypeQNames.removeAll(qnames); + searchTypeQNames.remove(ContentModel.TYPE_FOLDER); + } + } + + if (ignoreQNameTypes != null) + { + Set ignoreQNamesNotSearchTypes = new HashSet<>(ignoreQNameTypes); + ignoreQNamesNotSearchTypes.removeAll(searchTypeQNames); + ignoreQNamesNotSearchTypes.remove(ContentModel.TYPE_SYSTEM_FOLDER); + + if (ignoreQNamesNotSearchTypes.size() > 0) + { + ignoreAspectQNames = getAspectsToIgnore(ignoreQNamesNotSearchTypes); + } + + searchTypeQNames.removeAll(ignoreQNameTypes); + } + + return new Pair<>(searchTypeQNames, ignoreAspectQNames); + } + + private Set getAspectsToIgnore(Set ignoreQNames) + { + Set ignoreQNameAspects = new HashSet<>(ignoreQNames.size()); + for (QName qname : ignoreQNames) + { + if (dictionaryService.getAspect(qname) != null) + { + ignoreQNameAspects.add(qname); + } + } + return ignoreQNameAspects; + } + + @Override + public void deleteNode(String nodeId, Parameters parameters) + { + NodeRef nodeRef = validateOrLookupNode(nodeId, null); + + if (isSpecialNodeDoNotDelete(nodeRef, getNodeType(nodeRef))) + { + throw new PermissionDeniedException("Cannot delete: " + nodeId); + } + + // default false (if not provided) + boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT)); + + if (permanentDelete == true) + { + boolean isAdmin = authorityService.hasAdminAuthority(); + if (! isAdmin) + { + String owner = ownableService.getOwner(nodeRef); + if (! AuthenticationUtil.getRunAsUser().equals(owner)) + { + // non-owner/non-admin cannot permanently delete (even if they have delete permission) + throw new PermissionDeniedException("Non-owner/non-admin cannot permanently delete: " + nodeId); + } + } + + // Set as temporary to delete node instead of archiving. + nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); + } + + final ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); + postActivity(Activity_Type.DELETED, activityInfo, true); + + fileFolderService.delete(nodeRef); + } + + @Override + public Node createNode(String parentFolderNodeId, Node nodeInfo, Parameters parameters) + { + if (nodeInfo.getNodeRef() != null) + { + throw new InvalidArgumentException("Unexpected id when trying to create a new node: "+nodeInfo.getNodeRef().getId()); + } + + // check that requested parent node exists and it's type is a (sub-)type of folder + NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); + + // node name - mandatory + String nodeName = nodeInfo.getName(); + if ((nodeName == null) || nodeName.isEmpty()) + { + throw new InvalidArgumentException("Node name is expected: "+parentNodeRef.getId()); + } + + // node type - check that requested type is a (sub-) type of cm:object + String nodeType = nodeInfo.getNodeType(); + if ((nodeType == null) || nodeType.isEmpty()) + { + throw new InvalidArgumentException("Node type is expected: "+parentNodeRef.getId()+","+nodeName); + } + + QName nodeTypeQName = createQName(nodeType); + + boolean isContent = isSubClass(nodeTypeQName, ContentModel.TYPE_CONTENT); + if (! isContent) + { + validateCmObject(nodeTypeQName); + } + + /* RA-834: commented-out since not currently applicable for empty file + List thumbnailDefs = null; + String renditionsParam = parameters.getParameter(PARAM_RENDITIONS); + if (renditionsParam != null) + { + if (!isContent) + { + throw new InvalidArgumentException("Renditions ['"+renditionsParam+"'] only apply to content types: "+parentNodeRef.getId()+","+nodeName); + } + + thumbnailDefs = getThumbnailDefs(renditionsParam); + } + */ + + Map props = new HashMap<>(1); + + if (nodeInfo.getProperties() != null) + { + // node properties - set any additional properties + props = mapToNodeProperties(nodeInfo.getProperties()); + } + + // Existing file/folder name handling + boolean autoRename = Boolean.valueOf(parameters.getParameter(PARAM_AUTO_RENAME)); + if (autoRename && (isContent || isSubClass(nodeTypeQName, ContentModel.TYPE_FOLDER))) + { + NodeRef existingNode = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, nodeName); + if (existingNode != null) + { + // File already exists, find a unique name + nodeName = findUniqueName(parentNodeRef, nodeName); + } + } + + String relativePath = nodeInfo.getRelativePath(); + parentNodeRef = getOrCreatePath(parentNodeRef, relativePath); + + QName assocTypeQName = ContentModel.ASSOC_CONTAINS; + if ((nodeInfo.getAssociation() != null) && (nodeInfo.getAssociation().getAssocType() != null)) + { + assocTypeQName = getAssocType(nodeInfo.getAssociation().getAssocType()); + } + + // Create the node + NodeRef nodeRef = createNodeImpl(parentNodeRef, nodeName, nodeTypeQName, props, assocTypeQName); + + List aspectNames = nodeInfo.getAspectNames(); + if (aspectNames != null) + { + // node aspects - set any additional aspects + Set aspectQNames = mapToNodeAspects(aspectNames); + for (QName aspectQName : aspectQNames) + { + if (EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) + { + continue; // ignore + } + + nodeService.addAspect(nodeRef, aspectQName, null); + } + } + + if (isContent) + { + // add empty file + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + setWriterContentType(writer, new ContentInfoWrapper(nodeInfo.getContent()), nodeRef, false); + writer.putContent(""); + } + + // eg. to create mandatory assoc(s) + + if (nodeInfo.getTargets() != null) + { + addTargets(nodeRef.getId(), nodeInfo.getTargets()); + } + + if (nodeInfo.getSecondaryChildren() != null) + { + addChildren(nodeRef.getId(), nodeInfo.getSecondaryChildren()); + } + + Node newNode = getFolderOrDocument(nodeRef.getId(), parameters); + + /* RA-834: commented-out since not currently applicable for empty file + requestRenditions(thumbnailDefs, newNode); // note: noop for folder + */ + + return newNode; + } + + private NodeRef getOrCreatePath(NodeRef parentNodeRef, String relativePath) + { + if (relativePath != null) + { + List pathElements = getPathElements(relativePath); + + // Checks for the presence of, and creates as necessary, + // the folder structure in the provided path elements list. + if (!pathElements.isEmpty()) + { + parentNodeRef = makeFolders(parentNodeRef, pathElements); + } + } + + return parentNodeRef; + } + + public List addChildren(String parentNodeId, List entities) + { + NodeRef parentNodeRef = validateNode(parentNodeId); + + List result = new ArrayList<>(entities.size()); + + for (AssocChild assoc : entities) + { + QName assocTypeQName = getAssocType(assoc.getAssocType()); + + try + { + NodeRef childNodeRef = validateNode(assoc.getChildId()); + + String nodeName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); + QName assocChildQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)); + + nodeService.addChild(parentNodeRef, childNodeRef, assocTypeQName, assocChildQName); + } + catch (AssociationExistsException aee) + { + throw new ConstraintViolatedException(aee.getMessage()); + } + catch (DuplicateChildNodeNameException dcne) + { + throw new ConstraintViolatedException(dcne.getMessage()); + } + + result.add(assoc); + } + + return result; + } + + public List addTargets(String sourceNodeId, List entities) + { + List result = new ArrayList<>(entities.size()); + + NodeRef srcNodeRef = validateNode(sourceNodeId); + + for (AssocTarget assoc : entities) + { + String assocTypeStr = assoc.getAssocType(); + QName assocTypeQName = getAssocType(assocTypeStr); + + String targetNodeId = assoc.getTargetId(); + + try + { + NodeRef tgtNodeRef = validateNode(targetNodeId); + nodeAssocService.createAssociation(srcNodeRef, tgtNodeRef, assocTypeQName); + } + catch (AssociationExistsException aee) + { + throw new ConstraintViolatedException("Node association '"+assocTypeStr+"' already exists from "+sourceNodeId+" to "+targetNodeId); + } + catch (IllegalArgumentException iae) + { + // note: for now, we assume it is invalid assocType - alternatively, we could attempt to pre-validate via dictionary.getAssociation + throw new InvalidArgumentException(sourceNodeId+","+assocTypeStr+","+targetNodeId); + } + + result.add(assoc); + } + return result; + } + + public QName getAssocType(String assocTypeQNameStr) + { + return getAssocType(assocTypeQNameStr, true); + } + + public QName getAssocType(String assocTypeQNameStr, boolean mandatory) + { + QName assocType = null; + + if ((assocTypeQNameStr != null) && (! assocTypeQNameStr.isEmpty())) + { + assocType = createQName(assocTypeQNameStr); + if (dictionaryService.getAssociation(assocType) == null) + { + throw new InvalidArgumentException("Unknown assocType: " + assocTypeQNameStr); + } + + if (EXCLUDED_NS.contains(assocType.getNamespaceURI())) + { + throw new InvalidArgumentException("Invalid assocType: " + assocTypeQNameStr); + } + } + + if (mandatory && (assocType == null)) + { + throw new InvalidArgumentException("Missing assocType"); + } + + return assocType; + } + + + private NodeRef createNodeImpl(NodeRef parentNodeRef, String nodeName, QName nodeTypeQName, Map props, QName assocTypeQName) + { + NodeRef newNode = null; + if (props == null) + { + props = new HashMap<>(1); + } + props.put(ContentModel.PROP_NAME, nodeName); + + validatePropValues(props); + + QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)); + try + { + newNode = nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, props).getChildRef(); + } + catch (DuplicateChildNodeNameException dcne) + { + // duplicate - name clash + throw new ConstraintViolatedException(dcne.getMessage()); + } + + ActivityInfo activityInfo = getActivityInfo(parentNodeRef, newNode); + postActivity(Activity_Type.ADDED, activityInfo, false); + return newNode; + } + + /** + * Posts activites based on the activity_type. + * If the method is called with aSync=true then a TransactionListener is used post the activity + * afterCommit. Otherwise the activity posting is done synchronously. + * @param activity_type + * @param activityInfo + * @param aSync + */ + protected void postActivity(Activity_Type activity_type, ActivityInfo activityInfo, boolean aSync) + { + if (activityInfo == null) return; //Nothing to do. + + String activityType = determineActivityType(activity_type, activityInfo.getFileInfo().isFolder()); + if (activityType != null) + { + if (aSync) + { + ActivitiesTransactionListener txListener = new ActivitiesTransactionListener(activityType, activityInfo, + TenantUtil.getCurrentDomain(), Activities.APP_TOOL, Activities.RESTAPI_CLIENT, + poster, retryingTransactionHelper); + AlfrescoTransactionSupport.bindListener(txListener); + } + else + { + poster.postFileFolderActivity(activityType, null, TenantUtil.getCurrentDomain(), + activityInfo.getSiteId(), activityInfo.getParentNodeRef(), activityInfo.getNodeRef(), + activityInfo.getFileName(), Activities.APP_TOOL, Activities.RESTAPI_CLIENT, + activityInfo.getFileInfo()); + } + } + } + + protected ActivityInfo getActivityInfo(NodeRef parentNodeRef, NodeRef nodeRef) + { + SiteInfo siteInfo = siteService.getSite(nodeRef); + String siteId = (siteInfo != null ? siteInfo.getShortName() : null); + if(siteId != null && !siteId.equals("")) + { + FileInfo fileInfo = fileFolderService.getFileInfo(nodeRef); + if (fileInfo != null) + { + boolean isContent = isSubClass(fileInfo.getType(), ContentModel.TYPE_CONTENT); + + if (fileInfo.isFolder() || isContent) + { + return new ActivityInfo(null, parentNodeRef, siteId, fileInfo); + } + } + } + else + { + if (logger.isDebugEnabled()) + { + logger.debug("Non-site activity, so ignored " + nodeRef); + } + } + return null; + } + + protected static String determineActivityType(Activity_Type activity_type, boolean isFolder) + { + switch (activity_type) + { + case DELETED: + return isFolder ? ActivityType.FOLDER_DELETED:ActivityType.FILE_DELETED; + case ADDED: + return isFolder ? ActivityType.FOLDER_ADDED:ActivityType.FILE_ADDED; + case UPDATED: + if (!isFolder) return ActivityType.FILE_UPDATED; + break; + case DOWNLOADED: + if (!isFolder) return ActivityPoster.DOWNLOADED; + break; + } + return null; + } + + // check cm:cmobject (but *not* cm:systemfolder) + private void validateCmObject(QName nodeTypeQName) + { + if (! isSubClass(nodeTypeQName, ContentModel.TYPE_CMOBJECT)) + { + throw new InvalidArgumentException("Invalid type: " + nodeTypeQName + " - expected (sub-)type of cm:cmobject"); + } + + if (isSubClass(nodeTypeQName, ContentModel.TYPE_SYSTEM_FOLDER)) + { + throw new InvalidArgumentException("Invalid type: " + nodeTypeQName + " - cannot be (sub-)type of cm:systemfolder"); + } + } + + // special cases: additional validation of property values (if not done by underlying foundation services) + private void validatePropValues(Map props) + { + String newOwner = (String)props.get(ContentModel.PROP_OWNER); + if (newOwner != null) + { + // validate that user exists + if (! personService.personExists(newOwner)) + { + throw new InvalidArgumentException("Unknown owner: "+newOwner); + } + } + } + + // special case: additional delete validation (pending common lower-level service support) + // for blacklist of system nodes that should not be deleted, eg. Company Home, Sites, Data Dictionary + private boolean isSpecialNodeDoNotDelete(NodeRef nodeRef, QName type) + { + // Check for Company Home, Sites and Data Dictionary (note: must be tenant-aware) + + if (nodeRef.equals(repositoryHelper.getCompanyHome())) + { + return true; + } + else if (type.equals(SiteModel.TYPE_SITES) || type.equals(SiteModel.TYPE_SITE)) + { + // note: alternatively, we could inject SiteServiceInternal and use getSitesRoot (or indirectly via node locator) + return true; + } + else + { + String tenantDomain = TenantUtil.getCurrentDomain(); + NodeRef ddNodeRef = ddCache.get(tenantDomain); + if (ddNodeRef == null) + { + List ddAssocs = nodeService.getChildAssocs( + repositoryHelper.getCompanyHome(), + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "dictionary")); + if (ddAssocs.size() == 1) + { + ddNodeRef = ddAssocs.get(0).getChildRef(); + ddCache.put(tenantDomain, ddNodeRef); + } + } + + if (nodeRef.equals(ddNodeRef)) + { + return true; + } + } + + return false; + } + + @Override + public Node updateNode(String nodeId, Node nodeInfo, Parameters parameters) + { + final NodeRef nodeRef = validateNode(nodeId); + + QName nodeTypeQName = getNodeType(nodeRef); + + validateCmObject(nodeTypeQName); + + Map props = new HashMap<>(0); + + if (nodeInfo.getProperties() != null) + { + props = mapToNodeProperties(nodeInfo.getProperties()); + } + + String name = nodeInfo.getName(); + if ((name != null) && (! name.isEmpty())) + { + // update node name if needed - note: if the name is different than existing then this is equivalent of a rename (within parent folder) + props.put(ContentModel.PROP_NAME, name); + } + + String nodeType = nodeInfo.getNodeType(); + if ((nodeType != null) && (! nodeType.isEmpty())) + { + // update node type - ensure that we are performing a specialise (we do not support generalise) + QName destNodeTypeQName = createQName(nodeType); + + if ((! destNodeTypeQName.equals(nodeTypeQName)) && + isSubClass(destNodeTypeQName, nodeTypeQName) && + (! isSubClass(destNodeTypeQName, ContentModel.TYPE_SYSTEM_FOLDER))) + { + nodeService.setType(nodeRef, destNodeTypeQName); + } + else + { + throw new InvalidArgumentException("Failed to change (specialise) node type - from "+nodeTypeQName+" to "+destNodeTypeQName); + } + } + + NodeRef parentNodeRef = nodeInfo.getParentId(); + if (parentNodeRef != null) + { + NodeRef currentParentNodeRef = getParentNodeRef(nodeRef); + if (currentParentNodeRef == null) + { + // implies root (Company Home) hence return 403 here + throw new PermissionDeniedException(); + } + + if (! currentParentNodeRef.equals(parentNodeRef)) + { + //moveOrCopy(nodeRef, parentNodeRef, name, false); // not currently supported - client should use explicit POST /move operation instead + throw new InvalidArgumentException("Cannot update parentId of "+nodeId+" via PUT /nodes/{nodeId}. Please use explicit POST /nodes/{nodeId}/move operation instead"); + } + } + + List aspectNames = nodeInfo.getAspectNames(); + if (aspectNames != null) + { + // update aspects - note: can be empty (eg. to remove existing aspects+properties) but not cm:auditable, sys:referencable, sys:localized + + Set aspectQNames = mapToNodeAspects(aspectNames); + + Set existingAspects = nodeService.getAspects(nodeRef); + + Set aspectsToAdd = new HashSet<>(3); + Set aspectsToRemove = new HashSet<>(3); + + for (QName aspectQName : aspectQNames) + { + if (EXCLUDED_NS.contains(aspectQName.getNamespaceURI()) || EXCLUDED_ASPECTS.contains(aspectQName) || aspectQName.equals(ContentModel.ASPECT_AUDITABLE)) + { + continue; // ignore + } + + if (! existingAspects.contains(aspectQName)) + { + aspectsToAdd.add(aspectQName); + } + } + + for (QName existingAspect : existingAspects) + { + if (EXCLUDED_NS.contains(existingAspect.getNamespaceURI()) || EXCLUDED_ASPECTS.contains(existingAspect) || existingAspect.equals(ContentModel.ASPECT_AUDITABLE)) + { + continue; // ignore + } + + if (! aspectQNames.contains(existingAspect)) + { + aspectsToRemove.add(existingAspect); + } + } + + // Note: for now, if aspectNames are sent then all that are required should be sent (to avoid properties from other existing aspects being removed) + // TODO: optional PATCH mechanism to add one new new aspect (with some related aspect properties) without affecting existing aspects/properties + for (QName aQName : aspectsToRemove) + { + if (aQName.equals(QuickShareModel.ASPECT_QSHARE)) + { + String qSharedId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID); + if (qSharedId != null) + { + // note: for now, go via QuickShareLinks (rather than QuickShareService) to ensure consistent permission checks + // alternatively we could disallow (or ignore) "qshare:shared" aspect removal + quickShareLinks.delete(qSharedId, null); + } + } + + nodeService.removeAspect(nodeRef, aQName); + } + + for (QName aQName : aspectsToAdd) + { + if (aQName.equals(QuickShareModel.ASPECT_QSHARE)) + { + // note: for now, go via QuickShareLinks (rather than QuickShareService) to ensure consistent permission checks + // alternatively we could disallow (or ignore) "qshare:shared" aspect addition + QuickShareLink qs = new QuickShareLink(); + qs.setNodeId(nodeRef.getId()); + quickShareLinks.create(Collections.singletonList(qs), null); + } + + nodeService.addAspect(nodeRef, aQName, null); + } + } + + if (props.size() > 0) + { + validatePropValues(props); + + try + { + // update node properties - note: null will unset the specified property + nodeService.addProperties(nodeRef, props); + } + catch (DuplicateChildNodeNameException dcne) + { + throw new ConstraintViolatedException(dcne.getMessage()); + } + } + + ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); + postActivity(Activity_Type.UPDATED, activityInfo, false); + + return getFolderOrDocument(nodeRef.getId(), parameters); + } + + @Override + public Node moveOrCopyNode(String sourceNodeId, String targetParentId, String name, Parameters parameters, boolean isCopy) + { + if ((sourceNodeId == null) || (sourceNodeId.isEmpty())) + { + throw new InvalidArgumentException("Missing sourceNodeId"); + } + + if ((targetParentId == null) || (targetParentId.isEmpty())) + { + throw new InvalidArgumentException("Missing targetParentId"); + } + + final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null); + final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null); + + FileInfo fi = moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy); + return getFolderOrDocument(fi.getNodeRef().getId(), parameters); + } + + protected FileInfo moveOrCopyImpl(NodeRef nodeRef, NodeRef parentNodeRef, String name, boolean isCopy) + { + String targetParentId = parentNodeRef.getId(); + + try + { + if (isCopy) + { + // copy + FileInfo newFileInfo = fileFolderService.copy(nodeRef, parentNodeRef, name); + if (newFileInfo.getNodeRef().equals(nodeRef)) + { + // copy did not happen - eg. same parent folder and name (name can be null or same) + throw new FileExistsException(nodeRef, ""); + } + return newFileInfo; + } + else + { + // move + if ((! nodeRef.equals(parentNodeRef)) && isSpecialNodeDoNotDelete(nodeRef, getNodeType(nodeRef))) + { + throw new PermissionDeniedException("Cannot move: "+nodeRef.getId()); + } + + // updating "parentId" means moving primary parent ! + // note: in the future (as and when we support secondary parent/child assocs) we may also + // wish to select which parent to "move from" (in case where the node resides in multiple locations) + return fileFolderService.move(nodeRef, parentNodeRef, name); + } + } + catch (InvalidNodeRefException inre) + { + throw new EntityNotFoundException(targetParentId); + } + catch (FileNotFoundException fnfe) + { + // convert checked exception + throw new EntityNotFoundException(targetParentId); + } + catch (FileExistsException fee) + { + // duplicate - name clash + throw new ConstraintViolatedException("Name already exists in target parent: "+name); + } + catch (FileFolderServiceImpl.InvalidTypeException ite) + { + throw new InvalidArgumentException("Invalid type of target parent: "+targetParentId); + } + catch (CyclicChildRelationshipException ccre) + { + throw new InvalidArgumentException("Parent/child cycle detected: "+targetParentId); + } + } + + @Override + public BinaryResource getContent(String fileNodeId, Parameters parameters, boolean recordActivity) + { + final NodeRef nodeRef = validateNode(fileNodeId); + return getContent(nodeRef, parameters, recordActivity); + } + + @Override + public BinaryResource getContent(NodeRef nodeRef, Parameters parameters, boolean recordActivity) + { + if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) + { + throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef.getId()); + } + + Map nodeProps = nodeService.getProperties(nodeRef); + ContentData cd = (ContentData) nodeProps.get(ContentModel.PROP_CONTENT); + String name = (String) nodeProps.get(ContentModel.PROP_NAME); + + org.alfresco.rest.framework.resource.content.ContentInfo ci = null; + String mimeType = null; + if (cd != null) + { + mimeType = cd.getMimetype(); + ci = new org.alfresco.rest.framework.resource.content.ContentInfoImpl(mimeType, cd.getEncoding(), cd.getSize(), cd.getLocale()); + } + + // By default set attachment header (with filename) unless attachment=false *and* content type is pre-configured as non-attach + boolean attach = true; + String attachment = parameters.getParameter("attachment"); + if (attachment != null) + { + Boolean a = Boolean.valueOf(attachment); + if (!a) + { + if (nonAttachContentTypes.contains(mimeType)) + { + attach = false; + } + else + { + logger.warn("Ignored attachment=false for "+nodeRef.getId()+" since "+mimeType+" is not in the whitelist for non-attach content types"); + } + } + } + String attachFileName = (attach ? name : null); + + if (recordActivity) + { + final ActivityInfo activityInfo = getActivityInfo(getParentNodeRef(nodeRef), nodeRef); + postActivity(Activity_Type.DOWNLOADED, activityInfo, true); + } + + return new NodeBinaryResource(nodeRef, ContentModel.PROP_CONTENT, ci, attachFileName); + } + + @Override + public Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) + { + if (contentInfo.getMimeType().toLowerCase().startsWith("multipart")) + { + throw new UnsupportedMediaTypeException("Cannot update using "+contentInfo.getMimeType()); + } + + final NodeRef nodeRef = validateNode(fileNodeId); + + if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) + { + throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef.getId()); + } + + Boolean versionMajor = null; + String str = parameters.getParameter(PARAM_VERSION_MAJOR); + if (str != null) + { + versionMajor = new Boolean(str); + } + String versionComment = parameters.getParameter(PARAM_VERSION_COMMENT); + + final String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + return updateExistingFile(null, nodeRef, fileName, contentInfo, stream, parameters, versionMajor, versionComment); + } + + private Node updateExistingFile(NodeRef parentNodeRef, NodeRef nodeRef, String fileName, BasicContentInfo contentInfo, InputStream stream, Parameters parameters, Boolean versionMajor, String versionComment) + { + boolean isVersioned = versionService.isVersioned(nodeRef); + + behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); + try + { + writeContent(nodeRef, contentInfo, stream); + + if ((isVersioned) || (versionMajor != null) || (versionComment != null) ) + { + VersionType versionType = VersionType.MINOR; + if ((versionMajor != null) && (versionMajor == true)) + { + versionType = VersionType.MAJOR; + } + createVersion(nodeRef, isVersioned, versionType, versionComment); + } + + ActivityInfo activityInfo = getActivityInfo(parentNodeRef, nodeRef); + postActivity(Activity_Type.UPDATED, activityInfo, false); + + extractMetadata(nodeRef); + } + finally + { + behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); + } + + return getFolderOrDocumentFullInfo(nodeRef, null, null, parameters); + } + + private void writeContent(NodeRef nodeRef, BasicContentInfo contentInfo, InputStream stream) + { + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + setWriterContentType(writer, new ContentInfoWrapper(contentInfo), nodeRef, true); + writer.putContent(stream); + } + + protected void createVersion(NodeRef nodeRef, boolean isVersioned, VersionType versionType, String reason) + { + if (! isVersioned) + { + // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) + ensureVersioningEnabled(nodeRef, true, false); + } + else + { + Map versionProperties = new HashMap<>(2); + versionProperties.put(VersionModel.PROP_VERSION_TYPE, versionType); + if (reason != null) + { + versionProperties.put(VersionModel.PROP_DESCRIPTION, reason); + } + + versionService.createVersion(nodeRef, versionProperties); + } + } + + private void setWriterContentType(ContentWriter writer, ContentInfoWrapper contentInfo, NodeRef nodeRef, boolean guessEncodingIfNull) + { + String mimeType = contentInfo.mimeType; + // Manage MimeType + if ((mimeType == null) || mimeType.equals(DEFAULT_MIMETYPE)) + { + // the mimeType was not provided (or was the default binary mimeType) via the contentInfo, so try to guess + final String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + mimeType = mimetypeService.guessMimetype(fileName); + } + writer.setMimetype(mimeType); + + // Manage Encoding + if (contentInfo.encoding == null) + { + if (guessEncodingIfNull) + { + // the encoding was not provided, so try to guess + writer.guessEncoding(); + } + } + else + { + writer.setEncoding(contentInfo.encoding); + } + } + + + @Override + public Node upload(String parentFolderNodeId, FormData formData, Parameters parameters) + { + if (formData == null || !formData.getIsMultiPart()) + { + throw new InvalidArgumentException("The request content-type is not multipart: "+parentFolderNodeId); + } + + NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); + if (!nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) + { + throw new InvalidArgumentException("NodeId of folder is expected: " + parentNodeRef.getId()); + } + + String fileName = null; + Content content = null; + boolean autoRename = false; + QName nodeTypeQName = null; + boolean overwrite = false; // If a fileName clashes for a versionable file + Boolean majorVersion = null; + String versionComment = null; + String relativePath = null; + String renditionNames = null; + + Map qnameStrProps = new HashMap<>(); + Map properties = null; + + for (FormData.FormField field : formData.getFields()) + { + switch (field.getName().toLowerCase()) + { + case "name": + String str = getStringOrNull(field.getValue()); + if ((str != null) && (! str.isEmpty())) + { + fileName = str; + } + break; + + case "filedata": + if (field.getIsFile()) + { + fileName = (fileName != null ? fileName : field.getFilename()); + content = field.getContent(); + } + break; + + case "autorename": + autoRename = Boolean.valueOf(field.getValue()); + break; + + case "nodetype": + nodeTypeQName = createQName(getStringOrNull(field.getValue())); + if (! isSubClass(nodeTypeQName, ContentModel.TYPE_CONTENT)) + { + throw new InvalidArgumentException("Can only upload type of cm:content: " + nodeTypeQName); + } + break; + + case "overwrite": + overwrite = Boolean.valueOf(field.getValue()); + break; + + case "majorversion": + majorVersion = Boolean.valueOf(field.getValue()); + break; + + case "comment": + versionComment = getStringOrNull(field.getValue()); + break; + + case "relativepath": + relativePath = getStringOrNull(field.getValue()); + break; + + case "renditions": + renditionNames = getStringOrNull(field.getValue()); + break; + + default: + { + final String propName = field.getName(); + if (propName.indexOf(QName.NAMESPACE_PREFIX) > -1) + { + qnameStrProps.put(propName, field.getValue()); + } + } + } + } + + // MNT-7213 When alf_data runs out of disk space, Share uploads + // result in a success message, but the files do not appear. + if (formData.getFields().length == 0) + { + throw new ConstraintViolatedException("No disk space available"); + } + // Ensure mandatory file attributes have been located. Need either + // destination, or site + container or updateNodeRef + if ((fileName == null) || fileName.isEmpty() || (content == null)) + { + throw new InvalidArgumentException("Required parameters are missing"); + } + + if (autoRename && overwrite) + { + throw new InvalidArgumentException("Both 'overwrite' and 'autoRename' should not be true when uploading a file"); + } + + // if requested, make (get or create) path + parentNodeRef = getOrCreatePath(parentNodeRef, relativePath); + final QName assocTypeQName = ContentModel.ASSOC_CONTAINS; + final Set renditions = getRequestedRenditions(renditionNames); + + try + { + // Map the given properties, if any. + if (qnameStrProps.size() > 0) + { + properties = mapToNodeProperties(qnameStrProps); + } + + /* + * Existing file handling + */ + NodeRef existingFile = nodeService.getChildByName(parentNodeRef, assocTypeQName, fileName); + if (existingFile != null) + { + // File already exists, decide what to do + if (autoRename) + { + // attempt to find a unique name + fileName = findUniqueName(parentNodeRef, fileName); + + // drop-through ! + } + else if (overwrite && nodeService.hasAspect(existingFile, ContentModel.ASPECT_VERSIONABLE)) + { + // overwrite existing (versionable) file + BasicContentInfo contentInfo = new ContentInfoImpl(content.getMimetype(), content.getEncoding(), -1, null); + return updateExistingFile(parentNodeRef, existingFile, fileName, contentInfo, content.getInputStream(), parameters, majorVersion, versionComment); + } + else + { + // name clash (and no autoRename or overwrite) + throw new ConstraintViolatedException(fileName + " already exists."); + } + } + + // Create a new file. + final Node fileNode = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, assocTypeQName, parameters); + + // RA-1052 + try + { + List thumbnailDefs = getThumbnailDefs(renditions); + requestRenditions(thumbnailDefs, fileNode); + } + catch (Exception ex) + { + // Note: The log level is not 'error' as it could easily fill out the log file, especially in the Cloud. + if (logger.isDebugEnabled()) + { + // Don't throw the exception as we don't want the the upload to fail, just log it. + logger.debug("Asynchronous request to create a rendition upon upload failed: " + ex.getMessage()); + } + } + + return fileNode; + + // Do not clean formData temp files to allow for retries. + // Temp files will be deleted later when GC call DiskFileItem#finalize() method or by temp file cleaner. + } + catch (ApiException apiEx) + { + // As this is an public API fwk exception, there is no need to convert it, so just throw it. + throw apiEx; + } + catch (AccessDeniedException ade) + { + throw new PermissionDeniedException(ade.getMessage()); + } + catch (ContentQuotaException cqe) + { + throw new InsufficientStorageException(); + } + catch (ContentLimitViolationException clv) + { + throw new RequestEntityTooLargeException(clv.getMessage()); + } + catch (Exception ex) + { + /* + * NOTE: Do not clean formData temp files to allow for retries. It's + * possible for a temp file to remain if max retry attempts are + * made, but this is rare, so leave to usual temp file cleanup. + */ + + throw new ApiException("Unexpected error occurred during upload of new content.", ex); + } + } + + private Node createNewFile(NodeRef parentNodeRef, String fileName, QName nodeType, Content content, Map props, QName assocTypeQName, Parameters params) + { + if (nodeType == null) + { + nodeType = ContentModel.TYPE_CONTENT; + } + NodeRef newFile = createNodeImpl(parentNodeRef, fileName, nodeType, props, assocTypeQName); + + // Write content + write(newFile, content); + + // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) + ensureVersioningEnabled(newFile, true, false); + + // Extract the metadata + extractMetadata(newFile); + + // Create the response + return getFolderOrDocumentFullInfo(newFile, parentNodeRef, nodeType, params); + } + + private String getStringOrNull(String value) + { + if (StringUtils.isNotEmpty(value)) + { + return value.equalsIgnoreCase("null") ? null : value; + } + return null; + } + + private List getThumbnailDefs(Set renditionNames) + { + List thumbnailDefs = null; + + if (renditionNames != null) + { + // If thumbnail generation has been configured off, then don't bother. + if (!thumbnailService.getThumbnailsEnabled()) + { + throw new DisabledServiceException("Thumbnail generation has been disabled."); + } + + thumbnailDefs = new ArrayList<>(renditionNames.size()); + ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry(); + for (String renditionName : renditionNames) + { + // Use the thumbnail registry to get the details of the thumbnail + ThumbnailDefinition thumbnailDef = registry.getThumbnailDefinition(renditionName); + if (thumbnailDef == null) + { + throw new NotFoundException(renditionName + " is not registered."); + } + + thumbnailDefs.add(thumbnailDef); + + } + } + + return thumbnailDefs; + } + + private Set getRequestedRenditions(String renditionsParam) + { + if (renditionsParam == null) + { + return null; + } + + String[] renditionNames = renditionsParam.split(","); + + // Temporary - pending future improvements to thumbnail service to minimise chance of + // missing/failed thumbnails (when requested/generated 'concurrently') + if (renditionNames.length > 1) + { + throw new InvalidArgumentException("Please specify one rendition entity id only"); + } + + Set renditions = new LinkedHashSet<>(renditionNames.length); + for (String name : renditionNames) + { + name = name.trim(); + if (!name.isEmpty()) + { + renditions.add(name.trim()); + } + } + return renditions; + } + + private void requestRenditions(List thumbnailDefs, Node fileNode) + { + if (thumbnailDefs != null) + { + ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry(); + for (ThumbnailDefinition thumbnailDef : thumbnailDefs) + { + NodeRef sourceNodeRef = fileNode.getNodeRef(); + String mimeType = fileNode.getContent().getMimeType(); + long size = fileNode.getContent().getSizeInBytes(); + + // Check if anything is currently available to generate thumbnails for the specified mimeType + if (! registry.isThumbnailDefinitionAvailable(null, mimeType, size, sourceNodeRef, thumbnailDef)) + { + throw new InvalidArgumentException("Unable to create thumbnail '" + thumbnailDef.getName() + "' for " + + mimeType + " as no transformer is currently available."); + } + + Action action = ThumbnailHelper.createCreateThumbnailAction(thumbnailDef, sr); + + // Queue async creation of thumbnail + actionService.executeAction(action, sourceNodeRef, true, true); + } + } + } + + + + /** + * Writes the content to the repository. + * + * @param nodeRef the reference to the node having a content property + * @param content the content + */ + protected void write(NodeRef nodeRef, Content content) + { + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + // Per RA-637 & RA-885 requirement the mimeType provided by the client takes precedence, however, + // if the mimeType is null (or default binary mimeType) then it will be guessed. + setWriterContentType(writer, new ContentInfoWrapper(content), nodeRef, true); + writer.putContent(content.getInputStream()); + } + + /** + * Ensures the given node has the {@code cm:versionable} aspect applied to it, and + * that it has the initial version in the version store. + * + * @param nodeRef the reference to the node to be checked + * @param autoVersion If the {@code cm:versionable} aspect is applied, should auto + * versioning be requested? + * @param autoVersionProps If the {@code cm:versionable} aspect is applied, should + * auto versioning of properties be requested? + */ + protected void ensureVersioningEnabled(NodeRef nodeRef, boolean autoVersion, boolean autoVersionProps) + { + Map props = new HashMap<>(2); + props.put(ContentModel.PROP_AUTO_VERSION, autoVersion); + props.put(ContentModel.PROP_AUTO_VERSION_PROPS, autoVersionProps); + + versionService.ensureVersioningEnabled(nodeRef, props); + } + + /** + * Extracts the given node metadata asynchronously. + * + * The overwrite policy controls which if any parts of the document's properties are updated from this. + */ + private void extractMetadata(NodeRef nodeRef) + { + final String actionName = ContentMetadataExtracter.EXECUTOR_NAME; + ActionDefinition actionDef = actionService.getActionDefinition(actionName); + if (actionDef != null) + { + Action action = actionService.createAction(actionName); + actionService.executeAction(action, nodeRef); + } + } + + /** + * Creates a unique file name, if the upload component was configured to + * find a new unique name for clashing filenames. + * + * @param parentNodeRef the parent node + * @param fileName the original fileName + * @return a new file name + */ + private String findUniqueName(NodeRef parentNodeRef, String fileName) + { + int counter = 1; + String tmpFilename; + NodeRef existingFile; + do + { + int dotIndex = fileName.lastIndexOf('.'); + if (dotIndex == 0) + { + // File didn't have a proper 'name' instead it + // had just a suffix and started with a ".", create "1.txt" + tmpFilename = counter + fileName; + } + else if (dotIndex > 0) + { + // Filename contained ".", create "fileName-1.txt" + tmpFilename = fileName.substring(0, dotIndex) + "-" + counter + fileName.substring(dotIndex); + } + else + { + // Filename didn't contain a dot at all, create "fileName-1" + tmpFilename = fileName + "-" + counter; + } + existingFile = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, tmpFilename); + counter++; + + } while (existingFile != null); + + return tmpFilename; + } + + /** + * Helper to create a QName from either a fully qualified or short-name QName string + * + * @param qnameStr Fully qualified or short-name QName string + * @return QName + */ + public QName createQName(String qnameStr) + { + try + { + QName qname; + if (qnameStr.indexOf(QName.NAMESPACE_BEGIN) != -1) + { + qname = QName.createQName(qnameStr); + } + else + { + qname = QName.createQName(qnameStr, namespaceService); + } + return qname; + } + catch (Exception ex) + { + String msg = ex.getMessage(); + if (msg == null) + { + msg = ""; + } + throw new InvalidArgumentException(qnameStr + " isn't a valid QName. " + msg); + } + } + + /** + * Helper to create a QName from either a fully qualified or short-name QName string + * + * @param qnameStrList list of fully qualified or short-name QName string + * @return a list of {@code QName} objects + */ + protected List createQNames(List qnameStrList) + { + String PREFIX = PARAM_INCLUDE_PROPERTIES +"/"; + + List result = new ArrayList<>(qnameStrList.size()); + for (String str : qnameStrList) + { + if (str.startsWith(PREFIX)) + { + str = str.substring(PREFIX.length()); + } + + QName name = createQName(str); + if (!EXCLUDED_PROPS.contains(name)) + { + result.add(name); + } + } + return result; + } + + /** + * @author Jamal Kaabi-Mofrad + */ + private static class ContentInfoWrapper + { + private String mimeType; + private String encoding; + + ContentInfoWrapper(BasicContentInfo basicContentInfo) + { + if (basicContentInfo != null) + { + this.mimeType = basicContentInfo.getMimeType(); + this.encoding = basicContentInfo.getEncoding(); + } + } + + ContentInfoWrapper(ContentInfo contentInfo) + { + if (contentInfo != null) + { + this.mimeType = contentInfo.getMimeType(); + this.encoding = contentInfo.getEncoding(); + } + } + + ContentInfoWrapper(Content content) + { + if (content != null && StringUtils.isNotEmpty(content.getMimetype())) + { + try + { + // TODO I think it makes sense to push contentType parsing into org.springframework.extensions.webscripts.servlet.FormData + MediaType media = MediaType.parseMediaType(content.getMimetype()); + this.mimeType = media.getType() + '/' + media.getSubtype(); + + if (media.getCharSet() != null) + { + this.encoding = media.getCharSet().name(); + } + } + catch (InvalidMediaTypeException ime) + { + throw new InvalidArgumentException(ime.getMessage()); + } + } + } + } +} + diff --git a/source/java/org/alfresco/rest/api/impl/PeopleImpl.java b/source/java/org/alfresco/rest/api/impl/PeopleImpl.java index 79e57fbc2e..dfca5c3f20 100644 --- a/source/java/org/alfresco/rest/api/impl/PeopleImpl.java +++ b/source/java/org/alfresco/rest/api/impl/PeopleImpl.java @@ -1,323 +1,323 @@ -package org.alfresco.rest.api.impl; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.Company; -import org.alfresco.rest.api.model.Person; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.cmr.security.NoSuchPersonException; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.thumbnail.ThumbnailService; -import org.alfresco.service.cmr.usage.ContentUsageService; -import org.alfresco.service.namespace.QName; - -/** - * Centralises access to people services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class PeopleImpl implements People -{ - protected Nodes nodes; - protected Sites sites; - - protected SiteService siteService; - protected NodeService nodeService; - protected PersonService personService; - protected AuthenticationService authenticationService; - protected ContentUsageService contentUsageService; - protected ContentService contentService; - protected ThumbnailService thumbnailService; - - public void setSites(Sites sites) - { - this.sites = sites; - } - - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setPersonService(PersonService personService) - { - this.personService = personService; - } - - public void setAuthenticationService(AuthenticationService authenticationService) - { - this.authenticationService = authenticationService; - } - - public void setContentUsageService(ContentUsageService contentUsageService) - { - this.contentUsageService = contentUsageService; - } - - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - - public void setThumbnailService(ThumbnailService thumbnailService) - { - this.thumbnailService = thumbnailService; - } - - public String validatePerson(String personId) - { - return validatePerson(personId, false); - } - - public String validatePerson(String personId, boolean validateIsCurrentUser) - { - if(personId.equalsIgnoreCase(DEFAULT_USER)) - { - personId = AuthenticationUtil.getFullyAuthenticatedUser(); - } - - personId = personService.getUserIdentifier(personId); - if(personId == null) - { - // "User " + personId + " does not exist" - throw new EntityNotFoundException("personId is null."); - } - - if(validateIsCurrentUser) - { - String currentUserId = AuthenticationUtil.getFullyAuthenticatedUser(); - if(!currentUserId.equalsIgnoreCase(personId)) - { - throw new EntityNotFoundException(personId); - } - } - - return personId; - } - - protected void processPersonProperties(String userName, final Map nodeProps) - { - if(!contentUsageService.getEnabled()) - { - // quota used will always be 0 in this case so remove from the person properties - nodeProps.remove(ContentModel.PROP_SIZE_QUOTA); - nodeProps.remove(ContentModel.PROP_SIZE_CURRENT); - } - - final ContentData personDescription = (ContentData)nodeProps.get(ContentModel.PROP_PERSONDESC); - if(personDescription != null) - { - nodeProps.remove(ContentModel.PROP_PERSONDESC); - - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - ContentReader reader = contentService.getRawReader(personDescription.getContentUrl()); - if(reader != null && reader.exists()) - { - String description = reader.getContentString(); - nodeProps.put(Person.PROP_PERSON_DESCRIPTION, description); - } - - return null; - } - }); - } - } - - public boolean hasAvatar(NodeRef personNodeRef) - { - if(personNodeRef != null) - { - List avatorAssocs = nodeService.getTargetAssocs(personNodeRef, ContentModel.ASSOC_AVATAR); - return(avatorAssocs.size() > 0); - } - else - { - return false; - } - } - - public NodeRef getAvatar(String personId) - { - NodeRef avatar = null; - - personId = validatePerson(personId); - NodeRef personNode = personService.getPerson(personId); - if(personNode != null) - { - List avatorAssocs = nodeService.getTargetAssocs(personNode, ContentModel.ASSOC_AVATAR); - if(avatorAssocs.size() > 0) - { - AssociationRef ref = avatorAssocs.get(0); - NodeRef thumbnailNodeRef = thumbnailService.getThumbnailByName(ref.getTargetRef(), ContentModel.PROP_CONTENT, "avatar"); - if(thumbnailNodeRef != null) - { - avatar = thumbnailNodeRef; - } - else - { - throw new EntityNotFoundException("avatar"); - } - } - else - { - throw new EntityNotFoundException("avatar"); - } - } - else - { - throw new EntityNotFoundException(personId); - } - - return avatar; - } - - /** - * - * @throws NoSuchPersonException if personId does not exist - */ - public Person getPerson(String personId) - { - Person person = null; - - personId = validatePerson(personId); - NodeRef personNode = personService.getPerson(personId, false); - if (personNode != null) - { - Map nodeProps = nodeService.getProperties(personNode); - processPersonProperties(personId, nodeProps); - // TODO this needs to be run as admin but should we do this here? - final String pId = personId; - Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork() - { - public Boolean doWork() throws Exception - { - return authenticationService.getAuthenticationEnabled(pId); - } - }); - person = new Person(personNode, nodeProps, enabled); - - // get avatar information - if(hasAvatar(personNode)) - { - try - { - NodeRef avatar = getAvatar(personId); - person.setAvatarId(avatar); - } - catch(EntityNotFoundException e) - { - // shouldn't happen, but ok - } - } - } - else - { - throw new EntityNotFoundException(personId); - } - - return person; - } -/** - private void addToMap(Map properties, QName name, Serializable value) - { -// if(name != null && value != null) -// { - properties.put(name, value); -// } - } - - public Person updatePerson(String personId, final Person person) - { - personId = validatePerson(personId); - - final Map properties = new HashMap(); -// addToMap(properties, ContentModel.PROP_USERNAME, person.getUserName()); - addToMap(properties, ContentModel.PROP_FIRSTNAME, person.getFirstName()); - addToMap(properties, ContentModel.PROP_LASTNAME, person.getLastName()); - addToMap(properties, ContentModel.PROP_JOBTITLE, person.getJobTitle()); - addToMap(properties, ContentModel.PROP_LOCATION, person.getLocation()); - addToMap(properties, ContentModel.PROP_TELEPHONE, person.getTelephone()); - addToMap(properties, ContentModel.PROP_MOBILE, person.getMobile()); - addToMap(properties, ContentModel.PROP_EMAIL, person.getEmail()); - - Company company = person.getCompany(); - if(company != null) - { - addToMap(properties, ContentModel.PROP_ORGANIZATION, company.getOrganization()); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, company.getAddress1()); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, company.getAddress2()); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, company.getAddress3()); - addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode()); - addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone()); - addToMap(properties, ContentModel.PROP_COMPANYFAX, company.getFax()); - addToMap(properties, ContentModel.PROP_COMPANYEMAIL, company.getEmail()); - } - else - { - addToMap(properties, ContentModel.PROP_ORGANIZATION, null); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, null); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, null); - addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, null); - addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, null); - addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, null); - addToMap(properties, ContentModel.PROP_COMPANYFAX, null); - addToMap(properties, ContentModel.PROP_COMPANYEMAIL, null); - } - - addToMap(properties, ContentModel.PROP_SKYPE, person.getSkypeId()); - addToMap(properties, ContentModel.PROP_INSTANTMSG, person.getInstantMessageId()); - addToMap(properties, ContentModel.PROP_USER_STATUS, person.getUserStatus()); - addToMap(properties, ContentModel.PROP_USER_STATUS_TIME, person.getStatusUpdatedAt()); - addToMap(properties, ContentModel.PROP_GOOGLEUSERNAME, person.getGoogleId()); - addToMap(properties, ContentModel.PROP_SIZE_QUOTA, person.getQuota()); - addToMap(properties, ContentModel.PROP_SIZE_CURRENT, person.getQuotaUsed()); - addToMap(properties, ContentModel.PROP_DESCRIPTION, person.getDescription()); - - final String pId = personId; - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - personService.setPersonProperties(pId, properties, false); - return null; - } - - }); - - return getPerson(personId); - } - */ -} +package org.alfresco.rest.api.impl; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.Company; +import org.alfresco.rest.api.model.Person; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.NoSuchPersonException; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.cmr.usage.ContentUsageService; +import org.alfresco.service.namespace.QName; + +/** + * Centralises access to people services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class PeopleImpl implements People +{ + protected Nodes nodes; + protected Sites sites; + + protected SiteService siteService; + protected NodeService nodeService; + protected PersonService personService; + protected AuthenticationService authenticationService; + protected ContentUsageService contentUsageService; + protected ContentService contentService; + protected ThumbnailService thumbnailService; + + public void setSites(Sites sites) + { + this.sites = sites; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + public void setAuthenticationService(AuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + public void setContentUsageService(ContentUsageService contentUsageService) + { + this.contentUsageService = contentUsageService; + } + + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + public void setThumbnailService(ThumbnailService thumbnailService) + { + this.thumbnailService = thumbnailService; + } + + public String validatePerson(String personId) + { + return validatePerson(personId, false); + } + + public String validatePerson(String personId, boolean validateIsCurrentUser) + { + if(personId.equalsIgnoreCase(DEFAULT_USER)) + { + personId = AuthenticationUtil.getFullyAuthenticatedUser(); + } + + personId = personService.getUserIdentifier(personId); + if(personId == null) + { + // "User " + personId + " does not exist" + throw new EntityNotFoundException("personId is null."); + } + + if(validateIsCurrentUser) + { + String currentUserId = AuthenticationUtil.getFullyAuthenticatedUser(); + if(!currentUserId.equalsIgnoreCase(personId)) + { + throw new EntityNotFoundException(personId); + } + } + + return personId; + } + + protected void processPersonProperties(String userName, final Map nodeProps) + { + if(!contentUsageService.getEnabled()) + { + // quota used will always be 0 in this case so remove from the person properties + nodeProps.remove(ContentModel.PROP_SIZE_QUOTA); + nodeProps.remove(ContentModel.PROP_SIZE_CURRENT); + } + + final ContentData personDescription = (ContentData)nodeProps.get(ContentModel.PROP_PERSONDESC); + if(personDescription != null) + { + nodeProps.remove(ContentModel.PROP_PERSONDESC); + + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + ContentReader reader = contentService.getRawReader(personDescription.getContentUrl()); + if(reader != null && reader.exists()) + { + String description = reader.getContentString(); + nodeProps.put(Person.PROP_PERSON_DESCRIPTION, description); + } + + return null; + } + }); + } + } + + public boolean hasAvatar(NodeRef personNodeRef) + { + if(personNodeRef != null) + { + List avatorAssocs = nodeService.getTargetAssocs(personNodeRef, ContentModel.ASSOC_AVATAR); + return(avatorAssocs.size() > 0); + } + else + { + return false; + } + } + + public NodeRef getAvatar(String personId) + { + NodeRef avatar = null; + + personId = validatePerson(personId); + NodeRef personNode = personService.getPerson(personId); + if(personNode != null) + { + List avatorAssocs = nodeService.getTargetAssocs(personNode, ContentModel.ASSOC_AVATAR); + if(avatorAssocs.size() > 0) + { + AssociationRef ref = avatorAssocs.get(0); + NodeRef thumbnailNodeRef = thumbnailService.getThumbnailByName(ref.getTargetRef(), ContentModel.PROP_CONTENT, "avatar"); + if(thumbnailNodeRef != null) + { + avatar = thumbnailNodeRef; + } + else + { + throw new EntityNotFoundException("avatar"); + } + } + else + { + throw new EntityNotFoundException("avatar"); + } + } + else + { + throw new EntityNotFoundException(personId); + } + + return avatar; + } + + /** + * + * @throws NoSuchPersonException if personId does not exist + */ + public Person getPerson(String personId) + { + Person person = null; + + personId = validatePerson(personId); + NodeRef personNode = personService.getPerson(personId, false); + if (personNode != null) + { + Map nodeProps = nodeService.getProperties(personNode); + processPersonProperties(personId, nodeProps); + // TODO this needs to be run as admin but should we do this here? + final String pId = personId; + Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork() + { + public Boolean doWork() throws Exception + { + return authenticationService.getAuthenticationEnabled(pId); + } + }); + person = new Person(personNode, nodeProps, enabled); + + // get avatar information + if(hasAvatar(personNode)) + { + try + { + NodeRef avatar = getAvatar(personId); + person.setAvatarId(avatar); + } + catch(EntityNotFoundException e) + { + // shouldn't happen, but ok + } + } + } + else + { + throw new EntityNotFoundException(personId); + } + + return person; + } +/** + private void addToMap(Map properties, QName name, Serializable value) + { +// if(name != null && value != null) +// { + properties.put(name, value); +// } + } + + public Person updatePerson(String personId, final Person person) + { + personId = validatePerson(personId); + + final Map properties = new HashMap(); +// addToMap(properties, ContentModel.PROP_USERNAME, person.getUserName()); + addToMap(properties, ContentModel.PROP_FIRSTNAME, person.getFirstName()); + addToMap(properties, ContentModel.PROP_LASTNAME, person.getLastName()); + addToMap(properties, ContentModel.PROP_JOBTITLE, person.getJobTitle()); + addToMap(properties, ContentModel.PROP_LOCATION, person.getLocation()); + addToMap(properties, ContentModel.PROP_TELEPHONE, person.getTelephone()); + addToMap(properties, ContentModel.PROP_MOBILE, person.getMobile()); + addToMap(properties, ContentModel.PROP_EMAIL, person.getEmail()); + + Company company = person.getCompany(); + if(company != null) + { + addToMap(properties, ContentModel.PROP_ORGANIZATION, company.getOrganization()); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, company.getAddress1()); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, company.getAddress2()); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, company.getAddress3()); + addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode()); + addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone()); + addToMap(properties, ContentModel.PROP_COMPANYFAX, company.getFax()); + addToMap(properties, ContentModel.PROP_COMPANYEMAIL, company.getEmail()); + } + else + { + addToMap(properties, ContentModel.PROP_ORGANIZATION, null); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS1, null); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS2, null); + addToMap(properties, ContentModel.PROP_COMPANYADDRESS3, null); + addToMap(properties, ContentModel.PROP_COMPANYPOSTCODE, null); + addToMap(properties, ContentModel.PROP_COMPANYTELEPHONE, null); + addToMap(properties, ContentModel.PROP_COMPANYFAX, null); + addToMap(properties, ContentModel.PROP_COMPANYEMAIL, null); + } + + addToMap(properties, ContentModel.PROP_SKYPE, person.getSkypeId()); + addToMap(properties, ContentModel.PROP_INSTANTMSG, person.getInstantMessageId()); + addToMap(properties, ContentModel.PROP_USER_STATUS, person.getUserStatus()); + addToMap(properties, ContentModel.PROP_USER_STATUS_TIME, person.getStatusUpdatedAt()); + addToMap(properties, ContentModel.PROP_GOOGLEUSERNAME, person.getGoogleId()); + addToMap(properties, ContentModel.PROP_SIZE_QUOTA, person.getQuota()); + addToMap(properties, ContentModel.PROP_SIZE_CURRENT, person.getQuotaUsed()); + addToMap(properties, ContentModel.PROP_DESCRIPTION, person.getDescription()); + + final String pId = personId; + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + personService.setPersonProperties(pId, properties, false); + return null; + } + + }); + + return getPerson(personId); + } + */ +} diff --git a/source/java/org/alfresco/rest/api/impl/PreferencesImpl.java b/source/java/org/alfresco/rest/api/impl/PreferencesImpl.java index c666a65bc9..2d00e2cd00 100644 --- a/source/java/org/alfresco/rest/api/impl/PreferencesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/PreferencesImpl.java @@ -1,66 +1,66 @@ -package org.alfresco.rest.api.impl; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.query.PagingResults; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.Preferences; -import org.alfresco.rest.api.model.Preference; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.service.cmr.preference.PreferenceService; -import org.alfresco.util.Pair; - -/** - * Centralises access to preference services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class PreferencesImpl implements Preferences -{ - private People people; - private PreferenceService preferenceService; - - public void setPeople(People people) - { - this.people = people; - } - - public void setPreferenceService(PreferenceService preferenceService) - { - this.preferenceService = preferenceService; - } - - public Preference getPreference(String personId, String preferenceName) - { - personId = people.validatePerson(personId); - Serializable preferenceValue = preferenceService.getPreference(personId, preferenceName); - if(preferenceValue != null) - { - return new Preference(preferenceName, preferenceValue); - } - else - { - throw new RelationshipResourceNotFoundException(personId, preferenceName); - } - } - - public CollectionWithPagingInfo getPreferences(String personId, Paging paging) - { - personId = people.validatePerson(personId); - - PagingResults> preferences = preferenceService.getPagedPreferences(personId, null, Util.getPagingRequest(paging)); - List ret = new ArrayList(preferences.getPage().size()); - for(Pair prefEntity : preferences.getPage()) - { - Preference pref = new Preference(prefEntity.getFirst(), prefEntity.getSecond()); - ret.add(pref); - } - - return CollectionWithPagingInfo.asPaged(paging, ret, preferences.hasMoreItems(), preferences.getTotalResultCount().getFirst()); - } -} +package org.alfresco.rest.api.impl; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.query.PagingResults; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.Preferences; +import org.alfresco.rest.api.model.Preference; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.service.cmr.preference.PreferenceService; +import org.alfresco.util.Pair; + +/** + * Centralises access to preference services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class PreferencesImpl implements Preferences +{ + private People people; + private PreferenceService preferenceService; + + public void setPeople(People people) + { + this.people = people; + } + + public void setPreferenceService(PreferenceService preferenceService) + { + this.preferenceService = preferenceService; + } + + public Preference getPreference(String personId, String preferenceName) + { + personId = people.validatePerson(personId); + Serializable preferenceValue = preferenceService.getPreference(personId, preferenceName); + if(preferenceValue != null) + { + return new Preference(preferenceName, preferenceValue); + } + else + { + throw new RelationshipResourceNotFoundException(personId, preferenceName); + } + } + + public CollectionWithPagingInfo getPreferences(String personId, Paging paging) + { + personId = people.validatePerson(personId); + + PagingResults> preferences = preferenceService.getPagedPreferences(personId, null, Util.getPagingRequest(paging)); + List ret = new ArrayList(preferences.getPage().size()); + for(Pair prefEntity : preferences.getPage()) + { + Preference pref = new Preference(prefEntity.getFirst(), prefEntity.getSecond()); + ret.add(pref); + } + + return CollectionWithPagingInfo.asPaged(paging, ret, preferences.hasMoreItems(), preferences.getTotalResultCount().getFirst()); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsExceptionHandler.java b/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsExceptionHandler.java index 5ef3c10b08..ff1afbcacf 100644 --- a/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsExceptionHandler.java +++ b/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsExceptionHandler.java @@ -1,18 +1,18 @@ -package org.alfresco.rest.api.impl; - -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; - -public class SiteMembershipRequestsExceptionHandler extends DefaultExceptionHandler -{ - @Override - public boolean handle(Throwable t) - { - if(t instanceof InvitationExceptionForbidden) - { - // Note: security, no message to indicate why - throw new NotFoundException(); - } - return super.handle(t); - } -} +package org.alfresco.rest.api.impl; + +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; + +public class SiteMembershipRequestsExceptionHandler extends DefaultExceptionHandler +{ + @Override + public boolean handle(Throwable t) + { + if(t instanceof InvitationExceptionForbidden) + { + // Note: security, no message to indicate why + throw new NotFoundException(); + } + return super.handle(t); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java b/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java index 58fe8614b5..7b18fa7bb7 100644 --- a/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/SiteMembershipRequestsImpl.java @@ -1,445 +1,445 @@ -package org.alfresco.rest.api.impl; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.tenant.NetworksService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.SiteMembershipRequests; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.SiteMembershipRequest; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.service.cmr.invitation.Invitation; -import org.alfresco.service.cmr.invitation.Invitation.ResourceType; -import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; -import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; -import org.alfresco.service.cmr.invitation.InvitationService; -import org.alfresco.service.cmr.invitation.ModeratedInvitation; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Public REST API: centralises access to site membership requests and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class SiteMembershipRequestsImpl implements SiteMembershipRequests -{ - private static final Log logger = LogFactory.getLog(SiteMembershipRequestsImpl.class); - - // Default role to assign to the site membership request - public final static String DEFAULT_ROLE = SiteModel.SITE_CONSUMER; - - private People people; - private Sites sites; - private SiteService siteService; - private NodeService nodeService; - private InvitationService invitationService; - private NetworksService networksService; - - public void setNetworksService(NetworksService networksService) - { - this.networksService = networksService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setPeople(People people) - { - this.people = people; - } - - public void setSites(Sites sites) - { - this.sites = sites; - } - - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - public void setInvitationService(InvitationService invitationService) - { - this.invitationService = invitationService; - } - - private Invitation getSiteInvitation(String inviteeId, String siteId) - { - // Is there an outstanding site invite request for the invitee? - InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl(); - criteria.setInvitationType(InvitationType.MODERATED); - criteria.setInvitee(inviteeId); - criteria.setResourceName(siteId); - criteria.setResourceType(ResourceType.WEB_SITE); - List invitations = invitationService.searchInvitation(criteria); - if(invitations.size() > 1) - { - // TODO exception - throw new AlfrescoRuntimeException("There should be only one outstanding site invitation"); - } - return (invitations.size() == 0 ? null : invitations.get(0)); - } - - private List getSiteInvitations(String inviteeId) - { - InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl(); - criteria.setInvitationType(InvitationType.MODERATED); - criteria.setInvitee(inviteeId); - criteria.setResourceType(ResourceType.WEB_SITE); - List invitations = invitationService.searchInvitation(criteria); - return invitations; - } - - private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId, - final String inviteeRole) - { - ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole); - - SiteMembershipRequest ret = new SiteMembershipRequest(); - ret.setId(siteId); - ret.setMessage(message); - ret.setCreatedAt(invitation.getCreatedAt()); - return ret; - } - - private SiteMembershipRequest inviteToSite(String siteId, String inviteeId, String inviteeRole, String message) - { - siteService.setMembership(siteId, inviteeId, inviteeRole); - SiteMembershipRequest ret = new SiteMembershipRequest(); - ret.setId(siteId); - ret.setMessage(message); - Date createdAt = new Date(); - ret.setCreatedAt(createdAt); - return ret; - } - - private SiteMembershipRequest inviteToPublicSite(final SiteInfo siteInfo, final String message, final String inviteeId, - final String inviteeRole) - { - SiteMembershipRequest siteMembershipRequest = null; - - final String siteId = siteInfo.getShortName(); - NodeRef siteNodeRef = siteInfo.getNodeRef(); - String siteCreator = (String)nodeService.getProperty(siteNodeRef, ContentModel.PROP_CREATOR); - - final String siteNetwork = networksService.getUserDefaultNetwork(siteCreator); - if(StringUtils.isNotEmpty(siteNetwork)) - { - // MT - siteMembershipRequest = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public SiteMembershipRequest doWork() throws Exception - { - return inviteToSite(siteId, inviteeId, inviteeRole, message); - } - }, siteCreator, siteNetwork); - } - else - { - siteMembershipRequest = AuthenticationUtil.runAs(new RunAsWork() - { - @Override - public SiteMembershipRequest doWork() throws Exception - { - return inviteToSite(siteId, inviteeId, inviteeRole, message); - } - }, siteCreator); - } - - return siteMembershipRequest; - } - - @Override - public SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite) - { - SiteMembershipRequest request = null; - - inviteeId = people.validatePerson(inviteeId, true); - - // Note that the order of error checking is important. The server first needs to check for the status 404 - // conditions before checking for status 400 conditions. Otherwise the server is open to a probing attack. - String siteId = siteInvite.getId(); - final SiteInfo siteInfo = sites.validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - final SiteVisibility siteVisibility = siteInfo.getVisibility(); - - if(siteVisibility.equals(SiteVisibility.PRIVATE)) - { - // note: security, no indication that this is a private site - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - - // Is the invitee already a member of the site? - boolean isMember = siteService.isMember(siteId, inviteeId); - if(isMember) - { - // yes - throw new InvalidArgumentException(inviteeId + " is already a member of site " + siteId); - } - - // Is there an outstanding site invite request for the (invitee, site)? - Invitation invitation = getSiteInvitation(inviteeId, siteId); - if(invitation != null) - { - // yes - throw new InvalidArgumentException(inviteeId + " is already invited to site " + siteId); - } - - final String inviteeRole = DEFAULT_ROLE; - String message = siteInvite.getMessage(); - if(message == null) - { - // the invitation service ignores null messages so convert to an empty message. - message = ""; - } - - if(siteVisibility.equals(SiteVisibility.MODERATED)) - { - request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole); - } - else if(siteVisibility.equals(SiteVisibility.PUBLIC)) - { - request = inviteToPublicSite(siteInfo, message, inviteeId, inviteeRole); - } - else - { - // note: security, no indication that this is a private site - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - - return request; - } - - @Override - public SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite) - { - SiteMembershipRequest updatedSiteInvite = null; - - inviteeId = people.validatePerson(inviteeId, true); - - String siteId = siteInvite.getId(); - SiteInfo siteInfo = sites.validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - String message = siteInvite.getMessage(); - if(message == null) - { - // the invitation service ignores null messages so convert to an empty message. - message = ""; - } - - try - { - ModeratedInvitation updatedInvitation = invitationService.updateModeratedInvitation(inviteeId, siteId, message); - if(updatedInvitation == null) - { - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - updatedSiteInvite = getSiteMembershipRequest(updatedInvitation); - } - catch(InvitationExceptionNotFound e) - { - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - - if(updatedSiteInvite == null) - { - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - - return updatedSiteInvite; - } - - @Override - public void cancelSiteMembershipRequest(String inviteeId, String siteId) - { - inviteeId = people.validatePerson(inviteeId); - SiteInfo siteInfo = sites.validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - Invitation invitation = getSiteInvitation(inviteeId, siteId); - if(invitation == null) - { - // no such invitation - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - invitationService.cancel(invitation.getInviteId()); - } - - public SiteMembershipRequest getSiteMembershipRequest(String inviteeId, final String siteId) - { - inviteeId = people.validatePerson(inviteeId); - - SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public SiteInfo doWork() throws Exception - { - SiteInfo siteInfo = sites.validateSite(siteId); - return siteInfo; - } - }); - - if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED)) - { - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - String normalizedSiteId = siteInfo.getShortName(); - - Invitation invitation = getSiteInvitation(inviteeId, normalizedSiteId); - if(invitation == null) - { - // no such invitation - throw new RelationshipResourceNotFoundException(inviteeId, normalizedSiteId); - } - if(invitation instanceof ModeratedInvitation) - { - ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; - SiteMembershipRequest siteInvite = getSiteMembershipRequest(moderatedInvitation); - return siteInvite; - } - else - { - throw new InvalidArgumentException("Expected moderated invitation"); - } - } - else - { - // non-moderated sites cannot appear in a site membership request, so throw an exception - throw new RelationshipResourceNotFoundException(inviteeId, siteId); - } - } - - private SiteMembershipRequest getSiteMembershipRequest(ModeratedInvitation moderatedInvitation) - { - SiteMembershipRequest siteMembershipRequest = null; - - ResourceType resourceType = moderatedInvitation.getResourceType(); - if(resourceType.equals(ResourceType.WEB_SITE)) - { - final String siteId = moderatedInvitation.getResourceName(); - - SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public SiteInfo doWork() throws Exception - { - SiteInfo siteInfo = sites.validateSite(siteId); - return siteInfo; - } - }); - - if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED)) - { - // return a site membership request only if this is a moderated site - siteMembershipRequest = new SiteMembershipRequest(); - String title = siteInfo.getTitle(); - siteMembershipRequest.setTitle(title); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage(moderatedInvitation.getInviteeComments()); - siteMembershipRequest.setCreatedAt(moderatedInvitation.getCreatedAt()); - siteMembershipRequest.setModifiedAt(moderatedInvitation.getModifiedAt()); - } - } - else - { - logger.warn("Unexpected resource type " + resourceType + " for site membership request"); - } - - return siteMembershipRequest; - } - - @Override - public CollectionWithPagingInfo getPagedSiteMembershipRequests(String personId, Paging paging) - { - personId = people.validatePerson(personId, true); - - int skipCount = paging.getSkipCount(); - int maxItems = paging.getMaxItems(); - int max = skipCount + maxItems + 1; // to detect hasMoreItems - - List invitations = getSiteInvitations(personId); - List siteMembershipRequests = new ArrayList(invitations.size()); - for(Invitation invitation : invitations) - { - if(invitation instanceof ModeratedInvitation) - { - ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; - SiteMembershipRequest siteMembershipRequest = getSiteMembershipRequest(moderatedInvitation); - if(siteMembershipRequest != null) - { - // note: siteMembershipRequest may be null if the site is now no longer a moderated site - // or if the invitation is malformed and does not refer to a site. - siteMembershipRequests.add(siteMembershipRequest); - } - } - else - { - // just ignore, shouldn't happen because getSiteInvitations filters by ModeratedInvitation - } - } - - // unfortunately, need to sort in memory because there's no way to get site membership requests sorted by title from - // the workflow apis - Collections.sort(siteMembershipRequests); - - int totalItems = siteMembershipRequests.size(); - - if(skipCount >= totalItems) - { - List empty = Collections.emptyList(); - return CollectionWithPagingInfo.asPaged(paging, empty, false, totalItems); - } - else - { - int end = Math.min(max - 1, totalItems); - boolean hasMoreItems = totalItems > end; - - siteMembershipRequests = siteMembershipRequests.subList(skipCount, end); - return CollectionWithPagingInfo.asPaged(paging, siteMembershipRequests, hasMoreItems, totalItems); - } - } -} +package org.alfresco.rest.api.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.tenant.NetworksService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.SiteMembershipRequests; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.SiteMembershipRequest; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.Invitation.ResourceType; +import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; +import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; +import org.alfresco.service.cmr.invitation.InvitationService; +import org.alfresco.service.cmr.invitation.ModeratedInvitation; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Public REST API: centralises access to site membership requests and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class SiteMembershipRequestsImpl implements SiteMembershipRequests +{ + private static final Log logger = LogFactory.getLog(SiteMembershipRequestsImpl.class); + + // Default role to assign to the site membership request + public final static String DEFAULT_ROLE = SiteModel.SITE_CONSUMER; + + private People people; + private Sites sites; + private SiteService siteService; + private NodeService nodeService; + private InvitationService invitationService; + private NetworksService networksService; + + public void setNetworksService(NetworksService networksService) + { + this.networksService = networksService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPeople(People people) + { + this.people = people; + } + + public void setSites(Sites sites) + { + this.sites = sites; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setInvitationService(InvitationService invitationService) + { + this.invitationService = invitationService; + } + + private Invitation getSiteInvitation(String inviteeId, String siteId) + { + // Is there an outstanding site invite request for the invitee? + InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl(); + criteria.setInvitationType(InvitationType.MODERATED); + criteria.setInvitee(inviteeId); + criteria.setResourceName(siteId); + criteria.setResourceType(ResourceType.WEB_SITE); + List invitations = invitationService.searchInvitation(criteria); + if(invitations.size() > 1) + { + // TODO exception + throw new AlfrescoRuntimeException("There should be only one outstanding site invitation"); + } + return (invitations.size() == 0 ? null : invitations.get(0)); + } + + private List getSiteInvitations(String inviteeId) + { + InvitationSearchCriteriaImpl criteria = new InvitationSearchCriteriaImpl(); + criteria.setInvitationType(InvitationType.MODERATED); + criteria.setInvitee(inviteeId); + criteria.setResourceType(ResourceType.WEB_SITE); + List invitations = invitationService.searchInvitation(criteria); + return invitations; + } + + private SiteMembershipRequest inviteToModeratedSite(final String message, final String inviteeId, final String siteId, + final String inviteeRole) + { + ModeratedInvitation invitation = invitationService.inviteModerated(message, inviteeId, ResourceType.WEB_SITE, siteId, inviteeRole); + + SiteMembershipRequest ret = new SiteMembershipRequest(); + ret.setId(siteId); + ret.setMessage(message); + ret.setCreatedAt(invitation.getCreatedAt()); + return ret; + } + + private SiteMembershipRequest inviteToSite(String siteId, String inviteeId, String inviteeRole, String message) + { + siteService.setMembership(siteId, inviteeId, inviteeRole); + SiteMembershipRequest ret = new SiteMembershipRequest(); + ret.setId(siteId); + ret.setMessage(message); + Date createdAt = new Date(); + ret.setCreatedAt(createdAt); + return ret; + } + + private SiteMembershipRequest inviteToPublicSite(final SiteInfo siteInfo, final String message, final String inviteeId, + final String inviteeRole) + { + SiteMembershipRequest siteMembershipRequest = null; + + final String siteId = siteInfo.getShortName(); + NodeRef siteNodeRef = siteInfo.getNodeRef(); + String siteCreator = (String)nodeService.getProperty(siteNodeRef, ContentModel.PROP_CREATOR); + + final String siteNetwork = networksService.getUserDefaultNetwork(siteCreator); + if(StringUtils.isNotEmpty(siteNetwork)) + { + // MT + siteMembershipRequest = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public SiteMembershipRequest doWork() throws Exception + { + return inviteToSite(siteId, inviteeId, inviteeRole, message); + } + }, siteCreator, siteNetwork); + } + else + { + siteMembershipRequest = AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public SiteMembershipRequest doWork() throws Exception + { + return inviteToSite(siteId, inviteeId, inviteeRole, message); + } + }, siteCreator); + } + + return siteMembershipRequest; + } + + @Override + public SiteMembershipRequest createSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite) + { + SiteMembershipRequest request = null; + + inviteeId = people.validatePerson(inviteeId, true); + + // Note that the order of error checking is important. The server first needs to check for the status 404 + // conditions before checking for status 400 conditions. Otherwise the server is open to a probing attack. + String siteId = siteInvite.getId(); + final SiteInfo siteInfo = sites.validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + final SiteVisibility siteVisibility = siteInfo.getVisibility(); + + if(siteVisibility.equals(SiteVisibility.PRIVATE)) + { + // note: security, no indication that this is a private site + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + // Is the invitee already a member of the site? + boolean isMember = siteService.isMember(siteId, inviteeId); + if(isMember) + { + // yes + throw new InvalidArgumentException(inviteeId + " is already a member of site " + siteId); + } + + // Is there an outstanding site invite request for the (invitee, site)? + Invitation invitation = getSiteInvitation(inviteeId, siteId); + if(invitation != null) + { + // yes + throw new InvalidArgumentException(inviteeId + " is already invited to site " + siteId); + } + + final String inviteeRole = DEFAULT_ROLE; + String message = siteInvite.getMessage(); + if(message == null) + { + // the invitation service ignores null messages so convert to an empty message. + message = ""; + } + + if(siteVisibility.equals(SiteVisibility.MODERATED)) + { + request = inviteToModeratedSite(message, inviteeId, siteId, inviteeRole); + } + else if(siteVisibility.equals(SiteVisibility.PUBLIC)) + { + request = inviteToPublicSite(siteInfo, message, inviteeId, inviteeRole); + } + else + { + // note: security, no indication that this is a private site + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + return request; + } + + @Override + public SiteMembershipRequest updateSiteMembershipRequest(String inviteeId, final SiteMembershipRequest siteInvite) + { + SiteMembershipRequest updatedSiteInvite = null; + + inviteeId = people.validatePerson(inviteeId, true); + + String siteId = siteInvite.getId(); + SiteInfo siteInfo = sites.validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + String message = siteInvite.getMessage(); + if(message == null) + { + // the invitation service ignores null messages so convert to an empty message. + message = ""; + } + + try + { + ModeratedInvitation updatedInvitation = invitationService.updateModeratedInvitation(inviteeId, siteId, message); + if(updatedInvitation == null) + { + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + updatedSiteInvite = getSiteMembershipRequest(updatedInvitation); + } + catch(InvitationExceptionNotFound e) + { + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + if(updatedSiteInvite == null) + { + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + + return updatedSiteInvite; + } + + @Override + public void cancelSiteMembershipRequest(String inviteeId, String siteId) + { + inviteeId = people.validatePerson(inviteeId); + SiteInfo siteInfo = sites.validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + Invitation invitation = getSiteInvitation(inviteeId, siteId); + if(invitation == null) + { + // no such invitation + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + invitationService.cancel(invitation.getInviteId()); + } + + public SiteMembershipRequest getSiteMembershipRequest(String inviteeId, final String siteId) + { + inviteeId = people.validatePerson(inviteeId); + + SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public SiteInfo doWork() throws Exception + { + SiteInfo siteInfo = sites.validateSite(siteId); + return siteInfo; + } + }); + + if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED)) + { + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + String normalizedSiteId = siteInfo.getShortName(); + + Invitation invitation = getSiteInvitation(inviteeId, normalizedSiteId); + if(invitation == null) + { + // no such invitation + throw new RelationshipResourceNotFoundException(inviteeId, normalizedSiteId); + } + if(invitation instanceof ModeratedInvitation) + { + ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; + SiteMembershipRequest siteInvite = getSiteMembershipRequest(moderatedInvitation); + return siteInvite; + } + else + { + throw new InvalidArgumentException("Expected moderated invitation"); + } + } + else + { + // non-moderated sites cannot appear in a site membership request, so throw an exception + throw new RelationshipResourceNotFoundException(inviteeId, siteId); + } + } + + private SiteMembershipRequest getSiteMembershipRequest(ModeratedInvitation moderatedInvitation) + { + SiteMembershipRequest siteMembershipRequest = null; + + ResourceType resourceType = moderatedInvitation.getResourceType(); + if(resourceType.equals(ResourceType.WEB_SITE)) + { + final String siteId = moderatedInvitation.getResourceName(); + + SiteInfo siteInfo = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public SiteInfo doWork() throws Exception + { + SiteInfo siteInfo = sites.validateSite(siteId); + return siteInfo; + } + }); + + if(siteInfo.getVisibility().equals(SiteVisibility.MODERATED)) + { + // return a site membership request only if this is a moderated site + siteMembershipRequest = new SiteMembershipRequest(); + String title = siteInfo.getTitle(); + siteMembershipRequest.setTitle(title); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage(moderatedInvitation.getInviteeComments()); + siteMembershipRequest.setCreatedAt(moderatedInvitation.getCreatedAt()); + siteMembershipRequest.setModifiedAt(moderatedInvitation.getModifiedAt()); + } + } + else + { + logger.warn("Unexpected resource type " + resourceType + " for site membership request"); + } + + return siteMembershipRequest; + } + + @Override + public CollectionWithPagingInfo getPagedSiteMembershipRequests(String personId, Paging paging) + { + personId = people.validatePerson(personId, true); + + int skipCount = paging.getSkipCount(); + int maxItems = paging.getMaxItems(); + int max = skipCount + maxItems + 1; // to detect hasMoreItems + + List invitations = getSiteInvitations(personId); + List siteMembershipRequests = new ArrayList(invitations.size()); + for(Invitation invitation : invitations) + { + if(invitation instanceof ModeratedInvitation) + { + ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; + SiteMembershipRequest siteMembershipRequest = getSiteMembershipRequest(moderatedInvitation); + if(siteMembershipRequest != null) + { + // note: siteMembershipRequest may be null if the site is now no longer a moderated site + // or if the invitation is malformed and does not refer to a site. + siteMembershipRequests.add(siteMembershipRequest); + } + } + else + { + // just ignore, shouldn't happen because getSiteInvitations filters by ModeratedInvitation + } + } + + // unfortunately, need to sort in memory because there's no way to get site membership requests sorted by title from + // the workflow apis + Collections.sort(siteMembershipRequests); + + int totalItems = siteMembershipRequests.size(); + + if(skipCount >= totalItems) + { + List empty = Collections.emptyList(); + return CollectionWithPagingInfo.asPaged(paging, empty, false, totalItems); + } + else + { + int end = Math.min(max - 1, totalItems); + boolean hasMoreItems = totalItems > end; + + siteMembershipRequests = siteMembershipRequests.subList(skipCount, end); + return CollectionWithPagingInfo.asPaged(paging, siteMembershipRequests, hasMoreItems, totalItems); + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/SitesImpl.java b/source/java/org/alfresco/rest/api/impl/SitesImpl.java index b8175d2c09..39bc10452e 100644 --- a/source/java/org/alfresco/rest/api/impl/SitesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/SitesImpl.java @@ -1,1032 +1,1032 @@ -package org.alfresco.rest.api.impl; - -import java.io.Serializable; -import java.text.Collator; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.query.CannedQuerySortDetails.SortOrder; -import org.alfresco.query.PageDetails; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authority.UnknownAuthorityException; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.repo.site.SiteMembership; -import org.alfresco.repo.site.SiteMembershipComparator; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.site.SiteServiceException; -import org.alfresco.repo.site.SiteServiceImpl; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.People; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.FavouriteSite; -import org.alfresco.rest.api.model.MemberOfSite; -import org.alfresco.rest.api.model.Site; -import org.alfresco.rest.api.model.SiteContainer; -import org.alfresco.rest.api.model.SiteMember; -import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.rest.framework.resource.parameters.SortColumn; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.favourites.FavouritesService; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.preference.PreferenceService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.cmr.view.ImportPackageHandler; -import org.alfresco.service.cmr.view.ImporterBinding; -import org.alfresco.service.cmr.view.ImporterContentCache; -import org.alfresco.service.cmr.view.ImporterProgress; -import org.alfresco.service.cmr.view.ImporterService; -import org.alfresco.service.cmr.view.Location; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.ISO9075; -import org.alfresco.util.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Centralises access to site services and maps between representations. - * - * @author steveglover - * @author janv - * @since publicapi1.0 - */ -public class SitesImpl implements Sites -{ - private static final Log logger = LogFactory.getLog(SitesImpl.class); - - private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; - private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); - - // based on Share create site - private static final int SITE_MAXLEN_ID = 72; - private static final int SITE_MAXLEN_TITLE = 256; - private static final int SITE_MAXLEN_DESCRIPTION = 512; - - private static final String SITE_ID_VALID_CHARS_PARTIAL_REGEX = "A-Za-z0-9\\-"; - - protected Nodes nodes; - protected People people; - protected NodeService nodeService; - protected DictionaryService dictionaryService; - protected SiteService siteService; - protected FavouritesService favouritesService; - protected PreferenceService preferenceService; - protected ImporterService importerService; - protected SiteSurfConfig siteSurfConfig; - protected PermissionService permissionService; - protected SiteServiceImpl siteServiceImpl; - - public void setPreferenceService(PreferenceService preferenceService) - { - this.preferenceService = preferenceService; - } - - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setFavouritesService(FavouritesService favouritesService) - { - this.favouritesService = favouritesService; - } - - public void setPeople(People people) - { - this.people = people; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - public void setImporterService(ImporterService importerService) - { - this.importerService = importerService; - } - - public void setSiteSurfConfig(SiteSurfConfig siteSurfConfig) - { - this.siteSurfConfig = siteSurfConfig; - } - - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - public void setSiteServiceImpl(SiteServiceImpl siteServiceImpl) - { - this.siteServiceImpl = siteServiceImpl; - } - - - public SiteInfo validateSite(NodeRef guid) - { - SiteInfo siteInfo = null; - - if(guid == null) - { - throw new InvalidArgumentException("guid is null"); - } - nodes.validateNode(guid); - QName type = nodeService.getType(guid); - boolean isSiteNodeRef = dictionaryService.isSubClass(type, SiteModel.TYPE_SITE); - if(isSiteNodeRef) - { - siteInfo = siteService.getSite(guid); - if(siteInfo == null) - { - // not a site - throw new InvalidArgumentException(guid.getId() + " is not a site"); - } - } - else - { - // site does not exist - throw new EntityNotFoundException(guid.getId()); - } - - return siteInfo; - } - - public SiteInfo validateSite(String siteId) - { - if(siteId == null) - { - throw new InvalidArgumentException("siteId is null"); - } - SiteInfo siteInfo = siteService.getSite(siteId); - return siteInfo; - } - - public CollectionWithPagingInfo getSiteMembers(String siteId, Parameters parameters) - { - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - Paging paging = parameters.getPaging(); - - PagingRequest pagingRequest = Util.getPagingRequest(paging); - - final List> sort = new ArrayList>(); - sort.add(new Pair(SiteService.SortFields.LastName, Boolean.TRUE)); - sort.add(new Pair(SiteService.SortFields.FirstName, Boolean.TRUE)); - sort.add(new Pair(SiteService.SortFields.Role, Boolean.TRUE)); - sort.add(new Pair(SiteService.SortFields.Username, Boolean.TRUE)); - PagingResults pagedResults = siteService.listMembersPaged(siteId, true, sort, pagingRequest); - - List siteMembers = pagedResults.getPage(); - List ret = new ArrayList(siteMembers.size()); - for(SiteMembership siteMembership : siteMembers) - { - SiteMember siteMember = new SiteMember(siteMembership.getPersonId(), siteMembership.getRole()); - ret.add(siteMember); - } - - return CollectionWithPagingInfo.asPaged(paging, ret, pagedResults.hasMoreItems(), null); - } - - public String getSiteRole(String siteId) - { - String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - return getSiteRole(siteId, personId); - } - - public String getSiteRole(String siteId, String personId) - { - return siteService.getMembersRole(siteId, personId); - } - - public Site getSite(String siteId) - { - return getSite(siteId, true); - } - - public Site getSite(String siteId, boolean includeRole) - { - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - return getSite(siteInfo, includeRole); - } - - private Site getSite(SiteInfo siteInfo, boolean includeRole) - { - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - String siteId = siteInfo.getShortName(); - String role = null; - if(includeRole) - { - role = getSiteRole(siteId); - } - return new Site(siteInfo, role); - } - - /** - * people//sites/ - * - * @param siteId String - * @param personId String - * @return MemberOfSite - */ - public MemberOfSite getMemberOfSite(String personId, String siteId) - { - MemberOfSite siteMember = null; - - personId = people.validatePerson(personId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(personId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - String roleStr = siteService.getMembersRole(siteInfo.getShortName(), personId); - if(roleStr != null) - { - Site site = new Site(siteInfo, roleStr); - siteMember = new MemberOfSite(site.getId(), siteInfo.getNodeRef(), roleStr); - } - else - { - throw new RelationshipResourceNotFoundException(personId, siteId); - } - - return siteMember; - } - - public SiteMember getSiteMember(String personId, String siteId) - { - SiteMember siteMember = null; - - personId = people.validatePerson(personId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - logger.debug("Site does not exist: "+siteId); - throw new RelationshipResourceNotFoundException(personId, siteId); - } - siteId = siteInfo.getShortName(); - - logger.debug("Getting member role for "+siteId+ " person "+personId); - String role = siteService.getMembersRole(siteId, personId); - if(role != null) - { - siteMember = new SiteMember(personId, role); - } - else - { - logger.debug("Getting member role but role is null"); - throw new RelationshipResourceNotFoundException(personId, siteId); - } - - return siteMember; - } - - public SiteMember addSiteMember(String siteId, SiteMember siteMember) - { - String personId = people.validatePerson(siteMember.getPersonId()); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - logger.debug("addSiteMember: site does not exist "+siteId+ " person "+personId); - throw new EntityNotFoundException(siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - String role = siteMember.getRole(); - if(role == null) - { - logger.debug("addSiteMember: Must provide a role "+siteMember); - throw new InvalidArgumentException("Must provide a role"); - } - - if(siteService.isMember(siteId, personId)) - { - logger.debug("addSiteMember: "+ personId + " is already a member of site " + siteId); - throw new ConstraintViolatedException(personId + " is already a member of site " + siteId); - } - - if(!siteService.canAddMember(siteId, personId, role)) - { - logger.debug("addSiteMember: PermissionDeniedException "+siteId+ " person "+personId+ " role "+role); - throw new PermissionDeniedException(); - } - - try - { - siteService.setMembership(siteId, personId, role); - } - catch (UnknownAuthorityException e) - { - logger.debug("addSiteMember: UnknownAuthorityException "+siteId+ " person "+personId+ " role "+role); - throw new InvalidArgumentException("Unknown role '" + role + "'"); - } - return siteMember; - } - - public void removeSiteMember(String personId, String siteId) - { - personId = people.validatePerson(personId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(personId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - boolean isMember = siteService.isMember(siteId, personId); - if(!isMember) - { - throw new InvalidArgumentException(); - } - String role = siteService.getMembersRole(siteId, personId); - if(role != null) - { - if(role.equals(SiteModel.SITE_MANAGER)) - { - int numAuthorities = siteService.countAuthoritiesWithRole(siteId, SiteModel.SITE_MANAGER); - if(numAuthorities <= 1) - { - throw new InvalidArgumentException("Can't remove last manager of site " + siteId); - } - siteService.removeMembership(siteId, personId); - } - else - { - siteService.removeMembership(siteId, personId); - } - } - else - { - throw new AlfrescoRuntimeException("Unable to determine role of site member"); - } - } - - public SiteMember updateSiteMember(String siteId, SiteMember siteMember) - { - String siteMemberId = siteMember.getPersonId(); - if(siteMemberId == null) - { - throw new InvalidArgumentException("Member id is null"); - } - siteMemberId = people.validatePerson(siteMemberId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - siteId = siteInfo.getShortName(); - String siteRole = siteMember.getRole(); - if(siteRole == null) - { - throw new InvalidArgumentException("Must provide a role"); - } - - /* MNT-10551 : fix */ - if (!siteService.isMember(siteId, siteMember.getPersonId())) - { - throw new InvalidArgumentException("User is not a member of the site"); - } - - try - { - siteService.setMembership(siteId, siteMember.getPersonId(), siteRole); - } - catch (UnknownAuthorityException e) - { - throw new InvalidArgumentException("Unknown role '" + siteRole + "'"); - } - return siteMember; - } - - public CollectionWithPagingInfo getSites(String personId, Parameters parameters) - { - Paging paging = parameters.getPaging(); - - personId = people.validatePerson(personId); - - PagingRequest pagingRequest = Util.getPagingRequest(paging); - - // get the sorting options - List> sortPairs = new ArrayList>(parameters.getSorting().size()); - for (SortColumn sortColumn : parameters.getSorting()) - { - SiteService.SortFields sortField; - try - { - sortField= SiteService.SortFields.valueOf(sortColumn.column); - } - catch (IllegalArgumentException ex) - { - // invalid sort field - continue; - } - - sortPairs.add(new Pair( - sortField, - (sortColumn.asc ? SortOrder.ASCENDING : SortOrder.DESCENDING))); - } - - // if no sorting options were specify, sort by title - if(sortPairs.size() == 0) - { - sortPairs.add(new Pair( - SiteService.SortFields.SiteTitle, - SortOrder.ASCENDING )); - } - - // get the unsorted list of site memberships - List siteMembers = siteService.listSiteMemberships (personId, 0); - - // sort the list of site memberships - int totalSize = siteMembers.size(); - final List sortedSiteMembers = new ArrayList<>(siteMembers); - Collections.sort(sortedSiteMembers, new SiteMembershipComparator( - sortPairs, - SiteMembershipComparator.Type.SITES)); - - PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); - List ret = new ArrayList<>(totalSize); - - Iterator it = sortedSiteMembers.iterator(); - for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) - { - SiteMembership siteMember = it.next(); - - if(counter < pageDetails.getSkipCount()) - { - continue; - } - - if(counter > pageDetails.getEnd() - 1) - { - break; - } - - SiteInfo siteInfo = siteMember.getSiteInfo(); - MemberOfSite memberOfSite = new MemberOfSite(siteInfo.getShortName(), siteInfo.getNodeRef(), siteMember.getRole()); - ret.add(memberOfSite); - } - return CollectionWithPagingInfo.asPaged(paging, ret, pageDetails.hasMoreItems(), null); - - } - - public SiteContainer getSiteContainer(String siteId, String containerId) - { - // check site and container node validity - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(siteId, containerId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - NodeRef containerNodeRef = siteService.getContainer(siteId, containerId); - if(containerNodeRef == null) - { - throw new RelationshipResourceNotFoundException(siteId, containerId); - } - - // check that the containerId is actually a container for the specified site - SiteInfo testSiteInfo = siteService.getSite(containerNodeRef); - if(testSiteInfo == null) - { - throw new RelationshipResourceNotFoundException(siteId, containerId); - } - else - { - if(!testSiteInfo.getShortName().equals(siteId)) - { - throw new RelationshipResourceNotFoundException(siteId, containerId); - } - } - - String folderId = (String)nodeService.getProperty(containerNodeRef, SiteModel.PROP_COMPONENT_ID); - - SiteContainer siteContainer = new SiteContainer(folderId, containerNodeRef); - return siteContainer; - } - - public PagingResults getSiteContainers(String siteId, Paging paging) - { - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - - final PagingResults pagingResults = siteService.listContainers(siteInfo.getShortName(), Util.getPagingRequest(paging)); - List containerFileInfos = pagingResults.getPage(); - final List siteContainers = new ArrayList(containerFileInfos.size()); - for(FileInfo containerFileInfo : containerFileInfos) - { - NodeRef nodeRef = containerFileInfo.getNodeRef(); - String containerId = (String)nodeService.getProperty(nodeRef, SiteModel.PROP_COMPONENT_ID); - SiteContainer siteContainer = new SiteContainer(containerId, nodeRef); - siteContainers.add(siteContainer); - } - - return new PagingResults() - { - @Override - public List getPage() - { - return siteContainers; - } - - @Override - public boolean hasMoreItems() - { - return pagingResults.hasMoreItems(); - } - - @Override - public Pair getTotalResultCount() - { - return pagingResults.getTotalResultCount(); - } - - @Override - public String getQueryExecutionId() - { - return null; - } - }; - } - - public CollectionWithPagingInfo getSites(final Parameters parameters) - { - final BeanPropertiesFilter filter = parameters.getFilter(); - - Paging paging = parameters.getPaging(); - PagingRequest pagingRequest = Util.getPagingRequest(paging); -// pagingRequest.setRequestTotalCountMax(requestTotalCountMax) - List> sortProps = new ArrayList>(); - sortProps.add(new Pair(ContentModel.PROP_NAME, Boolean.TRUE)); - final PagingResults pagingResult = siteService.listSites(null, sortProps, pagingRequest); - final List sites = pagingResult.getPage(); - int totalItems = pagingResult.getTotalResultCount().getFirst(); - final String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - List page = new AbstractList() - { - @Override - public Site get(int index) - { - SiteInfo siteInfo = sites.get(index); - - String role = null; - if(filter.isAllowed(Site.ROLE)) - { - role = siteService.getMembersRole(siteInfo.getShortName(), personId); - } - return new Site(siteInfo, role); - } - - @Override - public int size() - { - return sites.size(); - } - }; - - return CollectionWithPagingInfo.asPaged(paging, page, pagingResult.hasMoreItems(), totalItems); - } - - public FavouriteSite getFavouriteSite(String personId, String siteId) - { - personId = people.validatePerson(personId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(personId, siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - NodeRef nodeRef = siteInfo.getNodeRef(); - - if(favouritesService.isFavourite(personId, nodeRef)) - { - String role = getSiteRole(siteId, personId); - return new FavouriteSite(siteInfo, role); - } - else - { - throw new RelationshipResourceNotFoundException(personId, siteId); - } - } - - public void addFavouriteSite(String personId, FavouriteSite favouriteSite) - { - personId = people.validatePerson(personId); - String siteId = favouriteSite.getId(); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - siteId = siteInfo.getShortName(); - - StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); - prefKey.append(siteId); - String value = (String)preferenceService.getPreference(personId, prefKey.toString()); - boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); - - if(isFavouriteSite) - { - throw new ConstraintViolatedException("Site " + siteId + " is already a favourite site"); - } - - prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); - prefKey.append(siteId); - - Map preferences = new HashMap(1); - preferences.put(prefKey.toString(), Boolean.TRUE); - preferenceService.setPreferences(personId, preferences); - } - - public void removeFavouriteSite(String personId, String siteId) - { - personId = people.validatePerson(personId); - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new RelationshipResourceNotFoundException(personId, siteId); - } - siteId = siteInfo.getShortName(); - - StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); - prefKey.append(siteId); - String value = (String)preferenceService.getPreference(personId, prefKey.toString()); - boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); - - if(!isFavouriteSite) - { - throw new NotFoundException("Site " + siteId + " is not a favourite site"); - } - - preferenceService.clearPreferences(personId, prefKey.toString()); - } - - private PagingResults getFavouriteSites(String userName, PagingRequest pagingRequest) - { - final Collator collator = Collator.getInstance(); - - final Set sortedFavouriteSites = new TreeSet(new Comparator() - { - @Override - public int compare(SiteInfo o1, SiteInfo o2) - { - return collator.compare(o1.getTitle(), o2.getTitle()); - } - }); - - Map prefs = preferenceService.getPreferences(userName, FAVOURITE_SITES_PREFIX); - for(Entry entry : prefs.entrySet()) - { - boolean isFavourite = false; - Serializable s = entry.getValue(); - if(s instanceof Boolean) - { - isFavourite = (Boolean)s; - } - if(isFavourite) - { - String siteShortName = entry.getKey().substring(FAVOURITE_SITES_PREFIX_LENGTH).replace(".favourited", ""); - SiteInfo siteInfo = siteService.getSite(siteShortName); - if(siteInfo != null) - { - sortedFavouriteSites.add(siteInfo); - } - } - } - - int totalSize = sortedFavouriteSites.size(); - final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); - - final List page = new ArrayList(pageDetails.getPageSize()); - Iterator it = sortedFavouriteSites.iterator(); - for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) - { - SiteInfo favouriteSite = it.next(); - - if(counter < pageDetails.getSkipCount()) - { - continue; - } - - if(counter > pageDetails.getEnd() - 1) - { - break; - } - - page.add(favouriteSite); - } - - return new PagingResults() - { - @Override - public List getPage() - { - return page; - } - - @Override - public boolean hasMoreItems() - { - return pageDetails.hasMoreItems(); - } - - @Override - public Pair getTotalResultCount() - { - Integer total = Integer.valueOf(sortedFavouriteSites.size()); - return new Pair(total, total); - } - - @Override - public String getQueryExecutionId() - { - return null; - } - }; - } - - public CollectionWithPagingInfo getFavouriteSites(String personId, Parameters parameters) - { - personId = people.validatePerson(personId); - - Paging paging = parameters.getPaging(); - BeanPropertiesFilter filter = parameters.getFilter(); - - PagingResults favouriteSites = getFavouriteSites(personId, Util.getPagingRequest(paging)); - List favourites = new ArrayList(favouriteSites.getPage().size()); - for(SiteInfo favouriteSite : favouriteSites.getPage()) - { - String role = null; - if(filter.isAllowed(Site.ROLE)) - { - role = getSiteRole(favouriteSite.getShortName(), personId); - } - FavouriteSite favourite = new FavouriteSite(favouriteSite, role); - favourites.add(favourite); - } - - return CollectionWithPagingInfo.asPaged(paging, favourites, favouriteSites.hasMoreItems(), favouriteSites.getTotalResultCount().getFirst()); - } - - public void deleteSite(String siteId, Parameters parameters) - { - SiteInfo siteInfo = validateSite(siteId); - if(siteInfo == null) - { - // site does not exist - throw new EntityNotFoundException(siteId); - } - siteId = siteInfo.getShortName(); - - NodeRef siteNodeRef = siteInfo.getNodeRef(); - - // belt-and-braces - double-check before purge/delete (rather than rollback) - if (permissionService.hasPermission(siteNodeRef, PermissionService.DELETE) != AccessStatus.ALLOWED) - { - throw new AccessDeniedException("Cannot delete site: "+siteId); - } - - // default false (if not provided) - boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT)); - - if (permanentDelete == true) - { - // Set as temporary to delete node instead of archiving. - nodeService.addAspect(siteNodeRef, ContentModel.ASPECT_TEMPORARY, null); - - // bypassing trashcan means that purge behaviour will not fire, so explicitly force cleanup here - siteServiceImpl.beforePurgeNode(siteNodeRef); - } - - siteService.deleteSite(siteId); - } - - - /** - * Create default/fixed preset (Share) site - with DocLib container/component - * - * @param site - * @return - */ - public Site createSite(Site site, Parameters parameters) - { - // note: if site id is null then will be generated from the site title - site = validateSite(site); - - SiteInfo siteInfo = null; - try - { - siteInfo = siteService.createSite("sitePreset", site.getId(), site.getTitle(), site.getDescription(), site.getVisibility()); - } - catch (SiteServiceException sse) - { - if (sse.getMsgId().equals("site_service.unable_to_create")) - { - throw new ConstraintViolatedException(sse.getMessage()); - } - else - { - throw sse; - } - } - - String siteId = siteInfo.getShortName(); - NodeRef siteNodeRef = siteInfo.getNodeRef(); - - // default false (if not provided) - boolean skipShareSurfConfig = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_SURF_CONFIGURATION)); - if (skipShareSurfConfig == false) - { - // import default/fixed preset Share surf config - importSite(siteId, siteNodeRef); - } - - // pre-create doclib - siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null); - - // default false (if not provided) - boolean skipAddToFavorites = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_ADDTOFAVORITES)); - if (skipAddToFavorites == false) - { - String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - favouritesService.addFavourite(personId, siteNodeRef); // ignore result - } - - return getSite(siteInfo, true); - } - - private Site validateSite(Site site) - { - // site title - mandatory - String siteTitle = site.getTitle(); - if ((siteTitle == null) || siteTitle.isEmpty()) - { - throw new InvalidArgumentException("Site title is expected: "+siteTitle); - } - else if (siteTitle.length() > SITE_MAXLEN_TITLE) - { - throw new InvalidArgumentException("Site title exceeds max length of "+SITE_MAXLEN_TITLE+" characters"); - } - - SiteVisibility siteVisibility = site.getVisibility(); - if (siteVisibility == null) - { - throw new InvalidArgumentException("Site visibility is expected: "+siteTitle+" (eg. PUBLIC, PRIVATE, MODERATED)"); - } - - String siteId = site.getId(); - if (siteId == null) - { - // generate a site id from title (similar to Share create site dialog) - siteId = siteTitle. - trim(). // trim leading & trailing whitespace - replaceAll("[^"+SITE_ID_VALID_CHARS_PARTIAL_REGEX+" ]",""). // remove special characters (except spaces) - replaceAll(" +", " "). // collapse multiple spaces to single space - replace(" ","-"). // replaces spaces with dashs - toLowerCase(); // lowercase :-) - } - else - { - if (! siteId.matches("^["+SITE_ID_VALID_CHARS_PARTIAL_REGEX+"]+")) - { - throw new InvalidArgumentException("Invalid site id - should consist of alphanumeric/dash characters"); - } - } - - if (siteId.length() > SITE_MAXLEN_ID) - { - throw new InvalidArgumentException("Site id exceeds max length of "+SITE_MAXLEN_ID+ "characters"); - } - - site.setId(siteId); - - String siteDescription = site.getDescription(); - - if (siteDescription == null) - { - // workaround: to avoid Share error (eg. in My Sites dashlet / freemarker template) - site.setDescription(""); - } - - if ((siteDescription != null) && (siteDescription.length() > SITE_MAXLEN_DESCRIPTION)) - { - throw new InvalidArgumentException("Site description exceeds max length of "+SITE_MAXLEN_DESCRIPTION+" characters"); - } - - return site; - } - - private void importSite(final String siteId, final NodeRef siteNodeRef) - { - ImportPackageHandler acpHandler = new SiteImportPackageHandler(siteSurfConfig, siteId); - Location location = new Location(siteNodeRef); - ImporterBinding binding = new ImporterBinding() - { - @Override - public String getValue(String key) - { - if (key.equals("siteId")) - { - return siteId; - } - return null; - } - - @Override - public UUID_BINDING getUUIDBinding() - { - return UUID_BINDING.CREATE_NEW; - } - - @Override - public QName[] getExcludedClasses() - { - return null; - } - - @Override - public boolean allowReferenceWithinTransaction() - { - return false; - } - - @Override - public ImporterContentCache getImportConentCache() - { - return null; - } - }; - importerService.importView(acpHandler, location, binding, (ImporterProgress)null); - } -} +package org.alfresco.rest.api.impl; + +import java.io.Serializable; +import java.text.Collator; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.query.CannedQuerySortDetails.SortOrder; +import org.alfresco.query.PageDetails; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authority.UnknownAuthorityException; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.site.SiteMembership; +import org.alfresco.repo.site.SiteMembershipComparator; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.site.SiteServiceException; +import org.alfresco.repo.site.SiteServiceImpl; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.People; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.FavouriteSite; +import org.alfresco.rest.api.model.MemberOfSite; +import org.alfresco.rest.api.model.Site; +import org.alfresco.rest.api.model.SiteContainer; +import org.alfresco.rest.api.model.SiteMember; +import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.resource.parameters.SortColumn; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.favourites.FavouritesService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.preference.PreferenceService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.cmr.view.ImportPackageHandler; +import org.alfresco.service.cmr.view.ImporterBinding; +import org.alfresco.service.cmr.view.ImporterContentCache; +import org.alfresco.service.cmr.view.ImporterProgress; +import org.alfresco.service.cmr.view.ImporterService; +import org.alfresco.service.cmr.view.Location; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Centralises access to site services and maps between representations. + * + * @author steveglover + * @author janv + * @since publicapi1.0 + */ +public class SitesImpl implements Sites +{ + private static final Log logger = LogFactory.getLog(SitesImpl.class); + + private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; + private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); + + // based on Share create site + private static final int SITE_MAXLEN_ID = 72; + private static final int SITE_MAXLEN_TITLE = 256; + private static final int SITE_MAXLEN_DESCRIPTION = 512; + + private static final String SITE_ID_VALID_CHARS_PARTIAL_REGEX = "A-Za-z0-9\\-"; + + protected Nodes nodes; + protected People people; + protected NodeService nodeService; + protected DictionaryService dictionaryService; + protected SiteService siteService; + protected FavouritesService favouritesService; + protected PreferenceService preferenceService; + protected ImporterService importerService; + protected SiteSurfConfig siteSurfConfig; + protected PermissionService permissionService; + protected SiteServiceImpl siteServiceImpl; + + public void setPreferenceService(PreferenceService preferenceService) + { + this.preferenceService = preferenceService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setFavouritesService(FavouritesService favouritesService) + { + this.favouritesService = favouritesService; + } + + public void setPeople(People people) + { + this.people = people; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setImporterService(ImporterService importerService) + { + this.importerService = importerService; + } + + public void setSiteSurfConfig(SiteSurfConfig siteSurfConfig) + { + this.siteSurfConfig = siteSurfConfig; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setSiteServiceImpl(SiteServiceImpl siteServiceImpl) + { + this.siteServiceImpl = siteServiceImpl; + } + + + public SiteInfo validateSite(NodeRef guid) + { + SiteInfo siteInfo = null; + + if(guid == null) + { + throw new InvalidArgumentException("guid is null"); + } + nodes.validateNode(guid); + QName type = nodeService.getType(guid); + boolean isSiteNodeRef = dictionaryService.isSubClass(type, SiteModel.TYPE_SITE); + if(isSiteNodeRef) + { + siteInfo = siteService.getSite(guid); + if(siteInfo == null) + { + // not a site + throw new InvalidArgumentException(guid.getId() + " is not a site"); + } + } + else + { + // site does not exist + throw new EntityNotFoundException(guid.getId()); + } + + return siteInfo; + } + + public SiteInfo validateSite(String siteId) + { + if(siteId == null) + { + throw new InvalidArgumentException("siteId is null"); + } + SiteInfo siteInfo = siteService.getSite(siteId); + return siteInfo; + } + + public CollectionWithPagingInfo getSiteMembers(String siteId, Parameters parameters) + { + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + Paging paging = parameters.getPaging(); + + PagingRequest pagingRequest = Util.getPagingRequest(paging); + + final List> sort = new ArrayList>(); + sort.add(new Pair(SiteService.SortFields.LastName, Boolean.TRUE)); + sort.add(new Pair(SiteService.SortFields.FirstName, Boolean.TRUE)); + sort.add(new Pair(SiteService.SortFields.Role, Boolean.TRUE)); + sort.add(new Pair(SiteService.SortFields.Username, Boolean.TRUE)); + PagingResults pagedResults = siteService.listMembersPaged(siteId, true, sort, pagingRequest); + + List siteMembers = pagedResults.getPage(); + List ret = new ArrayList(siteMembers.size()); + for(SiteMembership siteMembership : siteMembers) + { + SiteMember siteMember = new SiteMember(siteMembership.getPersonId(), siteMembership.getRole()); + ret.add(siteMember); + } + + return CollectionWithPagingInfo.asPaged(paging, ret, pagedResults.hasMoreItems(), null); + } + + public String getSiteRole(String siteId) + { + String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + return getSiteRole(siteId, personId); + } + + public String getSiteRole(String siteId, String personId) + { + return siteService.getMembersRole(siteId, personId); + } + + public Site getSite(String siteId) + { + return getSite(siteId, true); + } + + public Site getSite(String siteId, boolean includeRole) + { + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + return getSite(siteInfo, includeRole); + } + + private Site getSite(SiteInfo siteInfo, boolean includeRole) + { + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + String siteId = siteInfo.getShortName(); + String role = null; + if(includeRole) + { + role = getSiteRole(siteId); + } + return new Site(siteInfo, role); + } + + /** + * people//sites/ + * + * @param siteId String + * @param personId String + * @return MemberOfSite + */ + public MemberOfSite getMemberOfSite(String personId, String siteId) + { + MemberOfSite siteMember = null; + + personId = people.validatePerson(personId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(personId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + String roleStr = siteService.getMembersRole(siteInfo.getShortName(), personId); + if(roleStr != null) + { + Site site = new Site(siteInfo, roleStr); + siteMember = new MemberOfSite(site.getId(), siteInfo.getNodeRef(), roleStr); + } + else + { + throw new RelationshipResourceNotFoundException(personId, siteId); + } + + return siteMember; + } + + public SiteMember getSiteMember(String personId, String siteId) + { + SiteMember siteMember = null; + + personId = people.validatePerson(personId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + logger.debug("Site does not exist: "+siteId); + throw new RelationshipResourceNotFoundException(personId, siteId); + } + siteId = siteInfo.getShortName(); + + logger.debug("Getting member role for "+siteId+ " person "+personId); + String role = siteService.getMembersRole(siteId, personId); + if(role != null) + { + siteMember = new SiteMember(personId, role); + } + else + { + logger.debug("Getting member role but role is null"); + throw new RelationshipResourceNotFoundException(personId, siteId); + } + + return siteMember; + } + + public SiteMember addSiteMember(String siteId, SiteMember siteMember) + { + String personId = people.validatePerson(siteMember.getPersonId()); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + logger.debug("addSiteMember: site does not exist "+siteId+ " person "+personId); + throw new EntityNotFoundException(siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + String role = siteMember.getRole(); + if(role == null) + { + logger.debug("addSiteMember: Must provide a role "+siteMember); + throw new InvalidArgumentException("Must provide a role"); + } + + if(siteService.isMember(siteId, personId)) + { + logger.debug("addSiteMember: "+ personId + " is already a member of site " + siteId); + throw new ConstraintViolatedException(personId + " is already a member of site " + siteId); + } + + if(!siteService.canAddMember(siteId, personId, role)) + { + logger.debug("addSiteMember: PermissionDeniedException "+siteId+ " person "+personId+ " role "+role); + throw new PermissionDeniedException(); + } + + try + { + siteService.setMembership(siteId, personId, role); + } + catch (UnknownAuthorityException e) + { + logger.debug("addSiteMember: UnknownAuthorityException "+siteId+ " person "+personId+ " role "+role); + throw new InvalidArgumentException("Unknown role '" + role + "'"); + } + return siteMember; + } + + public void removeSiteMember(String personId, String siteId) + { + personId = people.validatePerson(personId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(personId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + boolean isMember = siteService.isMember(siteId, personId); + if(!isMember) + { + throw new InvalidArgumentException(); + } + String role = siteService.getMembersRole(siteId, personId); + if(role != null) + { + if(role.equals(SiteModel.SITE_MANAGER)) + { + int numAuthorities = siteService.countAuthoritiesWithRole(siteId, SiteModel.SITE_MANAGER); + if(numAuthorities <= 1) + { + throw new InvalidArgumentException("Can't remove last manager of site " + siteId); + } + siteService.removeMembership(siteId, personId); + } + else + { + siteService.removeMembership(siteId, personId); + } + } + else + { + throw new AlfrescoRuntimeException("Unable to determine role of site member"); + } + } + + public SiteMember updateSiteMember(String siteId, SiteMember siteMember) + { + String siteMemberId = siteMember.getPersonId(); + if(siteMemberId == null) + { + throw new InvalidArgumentException("Member id is null"); + } + siteMemberId = people.validatePerson(siteMemberId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + siteId = siteInfo.getShortName(); + String siteRole = siteMember.getRole(); + if(siteRole == null) + { + throw new InvalidArgumentException("Must provide a role"); + } + + /* MNT-10551 : fix */ + if (!siteService.isMember(siteId, siteMember.getPersonId())) + { + throw new InvalidArgumentException("User is not a member of the site"); + } + + try + { + siteService.setMembership(siteId, siteMember.getPersonId(), siteRole); + } + catch (UnknownAuthorityException e) + { + throw new InvalidArgumentException("Unknown role '" + siteRole + "'"); + } + return siteMember; + } + + public CollectionWithPagingInfo getSites(String personId, Parameters parameters) + { + Paging paging = parameters.getPaging(); + + personId = people.validatePerson(personId); + + PagingRequest pagingRequest = Util.getPagingRequest(paging); + + // get the sorting options + List> sortPairs = new ArrayList>(parameters.getSorting().size()); + for (SortColumn sortColumn : parameters.getSorting()) + { + SiteService.SortFields sortField; + try + { + sortField= SiteService.SortFields.valueOf(sortColumn.column); + } + catch (IllegalArgumentException ex) + { + // invalid sort field + continue; + } + + sortPairs.add(new Pair( + sortField, + (sortColumn.asc ? SortOrder.ASCENDING : SortOrder.DESCENDING))); + } + + // if no sorting options were specify, sort by title + if(sortPairs.size() == 0) + { + sortPairs.add(new Pair( + SiteService.SortFields.SiteTitle, + SortOrder.ASCENDING )); + } + + // get the unsorted list of site memberships + List siteMembers = siteService.listSiteMemberships (personId, 0); + + // sort the list of site memberships + int totalSize = siteMembers.size(); + final List sortedSiteMembers = new ArrayList<>(siteMembers); + Collections.sort(sortedSiteMembers, new SiteMembershipComparator( + sortPairs, + SiteMembershipComparator.Type.SITES)); + + PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); + List ret = new ArrayList<>(totalSize); + + Iterator it = sortedSiteMembers.iterator(); + for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) + { + SiteMembership siteMember = it.next(); + + if(counter < pageDetails.getSkipCount()) + { + continue; + } + + if(counter > pageDetails.getEnd() - 1) + { + break; + } + + SiteInfo siteInfo = siteMember.getSiteInfo(); + MemberOfSite memberOfSite = new MemberOfSite(siteInfo.getShortName(), siteInfo.getNodeRef(), siteMember.getRole()); + ret.add(memberOfSite); + } + return CollectionWithPagingInfo.asPaged(paging, ret, pageDetails.hasMoreItems(), null); + + } + + public SiteContainer getSiteContainer(String siteId, String containerId) + { + // check site and container node validity + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(siteId, containerId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + NodeRef containerNodeRef = siteService.getContainer(siteId, containerId); + if(containerNodeRef == null) + { + throw new RelationshipResourceNotFoundException(siteId, containerId); + } + + // check that the containerId is actually a container for the specified site + SiteInfo testSiteInfo = siteService.getSite(containerNodeRef); + if(testSiteInfo == null) + { + throw new RelationshipResourceNotFoundException(siteId, containerId); + } + else + { + if(!testSiteInfo.getShortName().equals(siteId)) + { + throw new RelationshipResourceNotFoundException(siteId, containerId); + } + } + + String folderId = (String)nodeService.getProperty(containerNodeRef, SiteModel.PROP_COMPONENT_ID); + + SiteContainer siteContainer = new SiteContainer(folderId, containerNodeRef); + return siteContainer; + } + + public PagingResults getSiteContainers(String siteId, Paging paging) + { + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + + final PagingResults pagingResults = siteService.listContainers(siteInfo.getShortName(), Util.getPagingRequest(paging)); + List containerFileInfos = pagingResults.getPage(); + final List siteContainers = new ArrayList(containerFileInfos.size()); + for(FileInfo containerFileInfo : containerFileInfos) + { + NodeRef nodeRef = containerFileInfo.getNodeRef(); + String containerId = (String)nodeService.getProperty(nodeRef, SiteModel.PROP_COMPONENT_ID); + SiteContainer siteContainer = new SiteContainer(containerId, nodeRef); + siteContainers.add(siteContainer); + } + + return new PagingResults() + { + @Override + public List getPage() + { + return siteContainers; + } + + @Override + public boolean hasMoreItems() + { + return pagingResults.hasMoreItems(); + } + + @Override + public Pair getTotalResultCount() + { + return pagingResults.getTotalResultCount(); + } + + @Override + public String getQueryExecutionId() + { + return null; + } + }; + } + + public CollectionWithPagingInfo getSites(final Parameters parameters) + { + final BeanPropertiesFilter filter = parameters.getFilter(); + + Paging paging = parameters.getPaging(); + PagingRequest pagingRequest = Util.getPagingRequest(paging); +// pagingRequest.setRequestTotalCountMax(requestTotalCountMax) + List> sortProps = new ArrayList>(); + sortProps.add(new Pair(ContentModel.PROP_NAME, Boolean.TRUE)); + final PagingResults pagingResult = siteService.listSites(null, sortProps, pagingRequest); + final List sites = pagingResult.getPage(); + int totalItems = pagingResult.getTotalResultCount().getFirst(); + final String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + List page = new AbstractList() + { + @Override + public Site get(int index) + { + SiteInfo siteInfo = sites.get(index); + + String role = null; + if(filter.isAllowed(Site.ROLE)) + { + role = siteService.getMembersRole(siteInfo.getShortName(), personId); + } + return new Site(siteInfo, role); + } + + @Override + public int size() + { + return sites.size(); + } + }; + + return CollectionWithPagingInfo.asPaged(paging, page, pagingResult.hasMoreItems(), totalItems); + } + + public FavouriteSite getFavouriteSite(String personId, String siteId) + { + personId = people.validatePerson(personId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(personId, siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + NodeRef nodeRef = siteInfo.getNodeRef(); + + if(favouritesService.isFavourite(personId, nodeRef)) + { + String role = getSiteRole(siteId, personId); + return new FavouriteSite(siteInfo, role); + } + else + { + throw new RelationshipResourceNotFoundException(personId, siteId); + } + } + + public void addFavouriteSite(String personId, FavouriteSite favouriteSite) + { + personId = people.validatePerson(personId); + String siteId = favouriteSite.getId(); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) + siteId = siteInfo.getShortName(); + + StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); + prefKey.append(siteId); + String value = (String)preferenceService.getPreference(personId, prefKey.toString()); + boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); + + if(isFavouriteSite) + { + throw new ConstraintViolatedException("Site " + siteId + " is already a favourite site"); + } + + prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); + prefKey.append(siteId); + + Map preferences = new HashMap(1); + preferences.put(prefKey.toString(), Boolean.TRUE); + preferenceService.setPreferences(personId, preferences); + } + + public void removeFavouriteSite(String personId, String siteId) + { + personId = people.validatePerson(personId); + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new RelationshipResourceNotFoundException(personId, siteId); + } + siteId = siteInfo.getShortName(); + + StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); + prefKey.append(siteId); + String value = (String)preferenceService.getPreference(personId, prefKey.toString()); + boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); + + if(!isFavouriteSite) + { + throw new NotFoundException("Site " + siteId + " is not a favourite site"); + } + + preferenceService.clearPreferences(personId, prefKey.toString()); + } + + private PagingResults getFavouriteSites(String userName, PagingRequest pagingRequest) + { + final Collator collator = Collator.getInstance(); + + final Set sortedFavouriteSites = new TreeSet(new Comparator() + { + @Override + public int compare(SiteInfo o1, SiteInfo o2) + { + return collator.compare(o1.getTitle(), o2.getTitle()); + } + }); + + Map prefs = preferenceService.getPreferences(userName, FAVOURITE_SITES_PREFIX); + for(Entry entry : prefs.entrySet()) + { + boolean isFavourite = false; + Serializable s = entry.getValue(); + if(s instanceof Boolean) + { + isFavourite = (Boolean)s; + } + if(isFavourite) + { + String siteShortName = entry.getKey().substring(FAVOURITE_SITES_PREFIX_LENGTH).replace(".favourited", ""); + SiteInfo siteInfo = siteService.getSite(siteShortName); + if(siteInfo != null) + { + sortedFavouriteSites.add(siteInfo); + } + } + } + + int totalSize = sortedFavouriteSites.size(); + final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); + + final List page = new ArrayList(pageDetails.getPageSize()); + Iterator it = sortedFavouriteSites.iterator(); + for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) + { + SiteInfo favouriteSite = it.next(); + + if(counter < pageDetails.getSkipCount()) + { + continue; + } + + if(counter > pageDetails.getEnd() - 1) + { + break; + } + + page.add(favouriteSite); + } + + return new PagingResults() + { + @Override + public List getPage() + { + return page; + } + + @Override + public boolean hasMoreItems() + { + return pageDetails.hasMoreItems(); + } + + @Override + public Pair getTotalResultCount() + { + Integer total = Integer.valueOf(sortedFavouriteSites.size()); + return new Pair(total, total); + } + + @Override + public String getQueryExecutionId() + { + return null; + } + }; + } + + public CollectionWithPagingInfo getFavouriteSites(String personId, Parameters parameters) + { + personId = people.validatePerson(personId); + + Paging paging = parameters.getPaging(); + BeanPropertiesFilter filter = parameters.getFilter(); + + PagingResults favouriteSites = getFavouriteSites(personId, Util.getPagingRequest(paging)); + List favourites = new ArrayList(favouriteSites.getPage().size()); + for(SiteInfo favouriteSite : favouriteSites.getPage()) + { + String role = null; + if(filter.isAllowed(Site.ROLE)) + { + role = getSiteRole(favouriteSite.getShortName(), personId); + } + FavouriteSite favourite = new FavouriteSite(favouriteSite, role); + favourites.add(favourite); + } + + return CollectionWithPagingInfo.asPaged(paging, favourites, favouriteSites.hasMoreItems(), favouriteSites.getTotalResultCount().getFirst()); + } + + public void deleteSite(String siteId, Parameters parameters) + { + SiteInfo siteInfo = validateSite(siteId); + if(siteInfo == null) + { + // site does not exist + throw new EntityNotFoundException(siteId); + } + siteId = siteInfo.getShortName(); + + NodeRef siteNodeRef = siteInfo.getNodeRef(); + + // belt-and-braces - double-check before purge/delete (rather than rollback) + if (permissionService.hasPermission(siteNodeRef, PermissionService.DELETE) != AccessStatus.ALLOWED) + { + throw new AccessDeniedException("Cannot delete site: "+siteId); + } + + // default false (if not provided) + boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT)); + + if (permanentDelete == true) + { + // Set as temporary to delete node instead of archiving. + nodeService.addAspect(siteNodeRef, ContentModel.ASPECT_TEMPORARY, null); + + // bypassing trashcan means that purge behaviour will not fire, so explicitly force cleanup here + siteServiceImpl.beforePurgeNode(siteNodeRef); + } + + siteService.deleteSite(siteId); + } + + + /** + * Create default/fixed preset (Share) site - with DocLib container/component + * + * @param site + * @return + */ + public Site createSite(Site site, Parameters parameters) + { + // note: if site id is null then will be generated from the site title + site = validateSite(site); + + SiteInfo siteInfo = null; + try + { + siteInfo = siteService.createSite("sitePreset", site.getId(), site.getTitle(), site.getDescription(), site.getVisibility()); + } + catch (SiteServiceException sse) + { + if (sse.getMsgId().equals("site_service.unable_to_create")) + { + throw new ConstraintViolatedException(sse.getMessage()); + } + else + { + throw sse; + } + } + + String siteId = siteInfo.getShortName(); + NodeRef siteNodeRef = siteInfo.getNodeRef(); + + // default false (if not provided) + boolean skipShareSurfConfig = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_SURF_CONFIGURATION)); + if (skipShareSurfConfig == false) + { + // import default/fixed preset Share surf config + importSite(siteId, siteNodeRef); + } + + // pre-create doclib + siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null); + + // default false (if not provided) + boolean skipAddToFavorites = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_ADDTOFAVORITES)); + if (skipAddToFavorites == false) + { + String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + favouritesService.addFavourite(personId, siteNodeRef); // ignore result + } + + return getSite(siteInfo, true); + } + + private Site validateSite(Site site) + { + // site title - mandatory + String siteTitle = site.getTitle(); + if ((siteTitle == null) || siteTitle.isEmpty()) + { + throw new InvalidArgumentException("Site title is expected: "+siteTitle); + } + else if (siteTitle.length() > SITE_MAXLEN_TITLE) + { + throw new InvalidArgumentException("Site title exceeds max length of "+SITE_MAXLEN_TITLE+" characters"); + } + + SiteVisibility siteVisibility = site.getVisibility(); + if (siteVisibility == null) + { + throw new InvalidArgumentException("Site visibility is expected: "+siteTitle+" (eg. PUBLIC, PRIVATE, MODERATED)"); + } + + String siteId = site.getId(); + if (siteId == null) + { + // generate a site id from title (similar to Share create site dialog) + siteId = siteTitle. + trim(). // trim leading & trailing whitespace + replaceAll("[^"+SITE_ID_VALID_CHARS_PARTIAL_REGEX+" ]",""). // remove special characters (except spaces) + replaceAll(" +", " "). // collapse multiple spaces to single space + replace(" ","-"). // replaces spaces with dashs + toLowerCase(); // lowercase :-) + } + else + { + if (! siteId.matches("^["+SITE_ID_VALID_CHARS_PARTIAL_REGEX+"]+")) + { + throw new InvalidArgumentException("Invalid site id - should consist of alphanumeric/dash characters"); + } + } + + if (siteId.length() > SITE_MAXLEN_ID) + { + throw new InvalidArgumentException("Site id exceeds max length of "+SITE_MAXLEN_ID+ "characters"); + } + + site.setId(siteId); + + String siteDescription = site.getDescription(); + + if (siteDescription == null) + { + // workaround: to avoid Share error (eg. in My Sites dashlet / freemarker template) + site.setDescription(""); + } + + if ((siteDescription != null) && (siteDescription.length() > SITE_MAXLEN_DESCRIPTION)) + { + throw new InvalidArgumentException("Site description exceeds max length of "+SITE_MAXLEN_DESCRIPTION+" characters"); + } + + return site; + } + + private void importSite(final String siteId, final NodeRef siteNodeRef) + { + ImportPackageHandler acpHandler = new SiteImportPackageHandler(siteSurfConfig, siteId); + Location location = new Location(siteNodeRef); + ImporterBinding binding = new ImporterBinding() + { + @Override + public String getValue(String key) + { + if (key.equals("siteId")) + { + return siteId; + } + return null; + } + + @Override + public UUID_BINDING getUUIDBinding() + { + return UUID_BINDING.CREATE_NEW; + } + + @Override + public QName[] getExcludedClasses() + { + return null; + } + + @Override + public boolean allowReferenceWithinTransaction() + { + return false; + } + + @Override + public ImporterContentCache getImportConentCache() + { + return null; + } + }; + importerService.importView(acpHandler, location, binding, (ImporterProgress)null); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/TagsImpl.java b/source/java/org/alfresco/rest/api/impl/TagsImpl.java index 4e34914b1a..3b6c94ff46 100644 --- a/source/java/org/alfresco/rest/api/impl/TagsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/TagsImpl.java @@ -1,188 +1,188 @@ -package org.alfresco.rest.api.impl; - -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.query.PagingResults; -import org.alfresco.repo.tagging.NonExistentTagException; -import org.alfresco.repo.tagging.TagExistsException; -import org.alfresco.repo.tagging.TaggingException; -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.Tags; -import org.alfresco.rest.api.model.Tag; -import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.tagging.TaggingService; -import org.alfresco.util.Pair; -import org.alfresco.util.TypeConstraint; - -/** - * Centralises access to tag services and maps between representations. - * - * @author steveglover - * @since publicapi1.0 - */ -public class TagsImpl implements Tags -{ - private Nodes nodes; - private TaggingService taggingService; - private TypeConstraint typeConstraint; - - public void setTypeConstraint(TypeConstraint typeConstraint) - { - this.typeConstraint = typeConstraint; - } - - public void setNodes(Nodes nodes) - { - this.nodes = nodes; - } - - public void setTaggingService(TaggingService taggingService) - { - this.taggingService = taggingService; - } - - public List addTags(String nodeId, final List tags) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - if(!typeConstraint.matches(nodeRef)) - { - throw new UnsupportedResourceOperationException("Cannot tag this node"); - } - - List tagValues = new AbstractList() - { - @Override - public String get(int arg0) - { - String tag = tags.get(arg0).getTag(); - return tag; - } - - @Override - public int size() - { - return tags.size(); - } - }; - try - { - List> tagNodeRefs = taggingService.addTags(nodeRef, tagValues); - List ret = new ArrayList(tags.size()); - for(Pair pair : tagNodeRefs) - { - ret.add(new Tag(pair.getSecond(), pair.getFirst())); - } - return ret; - } - catch(IllegalArgumentException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - public void deleteTag(String nodeId, String tagId) - { - NodeRef nodeRef = nodes.validateNode(nodeId); - getTag(tagId); - NodeRef existingTagNodeRef = validateTag(tagId); - String tagValue = taggingService.getTagName(existingTagNodeRef); - taggingService.removeTag(nodeRef, tagValue); - } - - public CollectionWithPagingInfo getTags(StoreRef storeRef, Paging paging) - { - PagingResults> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging)); - Integer totalItems = results.getTotalResultCount().getFirst(); - List> page = results.getPage(); - List tags = new ArrayList(page.size()); - for(Pair pair : page) - { - tags.add(new Tag(pair.getFirst(), pair.getSecond())); - } - - return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue())); - } - - public NodeRef validateTag(String tagId) - { - NodeRef tagNodeRef = nodes.validateNode(tagId); - if(tagNodeRef == null) - { - throw new EntityNotFoundException(tagId); - } - return tagNodeRef; - } - - public NodeRef validateTag(StoreRef storeRef, String tagId) - { - NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId); - if(tagNodeRef == null) - { - throw new EntityNotFoundException(tagId); - } - return tagNodeRef; - } - - public Tag changeTag(StoreRef storeRef, String tagId, Tag tag) - { - try - { - NodeRef existingTagNodeRef = validateTag(storeRef, tagId); - String existingTagName = taggingService.getTagName(existingTagNodeRef); - String newTagName = tag.getTag(); - NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName); - return new Tag(newTagNodeRef, newTagName); - } - catch(NonExistentTagException e) - { - throw new NotFoundException(e.getMessage()); - } - catch(TagExistsException e) - { - throw new ConstraintViolatedException(e.getMessage()); - } - catch(TaggingException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - public Tag getTag(String tagId) - { - return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId); - } - - public Tag getTag(StoreRef storeRef, String tagId) - { - NodeRef tagNodeRef = validateTag(storeRef, tagId); - String tagValue = taggingService.getTagName(tagNodeRef); - return new Tag(tagNodeRef, tagValue); - } - - public CollectionWithPagingInfo getTags(String nodeId, Parameters params) - { - NodeRef nodeRef = validateTag(nodeId); - - PagingResults> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging())); - Integer totalItems = results.getTotalResultCount().getFirst(); - List> page = results.getPage(); - List tags = new ArrayList(page.size()); - for(Pair pair : page) - { - tags.add(new Tag(pair.getFirst(), pair.getSecond())); - } - - return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue())); - } -} +package org.alfresco.rest.api.impl; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.query.PagingResults; +import org.alfresco.repo.tagging.NonExistentTagException; +import org.alfresco.repo.tagging.TagExistsException; +import org.alfresco.repo.tagging.TaggingException; +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.Tags; +import org.alfresco.rest.api.model.Tag; +import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.tagging.TaggingService; +import org.alfresco.util.Pair; +import org.alfresco.util.TypeConstraint; + +/** + * Centralises access to tag services and maps between representations. + * + * @author steveglover + * @since publicapi1.0 + */ +public class TagsImpl implements Tags +{ + private Nodes nodes; + private TaggingService taggingService; + private TypeConstraint typeConstraint; + + public void setTypeConstraint(TypeConstraint typeConstraint) + { + this.typeConstraint = typeConstraint; + } + + public void setNodes(Nodes nodes) + { + this.nodes = nodes; + } + + public void setTaggingService(TaggingService taggingService) + { + this.taggingService = taggingService; + } + + public List addTags(String nodeId, final List tags) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + if(!typeConstraint.matches(nodeRef)) + { + throw new UnsupportedResourceOperationException("Cannot tag this node"); + } + + List tagValues = new AbstractList() + { + @Override + public String get(int arg0) + { + String tag = tags.get(arg0).getTag(); + return tag; + } + + @Override + public int size() + { + return tags.size(); + } + }; + try + { + List> tagNodeRefs = taggingService.addTags(nodeRef, tagValues); + List ret = new ArrayList(tags.size()); + for(Pair pair : tagNodeRefs) + { + ret.add(new Tag(pair.getSecond(), pair.getFirst())); + } + return ret; + } + catch(IllegalArgumentException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + public void deleteTag(String nodeId, String tagId) + { + NodeRef nodeRef = nodes.validateNode(nodeId); + getTag(tagId); + NodeRef existingTagNodeRef = validateTag(tagId); + String tagValue = taggingService.getTagName(existingTagNodeRef); + taggingService.removeTag(nodeRef, tagValue); + } + + public CollectionWithPagingInfo getTags(StoreRef storeRef, Paging paging) + { + PagingResults> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging)); + Integer totalItems = results.getTotalResultCount().getFirst(); + List> page = results.getPage(); + List tags = new ArrayList(page.size()); + for(Pair pair : page) + { + tags.add(new Tag(pair.getFirst(), pair.getSecond())); + } + + return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue())); + } + + public NodeRef validateTag(String tagId) + { + NodeRef tagNodeRef = nodes.validateNode(tagId); + if(tagNodeRef == null) + { + throw new EntityNotFoundException(tagId); + } + return tagNodeRef; + } + + public NodeRef validateTag(StoreRef storeRef, String tagId) + { + NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId); + if(tagNodeRef == null) + { + throw new EntityNotFoundException(tagId); + } + return tagNodeRef; + } + + public Tag changeTag(StoreRef storeRef, String tagId, Tag tag) + { + try + { + NodeRef existingTagNodeRef = validateTag(storeRef, tagId); + String existingTagName = taggingService.getTagName(existingTagNodeRef); + String newTagName = tag.getTag(); + NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName); + return new Tag(newTagNodeRef, newTagName); + } + catch(NonExistentTagException e) + { + throw new NotFoundException(e.getMessage()); + } + catch(TagExistsException e) + { + throw new ConstraintViolatedException(e.getMessage()); + } + catch(TaggingException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + public Tag getTag(String tagId) + { + return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId); + } + + public Tag getTag(StoreRef storeRef, String tagId) + { + NodeRef tagNodeRef = validateTag(storeRef, tagId); + String tagValue = taggingService.getTagName(tagNodeRef); + return new Tag(tagNodeRef, tagValue); + } + + public CollectionWithPagingInfo getTags(String nodeId, Parameters params) + { + NodeRef nodeRef = validateTag(nodeId); + + PagingResults> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging())); + Integer totalItems = results.getTotalResultCount().getFirst(); + List> page = results.getPage(); + List tags = new ArrayList(page.size()); + for(Pair pair : page) + { + tags.add(new Tag(pair.getFirst(), pair.getSecond())); + } + + return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue())); + } +} diff --git a/source/java/org/alfresco/rest/api/impl/Util.java b/source/java/org/alfresco/rest/api/impl/Util.java index d2ea3206b9..d51946ffd5 100644 --- a/source/java/org/alfresco/rest/api/impl/Util.java +++ b/source/java/org/alfresco/rest/api/impl/Util.java @@ -1,90 +1,90 @@ -package org.alfresco.rest.api.impl; - -import org.alfresco.query.CannedQueryPageDetails; -import org.alfresco.query.PageDetails; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.util.Pair; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * @author steveglover - * @author Jamal Kaabi-Mofrad - */ -public class Util -{ - public static PagingRequest getPagingRequest(Paging paging) - { - PagingRequest pagingRequest = new PagingRequest(paging.getSkipCount(), paging.getMaxItems()); - pagingRequest.setRequestTotalCountMax(CannedQueryPageDetails.DEFAULT_PAGE_SIZE); - return pagingRequest; - } - - public static PagingResults wrapPagingResults(Paging paging, Collection result) - { - if (paging == null) - { - throw new InvalidArgumentException("paging object can't be null."); - } - if (result == null) - { - result = Collections.emptyList(); - } - - PagingRequest pagingRequest = getPagingRequest(paging); - - final int totalSize = result.size(); - final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); - - final List page = new ArrayList<>(pageDetails.getPageSize()); - Iterator it = result.iterator(); - for (int counter = 0, end = pageDetails.getEnd(); counter < end && it.hasNext(); counter++) - { - T element = it.next(); - if (counter < pageDetails.getSkipCount()) - { - continue; - } - if (counter > end - 1) - { - break; - } - page.add(element); - } - - return new PagingResults() - { - @Override - public List getPage() - { - return page; - } - - @Override - public boolean hasMoreItems() - { - return pageDetails.hasMoreItems(); - } - - @Override - public Pair getTotalResultCount() - { - Integer total = totalSize; - return new Pair<>(total, total); - } - - @Override - public String getQueryExecutionId() - { - return null; - } - }; - } -} +package org.alfresco.rest.api.impl; + +import org.alfresco.query.CannedQueryPageDetails; +import org.alfresco.query.PageDetails; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.util.Pair; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * @author steveglover + * @author Jamal Kaabi-Mofrad + */ +public class Util +{ + public static PagingRequest getPagingRequest(Paging paging) + { + PagingRequest pagingRequest = new PagingRequest(paging.getSkipCount(), paging.getMaxItems()); + pagingRequest.setRequestTotalCountMax(CannedQueryPageDetails.DEFAULT_PAGE_SIZE); + return pagingRequest; + } + + public static PagingResults wrapPagingResults(Paging paging, Collection result) + { + if (paging == null) + { + throw new InvalidArgumentException("paging object can't be null."); + } + if (result == null) + { + result = Collections.emptyList(); + } + + PagingRequest pagingRequest = getPagingRequest(paging); + + final int totalSize = result.size(); + final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); + + final List page = new ArrayList<>(pageDetails.getPageSize()); + Iterator it = result.iterator(); + for (int counter = 0, end = pageDetails.getEnd(); counter < end && it.hasNext(); counter++) + { + T element = it.next(); + if (counter < pageDetails.getSkipCount()) + { + continue; + } + if (counter > end - 1) + { + break; + } + page.add(element); + } + + return new PagingResults() + { + @Override + public List getPage() + { + return page; + } + + @Override + public boolean hasMoreItems() + { + return pageDetails.hasMoreItems(); + } + + @Override + public Pair getTotalResultCount() + { + Integer total = totalSize; + return new Pair<>(total, total); + } + + @Override + public String getQueryExecutionId() + { + return null; + } + }; + } +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/AbstractActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/AbstractActivitySummaryProcessor.java index cf8f226b3f..5f5771204c 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/AbstractActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/AbstractActivitySummaryProcessor.java @@ -1,119 +1,119 @@ -package org.alfresco.rest.api.impl.activities; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.context.ApplicationEvent; -import org.springframework.extensions.surf.util.AbstractLifecycleBean; - -public abstract class AbstractActivitySummaryProcessor extends AbstractLifecycleBean implements ActivitySummaryProcessor -{ - protected static Log logger = LogFactory.getLog(ActivitySummaryProcessor.class); - - protected ActivitySummaryProcessorRegistry registry; - private List eventTypes; - - public void setEventTypes(List eventTypes) - { - this.eventTypes = eventTypes; - } - - public void setRegistry(ActivitySummaryProcessorRegistry registry) - { - this.registry = registry; - } - - public void setCustomRenditions(List eventTypes) - { - this.eventTypes = eventTypes; - } - - /* - * (non-Javadoc) - * @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent) - */ - protected void onBootstrap(ApplicationEvent event) - { - register(); - } - - protected void onShutdown(ApplicationEvent event) - { - - } - - @Override - public Map process(Map entries) - { - List changes = new LinkedList(); - Map ret = new HashMap(entries.size()); - for(Map.Entry entry : entries.entrySet()) - { - String key = entry.getKey(); - Object value = entry.getValue(); - Change change = processEntry(key, value); - if(change != null) - { - changes.add(change); - } - } - - for(Change change : changes) - { - if(change != null) - { - change.process(entries); - } - } - - return ret; - } - - protected abstract Change processEntry(String key, Object value); - - protected void register() - { - for(String eventType : eventTypes) - { - registry.register(eventType, this); - } - } - - public static class ChangeKey implements Change - { - private String oldKey; - private String newKey; - - public ChangeKey(String oldKey, String newKey) { - super(); - this.oldKey = oldKey; - this.newKey = newKey; - } - - public void process(Map entries) - { - Object value = entries.remove(oldKey); - entries.put(newKey, value); - } - } - - public static class RemoveKey implements Change - { - private String key; - - public RemoveKey(String key) { - super(); - this.key = key; - } - - public void process(Map entries) - { - entries.remove(key); - } - } - -} +package org.alfresco.rest.api.impl.activities; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +public abstract class AbstractActivitySummaryProcessor extends AbstractLifecycleBean implements ActivitySummaryProcessor +{ + protected static Log logger = LogFactory.getLog(ActivitySummaryProcessor.class); + + protected ActivitySummaryProcessorRegistry registry; + private List eventTypes; + + public void setEventTypes(List eventTypes) + { + this.eventTypes = eventTypes; + } + + public void setRegistry(ActivitySummaryProcessorRegistry registry) + { + this.registry = registry; + } + + public void setCustomRenditions(List eventTypes) + { + this.eventTypes = eventTypes; + } + + /* + * (non-Javadoc) + * @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent) + */ + protected void onBootstrap(ApplicationEvent event) + { + register(); + } + + protected void onShutdown(ApplicationEvent event) + { + + } + + @Override + public Map process(Map entries) + { + List changes = new LinkedList(); + Map ret = new HashMap(entries.size()); + for(Map.Entry entry : entries.entrySet()) + { + String key = entry.getKey(); + Object value = entry.getValue(); + Change change = processEntry(key, value); + if(change != null) + { + changes.add(change); + } + } + + for(Change change : changes) + { + if(change != null) + { + change.process(entries); + } + } + + return ret; + } + + protected abstract Change processEntry(String key, Object value); + + protected void register() + { + for(String eventType : eventTypes) + { + registry.register(eventType, this); + } + } + + public static class ChangeKey implements Change + { + private String oldKey; + private String newKey; + + public ChangeKey(String oldKey, String newKey) { + super(); + this.oldKey = oldKey; + this.newKey = newKey; + } + + public void process(Map entries) + { + Object value = entries.remove(oldKey); + entries.put(newKey, value); + } + } + + public static class RemoveKey implements Change + { + private String key; + + public RemoveKey(String key) { + super(); + this.key = key; + } + + public void process(Map entries) + { + entries.remove(key); + } + } + +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryParser.java b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryParser.java index e6d618accb..4aa0ed8494 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryParser.java +++ b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryParser.java @@ -1,168 +1,168 @@ -package org.alfresco.rest.api.impl.activities; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.util.registry.NamedObjectRegistry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONException; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.springframework.extensions.surf.util.ISO8601DateFormat; - -/* - * Adapted from JSONtoFmModel - */ -public class ActivitySummaryParser implements ActivitySummaryProcessorRegistry -{ - private final Log logger = LogFactory.getLog(ActivitySummaryParser.class); - - // note: current format is dependent on ISO8601DateFormat.parser, eg. YYYY-MM-DDThh:mm:ss.sssTZD - private static String REGEXP_ISO8061 = "^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(.([0-9]){3})?(Z|[\\+\\-]([0-9]{2}):([0-9]{2}))$"; - private static Pattern matcherISO8601 = Pattern.compile(REGEXP_ISO8061); - private static final Pattern nodeRefPattern = Pattern.compile("^[a-zA-Z]+://.+/.+"); - - private NamedObjectRegistry processors; - - private boolean autoConvertISO8601 = true; - - public ActivitySummaryParser() - { - } - - public void setProcessors(NamedObjectRegistry processors) - { - this.processors = processors; - } - - public void register(String activityType, ActivitySummaryProcessor processor) - { - ActivitySummaryProcessor existingProcessor = processors.getNamedObject(activityType); - if(existingProcessor != null) - { - logger.warn("Activity summary processor " + existingProcessor + " is being overridden by " + processor + " for activity type " + activityType); - } - - processors.register(activityType, processor); - } - - private void processActivitySummary(String activityType, Map entries) - { - ActivitySummaryProcessor processor = processors.getNamedObject(activityType); - if(processor == null) - { - processor = new BaseActivitySummaryProcessor(); - } - - processor.process(entries); - } - - public Map parse(String activityType, String activitySummary) throws JSONException - { - JSONObject json = (JSONObject)JSONValue.parse(activitySummary); - Map map = convertJSONObjectToMap(json); - processActivitySummary(activityType, map); - return map; - } - - /** - * Determine if passed string conforms to the pattern of a node reference - * - * @param nodeRef the node reference as a string - * @return true => it matches the pattern of a node reference - */ - private boolean isNodeRef(String nodeRef) - { - Matcher matcher = nodeRefPattern.matcher(nodeRef); - return matcher.matches(); - } - - Map convertJSONObjectToMap(JSONObject jo) throws JSONException - { - Map model = new HashMap(); - - for(Object key : jo.keySet()) - { - Object value = jo.get(key); - if (value instanceof JSONObject) - { - model.put((String)key, convertJSONObjectToMap((JSONObject)value)); - } - else if (value instanceof JSONArray) - { - model.put((String)key, convertJSONArrayToList((JSONArray)value)); - } - else if (value == null) - { - model.put((String)key, null); - } - else - { - if ((value instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)value).matches())) - { - value = ISO8601DateFormat.parse((String)value); - } - - if ((value instanceof String) && isNodeRef((String)value)) - { - try - { - value = new NodeRef((String)value); - } - catch(AlfrescoRuntimeException e) - { - // cannot convert to a nodeRef, just keep as a string - logger.warn("Cannot convert activity summary NodeRef string " + value + " to a NodeRef"); - } - } - - model.put((String)key, value); - } - } - - return model; - } - - List convertJSONArrayToList(JSONArray ja) throws JSONException - { - List model = new ArrayList(); - - for (int i = 0; i < ja.size(); i++) - { - Object o = ja.get(i); - - if (o instanceof JSONArray) - { - model.add(convertJSONArrayToList((JSONArray)o)); - } - else if (o instanceof JSONObject) - { - model.add(convertJSONObjectToMap((JSONObject)o)); - } - else if (o == null) - { - model.add(null); - } - else - { - if ((o instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)o).matches())) - { - o = ISO8601DateFormat.parse((String)o); - } - - model.add(o); - } - } - - return model; - } - -} +package org.alfresco.rest.api.impl.activities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.registry.NamedObjectRegistry; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.springframework.extensions.surf.util.ISO8601DateFormat; + +/* + * Adapted from JSONtoFmModel + */ +public class ActivitySummaryParser implements ActivitySummaryProcessorRegistry +{ + private final Log logger = LogFactory.getLog(ActivitySummaryParser.class); + + // note: current format is dependent on ISO8601DateFormat.parser, eg. YYYY-MM-DDThh:mm:ss.sssTZD + private static String REGEXP_ISO8061 = "^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(.([0-9]){3})?(Z|[\\+\\-]([0-9]{2}):([0-9]{2}))$"; + private static Pattern matcherISO8601 = Pattern.compile(REGEXP_ISO8061); + private static final Pattern nodeRefPattern = Pattern.compile("^[a-zA-Z]+://.+/.+"); + + private NamedObjectRegistry processors; + + private boolean autoConvertISO8601 = true; + + public ActivitySummaryParser() + { + } + + public void setProcessors(NamedObjectRegistry processors) + { + this.processors = processors; + } + + public void register(String activityType, ActivitySummaryProcessor processor) + { + ActivitySummaryProcessor existingProcessor = processors.getNamedObject(activityType); + if(existingProcessor != null) + { + logger.warn("Activity summary processor " + existingProcessor + " is being overridden by " + processor + " for activity type " + activityType); + } + + processors.register(activityType, processor); + } + + private void processActivitySummary(String activityType, Map entries) + { + ActivitySummaryProcessor processor = processors.getNamedObject(activityType); + if(processor == null) + { + processor = new BaseActivitySummaryProcessor(); + } + + processor.process(entries); + } + + public Map parse(String activityType, String activitySummary) throws JSONException + { + JSONObject json = (JSONObject)JSONValue.parse(activitySummary); + Map map = convertJSONObjectToMap(json); + processActivitySummary(activityType, map); + return map; + } + + /** + * Determine if passed string conforms to the pattern of a node reference + * + * @param nodeRef the node reference as a string + * @return true => it matches the pattern of a node reference + */ + private boolean isNodeRef(String nodeRef) + { + Matcher matcher = nodeRefPattern.matcher(nodeRef); + return matcher.matches(); + } + + Map convertJSONObjectToMap(JSONObject jo) throws JSONException + { + Map model = new HashMap(); + + for(Object key : jo.keySet()) + { + Object value = jo.get(key); + if (value instanceof JSONObject) + { + model.put((String)key, convertJSONObjectToMap((JSONObject)value)); + } + else if (value instanceof JSONArray) + { + model.put((String)key, convertJSONArrayToList((JSONArray)value)); + } + else if (value == null) + { + model.put((String)key, null); + } + else + { + if ((value instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)value).matches())) + { + value = ISO8601DateFormat.parse((String)value); + } + + if ((value instanceof String) && isNodeRef((String)value)) + { + try + { + value = new NodeRef((String)value); + } + catch(AlfrescoRuntimeException e) + { + // cannot convert to a nodeRef, just keep as a string + logger.warn("Cannot convert activity summary NodeRef string " + value + " to a NodeRef"); + } + } + + model.put((String)key, value); + } + } + + return model; + } + + List convertJSONArrayToList(JSONArray ja) throws JSONException + { + List model = new ArrayList(); + + for (int i = 0; i < ja.size(); i++) + { + Object o = ja.get(i); + + if (o instanceof JSONArray) + { + model.add(convertJSONArrayToList((JSONArray)o)); + } + else if (o instanceof JSONObject) + { + model.add(convertJSONObjectToMap((JSONObject)o)); + } + else if (o == null) + { + model.add(null); + } + else + { + if ((o instanceof String) && autoConvertISO8601 && (matcherISO8601.matcher((String)o).matches())) + { + o = ISO8601DateFormat.parse((String)o); + } + + model.add(o); + } + } + + return model; + } + +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessor.java index 7043419ced..17b3e03a39 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessor.java @@ -1,13 +1,13 @@ -package org.alfresco.rest.api.impl.activities; - -import java.util.Map; - -public interface ActivitySummaryProcessor -{ - public interface Change - { - void process(Map entries); - } - - public Map process(Map entries); -} +package org.alfresco.rest.api.impl.activities; + +import java.util.Map; + +public interface ActivitySummaryProcessor +{ + public interface Change + { + void process(Map entries); + } + + public Map process(Map entries); +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessorRegistry.java b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessorRegistry.java index f9d3ae3b09..46e6fe2018 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessorRegistry.java +++ b/source/java/org/alfresco/rest/api/impl/activities/ActivitySummaryProcessorRegistry.java @@ -1,12 +1,12 @@ -package org.alfresco.rest.api.impl.activities; - -/** - * A registry for activity summary parsers/post processors. - * - * @author steveglover - * - */ -public interface ActivitySummaryProcessorRegistry -{ - public void register(String activityType, ActivitySummaryProcessor processor); -} +package org.alfresco.rest.api.impl.activities; + +/** + * A registry for activity summary parsers/post processors. + * + * @author steveglover + * + */ +public interface ActivitySummaryProcessorRegistry +{ + public void register(String activityType, ActivitySummaryProcessor processor); +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/BaseActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/BaseActivitySummaryProcessor.java index c73b640225..5a76d712a3 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/BaseActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/BaseActivitySummaryProcessor.java @@ -1,96 +1,96 @@ -package org.alfresco.rest.api.impl.activities; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.alfresco.rest.api.impl.activities.AbstractActivitySummaryProcessor.RemoveKey; -import org.alfresco.service.cmr.repository.NodeRef; - -public class BaseActivitySummaryProcessor extends AbstractActivitySummaryProcessor -{ - @Override - protected Change processEntry(String key, Object value) - { - Change change = null; - - if(key.equals("page")) - { - change = new ChangePageValue(key); - } - - if(key.equals("tenantDomain")) - { - change = new RemoveKey(key); - } - - if(key.equals("nodeRef")) - { - change = new ChangeKey(key, "objectId"); - } - - if(key.equals("parentNodeRef")) - { - change = new ChangeKey(key, "parentObjectId"); - } - - // remove null or empty properties - if(value == null || value.equals("")) - { - change = new RemoveKey(key); - } - - return change; - } - - public static class ChangePageValue implements Change - { - private String key; - private static final String regex = Pattern.quote("document-details?nodeRef=") + "(.*)"; - private static final Pattern pattern = Pattern.compile(regex); - - public ChangePageValue(String key) { - super(); - this.key = key; - } - - /* - * Extract and output the node id from input that looks like this: document-details?nodeRef=workspace%3A%2F%2FSpacesStore%2Fd4c1a75e-a17e-4033-94f4-988cca39a357 (non-Javadoc) - * - * @see org.alfresco.rest.api.impl.activities.ActivitySummaryProcessor.Change#process(java.util.Map) - */ - public void process(Map entries) - { - String value = (String)entries.remove(key); - try - { - value = URLDecoder.decode(value, "UTF-8"); - Matcher matcher = pattern.matcher(value); - if(matcher.matches()) - { - String nodeRefStr = matcher.group(1); - boolean isNodeRef = NodeRef.isNodeRef(nodeRefStr); - if(isNodeRef) - { - NodeRef nodeRef = new NodeRef(nodeRefStr); - entries.put("objectId", nodeRef.getId()); - } - else - { - logger.warn("Activity page url contains an invalid NodeRef " + value); - } - } - else - { - logger.warn("Failed to match activity page url for objectId extraction " + value); - } - } - catch (UnsupportedEncodingException e) - { - logger.warn("Unable to decode activity page url " + value); - } - } - } -} +package org.alfresco.rest.api.impl.activities; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.alfresco.rest.api.impl.activities.AbstractActivitySummaryProcessor.RemoveKey; +import org.alfresco.service.cmr.repository.NodeRef; + +public class BaseActivitySummaryProcessor extends AbstractActivitySummaryProcessor +{ + @Override + protected Change processEntry(String key, Object value) + { + Change change = null; + + if(key.equals("page")) + { + change = new ChangePageValue(key); + } + + if(key.equals("tenantDomain")) + { + change = new RemoveKey(key); + } + + if(key.equals("nodeRef")) + { + change = new ChangeKey(key, "objectId"); + } + + if(key.equals("parentNodeRef")) + { + change = new ChangeKey(key, "parentObjectId"); + } + + // remove null or empty properties + if(value == null || value.equals("")) + { + change = new RemoveKey(key); + } + + return change; + } + + public static class ChangePageValue implements Change + { + private String key; + private static final String regex = Pattern.quote("document-details?nodeRef=") + "(.*)"; + private static final Pattern pattern = Pattern.compile(regex); + + public ChangePageValue(String key) { + super(); + this.key = key; + } + + /* + * Extract and output the node id from input that looks like this: document-details?nodeRef=workspace%3A%2F%2FSpacesStore%2Fd4c1a75e-a17e-4033-94f4-988cca39a357 (non-Javadoc) + * + * @see org.alfresco.rest.api.impl.activities.ActivitySummaryProcessor.Change#process(java.util.Map) + */ + public void process(Map entries) + { + String value = (String)entries.remove(key); + try + { + value = URLDecoder.decode(value, "UTF-8"); + Matcher matcher = pattern.matcher(value); + if(matcher.matches()) + { + String nodeRefStr = matcher.group(1); + boolean isNodeRef = NodeRef.isNodeRef(nodeRefStr); + if(isNodeRef) + { + NodeRef nodeRef = new NodeRef(nodeRefStr); + entries.put("objectId", nodeRef.getId()); + } + else + { + logger.warn("Activity page url contains an invalid NodeRef " + value); + } + } + else + { + logger.warn("Failed to match activity page url for objectId extraction " + value); + } + } + catch (UnsupportedEncodingException e) + { + logger.warn("Unable to decode activity page url " + value); + } + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/CommentsActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/CommentsActivitySummaryProcessor.java index 8b7584331b..e8fde8cafa 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/CommentsActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/CommentsActivitySummaryProcessor.java @@ -1,7 +1,7 @@ -package org.alfresco.rest.api.impl.activities; - -public class CommentsActivitySummaryProcessor extends BaseActivitySummaryProcessor -{ - - -} +package org.alfresco.rest.api.impl.activities; + +public class CommentsActivitySummaryProcessor extends BaseActivitySummaryProcessor +{ + + +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/DiscussionsActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/DiscussionsActivitySummaryProcessor.java index 2dd53d5d5d..44b065f29e 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/DiscussionsActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/DiscussionsActivitySummaryProcessor.java @@ -1,17 +1,17 @@ -package org.alfresco.rest.api.impl.activities; - -public class DiscussionsActivitySummaryProcessor extends BaseActivitySummaryProcessor -{ - @Override - protected Change processEntry(String key, Object value) - { - Change change = null; - - if(key.equals("params")) - { - change = new RemoveKey(key); - } - - return change; - } -} +package org.alfresco.rest.api.impl.activities; + +public class DiscussionsActivitySummaryProcessor extends BaseActivitySummaryProcessor +{ + @Override + protected Change processEntry(String key, Object value) + { + Change change = null; + + if(key.equals("params")) + { + change = new RemoveKey(key); + } + + return change; + } +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/DocumentLibraryActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/DocumentLibraryActivitySummaryProcessor.java index 06025dd925..e9a985dd19 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/DocumentLibraryActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/DocumentLibraryActivitySummaryProcessor.java @@ -1,6 +1,6 @@ -package org.alfresco.rest.api.impl.activities; - -public class DocumentLibraryActivitySummaryProcessor extends BaseActivitySummaryProcessor -{ - -} +package org.alfresco.rest.api.impl.activities; + +public class DocumentLibraryActivitySummaryProcessor extends BaseActivitySummaryProcessor +{ + +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/SiteActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/SiteActivitySummaryProcessor.java index b5c360ae44..bee23e395e 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/SiteActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/SiteActivitySummaryProcessor.java @@ -1,18 +1,18 @@ -package org.alfresco.rest.api.impl.activities; - -public class SiteActivitySummaryProcessor extends BaseActivitySummaryProcessor -{ - @Override - protected Change processEntry(String key, Object value) - { - Change change = super.processEntry(key, value); - - if(key.equals("memberUserName")) - { - change = new ChangeKey(key, "memberPersonId"); - } - - return change; - } - -} +package org.alfresco.rest.api.impl.activities; + +public class SiteActivitySummaryProcessor extends BaseActivitySummaryProcessor +{ + @Override + protected Change processEntry(String key, Object value) + { + Change change = super.processEntry(key, value); + + if(key.equals("memberUserName")) + { + change = new ChangeKey(key, "memberPersonId"); + } + + return change; + } + +} diff --git a/source/java/org/alfresco/rest/api/impl/activities/SubscriptionsActivitySummaryProcessor.java b/source/java/org/alfresco/rest/api/impl/activities/SubscriptionsActivitySummaryProcessor.java index 278e3a1f0f..9302ba7482 100644 --- a/source/java/org/alfresco/rest/api/impl/activities/SubscriptionsActivitySummaryProcessor.java +++ b/source/java/org/alfresco/rest/api/impl/activities/SubscriptionsActivitySummaryProcessor.java @@ -1,26 +1,26 @@ -package org.alfresco.rest.api.impl.activities; - -public class SubscriptionsActivitySummaryProcessor extends BaseActivitySummaryProcessor -{ - //{"lastName":"Glover","userFirstName":"David","followerLastName":"Glover","userUserName":"david.bowie@alfresco.com","followerFirstName":"Steve", - // "userLastName":"Bowie","followerUserName":"steven.glover@alfresco.com","firstName":"Steve","tenantDomain":"alfresco.com"} - - @Override - protected Change processEntry(String key, Object value) - { - Change change = super.processEntry(key, value); - - if(key.equals("userUserName")) - { - change = new ChangeKey(key, "userPersonId"); - } - - if(key.equals("followerUserName")) - { - change = new ChangeKey(key, "followerPersonId"); - } - - return change; - } - -} +package org.alfresco.rest.api.impl.activities; + +public class SubscriptionsActivitySummaryProcessor extends BaseActivitySummaryProcessor +{ + //{"lastName":"Glover","userFirstName":"David","followerLastName":"Glover","userUserName":"david.bowie@alfresco.com","followerFirstName":"Steve", + // "userLastName":"Bowie","followerUserName":"steven.glover@alfresco.com","firstName":"Steve","tenantDomain":"alfresco.com"} + + @Override + protected Change processEntry(String key, Object value) + { + Change change = super.processEntry(key, value); + + if(key.equals("userUserName")) + { + change = new ChangeKey(key, "userPersonId"); + } + + if(key.equals("followerUserName")) + { + change = new ChangeKey(key, "followerPersonId"); + } + + return change; + } + +} diff --git a/source/java/org/alfresco/rest/api/impl/node/ratings/AbstractRatingScheme.java b/source/java/org/alfresco/rest/api/impl/node/ratings/AbstractRatingScheme.java index f3f4936a58..1c9669296f 100644 --- a/source/java/org/alfresco/rest/api/impl/node/ratings/AbstractRatingScheme.java +++ b/source/java/org/alfresco/rest/api/impl/node/ratings/AbstractRatingScheme.java @@ -1,211 +1,211 @@ -package org.alfresco.rest.api.impl.node.ratings; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Date; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.Client; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.rest.api.model.DocumentRatingSummary; -import org.alfresco.rest.api.model.NodeRating; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.service.cmr.activities.ActivityService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.rating.Rating; -import org.alfresco.service.cmr.rating.RatingService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.util.registry.NamedObjectRegistry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; -import org.springframework.beans.factory.InitializingBean; - -/** - * Manages the mapping between the rest api's representation of a node rating and the repository's - * representation of a node rating. - * - * @author steveglover - * - */ -public abstract class AbstractRatingScheme implements RatingScheme, InitializingBean -{ - private static Log logger = LogFactory.getLog(RatingScheme.class); - - protected String ratingSchemeName; // for interaction with the RatingService - protected String ratingSchemeId; // exposed through the api - protected RatingService ratingService; - protected NodeService nodeService; - protected DictionaryService dictionaryService; - protected ActivityService activityService; - protected SiteService siteService; - - protected NamedObjectRegistry nodeRatingSchemeRegistry; - - public AbstractRatingScheme(String ratingSchemeId, String ratingSchemeName) - { - super(); - this.ratingSchemeName = ratingSchemeName; - this.ratingSchemeId = ratingSchemeId; - } - - public String getRatingSchemeId() - { - return ratingSchemeId; - } - - public String getRatingServiceName() - { - return ratingSchemeName; - } - - public void setNodeRatingSchemeRegistry(NamedObjectRegistry nodeRatingSchemeRegistry) - { - this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry; - } - - public void setActivityService(ActivityService activityService) - { - this.activityService = activityService; - } - - public void setSiteService(SiteService siteService) - { - this.siteService = siteService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - public void setRatingService(RatingService ratingService) - { - this.ratingService = ratingService; - } - - protected org.alfresco.service.cmr.rating.RatingScheme getRepoRatingScheme() - { - return ratingService.getRatingScheme(ratingSchemeName); - } - - protected abstract DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef); - protected abstract Object getApiRating(Float rating); - - @Override - public void afterPropertiesSet() throws Exception - { - nodeRatingSchemeRegistry.register(ratingSchemeId, this); - nodeRatingSchemeRegistry.register(ratingSchemeName, this); - } - - public void validateRating(Float rating) - { - org.alfresco.service.cmr.rating.RatingScheme ratingScheme = getRepoRatingScheme(); - Float minRating = ratingScheme.getMinRating(); - Float maxRating = ratingScheme.getMaxRating(); - if(rating < minRating || rating > maxRating) - { - throw new InvalidArgumentException("Rating is out of bounds."); - } - } - - public NodeRating getNodeRating(NodeRef nodeRef) - { - Rating ratingByCurrentUser = ratingService.getRatingByCurrentUser(nodeRef, ratingSchemeName); - Float rating = null; - Date appliedAt = null; - - if(ratingByCurrentUser != null) - { - rating = ratingByCurrentUser.getScore(); - appliedAt = ratingByCurrentUser.getAppliedAt(); - } - - Object myRating = null; - if(rating != null) - { - validateRating(rating); - myRating = getApiRating(rating); - } - - DocumentRatingSummary documentRatingSummary = getDocumentRatingSummary(nodeRef); - - NodeRating nodeRating = new NodeRating(ratingSchemeId, myRating, appliedAt, documentRatingSummary); - return nodeRating; - } - - private String getSiteId(final NodeRef nodeRef) - { - // may not be able to read site data so run as system - String siteId = AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public String doWork() throws Exception - { - String siteId = null; - SiteInfo siteInfo = siteService.getSite(nodeRef); - if(siteInfo != null) - { - siteId = siteInfo.getShortName(); - } - return siteId; - } - }); - - return siteId; - } - - @SuppressWarnings("unchecked") - private JSONObject getActivityData(final NodeRef nodeRef, String siteId) - { - JSONObject activityData = null; - - if(siteId != null) - { - // may not be able to read these nodes, but we need to for the activity processing so run as system - activityData = AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public JSONObject doWork() throws Exception - { - JSONObject activityData = new JSONObject(); - activityData.put("title", nodeService.getProperty(nodeRef, ContentModel.PROP_NAME)); - try - { - StringBuilder sb = new StringBuilder("document-details?nodeRef="); - sb.append(URLEncoder.encode(nodeRef.toString(), "UTF-8")); - activityData.put("page", sb.toString()); - } - catch (UnsupportedEncodingException e) - { - logger.warn("Unable to urlencode page for create nodeRating activity"); - } - - return activityData; - } - }); - } - - return activityData; - } - - protected void postActivity(final NodeRef nodeRef, final String activityType) - { - String siteId = getSiteId(nodeRef); - JSONObject activityData = getActivityData(nodeRef, siteId); - if(activityData != null) - { - activityService.postActivity(activityType, siteId, "nodeRatings", activityData.toString(), Client.asType(Client.ClientType.restapi)); - } - } -} +package org.alfresco.rest.api.impl.node.ratings; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Date; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.Client; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.rest.api.model.DocumentRatingSummary; +import org.alfresco.rest.api.model.NodeRating; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.rating.Rating; +import org.alfresco.service.cmr.rating.RatingService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.util.registry.NamedObjectRegistry; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONObject; +import org.springframework.beans.factory.InitializingBean; + +/** + * Manages the mapping between the rest api's representation of a node rating and the repository's + * representation of a node rating. + * + * @author steveglover + * + */ +public abstract class AbstractRatingScheme implements RatingScheme, InitializingBean +{ + private static Log logger = LogFactory.getLog(RatingScheme.class); + + protected String ratingSchemeName; // for interaction with the RatingService + protected String ratingSchemeId; // exposed through the api + protected RatingService ratingService; + protected NodeService nodeService; + protected DictionaryService dictionaryService; + protected ActivityService activityService; + protected SiteService siteService; + + protected NamedObjectRegistry nodeRatingSchemeRegistry; + + public AbstractRatingScheme(String ratingSchemeId, String ratingSchemeName) + { + super(); + this.ratingSchemeName = ratingSchemeName; + this.ratingSchemeId = ratingSchemeId; + } + + public String getRatingSchemeId() + { + return ratingSchemeId; + } + + public String getRatingServiceName() + { + return ratingSchemeName; + } + + public void setNodeRatingSchemeRegistry(NamedObjectRegistry nodeRatingSchemeRegistry) + { + this.nodeRatingSchemeRegistry = nodeRatingSchemeRegistry; + } + + public void setActivityService(ActivityService activityService) + { + this.activityService = activityService; + } + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public void setRatingService(RatingService ratingService) + { + this.ratingService = ratingService; + } + + protected org.alfresco.service.cmr.rating.RatingScheme getRepoRatingScheme() + { + return ratingService.getRatingScheme(ratingSchemeName); + } + + protected abstract DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef); + protected abstract Object getApiRating(Float rating); + + @Override + public void afterPropertiesSet() throws Exception + { + nodeRatingSchemeRegistry.register(ratingSchemeId, this); + nodeRatingSchemeRegistry.register(ratingSchemeName, this); + } + + public void validateRating(Float rating) + { + org.alfresco.service.cmr.rating.RatingScheme ratingScheme = getRepoRatingScheme(); + Float minRating = ratingScheme.getMinRating(); + Float maxRating = ratingScheme.getMaxRating(); + if(rating < minRating || rating > maxRating) + { + throw new InvalidArgumentException("Rating is out of bounds."); + } + } + + public NodeRating getNodeRating(NodeRef nodeRef) + { + Rating ratingByCurrentUser = ratingService.getRatingByCurrentUser(nodeRef, ratingSchemeName); + Float rating = null; + Date appliedAt = null; + + if(ratingByCurrentUser != null) + { + rating = ratingByCurrentUser.getScore(); + appliedAt = ratingByCurrentUser.getAppliedAt(); + } + + Object myRating = null; + if(rating != null) + { + validateRating(rating); + myRating = getApiRating(rating); + } + + DocumentRatingSummary documentRatingSummary = getDocumentRatingSummary(nodeRef); + + NodeRating nodeRating = new NodeRating(ratingSchemeId, myRating, appliedAt, documentRatingSummary); + return nodeRating; + } + + private String getSiteId(final NodeRef nodeRef) + { + // may not be able to read site data so run as system + String siteId = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public String doWork() throws Exception + { + String siteId = null; + SiteInfo siteInfo = siteService.getSite(nodeRef); + if(siteInfo != null) + { + siteId = siteInfo.getShortName(); + } + return siteId; + } + }); + + return siteId; + } + + @SuppressWarnings("unchecked") + private JSONObject getActivityData(final NodeRef nodeRef, String siteId) + { + JSONObject activityData = null; + + if(siteId != null) + { + // may not be able to read these nodes, but we need to for the activity processing so run as system + activityData = AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public JSONObject doWork() throws Exception + { + JSONObject activityData = new JSONObject(); + activityData.put("title", nodeService.getProperty(nodeRef, ContentModel.PROP_NAME)); + try + { + StringBuilder sb = new StringBuilder("document-details?nodeRef="); + sb.append(URLEncoder.encode(nodeRef.toString(), "UTF-8")); + activityData.put("page", sb.toString()); + } + catch (UnsupportedEncodingException e) + { + logger.warn("Unable to urlencode page for create nodeRating activity"); + } + + return activityData; + } + }); + } + + return activityData; + } + + protected void postActivity(final NodeRef nodeRef, final String activityType) + { + String siteId = getSiteId(nodeRef); + JSONObject activityData = getActivityData(nodeRef, siteId); + if(activityData != null) + { + activityService.postActivity(activityType, siteId, "nodeRatings", activityData.toString(), Client.asType(Client.ClientType.restapi)); + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/node/ratings/FiveStarRatingScheme.java b/source/java/org/alfresco/rest/api/impl/node/ratings/FiveStarRatingScheme.java index 9e30a3fe42..c38bbccf65 100644 --- a/source/java/org/alfresco/rest/api/impl/node/ratings/FiveStarRatingScheme.java +++ b/source/java/org/alfresco/rest/api/impl/node/ratings/FiveStarRatingScheme.java @@ -1,79 +1,79 @@ -package org.alfresco.rest.api.impl.node.ratings; - -import org.alfresco.rest.api.model.DocumentRatingSummary; -import org.alfresco.rest.api.model.FiveStarRatingSummary; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.service.cmr.rating.RatingServiceException; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * The rest apis representation of the 'fiveStar' rating scheme. - * - * @author steveglover - * - */ -public class FiveStarRatingScheme extends AbstractRatingScheme -{ - public FiveStarRatingScheme() - { - super("fiveStar", "fiveStarRatingScheme"); - } - - public Float getRatingServiceRating(Object rating) - { - Float ratingToApply = null; - - if(rating instanceof Integer) - { - ratingToApply = ((Integer)rating).floatValue(); - } - else - { - throw new InvalidArgumentException("Rating should be non-null and an integer for 'fiveStar' rating scheme."); - } - - validateRating(ratingToApply); - - return ratingToApply; - } - - public Object getApiRating(Float rating) - { - Object apiRating = Integer.valueOf(rating.intValue()); - return apiRating; - } - - public DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef) - { - return new FiveStarRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName), - ratingService.getTotalRating(nodeRef, ratingSchemeName), - ratingService.getAverageRating(nodeRef, ratingSchemeName)); - } - - @Override - public void applyRating(NodeRef nodeRef, Object rating) - { - try - { - Float ratingServiceRating = getRatingServiceRating(rating); - ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName()); - } - catch(RatingServiceException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - @Override - public void removeRating(NodeRef nodeRef) - { - try - { - ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName()); - } - catch(RatingServiceException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } -} +package org.alfresco.rest.api.impl.node.ratings; + +import org.alfresco.rest.api.model.DocumentRatingSummary; +import org.alfresco.rest.api.model.FiveStarRatingSummary; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.service.cmr.rating.RatingServiceException; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * The rest apis representation of the 'fiveStar' rating scheme. + * + * @author steveglover + * + */ +public class FiveStarRatingScheme extends AbstractRatingScheme +{ + public FiveStarRatingScheme() + { + super("fiveStar", "fiveStarRatingScheme"); + } + + public Float getRatingServiceRating(Object rating) + { + Float ratingToApply = null; + + if(rating instanceof Integer) + { + ratingToApply = ((Integer)rating).floatValue(); + } + else + { + throw new InvalidArgumentException("Rating should be non-null and an integer for 'fiveStar' rating scheme."); + } + + validateRating(ratingToApply); + + return ratingToApply; + } + + public Object getApiRating(Float rating) + { + Object apiRating = Integer.valueOf(rating.intValue()); + return apiRating; + } + + public DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef) + { + return new FiveStarRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName), + ratingService.getTotalRating(nodeRef, ratingSchemeName), + ratingService.getAverageRating(nodeRef, ratingSchemeName)); + } + + @Override + public void applyRating(NodeRef nodeRef, Object rating) + { + try + { + Float ratingServiceRating = getRatingServiceRating(rating); + ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName()); + } + catch(RatingServiceException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + @Override + public void removeRating(NodeRef nodeRef) + { + try + { + ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName()); + } + catch(RatingServiceException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } +} diff --git a/source/java/org/alfresco/rest/api/impl/node/ratings/LikesRatingScheme.java b/source/java/org/alfresco/rest/api/impl/node/ratings/LikesRatingScheme.java index 4f44364184..c59ed99e49 100644 --- a/source/java/org/alfresco/rest/api/impl/node/ratings/LikesRatingScheme.java +++ b/source/java/org/alfresco/rest/api/impl/node/ratings/LikesRatingScheme.java @@ -1,100 +1,100 @@ -package org.alfresco.rest.api.impl.node.ratings; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.activities.ActivityType; -import org.alfresco.rest.api.model.DocumentRatingSummary; -import org.alfresco.rest.api.model.LikesRatingSummary; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.service.cmr.rating.RatingServiceException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -/** - * The rest api representation of the 'likes' rating scheme. - * - * @author steveglover - * - */ -public class LikesRatingScheme extends AbstractRatingScheme -{ - public LikesRatingScheme() - { - super("likes", "likesRatingScheme"); - } - - public Float getRatingServiceRating(Object rating) - { - Float ratingToApply = null; - - if(rating instanceof Boolean) - { - boolean liked = ((Boolean)rating).booleanValue(); - ratingToApply = Float.valueOf((liked ? 1.0f : 0.0f)); - } - else - { - throw new InvalidArgumentException("Rating should be non-null and a boolean for 'likes' rating scheme."); - } - - return ratingToApply; - } - - @Override - public void applyRating(NodeRef nodeRef, Object rating) - { - try - { - Float ratingServiceRating = getRatingServiceRating(rating); - ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName()); - - QName nodeType = nodeService.getType(nodeRef); - boolean isContainer = dictionaryService.isSubClass(nodeType, ContentModel.TYPE_FOLDER) && - !dictionaryService.isSubClass(nodeType, ContentModel.TYPE_SYSTEM_FOLDER); - postActivity(nodeRef, isContainer ? ActivityType.FOLDER_LIKED : ActivityType.FILE_LIKED); - } - catch(RatingServiceException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - @Override - public void removeRating(NodeRef nodeRef) - { - try - { - ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName()); - } - catch(RatingServiceException e) - { - throw new InvalidArgumentException(e.getMessage()); - } - } - - @Override - protected Object getApiRating(Float rating) - { - Object apiRating = null; - if(rating == 1.0f) - { - apiRating = true; - } - else if(rating == 0.0f) - { - apiRating = false; - } - else - { - throw new InvalidArgumentException("Rating is invalid."); - } - - return apiRating; - } - - @Override - protected DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef) - { - return new LikesRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName)); - } - -} +package org.alfresco.rest.api.impl.node.ratings; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.activities.ActivityType; +import org.alfresco.rest.api.model.DocumentRatingSummary; +import org.alfresco.rest.api.model.LikesRatingSummary; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.service.cmr.rating.RatingServiceException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * The rest api representation of the 'likes' rating scheme. + * + * @author steveglover + * + */ +public class LikesRatingScheme extends AbstractRatingScheme +{ + public LikesRatingScheme() + { + super("likes", "likesRatingScheme"); + } + + public Float getRatingServiceRating(Object rating) + { + Float ratingToApply = null; + + if(rating instanceof Boolean) + { + boolean liked = ((Boolean)rating).booleanValue(); + ratingToApply = Float.valueOf((liked ? 1.0f : 0.0f)); + } + else + { + throw new InvalidArgumentException("Rating should be non-null and a boolean for 'likes' rating scheme."); + } + + return ratingToApply; + } + + @Override + public void applyRating(NodeRef nodeRef, Object rating) + { + try + { + Float ratingServiceRating = getRatingServiceRating(rating); + ratingService.applyRating(nodeRef, ratingServiceRating, getRatingServiceName()); + + QName nodeType = nodeService.getType(nodeRef); + boolean isContainer = dictionaryService.isSubClass(nodeType, ContentModel.TYPE_FOLDER) && + !dictionaryService.isSubClass(nodeType, ContentModel.TYPE_SYSTEM_FOLDER); + postActivity(nodeRef, isContainer ? ActivityType.FOLDER_LIKED : ActivityType.FILE_LIKED); + } + catch(RatingServiceException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + @Override + public void removeRating(NodeRef nodeRef) + { + try + { + ratingService.removeRatingByCurrentUser(nodeRef, getRatingServiceName()); + } + catch(RatingServiceException e) + { + throw new InvalidArgumentException(e.getMessage()); + } + } + + @Override + protected Object getApiRating(Float rating) + { + Object apiRating = null; + if(rating == 1.0f) + { + apiRating = true; + } + else if(rating == 0.0f) + { + apiRating = false; + } + else + { + throw new InvalidArgumentException("Rating is invalid."); + } + + return apiRating; + } + + @Override + protected DocumentRatingSummary getDocumentRatingSummary(NodeRef nodeRef) + { + return new LikesRatingSummary(ratingService.getRatingsCount(nodeRef, ratingSchemeName)); + } + +} diff --git a/source/java/org/alfresco/rest/api/impl/node/ratings/RatingScheme.java b/source/java/org/alfresco/rest/api/impl/node/ratings/RatingScheme.java index 950f41c5b1..ef0098ff1f 100644 --- a/source/java/org/alfresco/rest/api/impl/node/ratings/RatingScheme.java +++ b/source/java/org/alfresco/rest/api/impl/node/ratings/RatingScheme.java @@ -1,11 +1,11 @@ -package org.alfresco.rest.api.impl.node.ratings; - -import org.alfresco.rest.api.model.NodeRating; -import org.alfresco.service.cmr.repository.NodeRef; - -public interface RatingScheme -{ - public void applyRating(NodeRef nodeRef, Object rating); - public void removeRating(NodeRef nodeRef); - public NodeRating getNodeRating(NodeRef nodeRef); -} +package org.alfresco.rest.api.impl.node.ratings; + +import org.alfresco.rest.api.model.NodeRating; +import org.alfresco.service.cmr.repository.NodeRef; + +public interface RatingScheme +{ + public void applyRating(NodeRef nodeRef, Object rating); + public void removeRating(NodeRef nodeRef); + public NodeRating getNodeRating(NodeRef nodeRef); +} diff --git a/source/java/org/alfresco/rest/api/model/Activity.java b/source/java/org/alfresco/rest/api/model/Activity.java index 6bdfd7e8f9..3a6658873e 100644 --- a/source/java/org/alfresco/rest/api/model/Activity.java +++ b/source/java/org/alfresco/rest/api/model/Activity.java @@ -1,140 +1,140 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; -import java.util.Map; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents an activity feed entry. - * - * @author steveglover - * - */ -public class Activity implements Comparable -{ - private Long id; - private String networkId; - private String siteId; - private String feedPersonId; - private String postPersonId; - private Date postedAt; - private String activityType; - private Map activitySummary; - - public Activity() - { - } - - public Activity(Long id, String networkId, String siteId, String feedPersonId, - String postPersonId, Date postedAt, String activityType, Map activitySummary) - { - super(); - this.id = id; - this.networkId = networkId; - this.siteId = siteId; - this.feedPersonId = feedPersonId; - this.postPersonId = postPersonId; - this.postedAt = postedAt; - this.activityType = activityType; - this.activitySummary = activitySummary; - } - - @UniqueId - public Long getId() - { - return id; - } - - public String getNetworkId() - { - return networkId; - } - - public String getSiteId() - { - return siteId; - } - - public String getFeedPersonId() - { - return feedPersonId; - } - - public String getPostPersonId() - { - return postPersonId; - } - - public String getActivityType() - { - return activityType; - } - - public Date getPostedAt() - { - return postedAt; - } - - public Map getActivitySummary() - { - return activitySummary; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - Activity other = (Activity) obj; - return(id.equals(other.id)); - } - - @Override - public int compareTo(Activity activity) - { - long otherId = activity.getId(); - long diff = id - otherId; - if(diff == 0) - { - return 0; - } - else - { - return diff < 0 ? -1 : 1; - } - } - - @Override - public String toString() - { - return "Activity [id=" + id + ", siteId=" + siteId - + ", feedPersonId=" + feedPersonId + ", postPersonId=" + postPersonId - + ", postedAt=" + postedAt - + ", activityType=" + activityType + ", activitySummary=" - + activitySummary + "]"; - } - -} +package org.alfresco.rest.api.model; + +import java.util.Date; +import java.util.Map; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents an activity feed entry. + * + * @author steveglover + * + */ +public class Activity implements Comparable +{ + private Long id; + private String networkId; + private String siteId; + private String feedPersonId; + private String postPersonId; + private Date postedAt; + private String activityType; + private Map activitySummary; + + public Activity() + { + } + + public Activity(Long id, String networkId, String siteId, String feedPersonId, + String postPersonId, Date postedAt, String activityType, Map activitySummary) + { + super(); + this.id = id; + this.networkId = networkId; + this.siteId = siteId; + this.feedPersonId = feedPersonId; + this.postPersonId = postPersonId; + this.postedAt = postedAt; + this.activityType = activityType; + this.activitySummary = activitySummary; + } + + @UniqueId + public Long getId() + { + return id; + } + + public String getNetworkId() + { + return networkId; + } + + public String getSiteId() + { + return siteId; + } + + public String getFeedPersonId() + { + return feedPersonId; + } + + public String getPostPersonId() + { + return postPersonId; + } + + public String getActivityType() + { + return activityType; + } + + public Date getPostedAt() + { + return postedAt; + } + + public Map getActivitySummary() + { + return activitySummary; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + Activity other = (Activity) obj; + return(id.equals(other.id)); + } + + @Override + public int compareTo(Activity activity) + { + long otherId = activity.getId(); + long diff = id - otherId; + if(diff == 0) + { + return 0; + } + else + { + return diff < 0 ? -1 : 1; + } + } + + @Override + public String toString() + { + return "Activity [id=" + id + ", siteId=" + siteId + + ", feedPersonId=" + feedPersonId + ", postPersonId=" + postPersonId + + ", postedAt=" + postedAt + + ", activityType=" + activityType + ", activitySummary=" + + activitySummary + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Company.java b/source/java/org/alfresco/rest/api/model/Company.java index 9520dc82d3..da7a02eaa1 100644 --- a/source/java/org/alfresco/rest/api/model/Company.java +++ b/source/java/org/alfresco/rest/api/model/Company.java @@ -1,83 +1,83 @@ -package org.alfresco.rest.api.model; - -/** - * Represents a company - * - * @author steveglover - * - */ -public class Company -{ - private String organization; - private String address1; - private String address2; - private String address3; - private String postcode; - private String telephone; - private String fax; - private String email; - - public Company(String organization, String address1, String address2, String address3, - String postcode, String telephone, String fax, String email) - { - super(); - this.organization = organization; - this.address1 = address1; - this.address2 = address2; - this.address3 = address3; - this.postcode = postcode; - this.telephone = telephone; - this.fax = fax; - this.email = email; - } - - public String getOrganization() - { - return organization; - } - - public String getAddress1() - { - return address1; - } - - public String getAddress2() - { - return address2; - } - - public String getAddress3() - { - return address3; - } - - public String getPostcode() - { - return postcode; - } - - public String getTelephone() - { - return telephone; - } - - public String getFax() - { - return fax; - } - - public String getEmail() - { - return email; - } - - @Override - public String toString() - { - return "Company [address1=" + address1 + ", address2=" + address2 - + ", address3=" + address3 + ", postcode=" + postcode - + ", telephone=" + telephone + ", fax=" + fax + ", email=" - + email + "]"; - } - -} +package org.alfresco.rest.api.model; + +/** + * Represents a company + * + * @author steveglover + * + */ +public class Company +{ + private String organization; + private String address1; + private String address2; + private String address3; + private String postcode; + private String telephone; + private String fax; + private String email; + + public Company(String organization, String address1, String address2, String address3, + String postcode, String telephone, String fax, String email) + { + super(); + this.organization = organization; + this.address1 = address1; + this.address2 = address2; + this.address3 = address3; + this.postcode = postcode; + this.telephone = telephone; + this.fax = fax; + this.email = email; + } + + public String getOrganization() + { + return organization; + } + + public String getAddress1() + { + return address1; + } + + public String getAddress2() + { + return address2; + } + + public String getAddress3() + { + return address3; + } + + public String getPostcode() + { + return postcode; + } + + public String getTelephone() + { + return telephone; + } + + public String getFax() + { + return fax; + } + + public String getEmail() + { + return email; + } + + @Override + public String toString() + { + return "Company [address1=" + address1 + ", address2=" + address2 + + ", address3=" + address3 + ", postcode=" + postcode + + ", telephone=" + telephone + ", fax=" + fax + ", email=" + + email + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Document.java b/source/java/org/alfresco/rest/api/model/Document.java index 39153f13e1..5f7f420f3d 100644 --- a/source/java/org/alfresco/rest/api/model/Document.java +++ b/source/java/org/alfresco/rest/api/model/Document.java @@ -1,136 +1,136 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.model; - -import java.io.Serializable; -import java.math.BigInteger; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import org.alfresco.model.ContentModel; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -/** - * Representation of a document node. - * - * @author steveglover - * @author janv - * - */ -public class Document extends Node -{ - public Document() { - super(); - } - - public Document(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) - { - super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); - - Serializable val = nodeProps.get(ContentModel.PROP_CONTENT); - - if ((val != null) && (val instanceof ContentData)) { - ContentData cd = (ContentData)val; - String mimeType = cd.getMimetype(); - String mimeTypeName = sr.getMimetypeService().getDisplaysByMimetype().get(mimeType); - contentInfo = new ContentInfo(mimeType, mimeTypeName, cd.getSize(), cd.getEncoding()); - } - - setIsFolder(false); - setIsFile(true); - } - - @Override - public ContentInfo getContent() - { - return contentInfo; - } - - @Override - public void setContent(ContentInfo contentInfoIn) - { - contentInfo = contentInfoIn; - } - - @Override - public String toString() - { - return "Document [contentInfo=" + contentInfo.toString() + ", nodeRef=" - + nodeRef + ", name=" + name + ", createdAt=" + createdAt - + ", modifiedAt=" + modifiedAt + ", createdBy=" + createdBy - + ", modifiedBy=" + modifiedBy + "]"; - } - - // TODO for backwards compat' - set explicitly when needed (ie. favourites) - private String mimeType; - private BigInteger sizeInBytes; - private String versionLabel; - - /** - * @deprecated - */ - public String getMimeType() - { - return mimeType; - } - - /** - * @deprecated - */ - public BigInteger getSizeInBytes() - { - return sizeInBytes; - } - - /** - * @deprecated - */ - public String getVersionLabel() - { - return versionLabel; - } - - /** - * @deprecated - */ - public void setMimeType(String mimeType) - { - this.mimeType = mimeType; - } - - /** - * @deprecated - */ - public void setSizeInBytes(BigInteger sizeInBytes) - { - this.sizeInBytes = sizeInBytes; - } - - /** - * @deprecated - */ - public void setVersionLabel(String versionLabel) - { - this.versionLabel = versionLabel; - } - -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.model; + +import java.io.Serializable; +import java.math.BigInteger; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.alfresco.model.ContentModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * Representation of a document node. + * + * @author steveglover + * @author janv + * + */ +public class Document extends Node +{ + public Document() { + super(); + } + + public Document(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) + { + super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); + + Serializable val = nodeProps.get(ContentModel.PROP_CONTENT); + + if ((val != null) && (val instanceof ContentData)) { + ContentData cd = (ContentData)val; + String mimeType = cd.getMimetype(); + String mimeTypeName = sr.getMimetypeService().getDisplaysByMimetype().get(mimeType); + contentInfo = new ContentInfo(mimeType, mimeTypeName, cd.getSize(), cd.getEncoding()); + } + + setIsFolder(false); + setIsFile(true); + } + + @Override + public ContentInfo getContent() + { + return contentInfo; + } + + @Override + public void setContent(ContentInfo contentInfoIn) + { + contentInfo = contentInfoIn; + } + + @Override + public String toString() + { + return "Document [contentInfo=" + contentInfo.toString() + ", nodeRef=" + + nodeRef + ", name=" + name + ", createdAt=" + createdAt + + ", modifiedAt=" + modifiedAt + ", createdBy=" + createdBy + + ", modifiedBy=" + modifiedBy + "]"; + } + + // TODO for backwards compat' - set explicitly when needed (ie. favourites) + private String mimeType; + private BigInteger sizeInBytes; + private String versionLabel; + + /** + * @deprecated + */ + public String getMimeType() + { + return mimeType; + } + + /** + * @deprecated + */ + public BigInteger getSizeInBytes() + { + return sizeInBytes; + } + + /** + * @deprecated + */ + public String getVersionLabel() + { + return versionLabel; + } + + /** + * @deprecated + */ + public void setMimeType(String mimeType) + { + this.mimeType = mimeType; + } + + /** + * @deprecated + */ + public void setSizeInBytes(BigInteger sizeInBytes) + { + this.sizeInBytes = sizeInBytes; + } + + /** + * @deprecated + */ + public void setVersionLabel(String versionLabel) + { + this.versionLabel = versionLabel; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/DocumentRatingSummary.java b/source/java/org/alfresco/rest/api/model/DocumentRatingSummary.java index 12d8826c5b..6fb198f121 100644 --- a/source/java/org/alfresco/rest/api/model/DocumentRatingSummary.java +++ b/source/java/org/alfresco/rest/api/model/DocumentRatingSummary.java @@ -1,5 +1,5 @@ -package org.alfresco.rest.api.model; - -public interface DocumentRatingSummary -{ -} +package org.alfresco.rest.api.model; + +public interface DocumentRatingSummary +{ +} diff --git a/source/java/org/alfresco/rest/api/model/DocumentTarget.java b/source/java/org/alfresco/rest/api/model/DocumentTarget.java index ddf9e64b7c..8413b045e6 100644 --- a/source/java/org/alfresco/rest/api/model/DocumentTarget.java +++ b/source/java/org/alfresco/rest/api/model/DocumentTarget.java @@ -1,40 +1,40 @@ -package org.alfresco.rest.api.model; - -/** - * A document target favourite. - * - * @author steveglover - * - */ -public class DocumentTarget extends Target -{ - private Document file; - - public DocumentTarget() - { - super(); - } - - public DocumentTarget(Document file) - { - super(); - this.file = file; - } - - public void setDocument(Document file) - { - this.file = file; - } - - public Document getFile() - { - return file; - } - - @Override - public String toString() - { - return "DocumentTarget [file=" + file + "]"; - } - -} +package org.alfresco.rest.api.model; + +/** + * A document target favourite. + * + * @author steveglover + * + */ +public class DocumentTarget extends Target +{ + private Document file; + + public DocumentTarget() + { + super(); + } + + public DocumentTarget(Document file) + { + super(); + this.file = file; + } + + public void setDocument(Document file) + { + this.file = file; + } + + public Document getFile() + { + return file; + } + + @Override + public String toString() + { + return "DocumentTarget [file=" + file + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Favourite.java b/source/java/org/alfresco/rest/api/model/Favourite.java index 30532327cd..19c4b6912e 100644 --- a/source/java/org/alfresco/rest/api/model/Favourite.java +++ b/source/java/org/alfresco/rest/api/model/Favourite.java @@ -1,56 +1,56 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Representation of a favourite (document, folder, site, ...). - * - * @author steveglover - * - */ -public class Favourite -{ - private String targetGuid; - private Date createdAt; - private Target target; - - public Date getCreatedAt() - { - return createdAt; - } - - public void setCreatedAt(Date createdAt) - { - this.createdAt = createdAt; - } - - @UniqueId(name="targetGuid") - public String getTargetGuid() - { - return targetGuid; - } - - public void setTargetGuid(String targetGuid) - { - this.targetGuid = targetGuid; - } - - public Target getTarget() - { - return target; - } - - public void setTarget(Target target) - { - this.target = target; - } - - @Override - public String toString() - { - return "Favourite [targetGuid=" + targetGuid - + ", createdAt=" + createdAt + ", target=" + target + "]"; - } +package org.alfresco.rest.api.model; + +import java.util.Date; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Representation of a favourite (document, folder, site, ...). + * + * @author steveglover + * + */ +public class Favourite +{ + private String targetGuid; + private Date createdAt; + private Target target; + + public Date getCreatedAt() + { + return createdAt; + } + + public void setCreatedAt(Date createdAt) + { + this.createdAt = createdAt; + } + + @UniqueId(name="targetGuid") + public String getTargetGuid() + { + return targetGuid; + } + + public void setTargetGuid(String targetGuid) + { + this.targetGuid = targetGuid; + } + + public Target getTarget() + { + return target; + } + + public void setTarget(Target target) + { + this.target = target; + } + + @Override + public String toString() + { + return "Favourite [targetGuid=" + targetGuid + + ", createdAt=" + createdAt + ", target=" + target + "]"; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/model/FavouriteSite.java b/source/java/org/alfresco/rest/api/model/FavouriteSite.java index 5721dbaddd..a270190f02 100644 --- a/source/java/org/alfresco/rest/api/model/FavouriteSite.java +++ b/source/java/org/alfresco/rest/api/model/FavouriteSite.java @@ -1,31 +1,31 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.service.cmr.site.SiteInfo; - -/** - * Represents a user's favourite site. - * - * Represented by a separate class in order to allow other attributes to be added. - * - * @author steveglover - * - */ -public class FavouriteSite extends Site -{ - public FavouriteSite() - { - } - - public FavouriteSite(SiteInfo siteInfo, String role) - { - super(siteInfo, role); - } - - @Override - public String toString() - { - return "FavouriteSite [id=" + id + ", guid=" + guid + ", title=" - + title + ", description=" + description + ", visibility=" - + visibility + ", role=" + role + "]"; - } -} +package org.alfresco.rest.api.model; + +import org.alfresco.service.cmr.site.SiteInfo; + +/** + * Represents a user's favourite site. + * + * Represented by a separate class in order to allow other attributes to be added. + * + * @author steveglover + * + */ +public class FavouriteSite extends Site +{ + public FavouriteSite() + { + } + + public FavouriteSite(SiteInfo siteInfo, String role) + { + super(siteInfo, role); + } + + @Override + public String toString() + { + return "FavouriteSite [id=" + id + ", guid=" + guid + ", title=" + + title + ", description=" + description + ", visibility=" + + visibility + ", role=" + role + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/FiveStarRatingSummary.java b/source/java/org/alfresco/rest/api/model/FiveStarRatingSummary.java index a389b882d1..d1e556b77e 100644 --- a/source/java/org/alfresco/rest/api/model/FiveStarRatingSummary.java +++ b/source/java/org/alfresco/rest/api/model/FiveStarRatingSummary.java @@ -1,32 +1,32 @@ -package org.alfresco.rest.api.model; - -public class FiveStarRatingSummary implements DocumentRatingSummary -{ - private Integer numberOfRatings; - private Float average; - - public FiveStarRatingSummary(Integer numberOfRatings, Float ratingTotal, Float average) - { - super(); - this.numberOfRatings = numberOfRatings; - this.average = (average == -1 ? null : average); - } - - public Integer getNumberOfRatings() - { - return numberOfRatings; - } - - public Float getAverage() - { - return average; - } - - @Override - public String toString() - { - return "FiveStarRatingSummary [numberOfRatings=" + numberOfRatings - + ", average=" + average + "]"; - } - -} +package org.alfresco.rest.api.model; + +public class FiveStarRatingSummary implements DocumentRatingSummary +{ + private Integer numberOfRatings; + private Float average; + + public FiveStarRatingSummary(Integer numberOfRatings, Float ratingTotal, Float average) + { + super(); + this.numberOfRatings = numberOfRatings; + this.average = (average == -1 ? null : average); + } + + public Integer getNumberOfRatings() + { + return numberOfRatings; + } + + public Float getAverage() + { + return average; + } + + @Override + public String toString() + { + return "FiveStarRatingSummary [numberOfRatings=" + numberOfRatings + + ", average=" + average + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Folder.java b/source/java/org/alfresco/rest/api/model/Folder.java index 76a49e3f6c..a210238ca8 100644 --- a/source/java/org/alfresco/rest/api/model/Folder.java +++ b/source/java/org/alfresco/rest/api/model/Folder.java @@ -1,69 +1,69 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.model; - -import java.io.Serializable; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -/** - * Representation of a folder node. - * - * @author steveglover - * @author janv - */ -public class Folder extends Node -{ - public Folder() - { - super(); - } - - public Folder(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) - { - super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); - - setIsFolder(true); - setIsFile(false); - } - - @Override - public ContentInfo getContent() - { - return null; - } - - @Override - public void setContent(ContentInfo contentInfo) - { - } - - @Override - public String toString() - { - return "Folder [nodeRef=" + nodeRef + ", name=" + name + ", title=" - + title + ", description=" + description + ", createdAt=" - + createdAt + ", modifiedAt=" + modifiedAt + ", createdBy=" - + createdBy + ", modifiedBy=" + modifiedBy + "]"; - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.model; + +import java.io.Serializable; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * Representation of a folder node. + * + * @author steveglover + * @author janv + */ +public class Folder extends Node +{ + public Folder() + { + super(); + } + + public Folder(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) + { + super(nodeRef, parentNodeRef, nodeProps, mapUserInfo, sr); + + setIsFolder(true); + setIsFile(false); + } + + @Override + public ContentInfo getContent() + { + return null; + } + + @Override + public void setContent(ContentInfo contentInfo) + { + } + + @Override + public String toString() + { + return "Folder [nodeRef=" + nodeRef + ", name=" + name + ", title=" + + title + ", description=" + description + ", createdAt=" + + createdAt + ", modifiedAt=" + modifiedAt + ", createdBy=" + + createdBy + ", modifiedBy=" + modifiedBy + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/FolderTarget.java b/source/java/org/alfresco/rest/api/model/FolderTarget.java index 6203fe2738..604c4483a9 100644 --- a/source/java/org/alfresco/rest/api/model/FolderTarget.java +++ b/source/java/org/alfresco/rest/api/model/FolderTarget.java @@ -1,39 +1,39 @@ -package org.alfresco.rest.api.model; - -/** - * A folder target favourite. - * - * @author steveglover - * - */ -public class FolderTarget extends Target -{ - private Folder folder; - - public FolderTarget() - { - super(); - } - - public FolderTarget(Folder folder) - { - super(); - this.folder = folder; - } - - public void setFolder(Folder folder) - { - this.folder = folder; - } - - public Folder getFolder() - { - return folder; - } - - @Override - public String toString() - { - return "FolderTarget [folder=" + folder + "]"; - } -} +package org.alfresco.rest.api.model; + +/** + * A folder target favourite. + * + * @author steveglover + * + */ +public class FolderTarget extends Target +{ + private Folder folder; + + public FolderTarget() + { + super(); + } + + public FolderTarget(Folder folder) + { + super(); + this.folder = folder; + } + + public void setFolder(Folder folder) + { + this.folder = folder; + } + + public Folder getFolder() + { + return folder; + } + + @Override + public String toString() + { + return "FolderTarget [folder=" + folder + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/LikesRatingSummary.java b/source/java/org/alfresco/rest/api/model/LikesRatingSummary.java index f9601eedb8..db12bf1939 100644 --- a/source/java/org/alfresco/rest/api/model/LikesRatingSummary.java +++ b/source/java/org/alfresco/rest/api/model/LikesRatingSummary.java @@ -1,24 +1,24 @@ -package org.alfresco.rest.api.model; - -public class LikesRatingSummary implements DocumentRatingSummary -{ - private Integer numberOfRatings; - - public LikesRatingSummary(Integer numberOfRatings) - { - super(); - this.numberOfRatings = numberOfRatings; - } - - public Integer getNumberOfRatings() - { - return numberOfRatings; - } - - @Override - public String toString() - { - return "LikesRatingSummary [numberOfRatings=" + numberOfRatings + "]"; - } - -} +package org.alfresco.rest.api.model; + +public class LikesRatingSummary implements DocumentRatingSummary +{ + private Integer numberOfRatings; + + public LikesRatingSummary(Integer numberOfRatings) + { + super(); + this.numberOfRatings = numberOfRatings; + } + + public Integer getNumberOfRatings() + { + return numberOfRatings; + } + + @Override + public String toString() + { + return "LikesRatingSummary [numberOfRatings=" + numberOfRatings + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/MemberOfSite.java b/source/java/org/alfresco/rest/api/model/MemberOfSite.java index 8f50348991..f2bcb8c4f8 100644 --- a/source/java/org/alfresco/rest/api/model/MemberOfSite.java +++ b/source/java/org/alfresco/rest/api/model/MemberOfSite.java @@ -1,146 +1,146 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.api.sites.SiteEntityResource; -import org.alfresco.rest.framework.resource.EmbeddedEntityResource; -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteInfo; - -/** - * Represents membership of a site. - * - * @author steveglover - * - */ -public class MemberOfSite implements Comparable -{ - private String role; - private String siteShortName; - private NodeRef guid; - - public MemberOfSite() - { - } - - public MemberOfSite(String siteShortName, NodeRef siteGuid, String role) - { - super(); - if(siteShortName == null) - { - throw new IllegalArgumentException(); - } - if(role == null) - { - throw new IllegalArgumentException(); - } - if(siteGuid == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - this.siteShortName = siteShortName; - this.guid = siteGuid; - } - - public static MemberOfSite getMemberOfSite(SiteInfo siteInfo, String siteRole) - { - MemberOfSite memberOfSite = new MemberOfSite(siteInfo.getShortName(), siteInfo.getNodeRef(), siteRole); - return memberOfSite; - } - - @UniqueId - @EmbeddedEntityResource(propertyName = "site", entityResource = SiteEntityResource.class) - public String getSiteShortName() - { - return siteShortName; - } - - public NodeRef getGuid() - { - return guid; - } - - public void setGuid(NodeRef guid) - { - this.guid = guid; - } - - public String getRole() - { - return role; - } - - public void setRole(String role) - { - if(role == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - } - - public void setSiteShortName(String siteShortName) - { - if(siteShortName == null) - { - throw new IllegalArgumentException(); - } - this.siteShortName = siteShortName; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((role == null) ? 0 : role.hashCode()); - result = prime * result - + ((siteShortName == null) ? 0 : siteShortName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - MemberOfSite other = (MemberOfSite) obj; - if (role != other.role) - { - return false; - } - - return siteShortName.equals(other.siteShortName); - } - - @Override - public int compareTo(MemberOfSite o) - { - int i = siteShortName.compareTo(o.getSiteShortName()); - if(i == 0) - { - i = role.compareTo(o.getRole()); - } - return i; - } - - @Override - public String toString() - { - return "MemberOfSite [role=" + role + ", siteShortName=" - + siteShortName + ", siteGuid=" + guid + "]"; - } -} +package org.alfresco.rest.api.model; + +import org.alfresco.rest.api.sites.SiteEntityResource; +import org.alfresco.rest.framework.resource.EmbeddedEntityResource; +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteInfo; + +/** + * Represents membership of a site. + * + * @author steveglover + * + */ +public class MemberOfSite implements Comparable +{ + private String role; + private String siteShortName; + private NodeRef guid; + + public MemberOfSite() + { + } + + public MemberOfSite(String siteShortName, NodeRef siteGuid, String role) + { + super(); + if(siteShortName == null) + { + throw new IllegalArgumentException(); + } + if(role == null) + { + throw new IllegalArgumentException(); + } + if(siteGuid == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + this.siteShortName = siteShortName; + this.guid = siteGuid; + } + + public static MemberOfSite getMemberOfSite(SiteInfo siteInfo, String siteRole) + { + MemberOfSite memberOfSite = new MemberOfSite(siteInfo.getShortName(), siteInfo.getNodeRef(), siteRole); + return memberOfSite; + } + + @UniqueId + @EmbeddedEntityResource(propertyName = "site", entityResource = SiteEntityResource.class) + public String getSiteShortName() + { + return siteShortName; + } + + public NodeRef getGuid() + { + return guid; + } + + public void setGuid(NodeRef guid) + { + this.guid = guid; + } + + public String getRole() + { + return role; + } + + public void setRole(String role) + { + if(role == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + } + + public void setSiteShortName(String siteShortName) + { + if(siteShortName == null) + { + throw new IllegalArgumentException(); + } + this.siteShortName = siteShortName; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((role == null) ? 0 : role.hashCode()); + result = prime * result + + ((siteShortName == null) ? 0 : siteShortName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + MemberOfSite other = (MemberOfSite) obj; + if (role != other.role) + { + return false; + } + + return siteShortName.equals(other.siteShortName); + } + + @Override + public int compareTo(MemberOfSite o) + { + int i = siteShortName.compareTo(o.getSiteShortName()); + if(i == 0) + { + i = role.compareTo(o.getRole()); + } + return i; + } + + @Override + public String toString() + { + return "MemberOfSite [role=" + role + ", siteShortName=" + + siteShortName + ", siteGuid=" + guid + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/Network.java b/source/java/org/alfresco/rest/api/model/Network.java index c32f95cfb8..1155e5ef8c 100644 --- a/source/java/org/alfresco/rest/api/model/Network.java +++ b/source/java/org/alfresco/rest/api/model/Network.java @@ -1,38 +1,38 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; -import java.util.List; - -/** - * Represents a cloud network (account). - * - * @author steveglover - * - */ -public interface Network -{ - public String getId(); - - /** - * Gets the date the account was created - * - * @return The account creation date - */ - public Date getCreatedAt(); - public List getQuotas(); - - /** - * Gets whether an account is enabled or not. - * - * @return true = account is enabled, false = account is disabled - */ - public Boolean getIsEnabled(); - - /** - * Gets the subscription level. - * @return String - */ - public String getSubscriptionLevel(); - - public Boolean getPaidNetwork(); +package org.alfresco.rest.api.model; + +import java.util.Date; +import java.util.List; + +/** + * Represents a cloud network (account). + * + * @author steveglover + * + */ +public interface Network +{ + public String getId(); + + /** + * Gets the date the account was created + * + * @return The account creation date + */ + public Date getCreatedAt(); + public List getQuotas(); + + /** + * Gets whether an account is enabled or not. + * + * @return true = account is enabled, false = account is disabled + */ + public Boolean getIsEnabled(); + + /** + * Gets the subscription level. + * @return String + */ + public String getSubscriptionLevel(); + + public Boolean getPaidNetwork(); } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/model/NetworkImpl.java b/source/java/org/alfresco/rest/api/model/NetworkImpl.java index a0c882616f..5647cde109 100644 --- a/source/java/org/alfresco/rest/api/model/NetworkImpl.java +++ b/source/java/org/alfresco/rest/api/model/NetworkImpl.java @@ -1,139 +1,139 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents a cloud network (account). - * - * @author steveglover - * - */ -public class NetworkImpl implements Comparable, Network -{ - private String id; - private Date createdAt; - private List quotas = new LinkedList(); - private Boolean isEnabled; - private String subscriptionLevel; - private Boolean paidNetwork; - - public NetworkImpl(org.alfresco.repo.tenant.Network network) - { - this.id = network.getTenantDomain(); - this.createdAt = network.getCreatedAt(); - this.isEnabled = network.isEnabled(); - this.paidNetwork = network.getPaidNetwork(); - this.subscriptionLevel = network.getSubscriptionLevel(); - } - - public NetworkImpl(String id, Date createdAt, Boolean isEnabled, String subscriptionLevel, Boolean paidNetwork) - { - this.id = id; - this.createdAt = createdAt; - this.isEnabled = isEnabled; - this.subscriptionLevel = subscriptionLevel; - this.paidNetwork = paidNetwork; - } - - /** - * Get the account name - * - * @return The name of the account - */ - @UniqueId - public String getId() - { - return id; - } - - /** - * Gets the date the account was created - * - * @return The account creation date - */ - public Date getCreatedAt() - { - return createdAt; - } - - public List getQuotas() - { - return quotas; - } - - /** - * Gets whether an account is enabled or not. - * - * @return true = account is enabled, false = account is disabled - */ - public Boolean getIsEnabled() - { - return isEnabled; - } - - /** - * Gets the subscription level. - * - * @return ths subscription level - */ - public String getSubscriptionLevel() - { - return subscriptionLevel; - } - - public Boolean getPaidNetwork() - { - return paidNetwork; - } - - @Override - public int compareTo(NetworkImpl network) - { - return id.compareTo(network.getId()); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - Network other = (Network) obj; - return(id.equals(other.getId())); - } - - @Override - public String toString() - { - return "Network [id=" + id - + ", createdAt=" + createdAt + ", quotas=" + quotas - + ", isEnabled=" + isEnabled + ", subscriptionLevel=" - + subscriptionLevel + "]"; - } - -} +package org.alfresco.rest.api.model; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a cloud network (account). + * + * @author steveglover + * + */ +public class NetworkImpl implements Comparable, Network +{ + private String id; + private Date createdAt; + private List quotas = new LinkedList(); + private Boolean isEnabled; + private String subscriptionLevel; + private Boolean paidNetwork; + + public NetworkImpl(org.alfresco.repo.tenant.Network network) + { + this.id = network.getTenantDomain(); + this.createdAt = network.getCreatedAt(); + this.isEnabled = network.isEnabled(); + this.paidNetwork = network.getPaidNetwork(); + this.subscriptionLevel = network.getSubscriptionLevel(); + } + + public NetworkImpl(String id, Date createdAt, Boolean isEnabled, String subscriptionLevel, Boolean paidNetwork) + { + this.id = id; + this.createdAt = createdAt; + this.isEnabled = isEnabled; + this.subscriptionLevel = subscriptionLevel; + this.paidNetwork = paidNetwork; + } + + /** + * Get the account name + * + * @return The name of the account + */ + @UniqueId + public String getId() + { + return id; + } + + /** + * Gets the date the account was created + * + * @return The account creation date + */ + public Date getCreatedAt() + { + return createdAt; + } + + public List getQuotas() + { + return quotas; + } + + /** + * Gets whether an account is enabled or not. + * + * @return true = account is enabled, false = account is disabled + */ + public Boolean getIsEnabled() + { + return isEnabled; + } + + /** + * Gets the subscription level. + * + * @return ths subscription level + */ + public String getSubscriptionLevel() + { + return subscriptionLevel; + } + + public Boolean getPaidNetwork() + { + return paidNetwork; + } + + @Override + public int compareTo(NetworkImpl network) + { + return id.compareTo(network.getId()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + Network other = (Network) obj; + return(id.equals(other.getId())); + } + + @Override + public String toString() + { + return "Network [id=" + id + + ", createdAt=" + createdAt + ", quotas=" + quotas + + ", isEnabled=" + isEnabled + ", subscriptionLevel=" + + subscriptionLevel + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/NodeRating.java b/source/java/org/alfresco/rest/api/model/NodeRating.java index c84b8d14f7..d21d8bc40f 100644 --- a/source/java/org/alfresco/rest/api/model/NodeRating.java +++ b/source/java/org/alfresco/rest/api/model/NodeRating.java @@ -1,120 +1,120 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents a node rating. - * - * @author steveglover - * - */ -public class NodeRating implements Comparable -{ - private String ratingSchemeId; - private Object myRating; - private Date ratedAt; - private DocumentRatingSummary documentRatingSummary; - - public NodeRating() - { - } - - public NodeRating(String ratingSchemeId, Object myRating, Date ratedAt, DocumentRatingSummary documentRatingSummary) - { - if(ratingSchemeId == null) - { - throw new IllegalArgumentException(); - } - - this.ratingSchemeId = ratingSchemeId; - this.documentRatingSummary = documentRatingSummary; - this.myRating = myRating; - this.ratedAt = ratedAt; - } - - @UniqueId - public String getScheme() - { - return ratingSchemeId; - } - - public void setScheme(String ratingSchemeId) - { - if(ratingSchemeId == null) - { - throw new IllegalArgumentException(); - } - this.ratingSchemeId = ratingSchemeId; - } - - public Date getRatedAt() - { - return ratedAt; - } - - public Object getMyRating() - { - return myRating; - } - - public void setMyRating(Object myRating) - { - this.myRating = myRating; - } - - public DocumentRatingSummary getAggregate() - { - return documentRatingSummary; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((ratingSchemeId == null) ? 0 : ratingSchemeId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NodeRating other = (NodeRating) obj; - if (ratingSchemeId == null) { - if (other.getScheme() != null) - return false; - } else if (!ratingSchemeId.equals(other.getScheme())) - return false; - return true; - } - - @Override - public int compareTo(NodeRating other) - { - if(other != null) - { - int ret = (ratingSchemeId.compareTo(other.getScheme())); - return ret; - } - else - { - throw new IllegalArgumentException(); - } - } - - @Override - public String toString() - { - return "NodeRating [scheme=" + ratingSchemeId + ", myRating=" + myRating - + ", ratedAt=" + ratedAt - + ", documentRatingSummary=" + documentRatingSummary + "]"; - } -} +package org.alfresco.rest.api.model; + +import java.util.Date; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a node rating. + * + * @author steveglover + * + */ +public class NodeRating implements Comparable +{ + private String ratingSchemeId; + private Object myRating; + private Date ratedAt; + private DocumentRatingSummary documentRatingSummary; + + public NodeRating() + { + } + + public NodeRating(String ratingSchemeId, Object myRating, Date ratedAt, DocumentRatingSummary documentRatingSummary) + { + if(ratingSchemeId == null) + { + throw new IllegalArgumentException(); + } + + this.ratingSchemeId = ratingSchemeId; + this.documentRatingSummary = documentRatingSummary; + this.myRating = myRating; + this.ratedAt = ratedAt; + } + + @UniqueId + public String getScheme() + { + return ratingSchemeId; + } + + public void setScheme(String ratingSchemeId) + { + if(ratingSchemeId == null) + { + throw new IllegalArgumentException(); + } + this.ratingSchemeId = ratingSchemeId; + } + + public Date getRatedAt() + { + return ratedAt; + } + + public Object getMyRating() + { + return myRating; + } + + public void setMyRating(Object myRating) + { + this.myRating = myRating; + } + + public DocumentRatingSummary getAggregate() + { + return documentRatingSummary; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((ratingSchemeId == null) ? 0 : ratingSchemeId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NodeRating other = (NodeRating) obj; + if (ratingSchemeId == null) { + if (other.getScheme() != null) + return false; + } else if (!ratingSchemeId.equals(other.getScheme())) + return false; + return true; + } + + @Override + public int compareTo(NodeRating other) + { + if(other != null) + { + int ret = (ratingSchemeId.compareTo(other.getScheme())); + return ret; + } + else + { + throw new IllegalArgumentException(); + } + } + + @Override + public String toString() + { + return "NodeRating [scheme=" + ratingSchemeId + ", myRating=" + myRating + + ", ratedAt=" + ratedAt + + ", documentRatingSummary=" + documentRatingSummary + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/Person.java b/source/java/org/alfresco/rest/api/model/Person.java index 584d76e1f8..828c145006 100644 --- a/source/java/org/alfresco/rest/api/model/Person.java +++ b/source/java/org/alfresco/rest/api/model/Person.java @@ -1,222 +1,222 @@ -package org.alfresco.rest.api.model; - -import java.io.Serializable; -import java.util.Date; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -/** - * Represents a user of the system. - * - * @author steveglover - * - */ -public class Person -{ - public static final QName PROP_PERSON_DESCRIPTION = QName.createQName("RestApi", "description"); - - protected String userName; - protected Boolean enabled; - protected NodeRef avatarId; - protected String firstName; - protected String lastName; - protected String jobTitle; - protected String location; - protected String telephone; - protected String mobile; - protected String email; - protected String skypeId; - protected String instantMessageId; - protected String userStatus; - protected Date statusUpdatedAt; - protected String googleId; - protected Long quota; - protected Long quotaUsed; - protected Boolean emailNotificationsEnabled; - protected String description; - protected Company company; - - public Person() - { - } - - public Person(NodeRef nodeRef, Map nodeProps, boolean enabled) - { - mapProperties(nodeProps); - this.enabled = enabled; - } - - protected void mapProperties(Map nodeProps) - { - nodeProps.remove(ContentModel.PROP_CONTENT); - - this.userName = (String) nodeProps.get(ContentModel.PROP_USERNAME); - this.firstName = (String) nodeProps.get(ContentModel.PROP_FIRSTNAME); - this.lastName = (String) nodeProps.get(ContentModel.PROP_LASTNAME); - this.jobTitle = (String) nodeProps.get(ContentModel.PROP_JOBTITLE); - - this.location = (String) nodeProps.get(ContentModel.PROP_LOCATION); - this.telephone = (String) nodeProps.get(ContentModel.PROP_TELEPHONE); - this.mobile = (String) nodeProps.get(ContentModel.PROP_MOBILE); - this.email = (String) nodeProps.get(ContentModel.PROP_EMAIL); - - String organization = (String) nodeProps.get(ContentModel.PROP_ORGANIZATION); - String companyAddress1 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS1); - String companyAddress2 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS2); - String companyAddress3 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS3); - String companyPostcode = (String) nodeProps.get(ContentModel.PROP_COMPANYPOSTCODE); - String companyTelephone = (String) nodeProps.get(ContentModel.PROP_COMPANYTELEPHONE); - String companyFax = (String) nodeProps.get(ContentModel.PROP_COMPANYFAX); - String companyEmail = (String) nodeProps.get(ContentModel.PROP_COMPANYEMAIL); - this.company = new Company(organization, companyAddress1, companyAddress2, companyAddress3, companyPostcode, companyTelephone, companyFax, companyEmail); - - this.skypeId = (String) nodeProps.get(ContentModel.PROP_SKYPE); - this.instantMessageId = (String) nodeProps.get(ContentModel.PROP_INSTANTMSG); - this.userStatus = (String) nodeProps.get(ContentModel.PROP_USER_STATUS); - this.statusUpdatedAt = (Date) nodeProps.get(ContentModel.PROP_USER_STATUS_TIME); - this.googleId = (String) nodeProps.get(ContentModel.PROP_GOOGLEUSERNAME); - this.quota = (Long) nodeProps.get(ContentModel.PROP_SIZE_QUOTA); - this.quotaUsed = (Long) nodeProps.get(ContentModel.PROP_SIZE_CURRENT); - Boolean bool = (Boolean)nodeProps.get(ContentModel.PROP_EMAIL_FEED_DISABLED); - this.emailNotificationsEnabled = (bool == null ? Boolean.TRUE : !bool.booleanValue()); - this.description = (String)nodeProps.get(PROP_PERSON_DESCRIPTION); - } - - public Company getCompany() - { - return company; - } - - public String getInstantMessageId() - { - return instantMessageId; - } - - public String getGoogleId() - { - return googleId; - } - - public Long getQuota() - { - return quota; - } - - public Long getQuotaUsed() - { - return quotaUsed; - } - - public String getDescription() - { - return description; - } - - @UniqueId - public String getUserName() - { - return userName; - } - - public Boolean isEnabled() - { - return enabled; - } - - public void setAvatarId(NodeRef avatarId) - { - this.avatarId = avatarId; - } - - public NodeRef getAvatarId() - { - return avatarId; - } - - public String getFirstName() - { - return firstName; - } - - public void setFirstName(String firstName) - { - this.firstName = firstName; - } - - public void setLastName(String lastName) - { - this.lastName = lastName; - } - - public String getLastName() - { - return lastName; - } - - public String getJobTitle() - { - return jobTitle; - } - - public String getLocation() - { - return location; - } - - public String getTelephone() - { - return telephone; - } - - public String getMobile() - { - return mobile; - } - - public String getEmail() - { - return email; - } - - public String getSkypeId() - { - return skypeId; - } - - public String getUserStatus() - { - return userStatus; - } - - public Date getStatusUpdatedAt() - { - return statusUpdatedAt; - } - - public Boolean isEmailNotificationsEnabled() - { - return emailNotificationsEnabled; - } - - @Override - public String toString() - { - return "Person [userName=" + userName + ", enabled=" + enabled - + ", avatarId=" + avatarId + ", firstName=" + firstName - + ", lastName=" + lastName + ", jobTitle=" + jobTitle - + ", location=" + location - + ", telephone=" + telephone + ", mobile=" + mobile - + ", email=" + email + ", skypeId=" + skypeId - + ", instantMessageId=" + instantMessageId + ", userStatus=" - + userStatus + ", statusUpdatedAt=" + statusUpdatedAt - + ", googleId=" + googleId + ", quota=" + quota - + ", quotaUsed=" + quotaUsed + ", emailNotificationsEnabled=" - + emailNotificationsEnabled + ", description=" + description - + ", company=" + company + "]"; - } - -} +package org.alfresco.rest.api.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * Represents a user of the system. + * + * @author steveglover + * + */ +public class Person +{ + public static final QName PROP_PERSON_DESCRIPTION = QName.createQName("RestApi", "description"); + + protected String userName; + protected Boolean enabled; + protected NodeRef avatarId; + protected String firstName; + protected String lastName; + protected String jobTitle; + protected String location; + protected String telephone; + protected String mobile; + protected String email; + protected String skypeId; + protected String instantMessageId; + protected String userStatus; + protected Date statusUpdatedAt; + protected String googleId; + protected Long quota; + protected Long quotaUsed; + protected Boolean emailNotificationsEnabled; + protected String description; + protected Company company; + + public Person() + { + } + + public Person(NodeRef nodeRef, Map nodeProps, boolean enabled) + { + mapProperties(nodeProps); + this.enabled = enabled; + } + + protected void mapProperties(Map nodeProps) + { + nodeProps.remove(ContentModel.PROP_CONTENT); + + this.userName = (String) nodeProps.get(ContentModel.PROP_USERNAME); + this.firstName = (String) nodeProps.get(ContentModel.PROP_FIRSTNAME); + this.lastName = (String) nodeProps.get(ContentModel.PROP_LASTNAME); + this.jobTitle = (String) nodeProps.get(ContentModel.PROP_JOBTITLE); + + this.location = (String) nodeProps.get(ContentModel.PROP_LOCATION); + this.telephone = (String) nodeProps.get(ContentModel.PROP_TELEPHONE); + this.mobile = (String) nodeProps.get(ContentModel.PROP_MOBILE); + this.email = (String) nodeProps.get(ContentModel.PROP_EMAIL); + + String organization = (String) nodeProps.get(ContentModel.PROP_ORGANIZATION); + String companyAddress1 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS1); + String companyAddress2 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS2); + String companyAddress3 = (String) nodeProps.get(ContentModel.PROP_COMPANYADDRESS3); + String companyPostcode = (String) nodeProps.get(ContentModel.PROP_COMPANYPOSTCODE); + String companyTelephone = (String) nodeProps.get(ContentModel.PROP_COMPANYTELEPHONE); + String companyFax = (String) nodeProps.get(ContentModel.PROP_COMPANYFAX); + String companyEmail = (String) nodeProps.get(ContentModel.PROP_COMPANYEMAIL); + this.company = new Company(organization, companyAddress1, companyAddress2, companyAddress3, companyPostcode, companyTelephone, companyFax, companyEmail); + + this.skypeId = (String) nodeProps.get(ContentModel.PROP_SKYPE); + this.instantMessageId = (String) nodeProps.get(ContentModel.PROP_INSTANTMSG); + this.userStatus = (String) nodeProps.get(ContentModel.PROP_USER_STATUS); + this.statusUpdatedAt = (Date) nodeProps.get(ContentModel.PROP_USER_STATUS_TIME); + this.googleId = (String) nodeProps.get(ContentModel.PROP_GOOGLEUSERNAME); + this.quota = (Long) nodeProps.get(ContentModel.PROP_SIZE_QUOTA); + this.quotaUsed = (Long) nodeProps.get(ContentModel.PROP_SIZE_CURRENT); + Boolean bool = (Boolean)nodeProps.get(ContentModel.PROP_EMAIL_FEED_DISABLED); + this.emailNotificationsEnabled = (bool == null ? Boolean.TRUE : !bool.booleanValue()); + this.description = (String)nodeProps.get(PROP_PERSON_DESCRIPTION); + } + + public Company getCompany() + { + return company; + } + + public String getInstantMessageId() + { + return instantMessageId; + } + + public String getGoogleId() + { + return googleId; + } + + public Long getQuota() + { + return quota; + } + + public Long getQuotaUsed() + { + return quotaUsed; + } + + public String getDescription() + { + return description; + } + + @UniqueId + public String getUserName() + { + return userName; + } + + public Boolean isEnabled() + { + return enabled; + } + + public void setAvatarId(NodeRef avatarId) + { + this.avatarId = avatarId; + } + + public NodeRef getAvatarId() + { + return avatarId; + } + + public String getFirstName() + { + return firstName; + } + + public void setFirstName(String firstName) + { + this.firstName = firstName; + } + + public void setLastName(String lastName) + { + this.lastName = lastName; + } + + public String getLastName() + { + return lastName; + } + + public String getJobTitle() + { + return jobTitle; + } + + public String getLocation() + { + return location; + } + + public String getTelephone() + { + return telephone; + } + + public String getMobile() + { + return mobile; + } + + public String getEmail() + { + return email; + } + + public String getSkypeId() + { + return skypeId; + } + + public String getUserStatus() + { + return userStatus; + } + + public Date getStatusUpdatedAt() + { + return statusUpdatedAt; + } + + public Boolean isEmailNotificationsEnabled() + { + return emailNotificationsEnabled; + } + + @Override + public String toString() + { + return "Person [userName=" + userName + ", enabled=" + enabled + + ", avatarId=" + avatarId + ", firstName=" + firstName + + ", lastName=" + lastName + ", jobTitle=" + jobTitle + + ", location=" + location + + ", telephone=" + telephone + ", mobile=" + mobile + + ", email=" + email + ", skypeId=" + skypeId + + ", instantMessageId=" + instantMessageId + ", userStatus=" + + userStatus + ", statusUpdatedAt=" + statusUpdatedAt + + ", googleId=" + googleId + ", quota=" + quota + + ", quotaUsed=" + quotaUsed + ", emailNotificationsEnabled=" + + emailNotificationsEnabled + ", description=" + description + + ", company=" + company + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/PersonNetwork.java b/source/java/org/alfresco/rest/api/model/PersonNetwork.java index 088c6be8fa..6aa60890aa 100644 --- a/source/java/org/alfresco/rest/api/model/PersonNetwork.java +++ b/source/java/org/alfresco/rest/api/model/PersonNetwork.java @@ -1,107 +1,107 @@ -package org.alfresco.rest.api.model; - -import java.util.Date; -import java.util.List; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents network membership. - * - * @author steveglover - * - */ -public class PersonNetwork implements Network, Comparable -{ - private Boolean homeNetwork; - private Network network; - - public PersonNetwork() - { - } - - public PersonNetwork(Boolean homeNetwork, Network network) - { - super(); - this.homeNetwork = homeNetwork; - this.network = network; - } - - @UniqueId - public String getId() - { - return network.getId(); - } - - public Date getCreatedAt() - { - return network.getCreatedAt(); - } - - public List getQuotas() - { - return network.getQuotas(); - } - - public Boolean getIsEnabled() - { - return network.getIsEnabled(); - } - - public String getSubscriptionLevel() - { - return network.getSubscriptionLevel(); - } - - public Boolean getPaidNetwork() - { - return network.getPaidNetwork(); - } - - @Override - public int compareTo(PersonNetwork member) - { - int ret = getId().compareTo(member.getId()); - return ret; - } - - public Boolean getHomeNetwork() - { - return homeNetwork; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((network == null) ? 0 : network.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - PersonNetwork other = (PersonNetwork) obj; - if (network == null) - { - if (other.network != null) - return false; - } - else if (!network.equals(other.network)) - return false; - return true; - } - - @Override - public String toString() - { - return "PersonNetwork [homeNetwork=" + homeNetwork + ", network=" - + network + "]"; - } -} +package org.alfresco.rest.api.model; + +import java.util.Date; +import java.util.List; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents network membership. + * + * @author steveglover + * + */ +public class PersonNetwork implements Network, Comparable +{ + private Boolean homeNetwork; + private Network network; + + public PersonNetwork() + { + } + + public PersonNetwork(Boolean homeNetwork, Network network) + { + super(); + this.homeNetwork = homeNetwork; + this.network = network; + } + + @UniqueId + public String getId() + { + return network.getId(); + } + + public Date getCreatedAt() + { + return network.getCreatedAt(); + } + + public List getQuotas() + { + return network.getQuotas(); + } + + public Boolean getIsEnabled() + { + return network.getIsEnabled(); + } + + public String getSubscriptionLevel() + { + return network.getSubscriptionLevel(); + } + + public Boolean getPaidNetwork() + { + return network.getPaidNetwork(); + } + + @Override + public int compareTo(PersonNetwork member) + { + int ret = getId().compareTo(member.getId()); + return ret; + } + + public Boolean getHomeNetwork() + { + return homeNetwork; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((network == null) ? 0 : network.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PersonNetwork other = (PersonNetwork) obj; + if (network == null) + { + if (other.network != null) + return false; + } + else if (!network.equals(other.network)) + return false; + return true; + } + + @Override + public String toString() + { + return "PersonNetwork [homeNetwork=" + homeNetwork + ", network=" + + network + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/Preference.java b/source/java/org/alfresco/rest/api/model/Preference.java index 0ba596bc4b..cbb984fd24 100644 --- a/source/java/org/alfresco/rest/api/model/Preference.java +++ b/source/java/org/alfresco/rest/api/model/Preference.java @@ -1,99 +1,99 @@ -package org.alfresco.rest.api.model; - -import java.io.Serializable; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents a user preference. - * - * @author steveglover - * - */ -public class Preference implements Comparable -{ - private String name; - private Serializable value; - - public Preference() - { - } - - public Preference(String name, Serializable value) - { - if(name == null) - { - throw new IllegalArgumentException(); - } - this.name = name; - this.value = value; - } - - @UniqueId - public String getName() - { - return name; - } - - public void setName(String name) - { - if(name == null) - { - throw new IllegalArgumentException(); - } - this.name = name; - } - - public Serializable getValue() - { - return value; - } - - public void setValue(Serializable value) - { - this.value = value; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - Preference other = (Preference) obj; - return name.equals(other.name); - } - - @Override - public int compareTo(Preference preference) - { - return name.compareTo(preference.getName()); - } - - @Override - public String toString() - { - return "Preference [name=" + name + ", value=" + value + "]"; - } -} +package org.alfresco.rest.api.model; + +import java.io.Serializable; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a user preference. + * + * @author steveglover + * + */ +public class Preference implements Comparable +{ + private String name; + private Serializable value; + + public Preference() + { + } + + public Preference(String name, Serializable value) + { + if(name == null) + { + throw new IllegalArgumentException(); + } + this.name = name; + this.value = value; + } + + @UniqueId + public String getName() + { + return name; + } + + public void setName(String name) + { + if(name == null) + { + throw new IllegalArgumentException(); + } + this.name = name; + } + + public Serializable getValue() + { + return value; + } + + public void setValue(Serializable value) + { + this.value = value; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + Preference other = (Preference) obj; + return name.equals(other.name); + } + + @Override + public int compareTo(Preference preference) + { + return name.compareTo(preference.getName()); + } + + @Override + public String toString() + { + return "Preference [name=" + name + ", value=" + value + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/Quota.java b/source/java/org/alfresco/rest/api/model/Quota.java index 1d20b58ea2..47a751ceea 100644 --- a/source/java/org/alfresco/rest/api/model/Quota.java +++ b/source/java/org/alfresco/rest/api/model/Quota.java @@ -1,66 +1,66 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents a network quota. - * - * @author steveglover - * - */ -public class Quota -{ - private String name; - private Long limit; - private Long usage; - - public Quota() - { - } - - public Quota(String name, Long limit, Long usage) - { - this.name = name; - this.limit = limit; - this.usage = usage; - } - - @UniqueId - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public Long getLimit() - { - return limit; - } - - public void setLimit(Long limit) - { - this.limit = limit; - } - - public Long getUsage() - { - return usage; - } - - public void setUsage(Long usage) - { - this.usage = usage; - } - - @Override - public String toString() - { - return "Quota [name=" + name + ", limit=" + limit + ", usage=" + usage - + "]"; - } - -} +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a network quota. + * + * @author steveglover + * + */ +public class Quota +{ + private String name; + private Long limit; + private Long usage; + + public Quota() + { + } + + public Quota(String name, Long limit, Long usage) + { + this.name = name; + this.limit = limit; + this.usage = usage; + } + + @UniqueId + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Long getLimit() + { + return limit; + } + + public void setLimit(Long limit) + { + this.limit = limit; + } + + public Long getUsage() + { + return usage; + } + + public void setUsage(Long usage) + { + this.usage = usage; + } + + @Override + public String toString() + { + return "Quota [name=" + name + ", limit=" + limit + ", usage=" + usage + + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Site.java b/source/java/org/alfresco/rest/api/model/Site.java index e7633eeb3c..cf21416acd 100644 --- a/source/java/org/alfresco/rest/api/model/Site.java +++ b/source/java/org/alfresco/rest/api/model/Site.java @@ -1,150 +1,150 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteVisibility; - -/** - * Represents a site. - * - * @author steveglover - * - */ -public class Site implements Comparable -{ - public static final String ROLE = "role"; - - protected String id; // site id (aka short name) - protected String guid; // site nodeId - protected String title; - protected String description; - - public void setTitle(String title) - { - this.title = title; - } - - public void setDescription(String description) - { - this.description = description; - } - - public void setVisibility(SiteVisibility visibility) - { - this.visibility = visibility; - } - - public void setRole(String role) - { - this.role = role; - } - - protected SiteVisibility visibility; - protected String role; - - public Site() - { - } - - public Site(SiteInfo siteInfo, String role) - { - if(siteInfo == null) - { - throw new IllegalArgumentException("Must provide siteInfo"); - } - this.id = siteInfo.getShortName(); - this.guid = siteInfo.getNodeRef().getId(); - this.title = siteInfo.getTitle(); - this.description = siteInfo.getDescription(); - this.visibility = siteInfo.getVisibility(); - this.role = role; - } - - @UniqueId - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public String getGuid() - { - return guid; - } - - public void setGuid(String guid) - { - this.guid = guid; - } - - public String getTitle() - { - return title; - } - - public String getDescription() - { - return description; - } - - public SiteVisibility getVisibility() - { - return visibility; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - Site other = (Site) obj; - return id.equals(other.id); - } - - @Override - public int compareTo(Site site) - { - return id.compareTo(site.getId()); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public String toString() - { - return "Site [id=" + id + ", guid=" + guid + ", title=" + title - + ", description=" + description + ", visibility=" + visibility - + "]"; - } - - public String getRole() - { - return role; - } +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteVisibility; + +/** + * Represents a site. + * + * @author steveglover + * + */ +public class Site implements Comparable +{ + public static final String ROLE = "role"; + + protected String id; // site id (aka short name) + protected String guid; // site nodeId + protected String title; + protected String description; + + public void setTitle(String title) + { + this.title = title; + } + + public void setDescription(String description) + { + this.description = description; + } + + public void setVisibility(SiteVisibility visibility) + { + this.visibility = visibility; + } + + public void setRole(String role) + { + this.role = role; + } + + protected SiteVisibility visibility; + protected String role; + + public Site() + { + } + + public Site(SiteInfo siteInfo, String role) + { + if(siteInfo == null) + { + throw new IllegalArgumentException("Must provide siteInfo"); + } + this.id = siteInfo.getShortName(); + this.guid = siteInfo.getNodeRef().getId(); + this.title = siteInfo.getTitle(); + this.description = siteInfo.getDescription(); + this.visibility = siteInfo.getVisibility(); + this.role = role; + } + + @UniqueId + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getGuid() + { + return guid; + } + + public void setGuid(String guid) + { + this.guid = guid; + } + + public String getTitle() + { + return title; + } + + public String getDescription() + { + return description; + } + + public SiteVisibility getVisibility() + { + return visibility; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + Site other = (Site) obj; + return id.equals(other.id); + } + + @Override + public int compareTo(Site site) + { + return id.compareTo(site.getId()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public String toString() + { + return "Site [id=" + id + ", guid=" + guid + ", title=" + title + + ", description=" + description + ", visibility=" + visibility + + "]"; + } + + public String getRole() + { + return role; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/model/SiteContainer.java b/source/java/org/alfresco/rest/api/model/SiteContainer.java index 0cd8c15a04..c2ff894858 100644 --- a/source/java/org/alfresco/rest/api/model/SiteContainer.java +++ b/source/java/org/alfresco/rest/api/model/SiteContainer.java @@ -1,92 +1,92 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * Represents a site container. - * - * @author steveglover - * - */ -public class SiteContainer implements Comparable -{ - private String folderId; - private NodeRef nodeRef; - - public SiteContainer() - { - } - - public SiteContainer(String folderId, NodeRef nodeRef) - { - super(); - if(folderId == null) - { - throw new IllegalArgumentException(); - } - if(nodeRef == null) - { - throw new IllegalArgumentException(); - } - this.folderId = folderId; - this.nodeRef = nodeRef; - } - - public String getFolderId() - { - return folderId; - } - - @UniqueId - public NodeRef getNodeRef() - { - return nodeRef; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((folderId == null) ? 0 : folderId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - SiteContainer other = (SiteContainer) obj; - return nodeRef.equals(other.getNodeRef()); - } - - @Override - public int compareTo(SiteContainer other) - { - return folderId.compareTo(other.getFolderId()); - } - - @Override - public String toString() - { - return "SiteContainer [folderId=" + folderId + ", nodeRef=" - + nodeRef + "]"; - } - -} +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Represents a site container. + * + * @author steveglover + * + */ +public class SiteContainer implements Comparable +{ + private String folderId; + private NodeRef nodeRef; + + public SiteContainer() + { + } + + public SiteContainer(String folderId, NodeRef nodeRef) + { + super(); + if(folderId == null) + { + throw new IllegalArgumentException(); + } + if(nodeRef == null) + { + throw new IllegalArgumentException(); + } + this.folderId = folderId; + this.nodeRef = nodeRef; + } + + public String getFolderId() + { + return folderId; + } + + @UniqueId + public NodeRef getNodeRef() + { + return nodeRef; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((folderId == null) ? 0 : folderId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + SiteContainer other = (SiteContainer) obj; + return nodeRef.equals(other.getNodeRef()); + } + + @Override + public int compareTo(SiteContainer other) + { + return folderId.compareTo(other.getFolderId()); + } + + @Override + public String toString() + { + return "SiteContainer [folderId=" + folderId + ", nodeRef=" + + nodeRef + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/SiteMember.java b/source/java/org/alfresco/rest/api/model/SiteMember.java index 3a0498ee44..97f09fbec2 100644 --- a/source/java/org/alfresco/rest/api/model/SiteMember.java +++ b/source/java/org/alfresco/rest/api/model/SiteMember.java @@ -1,112 +1,112 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.api.people.PeopleEntityResource; -import org.alfresco.rest.framework.resource.EmbeddedEntityResource; -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.site.SiteRole; - -/** - * Represents site membership. - * - * @author steveglover - * - */ -public class SiteMember -{ - private String personId; - private String role; - - public SiteMember() - { - } - - public SiteMember(String personId, String role) - { - super(); - if(personId == null) - { - throw new IllegalArgumentException(); - } - if(role == null) - { - throw new IllegalArgumentException(); - } - this.personId = personId; - this.role = role; - } - - @UniqueId - @EmbeddedEntityResource(propertyName = "person", entityResource = PeopleEntityResource.class) - public String getPersonId() - { - return personId; - } - - public String getRole() - { - return role; - } - - public void setRole(String role) - { - if(role == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - } - - public void setPersonId(String personId) - { - if(personId == null) - { - throw new IllegalArgumentException(); - } - this.personId = personId; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((personId == null) ? 0 : personId.hashCode()); - result = prime * result + ((role == null) ? 0 : role.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - SiteMember other = (SiteMember) obj; - if (!personId.equals(other.personId)) - { - return false; - } - - return(role == other.role); - } - - @Override - public String toString() - { - return "SiteMember [personId=" + personId + ", role=" + role + "]"; - } - +package org.alfresco.rest.api.model; + +import org.alfresco.rest.api.people.PeopleEntityResource; +import org.alfresco.rest.framework.resource.EmbeddedEntityResource; +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.site.SiteRole; + +/** + * Represents site membership. + * + * @author steveglover + * + */ +public class SiteMember +{ + private String personId; + private String role; + + public SiteMember() + { + } + + public SiteMember(String personId, String role) + { + super(); + if(personId == null) + { + throw new IllegalArgumentException(); + } + if(role == null) + { + throw new IllegalArgumentException(); + } + this.personId = personId; + this.role = role; + } + + @UniqueId + @EmbeddedEntityResource(propertyName = "person", entityResource = PeopleEntityResource.class) + public String getPersonId() + { + return personId; + } + + public String getRole() + { + return role; + } + + public void setRole(String role) + { + if(role == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + } + + public void setPersonId(String personId) + { + if(personId == null) + { + throw new IllegalArgumentException(); + } + this.personId = personId; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((personId == null) ? 0 : personId.hashCode()); + result = prime * result + ((role == null) ? 0 : role.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + SiteMember other = (SiteMember) obj; + if (!personId.equals(other.personId)) + { + return false; + } + + return(role == other.role); + } + + @Override + public String toString() + { + return "SiteMember [personId=" + personId + ", role=" + role + "]"; + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/model/SiteMembershipRequest.java b/source/java/org/alfresco/rest/api/model/SiteMembershipRequest.java index 067bdce2c9..c7815dff86 100644 --- a/source/java/org/alfresco/rest/api/model/SiteMembershipRequest.java +++ b/source/java/org/alfresco/rest/api/model/SiteMembershipRequest.java @@ -1,159 +1,159 @@ -package org.alfresco.rest.api.model; - -import java.text.Collator; -import java.util.Date; - -import org.alfresco.rest.api.sites.SiteEntityResource; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.resource.EmbeddedEntityResource; -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.util.Pair; -import org.codehaus.jackson.annotate.JsonIgnore; - -/** - * Representation of a site membership request for a specific user. - * - * Ordering is by id (site id). - * - * @author steveglover - * - */ -public class SiteMembershipRequest implements Comparable -{ - private static Collator collator = Collator.getInstance(); - - private String id; // site id - private String message; - private Date createdAt; - private Date modifiedAt; - private String title; // for sorting only - - public static Pair splitId(String id) - { - int idx = id.indexOf(":"); - if(idx != -1) - { - String workflowId = id.substring(0, idx); - String key = id.substring(idx + 1); - Pair ret = new Pair(workflowId, key); - return ret; - } - else - { - throw new InvalidArgumentException("Site invite id is invalid: " + id); - } - } - - public SiteMembershipRequest() - { - } - - @EmbeddedEntityResource(propertyName = "site", entityResource = SiteEntityResource.class) - @UniqueId - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public void setTitle(String title) - { - this.title = title; - } - - @JsonIgnore - public String getTitle() - { - return title; - } - - public Date getCreatedAt() - { - return createdAt; - } - - public void setCreatedAt(Date createdAt) - { - this.createdAt = createdAt; - } - - public Date getModifiedAt() - { - return modifiedAt; - } - - public void setModifiedAt(Date modifiedAt) - { - this.modifiedAt = modifiedAt; - } - - public String getMessage() - { - return message; - } - - public void setMessage(String message) - { - this.message = message; - } - - @Override - public String toString() - { - return "SiteMembershipRequest [id=" + id + ", message=" + message + ", createdAt=" + createdAt - + ", modifiedAt=" + modifiedAt + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SiteMembershipRequest other = (SiteMembershipRequest) obj; - if (id == null) - { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - @Override - public int compareTo(SiteMembershipRequest o) - { - int ret = 0; - - if(title == null && o.getTitle() != null) - { - ret = -1; - } - else if(title != null && o.getTitle() == null) - { - ret = 1; - } - else - { - ret = collator.compare(title, o.getTitle()); - } - - return ret; - } -} +package org.alfresco.rest.api.model; + +import java.text.Collator; +import java.util.Date; + +import org.alfresco.rest.api.sites.SiteEntityResource; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.resource.EmbeddedEntityResource; +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.util.Pair; +import org.codehaus.jackson.annotate.JsonIgnore; + +/** + * Representation of a site membership request for a specific user. + * + * Ordering is by id (site id). + * + * @author steveglover + * + */ +public class SiteMembershipRequest implements Comparable +{ + private static Collator collator = Collator.getInstance(); + + private String id; // site id + private String message; + private Date createdAt; + private Date modifiedAt; + private String title; // for sorting only + + public static Pair splitId(String id) + { + int idx = id.indexOf(":"); + if(idx != -1) + { + String workflowId = id.substring(0, idx); + String key = id.substring(idx + 1); + Pair ret = new Pair(workflowId, key); + return ret; + } + else + { + throw new InvalidArgumentException("Site invite id is invalid: " + id); + } + } + + public SiteMembershipRequest() + { + } + + @EmbeddedEntityResource(propertyName = "site", entityResource = SiteEntityResource.class) + @UniqueId + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public void setTitle(String title) + { + this.title = title; + } + + @JsonIgnore + public String getTitle() + { + return title; + } + + public Date getCreatedAt() + { + return createdAt; + } + + public void setCreatedAt(Date createdAt) + { + this.createdAt = createdAt; + } + + public Date getModifiedAt() + { + return modifiedAt; + } + + public void setModifiedAt(Date modifiedAt) + { + this.modifiedAt = modifiedAt; + } + + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + @Override + public String toString() + { + return "SiteMembershipRequest [id=" + id + ", message=" + message + ", createdAt=" + createdAt + + ", modifiedAt=" + modifiedAt + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SiteMembershipRequest other = (SiteMembershipRequest) obj; + if (id == null) + { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public int compareTo(SiteMembershipRequest o) + { + int ret = 0; + + if(title == null && o.getTitle() != null) + { + ret = -1; + } + else if(title != null && o.getTitle() == null) + { + ret = 1; + } + else + { + ret = collator.compare(title, o.getTitle()); + } + + return ret; + } +} diff --git a/source/java/org/alfresco/rest/api/model/SiteTarget.java b/source/java/org/alfresco/rest/api/model/SiteTarget.java index f243ac3231..76a66ad557 100644 --- a/source/java/org/alfresco/rest/api/model/SiteTarget.java +++ b/source/java/org/alfresco/rest/api/model/SiteTarget.java @@ -1,40 +1,40 @@ -package org.alfresco.rest.api.model; - - -/** - * A site target favourite. - * - * @author steveglover - * - */ -public class SiteTarget extends Target -{ - private Site site; - - public SiteTarget() - { - super(); - } - - public SiteTarget(Site site) - { - super(); - this.site = site; - } - - public void setSite(Site site) - { - this.site = site; - } - - public Site getSite() - { - return site; - } - - @Override - public String toString() - { - return "SiteTarget [site=" + site + "]"; - } -} +package org.alfresco.rest.api.model; + + +/** + * A site target favourite. + * + * @author steveglover + * + */ +public class SiteTarget extends Target +{ + private Site site; + + public SiteTarget() + { + super(); + } + + public SiteTarget(Site site) + { + super(); + this.site = site; + } + + public void setSite(Site site) + { + this.site = site; + } + + public Site getSite() + { + return site; + } + + @Override + public String toString() + { + return "SiteTarget [site=" + site + "]"; + } +} diff --git a/source/java/org/alfresco/rest/api/model/Tag.java b/source/java/org/alfresco/rest/api/model/Tag.java index fc4314749f..63529bdea2 100644 --- a/source/java/org/alfresco/rest/api/model/Tag.java +++ b/source/java/org/alfresco/rest/api/model/Tag.java @@ -1,101 +1,101 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * Represents a node tag. - * - * @author steveglover - * - */ -public class Tag implements Comparable -{ - private NodeRef nodeRef; - private String tag; - - public Tag() - { - } - - public Tag(NodeRef nodeRef, String tag) - { - this.nodeRef = nodeRef; - this.tag = tag; - } - - @UniqueId - public NodeRef getNodeRef() - { - return nodeRef; - } - - public void setNodeRef(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - } - - public String getTag() - { - return tag; - } - - public void setTag(String tag) - { - this.tag = tag; - } - - /* - * Note that comparison of tags is based on their string value. This should still - * be consistent with equals since tags that are equal implies NodeRefs that are equal. - * - * (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - @Override - public int compareTo(Tag o) - { - int ret = getTag().compareTo(o.getTag()); - return ret; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((nodeRef == null) ? 0 : nodeRef.hashCode()); - return result; - } - - /* - * Tags are equal if they have the same NodeRef - * - * (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Tag other = (Tag) obj; - if (nodeRef == null) { - if (other.nodeRef != null) - return false; - } else if (!nodeRef.equals(other.nodeRef)) - return false; - return true; - } - - @Override - public String toString() - { - return "Tag [nodeRef=" + nodeRef + ", tag=" + tag + "]"; - } - -} +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Represents a node tag. + * + * @author steveglover + * + */ +public class Tag implements Comparable +{ + private NodeRef nodeRef; + private String tag; + + public Tag() + { + } + + public Tag(NodeRef nodeRef, String tag) + { + this.nodeRef = nodeRef; + this.tag = tag; + } + + @UniqueId + public NodeRef getNodeRef() + { + return nodeRef; + } + + public void setNodeRef(NodeRef nodeRef) + { + this.nodeRef = nodeRef; + } + + public String getTag() + { + return tag; + } + + public void setTag(String tag) + { + this.tag = tag; + } + + /* + * Note that comparison of tags is based on their string value. This should still + * be consistent with equals since tags that are equal implies NodeRefs that are equal. + * + * (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(Tag o) + { + int ret = getTag().compareTo(o.getTag()); + return ret; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((nodeRef == null) ? 0 : nodeRef.hashCode()); + return result; + } + + /* + * Tags are equal if they have the same NodeRef + * + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Tag other = (Tag) obj; + if (nodeRef == null) { + if (other.nodeRef != null) + return false; + } else if (!nodeRef.equals(other.nodeRef)) + return false; + return true; + } + + @Override + public String toString() + { + return "Tag [nodeRef=" + nodeRef + ", tag=" + tag + "]"; + } + +} diff --git a/source/java/org/alfresco/rest/api/model/Target.java b/source/java/org/alfresco/rest/api/model/Target.java index a3b1109e9d..37233f9c2c 100644 --- a/source/java/org/alfresco/rest/api/model/Target.java +++ b/source/java/org/alfresco/rest/api/model/Target.java @@ -1,11 +1,11 @@ -package org.alfresco.rest.api.model; - -/** - * A favourite target entity. - * - * @author steveglover - * - */ -public abstract class Target -{ -} +package org.alfresco.rest.api.model; + +/** + * A favourite target entity. + * + * @author steveglover + * + */ +public abstract class Target +{ +} diff --git a/source/java/org/alfresco/rest/api/model/UserRating.java b/source/java/org/alfresco/rest/api/model/UserRating.java index 74ffbae8b3..06f097383c 100644 --- a/source/java/org/alfresco/rest/api/model/UserRating.java +++ b/source/java/org/alfresco/rest/api/model/UserRating.java @@ -1,42 +1,42 @@ -package org.alfresco.rest.api.model; - -import org.alfresco.rest.framework.resource.UniqueId; - -/** - * Represents a user rating for a node. - * - * @author steveglover - * - */ -public class UserRating -{ - private Float userRating; - private String personId; - - public UserRating(String personId, Float userRating) - { - super(); - this.userRating = userRating; - this.personId = personId; - } - - public Float getUserRating() - { - return userRating; - } - - @UniqueId - public String getPersonId() - { - return personId; - } - - @Override - public String toString() - { - return "UserRating [userRating=" + userRating + ", personId=" - + personId + "]"; - } - - -} +package org.alfresco.rest.api.model; + +import org.alfresco.rest.framework.resource.UniqueId; + +/** + * Represents a user rating for a node. + * + * @author steveglover + * + */ +public class UserRating +{ + private Float userRating; + private String personId; + + public UserRating(String personId, Float userRating) + { + super(); + this.userRating = userRating; + this.personId = personId; + } + + public Float getUserRating() + { + return userRating; + } + + @UniqueId + public String getPersonId() + { + return personId; + } + + @Override + public String toString() + { + return "UserRating [userRating=" + userRating + ", personId=" + + personId + "]"; + } + + +} diff --git a/source/java/org/alfresco/rest/api/networks/NetworksEntityResource.java b/source/java/org/alfresco/rest/api/networks/NetworksEntityResource.java index 789d6d4ba5..87e05403b9 100644 --- a/source/java/org/alfresco/rest/api/networks/NetworksEntityResource.java +++ b/source/java/org/alfresco/rest/api/networks/NetworksEntityResource.java @@ -1,38 +1,38 @@ -package org.alfresco.rest.api.networks; - -import org.alfresco.rest.api.Networks; -import org.alfresco.rest.api.model.Network; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.WebApiParam; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.springframework.beans.factory.InitializingBean; - -@EntityResource(name="networks", title = "Networks entity") -public class NetworksEntityResource implements EntityResourceAction.ReadById, InitializingBean -{ - public static final String NAME = "networks"; - - private Networks networks; - - public void setNetworks(Networks networks) - { - this.networks = networks; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("networks", this.networks); - } - - @Override - @WebApiDescription(title = "Get Network Information", description = "Get information for the network with id 'networkId'") - @WebApiParam(name = "networkId", title = "The network name") - public Network readById(final String networkId, Parameters parameters) - { - return networks.getNetwork(networkId); - } +package org.alfresco.rest.api.networks; + +import org.alfresco.rest.api.Networks; +import org.alfresco.rest.api.model.Network; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.WebApiParam; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@EntityResource(name="networks", title = "Networks entity") +public class NetworksEntityResource implements EntityResourceAction.ReadById, InitializingBean +{ + public static final String NAME = "networks"; + + private Networks networks; + + public void setNetworks(Networks networks) + { + this.networks = networks; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("networks", this.networks); + } + + @Override + @WebApiDescription(title = "Get Network Information", description = "Get information for the network with id 'networkId'") + @WebApiParam(name = "networkId", title = "The network name") + public Network readById(final String networkId, Parameters parameters) + { + return networks.getNetwork(networkId); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/nodes/NodeRatingsRelation.java b/source/java/org/alfresco/rest/api/nodes/NodeRatingsRelation.java index b2dc83f33c..896fe66759 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodeRatingsRelation.java +++ b/source/java/org/alfresco/rest/api/nodes/NodeRatingsRelation.java @@ -1,82 +1,82 @@ -package org.alfresco.rest.api.nodes; - -import java.util.Collections; -import java.util.List; - -import org.alfresco.rest.api.NodeRatings; -import org.alfresco.rest.api.model.NodeRating; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.WebApiParam; -import org.alfresco.rest.framework.WebApiParameters; -import org.alfresco.rest.framework.core.ResourceParameter; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "ratings", entityResource = NodesEntityResource.class, title = "Document or folder ratings") -public class NodeRatingsRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, RelationshipResourceAction.Delete, -RelationshipResourceAction.Create, InitializingBean -{ - private NodeRatings nodeRatings; - - public void setNodeRatings(NodeRatings nodeRatings) - { - this.nodeRatings = nodeRatings; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("nodeRatings", this.nodeRatings); - } - - @Override - @WebApiDescription(title="A paged list of ratings for node 'nodeId'.") - @WebApiParam(name="nodeId", title="The unique id of the Node being addressed", description="A single node id") - public CollectionWithPagingInfo readAll(String nodeId, Parameters parameters) - { - return nodeRatings.getNodeRatings(nodeId, parameters.getPaging()); - } - - /** - * Create a rating for the node with id 'nodeId'. - * - */ - @Override - @WebApiDescription(title="Rate a node for 'nodeId'.") - @WebApiParam(name="ratingEntity", title="A single rating", description="A single node rating, multiple ratings are not supported.", - kind=ResourceParameter.KIND.HTTP_BODY_OBJECT, allowMultiple=false) - public List create(String nodeId, List ratingEntity, Parameters parameters) - { - //There will always be 1 value because allowMultiple=false - NodeRating rating = ratingEntity.get(0); - String ratingSchemeId = rating.getScheme(); - nodeRatings.addRating(nodeId, ratingSchemeId, rating.getMyRating()); - return Collections.singletonList(nodeRatings.getNodeRating(nodeId, ratingSchemeId)); - } - - /** - * Returns the rating with id 'schemeName' for node with id 'nodeId'. - * - */ - @Override - @WebApiDescription(title="Get the rating with id 'ratingSchemeId' for node 'nodeId'.") - @WebApiParameters({ - @WebApiParam(name="nodeId", title="The unique id of the Node being addressed", description="A single node id"), - @WebApiParam(name="ratingSchemeId", title="The rating scheme type", description="Possible values are likesRatingScheme.")}) - public NodeRating readById(String nodeId, String ratingSchemeId, Parameters parameters) - { - return nodeRatings.getNodeRating(nodeId, ratingSchemeId); - } - - @Override - @WebApiDescription(title="Deletes a node rating") - public void delete(String nodeId, String ratingSchemeId, Parameters parameters) - { - nodeRatings.removeRating(nodeId, ratingSchemeId); - } - +package org.alfresco.rest.api.nodes; + +import java.util.Collections; +import java.util.List; + +import org.alfresco.rest.api.NodeRatings; +import org.alfresco.rest.api.model.NodeRating; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.WebApiParam; +import org.alfresco.rest.framework.WebApiParameters; +import org.alfresco.rest.framework.core.ResourceParameter; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "ratings", entityResource = NodesEntityResource.class, title = "Document or folder ratings") +public class NodeRatingsRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, RelationshipResourceAction.Delete, +RelationshipResourceAction.Create, InitializingBean +{ + private NodeRatings nodeRatings; + + public void setNodeRatings(NodeRatings nodeRatings) + { + this.nodeRatings = nodeRatings; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("nodeRatings", this.nodeRatings); + } + + @Override + @WebApiDescription(title="A paged list of ratings for node 'nodeId'.") + @WebApiParam(name="nodeId", title="The unique id of the Node being addressed", description="A single node id") + public CollectionWithPagingInfo readAll(String nodeId, Parameters parameters) + { + return nodeRatings.getNodeRatings(nodeId, parameters.getPaging()); + } + + /** + * Create a rating for the node with id 'nodeId'. + * + */ + @Override + @WebApiDescription(title="Rate a node for 'nodeId'.") + @WebApiParam(name="ratingEntity", title="A single rating", description="A single node rating, multiple ratings are not supported.", + kind=ResourceParameter.KIND.HTTP_BODY_OBJECT, allowMultiple=false) + public List create(String nodeId, List ratingEntity, Parameters parameters) + { + //There will always be 1 value because allowMultiple=false + NodeRating rating = ratingEntity.get(0); + String ratingSchemeId = rating.getScheme(); + nodeRatings.addRating(nodeId, ratingSchemeId, rating.getMyRating()); + return Collections.singletonList(nodeRatings.getNodeRating(nodeId, ratingSchemeId)); + } + + /** + * Returns the rating with id 'schemeName' for node with id 'nodeId'. + * + */ + @Override + @WebApiDescription(title="Get the rating with id 'ratingSchemeId' for node 'nodeId'.") + @WebApiParameters({ + @WebApiParam(name="nodeId", title="The unique id of the Node being addressed", description="A single node id"), + @WebApiParam(name="ratingSchemeId", title="The rating scheme type", description="Possible values are likesRatingScheme.")}) + public NodeRating readById(String nodeId, String ratingSchemeId, Parameters parameters) + { + return nodeRatings.getNodeRating(nodeId, ratingSchemeId); + } + + @Override + @WebApiDescription(title="Deletes a node rating") + public void delete(String nodeId, String ratingSchemeId, Parameters parameters) + { + nodeRatings.removeRating(nodeId, ratingSchemeId); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/nodes/NodeTagsRelation.java b/source/java/org/alfresco/rest/api/nodes/NodeTagsRelation.java index 6be7ea5c1c..71193858d0 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodeTagsRelation.java +++ b/source/java/org/alfresco/rest/api/nodes/NodeTagsRelation.java @@ -1,56 +1,56 @@ -package org.alfresco.rest.api.nodes; - -import java.util.List; - -import org.alfresco.rest.api.Tags; -import org.alfresco.rest.api.model.Tag; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "tags", entityResource = NodesEntityResource.class, title = "Document or folder tags") -public class NodeTagsRelation implements RelationshipResourceAction.Create, RelationshipResourceAction.Delete, RelationshipResourceAction.Read, InitializingBean -{ - private Tags tags; - - public void setTags(Tags tags) - { - this.tags = tags; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("tags", this.tags); - } - - /** - * Add the tag to the node with id 'nodeId'. - * - */ - @Override - @WebApiDescription(title="Adds one or more tags to the node with id 'nodeId'.") - public List create(String nodeId, List tagsToCreate, Parameters parameters) - { - return tags.addTags(nodeId, tagsToCreate); - } - - @Override - @WebApiDescription(title="Remove the tag from the node with id 'nodeId'.") - public void delete(String nodeId, String tagId, Parameters parameters) - { - tags.deleteTag(nodeId, tagId); - } - - @Override - @WebApiDescription(title="A paged list of tags on the node 'nodeId'.") - public CollectionWithPagingInfo readAll(String nodeId, Parameters params) - { - return tags.getTags(nodeId, params); - } - +package org.alfresco.rest.api.nodes; + +import java.util.List; + +import org.alfresco.rest.api.Tags; +import org.alfresco.rest.api.model.Tag; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "tags", entityResource = NodesEntityResource.class, title = "Document or folder tags") +public class NodeTagsRelation implements RelationshipResourceAction.Create, RelationshipResourceAction.Delete, RelationshipResourceAction.Read, InitializingBean +{ + private Tags tags; + + public void setTags(Tags tags) + { + this.tags = tags; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("tags", this.tags); + } + + /** + * Add the tag to the node with id 'nodeId'. + * + */ + @Override + @WebApiDescription(title="Adds one or more tags to the node with id 'nodeId'.") + public List create(String nodeId, List tagsToCreate, Parameters parameters) + { + return tags.addTags(nodeId, tagsToCreate); + } + + @Override + @WebApiDescription(title="Remove the tag from the node with id 'nodeId'.") + public void delete(String nodeId, String tagId, Parameters parameters) + { + tags.deleteTag(nodeId, tagId); + } + + @Override + @WebApiDescription(title="A paged list of tags on the node 'nodeId'.") + public CollectionWithPagingInfo readAll(String nodeId, Parameters params) + { + return tags.getTags(nodeId, params); + } + } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/people/PersonActivitiesRelation.java b/source/java/org/alfresco/rest/api/people/PersonActivitiesRelation.java index cb9ab7082d..df5d84f9c9 100644 --- a/source/java/org/alfresco/rest/api/people/PersonActivitiesRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonActivitiesRelation.java @@ -1,62 +1,62 @@ -package org.alfresco.rest.api.people; - -import org.alfresco.rest.api.Activities; -import org.alfresco.rest.api.model.Activity; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.WebApiParam; -import org.alfresco.rest.framework.WebApiParameters; -import org.alfresco.rest.framework.core.ResourceParameter.KIND; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * - * @author steveglover - * - */ -@RelationshipResource(name = "activities", entityResource = PeopleEntityResource.class, title = "Person Activities") -public class PersonActivitiesRelation implements RelationshipResourceAction.Read, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonActivitiesRelation.class); - - private Activities activities; - - public void setActivities(Activities activities) - { - this.activities = activities; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("activities", this.activities); - } - - /* - * List the user's activities, excluding those of other users. - * - * /people/[id]/activities - * - * ordered by postDate - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Get#get(java.io.Serializable) - */ - @Override - @WebApiDescription(title = "List the user's activities, excluding those of other users.") - @WebApiParameters({ - @WebApiParam(name = "who", title = "Who", - description="Filter to include the user's activities only ('me'), other user's activities only ('others'), or all activities (don't include the parameter).", kind=KIND.QUERY_STRING), - @WebApiParam(name = "siteId", title="siteId", description = "Include only activity feed entries relating to this site.", kind=KIND.QUERY_STRING) - }) - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return activities.getUserActivities(personId, parameters); - } - -} +package org.alfresco.rest.api.people; + +import org.alfresco.rest.api.Activities; +import org.alfresco.rest.api.model.Activity; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.WebApiParam; +import org.alfresco.rest.framework.WebApiParameters; +import org.alfresco.rest.framework.core.ResourceParameter.KIND; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * + * @author steveglover + * + */ +@RelationshipResource(name = "activities", entityResource = PeopleEntityResource.class, title = "Person Activities") +public class PersonActivitiesRelation implements RelationshipResourceAction.Read, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonActivitiesRelation.class); + + private Activities activities; + + public void setActivities(Activities activities) + { + this.activities = activities; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("activities", this.activities); + } + + /* + * List the user's activities, excluding those of other users. + * + * /people/[id]/activities + * + * ordered by postDate + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Get#get(java.io.Serializable) + */ + @Override + @WebApiDescription(title = "List the user's activities, excluding those of other users.") + @WebApiParameters({ + @WebApiParam(name = "who", title = "Who", + description="Filter to include the user's activities only ('me'), other user's activities only ('others'), or all activities (don't include the parameter).", kind=KIND.QUERY_STRING), + @WebApiParam(name = "siteId", title="siteId", description = "Include only activity feed entries relating to this site.", kind=KIND.QUERY_STRING) + }) + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return activities.getUserActivities(personId, parameters); + } + +} diff --git a/source/java/org/alfresco/rest/api/people/PersonFavouriteSitesRelation.java b/source/java/org/alfresco/rest/api/people/PersonFavouriteSitesRelation.java index 99031afd5c..348ee5ef4f 100644 --- a/source/java/org/alfresco/rest/api/people/PersonFavouriteSitesRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonFavouriteSitesRelation.java @@ -1,88 +1,88 @@ -package org.alfresco.rest.api.people; - -import java.util.List; - -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.FavouriteSite; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * - * @author steveglover - * - */ -@RelationshipResource(name = "favorite-sites", entityResource = PeopleEntityResource.class, title = "Person Favorite Sites") -public class PersonFavouriteSitesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, -RelationshipResourceAction.Create, RelationshipResourceAction.Delete, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonFavouriteSitesRelation.class); - - private Sites sites; - - public void setSites(Sites sites) - { - this.sites = sites; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("sites", this.sites); - } - - /** - * List the user's favourite sites. - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Get Person Favorite Sites", description = "Get a paged list of the person's favorite sites") - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return sites.getFavouriteSites(personId, parameters); - } - - /** - * List the favourite site information for a specific site. - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.ReadById#readById(String, String, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Get Person Favorite Site", description = "Get information on a person's specific favorite site") - public FavouriteSite readById(String personId, String siteShortName, Parameters parameters) - { - return sites.getFavouriteSite(personId, siteShortName); - } - - /** - * Adds the given site as a favourite site for the user. - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Add Person Favorite Site", description = "Favorite a site") - public List create(String personId, List entity, Parameters parameters) - { - for (FavouriteSite favSite : entity) - { - sites.addFavouriteSite(personId, favSite); - } - return entity; - } - - @Override - @WebApiDescription(title = "Remove Person Favorite Site", description = "Un-favorite a site") - public void delete(String personId, String siteId, Parameters parameters) - { - sites.removeFavouriteSite(personId, siteId); - } - -} +package org.alfresco.rest.api.people; + +import java.util.List; + +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.FavouriteSite; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * + * @author steveglover + * + */ +@RelationshipResource(name = "favorite-sites", entityResource = PeopleEntityResource.class, title = "Person Favorite Sites") +public class PersonFavouriteSitesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, +RelationshipResourceAction.Create, RelationshipResourceAction.Delete, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonFavouriteSitesRelation.class); + + private Sites sites; + + public void setSites(Sites sites) + { + this.sites = sites; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("sites", this.sites); + } + + /** + * List the user's favourite sites. + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Get Person Favorite Sites", description = "Get a paged list of the person's favorite sites") + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return sites.getFavouriteSites(personId, parameters); + } + + /** + * List the favourite site information for a specific site. + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.ReadById#readById(String, String, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Get Person Favorite Site", description = "Get information on a person's specific favorite site") + public FavouriteSite readById(String personId, String siteShortName, Parameters parameters) + { + return sites.getFavouriteSite(personId, siteShortName); + } + + /** + * Adds the given site as a favourite site for the user. + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Add Person Favorite Site", description = "Favorite a site") + public List create(String personId, List entity, Parameters parameters) + { + for (FavouriteSite favSite : entity) + { + sites.addFavouriteSite(personId, favSite); + } + return entity; + } + + @Override + @WebApiDescription(title = "Remove Person Favorite Site", description = "Un-favorite a site") + public void delete(String personId, String siteId, Parameters parameters) + { + sites.removeFavouriteSite(personId, siteId); + } + +} diff --git a/source/java/org/alfresco/rest/api/people/PersonFavouritesRelation.java b/source/java/org/alfresco/rest/api/people/PersonFavouritesRelation.java index f46ce8a706..82ea7eff6c 100644 --- a/source/java/org/alfresco/rest/api/people/PersonFavouritesRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonFavouritesRelation.java @@ -1,80 +1,80 @@ -package org.alfresco.rest.api.people; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.Favourites; -import org.alfresco.rest.api.model.Favourite; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "favorites", entityResource = PeopleEntityResource.class, title = "Person Favorites") -public class PersonFavouritesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, -RelationshipResourceAction.Create, RelationshipResourceAction.Delete, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonFavouritesRelation.class); - - private Favourites favourites; - - public void setFavourites(Favourites favourites) - { - this.favourites = favourites; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("favourites", this.favourites); - } - - /** - * List the user's favourites. - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Get Person Favorites", description = "Get a paged list of the person's favorites") - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return favourites.getFavourites(personId, parameters); - } - - /** - * Adds the given site as a favourite site for the user. - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Add Person Favorite", description = "Favorite something") - public List create(String personId, List entity, Parameters parameters) - { - List ret = new ArrayList(entity.size()); - for(Favourite favourite : entity) - { - ret.add(favourites.addFavourite(personId, favourite)); - } - return ret; - } - - @Override - @WebApiDescription(title = "Remove Person Favorite", description = "Un-favorite something") - public void delete(String personId, String id, Parameters parameters) - { - favourites.removeFavourite(personId, id); - } - - @Override - public Favourite readById(String personId, String favouriteId, Parameters parameters) - throws RelationshipResourceNotFoundException - { - return favourites.getFavourite(personId, favouriteId); - } -} +package org.alfresco.rest.api.people; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.Favourites; +import org.alfresco.rest.api.model.Favourite; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "favorites", entityResource = PeopleEntityResource.class, title = "Person Favorites") +public class PersonFavouritesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, +RelationshipResourceAction.Create, RelationshipResourceAction.Delete, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonFavouritesRelation.class); + + private Favourites favourites; + + public void setFavourites(Favourites favourites) + { + this.favourites = favourites; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("favourites", this.favourites); + } + + /** + * List the user's favourites. + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Get Person Favorites", description = "Get a paged list of the person's favorites") + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return favourites.getFavourites(personId, parameters); + } + + /** + * Adds the given site as a favourite site for the user. + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Add Person Favorite", description = "Favorite something") + public List create(String personId, List entity, Parameters parameters) + { + List ret = new ArrayList(entity.size()); + for(Favourite favourite : entity) + { + ret.add(favourites.addFavourite(personId, favourite)); + } + return ret; + } + + @Override + @WebApiDescription(title = "Remove Person Favorite", description = "Un-favorite something") + public void delete(String personId, String id, Parameters parameters) + { + favourites.removeFavourite(personId, id); + } + + @Override + public Favourite readById(String personId, String favouriteId, Parameters parameters) + throws RelationshipResourceNotFoundException + { + return favourites.getFavourite(personId, favouriteId); + } +} diff --git a/source/java/org/alfresco/rest/api/people/PersonNetworksRelation.java b/source/java/org/alfresco/rest/api/people/PersonNetworksRelation.java index 618f083cab..f1271ecafb 100644 --- a/source/java/org/alfresco/rest/api/people/PersonNetworksRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonNetworksRelation.java @@ -1,52 +1,52 @@ -package org.alfresco.rest.api.people; - -import org.alfresco.rest.api.Networks; -import org.alfresco.rest.api.model.PersonNetwork; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * - * @author steveglover - * - */ -@RelationshipResource(name = "networks", entityResource = PeopleEntityResource.class, title = "Person Networks") -public class PersonNetworksRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonNetworksRelation.class); - - private Networks networks; - - public void setNetworks(Networks networks) - { - this.networks = networks; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("networks", this.networks); - } - - @Override - @WebApiDescription(title = "A paged list of the person's network memberships.") - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return networks.getNetworks(personId, parameters.getPaging()); - } - - @Override - @WebApiDescription(title = "Network membership for person 'personId' in network 'networkId'.") - public PersonNetwork readById(String personId, String networkId, Parameters parameters) - { - return networks.getNetwork(personId, networkId); - } - -} +package org.alfresco.rest.api.people; + +import org.alfresco.rest.api.Networks; +import org.alfresco.rest.api.model.PersonNetwork; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * + * @author steveglover + * + */ +@RelationshipResource(name = "networks", entityResource = PeopleEntityResource.class, title = "Person Networks") +public class PersonNetworksRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonNetworksRelation.class); + + private Networks networks; + + public void setNetworks(Networks networks) + { + this.networks = networks; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("networks", this.networks); + } + + @Override + @WebApiDescription(title = "A paged list of the person's network memberships.") + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return networks.getNetworks(personId, parameters.getPaging()); + } + + @Override + @WebApiDescription(title = "Network membership for person 'personId' in network 'networkId'.") + public PersonNetwork readById(String personId, String networkId, Parameters parameters) + { + return networks.getNetwork(personId, networkId); + } + +} diff --git a/source/java/org/alfresco/rest/api/people/PersonPreferencesRelation.java b/source/java/org/alfresco/rest/api/people/PersonPreferencesRelation.java index b871b134ec..e8428c7520 100644 --- a/source/java/org/alfresco/rest/api/people/PersonPreferencesRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonPreferencesRelation.java @@ -1,61 +1,61 @@ -package org.alfresco.rest.api.people; - -import org.alfresco.rest.api.Preferences; -import org.alfresco.rest.api.model.Preference; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "preferences", entityResource = PeopleEntityResource.class, title = "Person Preferences") -public class PersonPreferencesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonPreferencesRelation.class); - - private Preferences preferences; - - public void setPreferences(Preferences preferences) - { - this.preferences = preferences; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("preferences", this.preferences); - } - - /** - * Returns a paged list of preferences for the user personId. - * - * If personId does not exist, NotFoundException (status 404). - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "A paged list of the persons preferences.") - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return preferences.getPreferences(personId, parameters.getPaging()); - } - - /** - * Returns information regarding the preference 'preferenceName' for user personId. - * - * If personId does not exist, NotFoundException (status 404). - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.ReadById#readById(String, String, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title = "Preference value for preference 'preferenceName' for person 'personId'.") - public Preference readById(String personId, String preferenceName, Parameters parameters) - { - return preferences.getPreference(personId, preferenceName); - } - -} +package org.alfresco.rest.api.people; + +import org.alfresco.rest.api.Preferences; +import org.alfresco.rest.api.model.Preference; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "preferences", entityResource = PeopleEntityResource.class, title = "Person Preferences") +public class PersonPreferencesRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonPreferencesRelation.class); + + private Preferences preferences; + + public void setPreferences(Preferences preferences) + { + this.preferences = preferences; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("preferences", this.preferences); + } + + /** + * Returns a paged list of preferences for the user personId. + * + * If personId does not exist, NotFoundException (status 404). + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Read#readAll(java.lang.String, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "A paged list of the persons preferences.") + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return preferences.getPreferences(personId, parameters.getPaging()); + } + + /** + * Returns information regarding the preference 'preferenceName' for user personId. + * + * If personId does not exist, NotFoundException (status 404). + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.ReadById#readById(String, String, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title = "Preference value for preference 'preferenceName' for person 'personId'.") + public Preference readById(String personId, String preferenceName, Parameters parameters) + { + return preferences.getPreference(personId, preferenceName); + } + +} diff --git a/source/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java b/source/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java index 014ac77ca0..e66058d106 100644 --- a/source/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java +++ b/source/java/org/alfresco/rest/api/people/PersonSiteMembershipRequestsRelation.java @@ -1,77 +1,77 @@ -package org.alfresco.rest.api.people; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.SiteMembershipRequests; -import org.alfresco.rest.api.model.SiteMembershipRequest; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "site-membership-requests", entityResource = PeopleEntityResource.class, title = "Site Membership Requests") -public class PersonSiteMembershipRequestsRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.Delete, RelationshipResourceAction.Update, -RelationshipResourceAction.Create, RelationshipResourceAction.ReadById, InitializingBean -{ - private static final Log logger = LogFactory.getLog(PersonSiteMembershipRequestsRelation.class); - - private SiteMembershipRequests siteMembershipRequests; - - public void setSiteMembershipRequests(SiteMembershipRequests siteMembershipRequests) - { - this.siteMembershipRequests = siteMembershipRequests; - } - - @Override - public void afterPropertiesSet() throws Exception - { - } - - @Override - @WebApiDescription(title = "The site membership request for personId and siteId, if it exists.") - public SiteMembershipRequest readById(String personId, String siteId, Parameters parameters) throws RelationshipResourceNotFoundException - { - SiteMembershipRequest siteInvite = siteMembershipRequests.getSiteMembershipRequest(personId, siteId); - return siteInvite; - } - - @Override - @WebApiDescription(title = "Create a site membership request for personId and siteIds. The personId will be invited to the site as a SiteConsumer.") - public List create(String personId, List invites, Parameters parameters) - { - List result = new ArrayList(invites.size()); - for(SiteMembershipRequest invite : invites) - { - SiteMembershipRequest siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite); - result.add(siteInvite); - } - return result; - } - - @Override - @WebApiDescription(title = "Remove an existing site membership request for personId and siteId, if it exists.") - public void delete(String personId, String siteId, Parameters parameters) - { - siteMembershipRequests.cancelSiteMembershipRequest(personId, siteId); - } - - @Override - @WebApiDescription(title = "A paged list of site membership requests for personId.") - public CollectionWithPagingInfo readAll(String personId, Parameters parameters) - { - return siteMembershipRequests.getPagedSiteMembershipRequests(personId, parameters.getPaging()); - } - - @Override - @WebApiDescription(title = "Update the comment for the site membership request for personId and siteId.") - public SiteMembershipRequest update(String personId, SiteMembershipRequest siteInvite, Parameters parameters) - { - return siteMembershipRequests.updateSiteMembershipRequest(personId, siteInvite); - } +package org.alfresco.rest.api.people; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.SiteMembershipRequests; +import org.alfresco.rest.api.model.SiteMembershipRequest; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "site-membership-requests", entityResource = PeopleEntityResource.class, title = "Site Membership Requests") +public class PersonSiteMembershipRequestsRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.Delete, RelationshipResourceAction.Update, +RelationshipResourceAction.Create, RelationshipResourceAction.ReadById, InitializingBean +{ + private static final Log logger = LogFactory.getLog(PersonSiteMembershipRequestsRelation.class); + + private SiteMembershipRequests siteMembershipRequests; + + public void setSiteMembershipRequests(SiteMembershipRequests siteMembershipRequests) + { + this.siteMembershipRequests = siteMembershipRequests; + } + + @Override + public void afterPropertiesSet() throws Exception + { + } + + @Override + @WebApiDescription(title = "The site membership request for personId and siteId, if it exists.") + public SiteMembershipRequest readById(String personId, String siteId, Parameters parameters) throws RelationshipResourceNotFoundException + { + SiteMembershipRequest siteInvite = siteMembershipRequests.getSiteMembershipRequest(personId, siteId); + return siteInvite; + } + + @Override + @WebApiDescription(title = "Create a site membership request for personId and siteIds. The personId will be invited to the site as a SiteConsumer.") + public List create(String personId, List invites, Parameters parameters) + { + List result = new ArrayList(invites.size()); + for(SiteMembershipRequest invite : invites) + { + SiteMembershipRequest siteInvite = siteMembershipRequests.createSiteMembershipRequest(personId, invite); + result.add(siteInvite); + } + return result; + } + + @Override + @WebApiDescription(title = "Remove an existing site membership request for personId and siteId, if it exists.") + public void delete(String personId, String siteId, Parameters parameters) + { + siteMembershipRequests.cancelSiteMembershipRequest(personId, siteId); + } + + @Override + @WebApiDescription(title = "A paged list of site membership requests for personId.") + public CollectionWithPagingInfo readAll(String personId, Parameters parameters) + { + return siteMembershipRequests.getPagedSiteMembershipRequests(personId, parameters.getPaging()); + } + + @Override + @WebApiDescription(title = "Update the comment for the site membership request for personId and siteId.") + public SiteMembershipRequest update(String personId, SiteMembershipRequest siteInvite, Parameters parameters) + { + return siteMembershipRequests.updateSiteMembershipRequest(personId, siteInvite); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/sites/SiteContainersRelation.java b/source/java/org/alfresco/rest/api/sites/SiteContainersRelation.java index 01a503165e..5d7a72abd1 100644 --- a/source/java/org/alfresco/rest/api/sites/SiteContainersRelation.java +++ b/source/java/org/alfresco/rest/api/sites/SiteContainersRelation.java @@ -1,56 +1,56 @@ -package org.alfresco.rest.api.sites; - -import org.alfresco.query.PagingResults; -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.SiteContainer; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -@RelationshipResource(name = "containers", entityResource = SiteEntityResource.class, title = "Site Containers") -public class SiteContainersRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean -{ - private static final Log logger = LogFactory.getLog(SiteContainersRelation.class); - - private Sites sites; - - public void setSites(Sites sites) - { - this.sites = sites; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("sites", this.sites); - } - - /** - * Returns information regarding the top level container 'containerId' for site 'siteId'. - * - */ - @Override - @WebApiDescription(title = "Site container information for container 'containerId' in site 'siteId'.") - public SiteContainer readById(String siteId, String containerId, Parameters parameters) - { - return sites.getSiteContainer(siteId, containerId); - } - - /** - * Returns information regarding the top level containers for site 'siteId'. - * - */ - @Override - @WebApiDescription(title = "A paged list of site containers.") - public CollectionWithPagingInfo readAll(String siteId, Parameters parameters) - { - PagingResults siteContainers = sites.getSiteContainers(siteId, parameters.getPaging()); - return CollectionWithPagingInfo.asPaged(parameters.getPaging(), siteContainers.getPage(), siteContainers.hasMoreItems(), siteContainers.getTotalResultCount().getFirst()); - } -} +package org.alfresco.rest.api.sites; + +import org.alfresco.query.PagingResults; +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.SiteContainer; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +@RelationshipResource(name = "containers", entityResource = SiteEntityResource.class, title = "Site Containers") +public class SiteContainersRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.ReadById, InitializingBean +{ + private static final Log logger = LogFactory.getLog(SiteContainersRelation.class); + + private Sites sites; + + public void setSites(Sites sites) + { + this.sites = sites; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("sites", this.sites); + } + + /** + * Returns information regarding the top level container 'containerId' for site 'siteId'. + * + */ + @Override + @WebApiDescription(title = "Site container information for container 'containerId' in site 'siteId'.") + public SiteContainer readById(String siteId, String containerId, Parameters parameters) + { + return sites.getSiteContainer(siteId, containerId); + } + + /** + * Returns information regarding the top level containers for site 'siteId'. + * + */ + @Override + @WebApiDescription(title = "A paged list of site containers.") + public CollectionWithPagingInfo readAll(String siteId, Parameters parameters) + { + PagingResults siteContainers = sites.getSiteContainers(siteId, parameters.getPaging()); + return CollectionWithPagingInfo.asPaged(parameters.getPaging(), siteContainers.getPage(), siteContainers.hasMoreItems(), siteContainers.getTotalResultCount().getFirst()); + } +} diff --git a/source/java/org/alfresco/rest/api/sites/SiteMembersRelation.java b/source/java/org/alfresco/rest/api/sites/SiteMembersRelation.java index 821ada524d..48f730fa43 100644 --- a/source/java/org/alfresco/rest/api/sites/SiteMembersRelation.java +++ b/source/java/org/alfresco/rest/api/sites/SiteMembersRelation.java @@ -1,120 +1,120 @@ -package org.alfresco.rest.api.sites; - -import info.bliki.wiki.template.If; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.Sites; -import org.alfresco.rest.api.model.SiteMember; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.ParameterCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * @author steveglover - * - */ -@RelationshipResource(name = "members", entityResource = SiteEntityResource.class, title = "Site Members") -public class SiteMembersRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.Delete, -RelationshipResourceAction.Create, RelationshipResourceAction.Update, RelationshipResourceAction.ReadById, InitializingBean -{ - private static final Log logger = LogFactory.getLog(SiteMembersRelation.class); - - private Sites sites; - - public void setSites(Sites sites) - { - this.sites = sites; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("sites", this.sites); - } - - /** - * - * Returns a paged list of all the members of the site 'siteId'. - * - * If siteId does not exist, throws NotFoundException (status 404). - * - * (non-Javadoc) - * @see org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction.Read#readAll(org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title="A paged list of all the members of the site 'siteId'.") - public CollectionWithPagingInfo readAll(String siteId, Parameters parameters) - { - return sites.getSiteMembers(siteId, parameters); - } - - /** - * - * POST sites//members - * - * Adds personId as a member of site siteId. - * - * If personId does not exist throws NotFoundException (status 404). - * If siteMember. does not exist throws NotFoundException (status 404). - * - * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) - */ - @Override - @WebApiDescription(title="Adds personId as a member of site siteId.") - public List create(String siteId, List siteMembers, Parameters parameters) - { - List result = new ArrayList(siteMembers.size()); - for (SiteMember siteMember : siteMembers) - { - result.add(sites.addSiteMember(siteId, siteMember)); - } - return result; - } - - /** - * - * DELETE sites//members/ - * - * Removes personId as a member of site siteId. - */ - @Override - @WebApiDescription(title="Removes personId as a member of site siteId.") - public void delete(String siteId, String personId, Parameters parameters) - { - sites.removeSiteMember(personId, siteId); - } - - /** - * - * PUT sites//members - * - * Updates the membership of personId in the site (of which personId must be an existing member). - */ - @Override - @WebApiDescription(title="Updates the membership of personId in the site (of which personId must be an existing member).") - public SiteMember update(String siteId, SiteMember siteMember, Parameters parameters) - { - return sites.updateSiteMember(siteId, siteMember); - } - - /** - * - * Returns site membership information for personId in siteId. - * - * GET sites//members/ - */ - @Override - @WebApiDescription(title="Returns site membership information for personId in siteId.") - public SiteMember readById(String siteId, String personId, Parameters parameters) - { - return sites.getSiteMember(personId, siteId); - } +package org.alfresco.rest.api.sites; + +import info.bliki.wiki.template.If; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.Sites; +import org.alfresco.rest.api.model.SiteMember; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.ParameterCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * @author steveglover + * + */ +@RelationshipResource(name = "members", entityResource = SiteEntityResource.class, title = "Site Members") +public class SiteMembersRelation implements RelationshipResourceAction.Read, RelationshipResourceAction.Delete, +RelationshipResourceAction.Create, RelationshipResourceAction.Update, RelationshipResourceAction.ReadById, InitializingBean +{ + private static final Log logger = LogFactory.getLog(SiteMembersRelation.class); + + private Sites sites; + + public void setSites(Sites sites) + { + this.sites = sites; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("sites", this.sites); + } + + /** + * + * Returns a paged list of all the members of the site 'siteId'. + * + * If siteId does not exist, throws NotFoundException (status 404). + * + * (non-Javadoc) + * @see org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction.Read#readAll(org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title="A paged list of all the members of the site 'siteId'.") + public CollectionWithPagingInfo readAll(String siteId, Parameters parameters) + { + return sites.getSiteMembers(siteId, parameters); + } + + /** + * + * POST sites//members + * + * Adds personId as a member of site siteId. + * + * If personId does not exist throws NotFoundException (status 404). + * If siteMember. does not exist throws NotFoundException (status 404). + * + * @see org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction.Create#create(String, java.util.List, org.alfresco.rest.framework.resource.parameters.Parameters) + */ + @Override + @WebApiDescription(title="Adds personId as a member of site siteId.") + public List create(String siteId, List siteMembers, Parameters parameters) + { + List result = new ArrayList(siteMembers.size()); + for (SiteMember siteMember : siteMembers) + { + result.add(sites.addSiteMember(siteId, siteMember)); + } + return result; + } + + /** + * + * DELETE sites//members/ + * + * Removes personId as a member of site siteId. + */ + @Override + @WebApiDescription(title="Removes personId as a member of site siteId.") + public void delete(String siteId, String personId, Parameters parameters) + { + sites.removeSiteMember(personId, siteId); + } + + /** + * + * PUT sites//members + * + * Updates the membership of personId in the site (of which personId must be an existing member). + */ + @Override + @WebApiDescription(title="Updates the membership of personId in the site (of which personId must be an existing member).") + public SiteMember update(String siteId, SiteMember siteMember, Parameters parameters) + { + return sites.updateSiteMember(siteId, siteMember); + } + + /** + * + * Returns site membership information for personId in siteId. + * + * GET sites//members/ + */ + @Override + @WebApiDescription(title="Returns site membership information for personId in siteId.") + public SiteMember readById(String siteId, String personId, Parameters parameters) + { + return sites.getSiteMember(personId, siteId); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/tags/TagsEntityResource.java b/source/java/org/alfresco/rest/api/tags/TagsEntityResource.java index 2b518f2e05..3bd3ccc91d 100644 --- a/source/java/org/alfresco/rest/api/tags/TagsEntityResource.java +++ b/source/java/org/alfresco/rest/api/tags/TagsEntityResource.java @@ -1,55 +1,55 @@ -package org.alfresco.rest.api.tags; - -import org.alfresco.rest.api.Tags; -import org.alfresco.rest.api.model.Tag; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.util.ParameterCheck; -import org.springframework.beans.factory.InitializingBean; - -@EntityResource(name="tags", title = "Tags") -public class TagsEntityResource implements EntityResourceAction.Read, EntityResourceAction.ReadById, EntityResourceAction.Update, InitializingBean -{ - private Tags tags; - - public void setTags(Tags tags) - { - this.tags = tags; - } - - @Override - public void afterPropertiesSet() - { - ParameterCheck.mandatory("tags", this.tags); - } - - /** - * - * Returns a paged list of all currently used tags in the store workspace://SpacesStore for the current tenant. - * - */ - @Override - @WebApiDescription(title="A paged list of all tags in the network.") - public CollectionWithPagingInfo readAll(Parameters parameters) - { - return tags.getTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, parameters.getPaging()); - } - - @Override - @WebApiDescription(title="Updates a tag by unique Id") - public Tag update(String id, Tag entity, Parameters parameters) - { - return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity); - } - - @Override - public Tag readById(String id, Parameters parameters) throws EntityNotFoundException - { - return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id); - } -} +package org.alfresco.rest.api.tags; + +import org.alfresco.rest.api.Tags; +import org.alfresco.rest.api.model.Tag; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.util.ParameterCheck; +import org.springframework.beans.factory.InitializingBean; + +@EntityResource(name="tags", title = "Tags") +public class TagsEntityResource implements EntityResourceAction.Read, EntityResourceAction.ReadById, EntityResourceAction.Update, InitializingBean +{ + private Tags tags; + + public void setTags(Tags tags) + { + this.tags = tags; + } + + @Override + public void afterPropertiesSet() + { + ParameterCheck.mandatory("tags", this.tags); + } + + /** + * + * Returns a paged list of all currently used tags in the store workspace://SpacesStore for the current tenant. + * + */ + @Override + @WebApiDescription(title="A paged list of all tags in the network.") + public CollectionWithPagingInfo readAll(Parameters parameters) + { + return tags.getTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, parameters.getPaging()); + } + + @Override + @WebApiDescription(title="Updates a tag by unique Id") + public Tag update(String id, Tag entity, Parameters parameters) + { + return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity); + } + + @Override + public Tag readById(String id, Parameters parameters) throws EntityNotFoundException + { + return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id); + } +} diff --git a/source/java/org/alfresco/rest/framework/BinaryProperties.java b/source/java/org/alfresco/rest/framework/BinaryProperties.java index 9bce0d2a4c..e9f2db967b 100755 --- a/source/java/org/alfresco/rest/framework/BinaryProperties.java +++ b/source/java/org/alfresco/rest/framework/BinaryProperties.java @@ -1,18 +1,18 @@ -package org.alfresco.rest.framework; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * An array of binary property names used on a resource method operation in the Rest API - * - * @author Gethin James - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface BinaryProperties { - String[] value(); -} - +package org.alfresco.rest.framework; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An array of binary property names used on a resource method operation in the Rest API + * + * @author Gethin James + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface BinaryProperties { + String[] value(); +} + diff --git a/source/java/org/alfresco/rest/framework/core/ResourceInspectorUtil.java b/source/java/org/alfresco/rest/framework/core/ResourceInspectorUtil.java index 435e1756fa..a4307bb314 100755 --- a/source/java/org/alfresco/rest/framework/core/ResourceInspectorUtil.java +++ b/source/java/org/alfresco/rest/framework/core/ResourceInspectorUtil.java @@ -1,167 +1,167 @@ -package org.alfresco.rest.framework.core; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.framework.Operation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.core.BridgeMethodResolver; -import org.springframework.core.GenericCollectionTypeResolver; -import org.springframework.core.GenericTypeResolver; -import org.springframework.core.annotation.AnnotationUtils; - -/** - * Generic methods used by ResourceInspector - * @author Gethin James - */ -public class ResourceInspectorUtil -{ - private static Log logger = LogFactory.getLog(ResourceInspectorUtil.class); - /** - * Determine the expected type as the returned type of the method. - * If the return type is a List it will return the generic element type instead of a List. - * @param resource - resource with methods - * @param method Method - * @return Class - type of class it needs. - */ - @SuppressWarnings("rawtypes") - protected static Class determineType(Class resource, Method method) - { - Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); - - /* - * The api is consistent that the object passed in must match the object passed out - * however, operations are different, if the param is supplied it doesn't have to match - * the return type. - * So we need special logic for operations - */ - Annotation annot = AnnotationUtils.findAnnotation(resolvedMethod, Operation.class); - if (annot != null) - { - return determineOperationType(resource, method); - } - else - { - Class returnType = GenericTypeResolver.resolveReturnType(resolvedMethod, resource); - if (List.class.isAssignableFrom(returnType)) - { - return GenericCollectionTypeResolver.getCollectionReturnType(method); - } - return returnType; - } - } - - protected static Class determineOperationType(Class resource, Method method) - { - //Its an operation annotated method and its a bit special - Class[] paramTypes = method.getParameterTypes(); - if (paramTypes!= null) - { - switch (paramTypes.length) - { - case 4: - //EntityResource operation by id, same logic as RelationshipEntityResource operation by id - case 5: - int position = paramTypes.length-3; - if (Void.class.equals(paramTypes[position])) - { - return null; - } - else - { - return paramTypes[position]; - } - } - } - - throw new IllegalArgumentException("Your method signature should have 4 parameters (uniqueId, typePassedin, Parameters, WithResponse)," + - " use Void if you are not interested in the second argument. "+resource.getName()+ " "+ method.getName()); - } - - /** - * Finds methods for the given annotation - * - * It first finds all public member methods of the class or interface represented by objClass, - * including those inherited from superclasses and superinterfaces. - * - * It then loops through these methods searching for a single Annotation of annotationType, - * traversing its super methods if no annotation can be found on the given method itself. - * - * @param objClass - the class - * @param annotationType - the annotation to find - * @return - the List of Method or an empty List - */ - @SuppressWarnings("rawtypes") - public static List findMethodsByAnnotation(Class objClass, Class annotationType) - { - - List annotatedMethods = new ArrayList(); - Method[] methods = objClass.getMethods(); - for (Method method : methods) - { - Annotation annot = AnnotationUtils.findAnnotation(method, annotationType); - if (annot != null) { - //Just to be sure, lets make sure its not a Bridged (Generic) Method - Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); - annotatedMethods.add(resolvedMethod); - } - } - - return annotatedMethods; - - } - /** - * Invokes a no arg method and returns the result - * @param annotatedMethod Method - * @param obj Object - * @return result of method call - */ - public static Object invokeMethod(Method annotatedMethod, Object obj) - { - try - { - return invokeMethod(annotatedMethod, obj, null); - } - catch (Throwable error) - { - logger.error("Invocation failure", error); - return null; - } - } - - /** - * Invokes a method and returns the result - * @param annotatedMethod Method - * @param obj Object - * @return result of method call - */ - public static Object invokeMethod(Method annotatedMethod, Object obj, Object... args) throws Throwable - { - if (annotatedMethod != null) - { - try - { - return annotatedMethod.invoke(obj, args); - } - catch (IllegalArgumentException error) - { - logger.warn("Invocation error", error); - } - catch (IllegalAccessException error) - { - logger.warn("IllegalAccessException", error); - } - catch (InvocationTargetException error) - { - logger.warn("InvocationTargetException", error); - throw error.getCause(); - } - } - return null; - } - -} +package org.alfresco.rest.framework.core; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.framework.Operation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.BridgeMethodResolver; +import org.springframework.core.GenericCollectionTypeResolver; +import org.springframework.core.GenericTypeResolver; +import org.springframework.core.annotation.AnnotationUtils; + +/** + * Generic methods used by ResourceInspector + * @author Gethin James + */ +public class ResourceInspectorUtil +{ + private static Log logger = LogFactory.getLog(ResourceInspectorUtil.class); + /** + * Determine the expected type as the returned type of the method. + * If the return type is a List it will return the generic element type instead of a List. + * @param resource - resource with methods + * @param method Method + * @return Class - type of class it needs. + */ + @SuppressWarnings("rawtypes") + protected static Class determineType(Class resource, Method method) + { + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + + /* + * The api is consistent that the object passed in must match the object passed out + * however, operations are different, if the param is supplied it doesn't have to match + * the return type. + * So we need special logic for operations + */ + Annotation annot = AnnotationUtils.findAnnotation(resolvedMethod, Operation.class); + if (annot != null) + { + return determineOperationType(resource, method); + } + else + { + Class returnType = GenericTypeResolver.resolveReturnType(resolvedMethod, resource); + if (List.class.isAssignableFrom(returnType)) + { + return GenericCollectionTypeResolver.getCollectionReturnType(method); + } + return returnType; + } + } + + protected static Class determineOperationType(Class resource, Method method) + { + //Its an operation annotated method and its a bit special + Class[] paramTypes = method.getParameterTypes(); + if (paramTypes!= null) + { + switch (paramTypes.length) + { + case 4: + //EntityResource operation by id, same logic as RelationshipEntityResource operation by id + case 5: + int position = paramTypes.length-3; + if (Void.class.equals(paramTypes[position])) + { + return null; + } + else + { + return paramTypes[position]; + } + } + } + + throw new IllegalArgumentException("Your method signature should have 4 parameters (uniqueId, typePassedin, Parameters, WithResponse)," + + " use Void if you are not interested in the second argument. "+resource.getName()+ " "+ method.getName()); + } + + /** + * Finds methods for the given annotation + * + * It first finds all public member methods of the class or interface represented by objClass, + * including those inherited from superclasses and superinterfaces. + * + * It then loops through these methods searching for a single Annotation of annotationType, + * traversing its super methods if no annotation can be found on the given method itself. + * + * @param objClass - the class + * @param annotationType - the annotation to find + * @return - the List of Method or an empty List + */ + @SuppressWarnings("rawtypes") + public static List findMethodsByAnnotation(Class objClass, Class annotationType) + { + + List annotatedMethods = new ArrayList(); + Method[] methods = objClass.getMethods(); + for (Method method : methods) + { + Annotation annot = AnnotationUtils.findAnnotation(method, annotationType); + if (annot != null) { + //Just to be sure, lets make sure its not a Bridged (Generic) Method + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + annotatedMethods.add(resolvedMethod); + } + } + + return annotatedMethods; + + } + /** + * Invokes a no arg method and returns the result + * @param annotatedMethod Method + * @param obj Object + * @return result of method call + */ + public static Object invokeMethod(Method annotatedMethod, Object obj) + { + try + { + return invokeMethod(annotatedMethod, obj, null); + } + catch (Throwable error) + { + logger.error("Invocation failure", error); + return null; + } + } + + /** + * Invokes a method and returns the result + * @param annotatedMethod Method + * @param obj Object + * @return result of method call + */ + public static Object invokeMethod(Method annotatedMethod, Object obj, Object... args) throws Throwable + { + if (annotatedMethod != null) + { + try + { + return annotatedMethod.invoke(obj, args); + } + catch (IllegalArgumentException error) + { + logger.warn("Invocation error", error); + } + catch (IllegalAccessException error) + { + logger.warn("IllegalAccessException", error); + } + catch (InvocationTargetException error) + { + logger.warn("InvocationTargetException", error); + throw error.getCause(); + } + } + return null; + } + +} diff --git a/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefDeserializer.java b/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefDeserializer.java index a21d35ea91..05a849bd73 100644 --- a/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefDeserializer.java +++ b/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefDeserializer.java @@ -1,48 +1,48 @@ -package org.alfresco.rest.framework.jacksonextensions; - -import java.io.IOException; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; - -public class NodeRefDeserializer extends JsonDeserializer -{ - private NodeRef getNodeRef(String nodeRefString) - { - NodeRef nodeRef = null; - - if(!NodeRef.isNodeRef(nodeRefString)) - { - nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRefString); - } - else - { - nodeRef = new NodeRef(nodeRefString); - } - - return nodeRef; - } - - @Override - public NodeRef deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException - { - JsonToken curr = jp.getCurrentToken(); - - if (curr == JsonToken.VALUE_STRING) - { - String nodeRefString = jp.getText(); - NodeRef nodeRef = getNodeRef(nodeRefString); - return nodeRef; - } - else - { - throw new IOException("Unable to deserialize nodeRef: " + curr.asString()); - } - } -} +package org.alfresco.rest.framework.jacksonextensions; + +import java.io.IOException; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +public class NodeRefDeserializer extends JsonDeserializer +{ + private NodeRef getNodeRef(String nodeRefString) + { + NodeRef nodeRef = null; + + if(!NodeRef.isNodeRef(nodeRefString)) + { + nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRefString); + } + else + { + nodeRef = new NodeRef(nodeRefString); + } + + return nodeRef; + } + + @Override + public NodeRef deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + + if (curr == JsonToken.VALUE_STRING) + { + String nodeRefString = jp.getText(); + NodeRef nodeRef = getNodeRef(nodeRefString); + return nodeRef; + } + else + { + throw new IOException("Unable to deserialize nodeRef: " + curr.asString()); + } + } +} diff --git a/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefSerializer.java b/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefSerializer.java index 7358b20581..8cfafa2ca3 100644 --- a/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefSerializer.java +++ b/source/java/org/alfresco/rest/framework/jacksonextensions/NodeRefSerializer.java @@ -1,25 +1,25 @@ -package org.alfresco.rest.framework.jacksonextensions; - -import java.io.IOException; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.map.SerializerProvider; -import org.codehaus.jackson.map.ser.std.SerializerBase; - -public class NodeRefSerializer extends SerializerBase -{ - protected NodeRefSerializer() - { - super(NodeRef.class); - } - - @Override - public void serialize(NodeRef nodeRef, JsonGenerator jgen, SerializerProvider provider) - throws IOException, JsonGenerationException - { - jgen.writeString(nodeRef.getId()); - } - -} +package org.alfresco.rest.framework.jacksonextensions; + +import java.io.IOException; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +public class NodeRefSerializer extends SerializerBase +{ + protected NodeRefSerializer() + { + super(NodeRef.class); + } + + @Override + public void serialize(NodeRef nodeRef, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(nodeRef.getId()); + } + +} diff --git a/source/java/org/alfresco/rest/framework/jacksonextensions/RestApiStringDeserializer.java b/source/java/org/alfresco/rest/framework/jacksonextensions/RestApiStringDeserializer.java index ca09841860..8163a1b132 100644 --- a/source/java/org/alfresco/rest/framework/jacksonextensions/RestApiStringDeserializer.java +++ b/source/java/org/alfresco/rest/framework/jacksonextensions/RestApiStringDeserializer.java @@ -1,31 +1,31 @@ -package org.alfresco.rest.framework.jacksonextensions; - -import java.io.IOException; - -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.deser.std.StringDeserializer; - -/** - * Rest api string deserializer that ensures that empty strings are treated as null strings. - * - * @author steveglover - * - */ -public class RestApiStringDeserializer extends StringDeserializer -{ - @Override - public String deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException - { - String ret = super.deserialize(jp, ctxt); - - if(ret != null && ret.length() == 0) - { - ret = null; - } - - return ret; - } -} +package org.alfresco.rest.framework.jacksonextensions; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.std.StringDeserializer; + +/** + * Rest api string deserializer that ensures that empty strings are treated as null strings. + * + * @author steveglover + * + */ +public class RestApiStringDeserializer extends StringDeserializer +{ + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + String ret = super.deserialize(jp, ctxt); + + if(ret != null && ret.length() == 0) + { + ret = null; + } + + return ret; + } +} diff --git a/source/java/org/alfresco/rest/framework/jacksonextensions/TargetDeserializer.java b/source/java/org/alfresco/rest/framework/jacksonextensions/TargetDeserializer.java index 4c2d11e0f9..7f67dd8bb0 100644 --- a/source/java/org/alfresco/rest/framework/jacksonextensions/TargetDeserializer.java +++ b/source/java/org/alfresco/rest/framework/jacksonextensions/TargetDeserializer.java @@ -1,98 +1,98 @@ -package org.alfresco.rest.framework.jacksonextensions; - -import java.io.IOException; - -import org.alfresco.rest.api.model.Document; -import org.alfresco.rest.api.model.DocumentTarget; -import org.alfresco.rest.api.model.Folder; -import org.alfresco.rest.api.model.FolderTarget; -import org.alfresco.rest.api.model.Site; -import org.alfresco.rest.api.model.SiteTarget; -import org.alfresco.rest.api.model.Target; -import org.alfresco.service.cmr.favourites.FavouritesService.Type; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.BeanProperty; -import org.codehaus.jackson.map.BeanProperty.Std; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.type.SimpleType; -import org.codehaus.jackson.type.JavaType; - -public class TargetDeserializer extends JsonDeserializer -{ - @Override - public Target deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException - { - Target target = null; - JsonToken curr = jp.getCurrentToken(); - - if (curr == JsonToken.START_OBJECT) - { - while(jp.nextToken() != JsonToken.END_OBJECT) - { - String fieldname = jp.getCurrentName(); - if(Type.SITE.toString().equals(fieldname.toUpperCase())) - { - jp.nextToken(); - try - { - JavaType t = SimpleType.construct(Site.class); - BeanProperty p = new Std("", t, null, null); - JsonDeserializer siteDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); - - Site site = (Site)siteDeserializer.deserialize(jp, ctxt); - target = new SiteTarget(site); - } - catch(JsonMappingException e) - { - throw new IllegalArgumentException("Target body is invalid for target type"); - } - } - else if(Type.FILE.toString().equals(fieldname.toUpperCase())) - { - jp.nextToken(); - try - { - JavaType t = SimpleType.construct(Document.class); - BeanProperty p = new Std("", t, null, null); - JsonDeserializer documentDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); - - Document document = (Document)documentDeserializer.deserialize(jp, ctxt); - target = new DocumentTarget(document); - } - catch(JsonMappingException e) - { - throw new IllegalArgumentException("Target body is invalid for target type"); - } - } - else if(Type.FOLDER.toString().equals(fieldname.toUpperCase())) - { - jp.nextToken(); - try - { - JavaType t = SimpleType.construct(Folder.class); - BeanProperty p = new Std("", t, null, null); - JsonDeserializer folderDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); - - Folder folder = (Folder)folderDeserializer.deserialize(jp, ctxt); - target = new FolderTarget(folder); - } - catch(JsonMappingException e) - { - throw new IllegalArgumentException("Target body is invalid for target type"); - } - } - } - - return target; - } - else - { - throw new IOException("Unable to deserialize favourite: " + curr.asString()); - } - } -} +package org.alfresco.rest.framework.jacksonextensions; + +import java.io.IOException; + +import org.alfresco.rest.api.model.Document; +import org.alfresco.rest.api.model.DocumentTarget; +import org.alfresco.rest.api.model.Folder; +import org.alfresco.rest.api.model.FolderTarget; +import org.alfresco.rest.api.model.Site; +import org.alfresco.rest.api.model.SiteTarget; +import org.alfresco.rest.api.model.Target; +import org.alfresco.service.cmr.favourites.FavouritesService.Type; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.BeanProperty.Std; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.type.SimpleType; +import org.codehaus.jackson.type.JavaType; + +public class TargetDeserializer extends JsonDeserializer +{ + @Override + public Target deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + Target target = null; + JsonToken curr = jp.getCurrentToken(); + + if (curr == JsonToken.START_OBJECT) + { + while(jp.nextToken() != JsonToken.END_OBJECT) + { + String fieldname = jp.getCurrentName(); + if(Type.SITE.toString().equals(fieldname.toUpperCase())) + { + jp.nextToken(); + try + { + JavaType t = SimpleType.construct(Site.class); + BeanProperty p = new Std("", t, null, null); + JsonDeserializer siteDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); + + Site site = (Site)siteDeserializer.deserialize(jp, ctxt); + target = new SiteTarget(site); + } + catch(JsonMappingException e) + { + throw new IllegalArgumentException("Target body is invalid for target type"); + } + } + else if(Type.FILE.toString().equals(fieldname.toUpperCase())) + { + jp.nextToken(); + try + { + JavaType t = SimpleType.construct(Document.class); + BeanProperty p = new Std("", t, null, null); + JsonDeserializer documentDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); + + Document document = (Document)documentDeserializer.deserialize(jp, ctxt); + target = new DocumentTarget(document); + } + catch(JsonMappingException e) + { + throw new IllegalArgumentException("Target body is invalid for target type"); + } + } + else if(Type.FOLDER.toString().equals(fieldname.toUpperCase())) + { + jp.nextToken(); + try + { + JavaType t = SimpleType.construct(Folder.class); + BeanProperty p = new Std("", t, null, null); + JsonDeserializer folderDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), t, p); + + Folder folder = (Folder)folderDeserializer.deserialize(jp, ctxt); + target = new FolderTarget(folder); + } + catch(JsonMappingException e) + { + throw new IllegalArgumentException("Target body is invalid for target type"); + } + } + } + + return target; + } + else + { + throw new IOException("Unable to deserialize favourite: " + curr.asString()); + } + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java b/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java index c391840276..2469252d21 100755 --- a/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java +++ b/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java @@ -1,119 +1,119 @@ -package org.alfresco.rest.framework.resource.actions.interfaces; - -import java.io.InputStream; - -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.content.FileBinaryResource; -import org.alfresco.rest.framework.resource.content.NodeBinaryResource; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.rest.framework.webscripts.WithResponse; - -/** - * Permissible actions for binary resources of an Entity Resource - * - * Supports full CRUD (Read, Update, Delete) - * - * @author Gethin James - */ - -public interface BinaryResourceAction -{ - - /** - * HTTP GET - Retrieve a binary resource - */ - public static interface Read extends ResourceAction - { - /** - * Retrieves a binary property by returning a BinaryResource object. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param parameters {@link Parameters} - * @return BinaryResource - Either {@link FileBinaryResource} or {@link NodeBinaryResource} - * @throws EntityNotFoundException - */ - public BinaryResource readProperty (String entityId, Parameters parameters) throws EntityNotFoundException; - } - - /** - * HTTP GET - Retrieve a binary resource - */ - public static interface ReadWithResponse extends ResourceAction - { - /** - * Retrieves a binary property by returning a BinaryResource object. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param parameters {@link Parameters} - * @return BinaryResource - Either {@link FileBinaryResource} or {@link NodeBinaryResource} - * @throws EntityNotFoundException - */ - public BinaryResource readProperty (String entityId, Parameters parameters, WithResponse withResponse) throws EntityNotFoundException; - } - - /** - * HTTP DELETE - Deletes a binary resource - */ - public static interface Delete extends ResourceAction - { - - /** - * Deletes a binary property. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param parameters {@link Parameters} - */ - public void deleteProperty (String entityId, Parameters parameters); - } - - /** - * HTTP DELETE - Deletes a binary resource - */ - public static interface DeleteWithResponse extends ResourceAction - { - - /** - * Deletes a binary property. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param parameters {@link Parameters} - */ - public void deleteProperty (String entityId, Parameters parameters, WithResponse withResponse); - } - - /** - * HTTP PUT - Updates a binary resource if it exists, error if not - */ - public static interface Update extends ResourceAction - { - - /** - * Updates a binary property. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param stream An inputstream - * @param contentInfo Basic information about the content stream - * @param params {@link Parameters} - */ - public E updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params); - } - - /** - * HTTP PUT - Updates a binary resource if it exists, error if not - */ - public static interface UpdateWithResponse extends ResourceAction - { - - /** - * Updates a binary property. The specific property is specified in the {@link Parameters} object. - * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} - * @param entityId unique id - * @param stream An inputstream - * @param contentInfo Basic information about the content stream - * @param params {@link Parameters} - */ - public E updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params, WithResponse withResponse); - } -} +package org.alfresco.rest.framework.resource.actions.interfaces; + +import java.io.InputStream; + +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.content.FileBinaryResource; +import org.alfresco.rest.framework.resource.content.NodeBinaryResource; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.webscripts.WithResponse; + +/** + * Permissible actions for binary resources of an Entity Resource + * + * Supports full CRUD (Read, Update, Delete) + * + * @author Gethin James + */ + +public interface BinaryResourceAction +{ + + /** + * HTTP GET - Retrieve a binary resource + */ + public static interface Read extends ResourceAction + { + /** + * Retrieves a binary property by returning a BinaryResource object. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param parameters {@link Parameters} + * @return BinaryResource - Either {@link FileBinaryResource} or {@link NodeBinaryResource} + * @throws EntityNotFoundException + */ + public BinaryResource readProperty (String entityId, Parameters parameters) throws EntityNotFoundException; + } + + /** + * HTTP GET - Retrieve a binary resource + */ + public static interface ReadWithResponse extends ResourceAction + { + /** + * Retrieves a binary property by returning a BinaryResource object. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param parameters {@link Parameters} + * @return BinaryResource - Either {@link FileBinaryResource} or {@link NodeBinaryResource} + * @throws EntityNotFoundException + */ + public BinaryResource readProperty (String entityId, Parameters parameters, WithResponse withResponse) throws EntityNotFoundException; + } + + /** + * HTTP DELETE - Deletes a binary resource + */ + public static interface Delete extends ResourceAction + { + + /** + * Deletes a binary property. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param parameters {@link Parameters} + */ + public void deleteProperty (String entityId, Parameters parameters); + } + + /** + * HTTP DELETE - Deletes a binary resource + */ + public static interface DeleteWithResponse extends ResourceAction + { + + /** + * Deletes a binary property. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param parameters {@link Parameters} + */ + public void deleteProperty (String entityId, Parameters parameters, WithResponse withResponse); + } + + /** + * HTTP PUT - Updates a binary resource if it exists, error if not + */ + public static interface Update extends ResourceAction + { + + /** + * Updates a binary property. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param stream An inputstream + * @param contentInfo Basic information about the content stream + * @param params {@link Parameters} + */ + public E updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params); + } + + /** + * HTTP PUT - Updates a binary resource if it exists, error if not + */ + public static interface UpdateWithResponse extends ResourceAction + { + + /** + * Updates a binary property. The specific property is specified in the {@link Parameters} object. + * See {@link Parameters#hasBinaryProperty(String)} or {@link Parameters#getBinaryProperty()} + * @param entityId unique id + * @param stream An inputstream + * @param contentInfo Basic information about the content stream + * @param params {@link Parameters} + */ + public E updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params, WithResponse withResponse); + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/BasicContentInfo.java b/source/java/org/alfresco/rest/framework/resource/content/BasicContentInfo.java index 08a13a0543..715e11837d 100644 --- a/source/java/org/alfresco/rest/framework/resource/content/BasicContentInfo.java +++ b/source/java/org/alfresco/rest/framework/resource/content/BasicContentInfo.java @@ -1,12 +1,12 @@ -package org.alfresco.rest.framework.resource.content; - - -/** - * Basic information about content. Typically taken from a HTTPServletRequest. - * You may choose to trust it but there is no guarantee that it accurately describes the content. - */ -public interface BasicContentInfo { - public String getMimeType(); - public String getEncoding(); - -} +package org.alfresco.rest.framework.resource.content; + + +/** + * Basic information about content. Typically taken from a HTTPServletRequest. + * You may choose to trust it but there is no guarantee that it accurately describes the content. + */ +public interface BasicContentInfo { + public String getMimeType(); + public String getEncoding(); + +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/BinaryProperty.java b/source/java/org/alfresco/rest/framework/resource/content/BinaryProperty.java index e41e0381f5..1034deb07b 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/BinaryProperty.java +++ b/source/java/org/alfresco/rest/framework/resource/content/BinaryProperty.java @@ -1,102 +1,102 @@ -package org.alfresco.rest.framework.resource.content; - -import java.io.Serializable; -import java.util.Locale; - -import org.alfresco.service.cmr.repository.ContentReader; -import org.codehaus.jackson.annotate.JsonIgnore; - -/** - * A POJO property that is of type "Binary" - * - * You can add this to your object to be serialized as a normal property. - * - * @author Gethin James - */ - -public class BinaryProperty implements ContentInfo, Serializable -{ - private static final long serialVersionUID = 7392073427641063968L; - - private final String mimeType; - private final String encoding; - private final long length; - private final Locale locale; - - /** - * Sets the content length to zero, Locale to null, no stream and no caching - * @param mimeType String - * @param encoding String - */ - public BinaryProperty(String mimeType, String encoding) - { - super(); - this.mimeType = mimeType; - this.encoding = encoding; - this.length = 0; - this.locale = null; - } - - /** - * This is the preferred constructor to use. Takes the properties from content reader that it needs. - * @param reader ContentReader - */ - public BinaryProperty(ContentReader reader) - { - super(); - this.mimeType = reader.getMimetype(); - this.encoding = reader.getEncoding(); - this.length = reader.getSize(); - this.locale = reader.getLocale(); - } - - /** - * Sets no stream and no caching - * @param mimeType String - * @param encoding String - * @param length long - * @param locale Locale - */ - public BinaryProperty(String mimeType, String encoding, long length, Locale locale) - { - super(); - this.mimeType = mimeType; - this.encoding = encoding; - this.length = length; - this.locale = locale; - } - - public String getMimeType() - { - return this.mimeType; - } - - @JsonIgnore - public String getEncoding() - { - return this.encoding; - } - - /** - * Used for serialization. If the length is unknown then this method returns null - * and is therefore not serialized. - * - * @return Long size - null if unknown. - */ - public Long getSizeInBytes() - { - return this.length>0?this.length:null; - } - - @JsonIgnore - public long getLength() - { - return this.length; - } - @JsonIgnore - public Locale getLocale() - { - return this.locale; - } - -} +package org.alfresco.rest.framework.resource.content; + +import java.io.Serializable; +import java.util.Locale; + +import org.alfresco.service.cmr.repository.ContentReader; +import org.codehaus.jackson.annotate.JsonIgnore; + +/** + * A POJO property that is of type "Binary" + * + * You can add this to your object to be serialized as a normal property. + * + * @author Gethin James + */ + +public class BinaryProperty implements ContentInfo, Serializable +{ + private static final long serialVersionUID = 7392073427641063968L; + + private final String mimeType; + private final String encoding; + private final long length; + private final Locale locale; + + /** + * Sets the content length to zero, Locale to null, no stream and no caching + * @param mimeType String + * @param encoding String + */ + public BinaryProperty(String mimeType, String encoding) + { + super(); + this.mimeType = mimeType; + this.encoding = encoding; + this.length = 0; + this.locale = null; + } + + /** + * This is the preferred constructor to use. Takes the properties from content reader that it needs. + * @param reader ContentReader + */ + public BinaryProperty(ContentReader reader) + { + super(); + this.mimeType = reader.getMimetype(); + this.encoding = reader.getEncoding(); + this.length = reader.getSize(); + this.locale = reader.getLocale(); + } + + /** + * Sets no stream and no caching + * @param mimeType String + * @param encoding String + * @param length long + * @param locale Locale + */ + public BinaryProperty(String mimeType, String encoding, long length, Locale locale) + { + super(); + this.mimeType = mimeType; + this.encoding = encoding; + this.length = length; + this.locale = locale; + } + + public String getMimeType() + { + return this.mimeType; + } + + @JsonIgnore + public String getEncoding() + { + return this.encoding; + } + + /** + * Used for serialization. If the length is unknown then this method returns null + * and is therefore not serialized. + * + * @return Long size - null if unknown. + */ + public Long getSizeInBytes() + { + return this.length>0?this.length:null; + } + + @JsonIgnore + public long getLength() + { + return this.length; + } + @JsonIgnore + public Locale getLocale() + { + return this.locale; + } + +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/BinaryResource.java b/source/java/org/alfresco/rest/framework/resource/content/BinaryResource.java index 790f723701..e6131b2bf1 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/BinaryResource.java +++ b/source/java/org/alfresco/rest/framework/resource/content/BinaryResource.java @@ -1,11 +1,11 @@ -package org.alfresco.rest.framework.resource.content; - -/** - * A resource that is of type "Binary" - * - * @author Gethin James - */ -public interface BinaryResource -{ - -} +package org.alfresco.rest.framework.resource.content; + +/** + * A resource that is of type "Binary" + * + * @author Gethin James + */ +public interface BinaryResource +{ + +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/ContentInfo.java b/source/java/org/alfresco/rest/framework/resource/content/ContentInfo.java index b417f8e858..4aaa987d90 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/ContentInfo.java +++ b/source/java/org/alfresco/rest/framework/resource/content/ContentInfo.java @@ -1,11 +1,11 @@ -package org.alfresco.rest.framework.resource.content; - -import java.util.Locale; - -/** - * Basic information about content. Typically used with HTTPServletResponse - */ -public interface ContentInfo extends BasicContentInfo{ - public long getLength(); - public Locale getLocale(); -} +package org.alfresco.rest.framework.resource.content; + +import java.util.Locale; + +/** + * Basic information about content. Typically used with HTTPServletResponse + */ +public interface ContentInfo extends BasicContentInfo{ + public long getLength(); + public Locale getLocale(); +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/ContentInfoImpl.java b/source/java/org/alfresco/rest/framework/resource/content/ContentInfoImpl.java index 263e36da72..b73d40dcaf 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/ContentInfoImpl.java +++ b/source/java/org/alfresco/rest/framework/resource/content/ContentInfoImpl.java @@ -1,44 +1,44 @@ -package org.alfresco.rest.framework.resource.content; - -import java.util.Locale; - -/** - * Basic implementation of information about the returned content. - */ -public class ContentInfoImpl implements ContentInfo -{ - private final String mimeType; - private final String encoding; - private final long length; - private final Locale locale; - - public ContentInfoImpl(String mimeType, String encoding, long length, Locale locale) - { - super(); - this.mimeType = mimeType; - this.encoding = encoding; - this.length = length; - this.locale = locale; - } - - @Override - public String getMimeType() - { - return this.mimeType; - } - @Override - public String getEncoding() - { - return this.encoding; - } - @Override - public long getLength() - { - return this.length; - } - @Override - public Locale getLocale() - { - return this.locale; - } -} +package org.alfresco.rest.framework.resource.content; + +import java.util.Locale; + +/** + * Basic implementation of information about the returned content. + */ +public class ContentInfoImpl implements ContentInfo +{ + private final String mimeType; + private final String encoding; + private final long length; + private final Locale locale; + + public ContentInfoImpl(String mimeType, String encoding, long length, Locale locale) + { + super(); + this.mimeType = mimeType; + this.encoding = encoding; + this.length = length; + this.locale = locale; + } + + @Override + public String getMimeType() + { + return this.mimeType; + } + @Override + public String getEncoding() + { + return this.encoding; + } + @Override + public long getLength() + { + return this.length; + } + @Override + public Locale getLocale() + { + return this.locale; + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java b/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java index a9087d47f6..53d534420d 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java +++ b/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java @@ -1,48 +1,48 @@ -/* - * Copyright (C) 2005-2016 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 . - */ - -package org.alfresco.rest.framework.resource.content; - -import java.io.File; - -/** - * A binary resource based on a File. - * - * @author Gethin James - */ -public class FileBinaryResource extends AbstractBinaryResource -{ - final File file; - - public FileBinaryResource(File file) - { - this(file, null); - } - - public FileBinaryResource(File file, String attachFileName) - { - super(attachFileName, null); - this.file = file; - } - - public File getFile() - { - return this.file; - } -} +/* + * Copyright (C) 2005-2016 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 . + */ + +package org.alfresco.rest.framework.resource.content; + +import java.io.File; + +/** + * A binary resource based on a File. + * + * @author Gethin James + */ +public class FileBinaryResource extends AbstractBinaryResource +{ + final File file; + + public FileBinaryResource(File file) + { + this(file, null); + } + + public FileBinaryResource(File file, String attachFileName) + { + super(attachFileName, null); + this.file = file; + } + + public File getFile() + { + return this.file; + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java b/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java index 5fc28eb1ae..cf21d1e56e 100755 --- a/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java +++ b/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java @@ -1,63 +1,63 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.framework.resource.content; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; - -/** - * A binary resource based on a Node reference. - * - * @author Gethin James - */ -public class NodeBinaryResource extends AbstractBinaryResource -{ - - final NodeRef nodeRef; - final QName propertyQName; - final ContentInfo contentInfo; - - public NodeBinaryResource(NodeRef nodeRef, QName propertyQName, ContentInfo contentInfo, String attachFileName) - { - this(nodeRef, propertyQName, contentInfo, attachFileName, null); - } - - public NodeBinaryResource(NodeRef nodeRef, QName propertyQName, ContentInfo contentInfo, String attachFileName, CacheDirective cacheDirective) - { - super(attachFileName, cacheDirective); - this.nodeRef = nodeRef; - this.propertyQName = propertyQName; - this.contentInfo = contentInfo; - } - - public NodeRef getNodeRef() - { - return this.nodeRef; - } - - public QName getPropertyQName() - { - return this.propertyQName; - } - - public ContentInfo getContentInfo() - { - return this.contentInfo; - } +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.framework.resource.content; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * A binary resource based on a Node reference. + * + * @author Gethin James + */ +public class NodeBinaryResource extends AbstractBinaryResource +{ + + final NodeRef nodeRef; + final QName propertyQName; + final ContentInfo contentInfo; + + public NodeBinaryResource(NodeRef nodeRef, QName propertyQName, ContentInfo contentInfo, String attachFileName) + { + this(nodeRef, propertyQName, contentInfo, attachFileName, null); + } + + public NodeBinaryResource(NodeRef nodeRef, QName propertyQName, ContentInfo contentInfo, String attachFileName, CacheDirective cacheDirective) + { + super(attachFileName, cacheDirective); + this.nodeRef = nodeRef; + this.propertyQName = propertyQName; + this.contentInfo = contentInfo; + } + + public NodeRef getNodeRef() + { + return this.nodeRef; + } + + public QName getPropertyQName() + { + return this.propertyQName; + } + + public ContentInfo getContentInfo() + { + return this.contentInfo; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/framework/resource/parameters/InvalidSelectException.java b/source/java/org/alfresco/rest/framework/resource/parameters/InvalidSelectException.java index 3cf5a3cdc7..8c5df1d35c 100755 --- a/source/java/org/alfresco/rest/framework/resource/parameters/InvalidSelectException.java +++ b/source/java/org/alfresco/rest/framework/resource/parameters/InvalidSelectException.java @@ -1,20 +1,20 @@ -package org.alfresco.rest.framework.resource.parameters; - -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; - -/** - * Thrown when an invalid select syntax is used. - * - * @author Gethin James - */ -public class InvalidSelectException extends InvalidArgumentException -{ - private static final long serialVersionUID = -8631890798598434965L; - - public static String DEFAULT_MESSAGE_ID = "framework.exception.InvalidSelect"; - - public InvalidSelectException(String paramName, Object queryParam) - { - super(DEFAULT_MESSAGE_ID, new Object[] {queryParam, paramName}); - } -} +package org.alfresco.rest.framework.resource.parameters; + +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; + +/** + * Thrown when an invalid select syntax is used. + * + * @author Gethin James + */ +public class InvalidSelectException extends InvalidArgumentException +{ + private static final long serialVersionUID = -8631890798598434965L; + + public static String DEFAULT_MESSAGE_ID = "framework.exception.InvalidSelect"; + + public InvalidSelectException(String paramName, Object queryParam) + { + super(DEFAULT_MESSAGE_ID, new Object[] {queryParam, paramName}); + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/parameters/where/InvalidQueryException.java b/source/java/org/alfresco/rest/framework/resource/parameters/where/InvalidQueryException.java index ac64fac492..8f442fd1e0 100644 --- a/source/java/org/alfresco/rest/framework/resource/parameters/where/InvalidQueryException.java +++ b/source/java/org/alfresco/rest/framework/resource/parameters/where/InvalidQueryException.java @@ -1,31 +1,31 @@ -package org.alfresco.rest.framework.resource.parameters.where; - -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; - -/** - * Thrown when an invalid query syntax is used. - * - * @author Gethin James - */ -public class InvalidQueryException extends InvalidArgumentException -{ - private static final long serialVersionUID = 8825573452685077660L; - public static String DEFAULT_MESSAGE_ID = "framework.exception.InvalidQuery"; - private Object queryParam; - - public InvalidQueryException() { - super(DEFAULT_MESSAGE_ID); - } - - public InvalidQueryException(Object queryParam) - { - super(DEFAULT_MESSAGE_ID, new Object[] {queryParam}); - this.queryParam = queryParam; - } - - public Object getQueryParam() - { - return queryParam; - } - -} +package org.alfresco.rest.framework.resource.parameters.where; + +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; + +/** + * Thrown when an invalid query syntax is used. + * + * @author Gethin James + */ +public class InvalidQueryException extends InvalidArgumentException +{ + private static final long serialVersionUID = 8825573452685077660L; + public static String DEFAULT_MESSAGE_ID = "framework.exception.InvalidQuery"; + private Object queryParam; + + public InvalidQueryException() { + super(DEFAULT_MESSAGE_ID); + } + + public InvalidQueryException(Object queryParam) + { + super(DEFAULT_MESSAGE_ID, new Object[] {queryParam}); + this.queryParam = queryParam; + } + + public Object getQueryParam() + { + return queryParam; + } + +} diff --git a/source/java/org/alfresco/rest/framework/resource/parameters/where/Query.java b/source/java/org/alfresco/rest/framework/resource/parameters/where/Query.java index 8ed1d36542..9d5f0b80de 100644 --- a/source/java/org/alfresco/rest/framework/resource/parameters/where/Query.java +++ b/source/java/org/alfresco/rest/framework/resource/parameters/where/Query.java @@ -1,18 +1,18 @@ -package org.alfresco.rest.framework.resource.parameters.where; - -import org.antlr.runtime.tree.CommonTree; - -/** - * Represents a Query defined by a WHERE clause, passed in as a parameter in a GET call to the Rest api. - * - * @author Gethin James - */ -public interface Query -{ - - /** - * Returns the list of operations - */ - CommonTree getTree(); - -} +package org.alfresco.rest.framework.resource.parameters.where; + +import org.antlr.runtime.tree.CommonTree; + +/** + * Represents a Query defined by a WHERE clause, passed in as a parameter in a GET call to the Rest api. + * + * @author Gethin James + */ +public interface Query +{ + + /** + * Returns the list of operations + */ + CommonTree getTree(); + +} diff --git a/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryHelper.java b/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryHelper.java index f5321169c9..55e76305c3 100644 --- a/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryHelper.java +++ b/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryHelper.java @@ -1,264 +1,264 @@ -package org.alfresco.rest.framework.resource.parameters.where; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import org.alfresco.rest.antlr.WhereClauseParser; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; -import org.apache.commons.lang.StringUtils; - -/** - * Provides helper methods for handling a WHERE query. - * - * @author Gethin James - */ -public abstract class QueryHelper -{ - /** - * An interface used when walking a query tree. Calls are made to methods when the particular clause is encountered. - */ - public static interface WalkerCallback - { - /** - * Called any time an EXISTS clause is encountered. - * @param propertyName Name of the property - * @param negated returns true if "NOT EXISTS" was used - */ - void exists(String propertyName, boolean negated); - - /** - * Called any time a BETWEEN clause is encountered. - * @param propertyName Name of the property - * @param firstValue String - * @param secondValue String - * @param negated returns true if "NOT BETWEEN" was used - */ - void between(String propertyName, String firstValue, String secondValue, boolean negated); - - /** - * One of EQUALS LESSTHAN GREATERTHAN LESSTHANOREQUALS GREATERTHANOREQUALS; - */ - void comparison(int type, String propertyName, String propertyValue); - - /** - * Called any time an IN clause is encountered. - * @param property Name of the property - * @param negated returns true if "NOT IN" was used - * @param propertyValues the property values - */ - void in(String property, boolean negated, String... propertyValues); - - - /** - * Called any time a MATCHES clause is encountered. - * @param property Name of the property - * @param propertyValue String - * @param negated returns true if "NOT MATCHES" was used - */ - void matches(String property, String propertyValue, boolean negated); - - /** - * Called any time an AND is encountered. - */ - void and(); - /** - * Called any time an OR is encountered. - */ - void or(); - } - - /** - * Default implementation. Override the methods you are interested in. If you don't - * override the methods then an InvalidQueryException will be thrown. - */ - private static final String UNSUPPORTED_TEXT = "Unsupported Predicate"; - private static final InvalidQueryException UNSUPPORTED = new InvalidQueryException(UNSUPPORTED_TEXT); - - public static class WalkerCallbackAdapter implements WalkerCallback - { - @Override - public void exists(String propertyName, boolean negated) { throw UNSUPPORTED;} - @Override - public void between(String propertyName, String firstValue, String secondValue, boolean negated) { throw UNSUPPORTED;} - @Override - public void comparison(int type, String propertyName, String propertyValue) { throw UNSUPPORTED;} - @Override - public void in(String propertyName, boolean negated, String... propertyValues) { throw UNSUPPORTED;} - @Override - public void matches(String property, String value, boolean negated) { throw UNSUPPORTED;} - @Override - public void and() {throw UNSUPPORTED;} - @Override - public void or() {throw UNSUPPORTED;} - } - - /** - * Walks a query with a callback for each operation - * @param query the query - * @param callback a callback - */ - public static void walk(Query query, WalkerCallback callback) - { - - CommonTree tree = query.getTree(); - if (tree != null) - { - LinkedList stack = new LinkedList(); - stack.push(tree); - callbackTree(tree, callback, false); - } - } - - /** - * Processes a tree type and calls the corresponding callback method. - * @param tree Tree - * @param callback WalkerCallback - * @param negated boolean - */ - protected static void callbackTree(Tree tree, WalkerCallback callback, boolean negated) - { - if (tree != null) - { - switch (tree.getType()) { - case WhereClauseParser.EXISTS: - if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) - { - callback.exists(tree.getChild(0).getText(), negated); - return; - } - break; - case WhereClauseParser.MATCHES: - if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) - { - callback.matches(tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText()), negated); - return; - } - break; - case WhereClauseParser.IN: - if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) - { - List children = getChildren(tree); - //Don't need the first item because its the property name - String[] inVals = new String[children.size()-1]; - for (int i = 1; i < children.size(); i++) { - inVals[i-1] = stripQuotes(children.get(i).getText()); - } - callback.in(tree.getChild(0).getText(), negated, inVals); - return; - } - break; - case WhereClauseParser.BETWEEN: - if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) - { - callback.between(tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText()), stripQuotes(tree.getChild(2).getText()), negated); - return; - } - break; - case WhereClauseParser.EQUALS: //fall through (comparison) - case WhereClauseParser.LESSTHAN: //fall through (comparison) - case WhereClauseParser.GREATERTHAN: //fall through (comparison) - case WhereClauseParser.LESSTHANOREQUALS: //fall through (comparison) - case WhereClauseParser.GREATERTHANOREQUALS: - if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType() && - WhereClauseParser.PROPERTYVALUE == tree.getChild(1).getType()) - { - callback.comparison(tree.getType(), tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText())); - return; - } - break; - case WhereClauseParser.NEGATION: - //Negate the next element - callbackTree(tree.getChild(0), callback, true); - return; - case WhereClauseParser.OR: - callback.or(); - List children = getChildren(tree); - for (Tree child : children) { - callbackTree(child, callback, negated); - } - return; - case WhereClauseParser.AND: - callback.and(); - List childrenOfAnd = getChildren(tree); - for (Tree child : childrenOfAnd) { - callbackTree(child, callback, negated); - } - return; - default: - } - callbackTree(tree.getChild(0), callback, negated); //Callback on the next node - } - } - - /** - * Finds the siblings of the current tree item (does not include the current item) - * that are after it in the tree (but at the same level). - * @param tree the current tree - * @return siblings - all the elements at the same level in the tree - */ -// public static List getYoungerSiblings(Tree tree) -// { -// Tree parent = tree.getParent(); -// -// if (parent!=null && parent.getChildCount() > 0) -// { -// List sibs = new ArrayList(parent.getChildCount()-1); -// boolean laterChildren = false; -// for (int i = 0; i < parent.getChildCount(); i++) { -// Tree child = parent.getChild(i); -// if (tree.equals(child)) -// { -// laterChildren = true; -// } -// else -// { -// if (laterChildren) sibs.add(child); -// } -// } -// return sibs; -// } -// -// -// } - - /** - * Gets the children as a List - * @param tree Tree - * @return either emptyList or the children. - */ - public static List getChildren(Tree tree) - { - if (tree!=null && tree.getChildCount() > 0) - { - List children = new ArrayList(tree.getChildCount()); - for (int i = 0; i < tree.getChildCount(); i++) { - Tree child = tree.getChild(i); - children.add(child); - } - return children; - } - - //Default - return Collections.emptyList(); - } - - private static final String SINGLE_QUOTE = "'"; - - /** - * Strips off any leading or trailing single quotes. - * @param toBeStripped String - * @return the String that has been stripped - */ - public static String stripQuotes(String toBeStripped) - { - if (StringUtils.isNotEmpty(toBeStripped) && toBeStripped.startsWith(SINGLE_QUOTE) && toBeStripped.endsWith(SINGLE_QUOTE)) - { - return toBeStripped.substring(1,toBeStripped.length()-1); - } - return toBeStripped; //default to return the String unchanged. - } -} +package org.alfresco.rest.framework.resource.parameters.where; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.rest.antlr.WhereClauseParser; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; +import org.apache.commons.lang.StringUtils; + +/** + * Provides helper methods for handling a WHERE query. + * + * @author Gethin James + */ +public abstract class QueryHelper +{ + /** + * An interface used when walking a query tree. Calls are made to methods when the particular clause is encountered. + */ + public static interface WalkerCallback + { + /** + * Called any time an EXISTS clause is encountered. + * @param propertyName Name of the property + * @param negated returns true if "NOT EXISTS" was used + */ + void exists(String propertyName, boolean negated); + + /** + * Called any time a BETWEEN clause is encountered. + * @param propertyName Name of the property + * @param firstValue String + * @param secondValue String + * @param negated returns true if "NOT BETWEEN" was used + */ + void between(String propertyName, String firstValue, String secondValue, boolean negated); + + /** + * One of EQUALS LESSTHAN GREATERTHAN LESSTHANOREQUALS GREATERTHANOREQUALS; + */ + void comparison(int type, String propertyName, String propertyValue); + + /** + * Called any time an IN clause is encountered. + * @param property Name of the property + * @param negated returns true if "NOT IN" was used + * @param propertyValues the property values + */ + void in(String property, boolean negated, String... propertyValues); + + + /** + * Called any time a MATCHES clause is encountered. + * @param property Name of the property + * @param propertyValue String + * @param negated returns true if "NOT MATCHES" was used + */ + void matches(String property, String propertyValue, boolean negated); + + /** + * Called any time an AND is encountered. + */ + void and(); + /** + * Called any time an OR is encountered. + */ + void or(); + } + + /** + * Default implementation. Override the methods you are interested in. If you don't + * override the methods then an InvalidQueryException will be thrown. + */ + private static final String UNSUPPORTED_TEXT = "Unsupported Predicate"; + private static final InvalidQueryException UNSUPPORTED = new InvalidQueryException(UNSUPPORTED_TEXT); + + public static class WalkerCallbackAdapter implements WalkerCallback + { + @Override + public void exists(String propertyName, boolean negated) { throw UNSUPPORTED;} + @Override + public void between(String propertyName, String firstValue, String secondValue, boolean negated) { throw UNSUPPORTED;} + @Override + public void comparison(int type, String propertyName, String propertyValue) { throw UNSUPPORTED;} + @Override + public void in(String propertyName, boolean negated, String... propertyValues) { throw UNSUPPORTED;} + @Override + public void matches(String property, String value, boolean negated) { throw UNSUPPORTED;} + @Override + public void and() {throw UNSUPPORTED;} + @Override + public void or() {throw UNSUPPORTED;} + } + + /** + * Walks a query with a callback for each operation + * @param query the query + * @param callback a callback + */ + public static void walk(Query query, WalkerCallback callback) + { + + CommonTree tree = query.getTree(); + if (tree != null) + { + LinkedList stack = new LinkedList(); + stack.push(tree); + callbackTree(tree, callback, false); + } + } + + /** + * Processes a tree type and calls the corresponding callback method. + * @param tree Tree + * @param callback WalkerCallback + * @param negated boolean + */ + protected static void callbackTree(Tree tree, WalkerCallback callback, boolean negated) + { + if (tree != null) + { + switch (tree.getType()) { + case WhereClauseParser.EXISTS: + if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) + { + callback.exists(tree.getChild(0).getText(), negated); + return; + } + break; + case WhereClauseParser.MATCHES: + if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) + { + callback.matches(tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText()), negated); + return; + } + break; + case WhereClauseParser.IN: + if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) + { + List children = getChildren(tree); + //Don't need the first item because its the property name + String[] inVals = new String[children.size()-1]; + for (int i = 1; i < children.size(); i++) { + inVals[i-1] = stripQuotes(children.get(i).getText()); + } + callback.in(tree.getChild(0).getText(), negated, inVals); + return; + } + break; + case WhereClauseParser.BETWEEN: + if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType()) + { + callback.between(tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText()), stripQuotes(tree.getChild(2).getText()), negated); + return; + } + break; + case WhereClauseParser.EQUALS: //fall through (comparison) + case WhereClauseParser.LESSTHAN: //fall through (comparison) + case WhereClauseParser.GREATERTHAN: //fall through (comparison) + case WhereClauseParser.LESSTHANOREQUALS: //fall through (comparison) + case WhereClauseParser.GREATERTHANOREQUALS: + if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType() && + WhereClauseParser.PROPERTYVALUE == tree.getChild(1).getType()) + { + callback.comparison(tree.getType(), tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText())); + return; + } + break; + case WhereClauseParser.NEGATION: + //Negate the next element + callbackTree(tree.getChild(0), callback, true); + return; + case WhereClauseParser.OR: + callback.or(); + List children = getChildren(tree); + for (Tree child : children) { + callbackTree(child, callback, negated); + } + return; + case WhereClauseParser.AND: + callback.and(); + List childrenOfAnd = getChildren(tree); + for (Tree child : childrenOfAnd) { + callbackTree(child, callback, negated); + } + return; + default: + } + callbackTree(tree.getChild(0), callback, negated); //Callback on the next node + } + } + + /** + * Finds the siblings of the current tree item (does not include the current item) + * that are after it in the tree (but at the same level). + * @param tree the current tree + * @return siblings - all the elements at the same level in the tree + */ +// public static List getYoungerSiblings(Tree tree) +// { +// Tree parent = tree.getParent(); +// +// if (parent!=null && parent.getChildCount() > 0) +// { +// List sibs = new ArrayList(parent.getChildCount()-1); +// boolean laterChildren = false; +// for (int i = 0; i < parent.getChildCount(); i++) { +// Tree child = parent.getChild(i); +// if (tree.equals(child)) +// { +// laterChildren = true; +// } +// else +// { +// if (laterChildren) sibs.add(child); +// } +// } +// return sibs; +// } +// +// +// } + + /** + * Gets the children as a List + * @param tree Tree + * @return either emptyList or the children. + */ + public static List getChildren(Tree tree) + { + if (tree!=null && tree.getChildCount() > 0) + { + List children = new ArrayList(tree.getChildCount()); + for (int i = 0; i < tree.getChildCount(); i++) { + Tree child = tree.getChild(i); + children.add(child); + } + return children; + } + + //Default + return Collections.emptyList(); + } + + private static final String SINGLE_QUOTE = "'"; + + /** + * Strips off any leading or trailing single quotes. + * @param toBeStripped String + * @return the String that has been stripped + */ + public static String stripQuotes(String toBeStripped) + { + if (StringUtils.isNotEmpty(toBeStripped) && toBeStripped.startsWith(SINGLE_QUOTE) && toBeStripped.endsWith(SINGLE_QUOTE)) + { + return toBeStripped.substring(1,toBeStripped.length()-1); + } + return toBeStripped; //default to return the String unchanged. + } +} diff --git a/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryImpl.java b/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryImpl.java index a4fee0a0bc..7d0f5779a3 100644 --- a/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryImpl.java +++ b/source/java/org/alfresco/rest/framework/resource/parameters/where/QueryImpl.java @@ -1,35 +1,35 @@ -package org.alfresco.rest.framework.resource.parameters.where; - -import org.antlr.runtime.tree.CommonTree; - -/** - * Represents a Query defined by a WHERE clause, passed in as a parameter in a GET call to the Rest api. - * @author Gethin James - */ -public class QueryImpl implements Query -{ - public static final Query EMPTY = new QueryImpl(); - private final CommonTree tree; - - private QueryImpl() - { - super(); - this.tree = null; - } - - public QueryImpl(CommonTree tree) { - super(); - this.tree = tree; - } - - @Override - public CommonTree getTree() { - return tree; - } - - @Override - public String toString() { - return "QueryImpl [tree=" + tree + "]"; - } - -} +package org.alfresco.rest.framework.resource.parameters.where; + +import org.antlr.runtime.tree.CommonTree; + +/** + * Represents a Query defined by a WHERE clause, passed in as a parameter in a GET call to the Rest api. + * @author Gethin James + */ +public class QueryImpl implements Query +{ + public static final Query EMPTY = new QueryImpl(); + private final CommonTree tree; + + private QueryImpl() + { + super(); + this.tree = null; + } + + public QueryImpl(CommonTree tree) { + super(); + this.tree = tree; + } + + @Override + public CommonTree getTree() { + return tree; + } + + @Override + public String toString() { + return "QueryImpl [tree=" + tree + "]"; + } + +} diff --git a/source/java/org/alfresco/web/app/servlet/HTTPProxy.java b/source/java/org/alfresco/web/app/servlet/HTTPProxy.java index 30121f6ce8..8e3d8fc135 100644 --- a/source/java/org/alfresco/web/app/servlet/HTTPProxy.java +++ b/source/java/org/alfresco/web/app/servlet/HTTPProxy.java @@ -1,130 +1,130 @@ -package org.alfresco.web.app.servlet; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; - -import javax.servlet.http.HttpServletResponse; - - -/** - * Simple server-side HTTP Request / Response - * - * @author davidc - */ -public class HTTPProxy -{ - protected URL url; - protected HttpServletResponse response; - - - /** - * Construct - * - * @param requestUrl url to request - * @param response response to write request back to - * @throws MalformedURLException - */ - public HTTPProxy(String requestUrl, HttpServletResponse response) - throws MalformedURLException - { - this.url = new URL(requestUrl); - this.response = response; - } - - /** - * Perform request - * - * @throws IOException - */ - public void service() - throws IOException - { - HttpURLConnection connection = (HttpURLConnection)url.openConnection(); - setRequestHeaders(connection); - initialiseResponse(connection); - InputStream input = connection.getInputStream(); - OutputStream output = response.getOutputStream(); - try - { - writeResponse(input, output); - } - finally - { - try - { - if (input != null) - { - input.close(); - } - if (output != null) - { - output.flush(); - output.close(); - } - // TODO: required? - connection.disconnect(); - } - catch(IOException e) - { - // TODO: log io exceptions? - } - } - } - - /** - * Initialise response - * - * @param urlConnection url connection - */ - protected void initialiseResponse(URLConnection urlConnection) - { - String type = urlConnection.getContentType(); - if (type != null) - { - int encodingIdx = type.lastIndexOf("charset="); - if (encodingIdx == -1) - { - String encoding = urlConnection.getContentEncoding(); - if (encoding != null && encoding.length() > 0) - { - type += ";charset=" + encoding; - } - } - - response.setContentType(type); - } - } - - /** - * Set request headers - * - * @param urlConnection url connection - */ - protected void setRequestHeaders(URLConnection urlConnection) - { - } - - /** - * Write response - * - * @param input input stream of request - * @param output output stream of response - * @throws IOException - */ - protected void writeResponse(InputStream input, OutputStream output) - throws IOException - { - byte[] buffer = new byte[4096]; - int read = input.read(buffer); - while (read != -1) - { - output.write(buffer, 0, read); - read = input.read(buffer); - } - } -} +package org.alfresco.web.app.servlet; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + +import javax.servlet.http.HttpServletResponse; + + +/** + * Simple server-side HTTP Request / Response + * + * @author davidc + */ +public class HTTPProxy +{ + protected URL url; + protected HttpServletResponse response; + + + /** + * Construct + * + * @param requestUrl url to request + * @param response response to write request back to + * @throws MalformedURLException + */ + public HTTPProxy(String requestUrl, HttpServletResponse response) + throws MalformedURLException + { + this.url = new URL(requestUrl); + this.response = response; + } + + /** + * Perform request + * + * @throws IOException + */ + public void service() + throws IOException + { + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + setRequestHeaders(connection); + initialiseResponse(connection); + InputStream input = connection.getInputStream(); + OutputStream output = response.getOutputStream(); + try + { + writeResponse(input, output); + } + finally + { + try + { + if (input != null) + { + input.close(); + } + if (output != null) + { + output.flush(); + output.close(); + } + // TODO: required? + connection.disconnect(); + } + catch(IOException e) + { + // TODO: log io exceptions? + } + } + } + + /** + * Initialise response + * + * @param urlConnection url connection + */ + protected void initialiseResponse(URLConnection urlConnection) + { + String type = urlConnection.getContentType(); + if (type != null) + { + int encodingIdx = type.lastIndexOf("charset="); + if (encodingIdx == -1) + { + String encoding = urlConnection.getContentEncoding(); + if (encoding != null && encoding.length() > 0) + { + type += ";charset=" + encoding; + } + } + + response.setContentType(type); + } + } + + /** + * Set request headers + * + * @param urlConnection url connection + */ + protected void setRequestHeaders(URLConnection urlConnection) + { + } + + /** + * Write response + * + * @param input input stream of request + * @param output output stream of response + * @throws IOException + */ + protected void writeResponse(InputStream input, OutputStream output) + throws IOException + { + byte[] buffer = new byte[4096]; + int read = input.read(buffer); + while (read != -1) + { + output.write(buffer, 0, read); + read = input.read(buffer); + } + } +} diff --git a/source/java/org/alfresco/web/app/servlet/HTTPProxyServlet.java b/source/java/org/alfresco/web/app/servlet/HTTPProxyServlet.java index 8d9e7e41c9..5dbb68e6bf 100644 --- a/source/java/org/alfresco/web/app/servlet/HTTPProxyServlet.java +++ b/source/java/org/alfresco/web/app/servlet/HTTPProxyServlet.java @@ -1,110 +1,110 @@ -package org.alfresco.web.app.servlet; - -import java.io.IOException; -import java.util.Map; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.extensions.surf.util.URLEncoder; - - -/** - * HTTP Proxy Servlet - * - * Provides the ability to submit a URL request via the Alfresco Server i.e. - * the Alfresco server acts as a proxy. - * - * This servlet accepts: - * - * /proxy?endpoint=[&=]* - * - * Where: - * - * - endpointUrl is the URL to make a request against - * - argName is the name of a URL argument to append to the request - * - argValue is the value of URL argument - * - * E.g.: - * - * /proxy?endpoint=http://www.alfresco.com&arg1=value1&arg2=value2 - * - * @author davidc - */ -public class HTTPProxyServlet extends HttpServlet -{ - private static final long serialVersionUID = -576405943603122206L; - - private static final String PARAM_ENDPOINT = "endpoint"; - - - /** - * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - protected void doGet(HttpServletRequest req, HttpServletResponse res) - throws ServletException, IOException - { - String endpoint = null; - StringBuilder args = new StringBuilder(32); - - Map parameters = req.getParameterMap(); - for (Map.Entry parameter : parameters.entrySet()) - { - String[] values = parameter.getValue(); - int startIdx = 0; - - if (parameter.getKey().equals(PARAM_ENDPOINT) && values.length != 0) - { - endpoint = values[0]; - startIdx++; - } - - for (int i = startIdx; i < values.length; i++) - { - if (args.length() != 0) - { - args.append("&"); - } - args.append(parameter.getKey()).append('=').append(URLEncoder.encode(values[i])); - } - } - - if (endpoint == null || endpoint.length() == 0) - { - throw new IllegalArgumentException("endpoint argument not specified"); - } - - String url = endpoint + ((args.length() == 0) ? "" : "?" + args.toString()); - HTTPProxy proxy = new HTTPProxy(url, res); - proxy.service(); - } - - /** - * Construct a "proxied" URL - * - * Note: the "proxied" URL is a relative url - it is assumed that the servlet path is /proxy - * - * @param url the URL to proxy - * @return the "proxied" url - */ - public static String createProxyUrl(String url) - { - String proxy = "/proxy"; - if (url != null && url.length() > 0) - { - int argIndex = url.lastIndexOf("?"); - if (argIndex == -1) - { - proxy += "?endpoint=" + url; - } - else - { - proxy += "?endpoint=" + url.substring(0, argIndex) + "&" + url.substring(argIndex + 1); - } - } - - return proxy; - } -} +package org.alfresco.web.app.servlet; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.extensions.surf.util.URLEncoder; + + +/** + * HTTP Proxy Servlet + * + * Provides the ability to submit a URL request via the Alfresco Server i.e. + * the Alfresco server acts as a proxy. + * + * This servlet accepts: + * + * /proxy?endpoint=[&=]* + * + * Where: + * + * - endpointUrl is the URL to make a request against + * - argName is the name of a URL argument to append to the request + * - argValue is the value of URL argument + * + * E.g.: + * + * /proxy?endpoint=http://www.alfresco.com&arg1=value1&arg2=value2 + * + * @author davidc + */ +public class HTTPProxyServlet extends HttpServlet +{ + private static final long serialVersionUID = -576405943603122206L; + + private static final String PARAM_ENDPOINT = "endpoint"; + + + /** + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + protected void doGet(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException + { + String endpoint = null; + StringBuilder args = new StringBuilder(32); + + Map parameters = req.getParameterMap(); + for (Map.Entry parameter : parameters.entrySet()) + { + String[] values = parameter.getValue(); + int startIdx = 0; + + if (parameter.getKey().equals(PARAM_ENDPOINT) && values.length != 0) + { + endpoint = values[0]; + startIdx++; + } + + for (int i = startIdx; i < values.length; i++) + { + if (args.length() != 0) + { + args.append("&"); + } + args.append(parameter.getKey()).append('=').append(URLEncoder.encode(values[i])); + } + } + + if (endpoint == null || endpoint.length() == 0) + { + throw new IllegalArgumentException("endpoint argument not specified"); + } + + String url = endpoint + ((args.length() == 0) ? "" : "?" + args.toString()); + HTTPProxy proxy = new HTTPProxy(url, res); + proxy.service(); + } + + /** + * Construct a "proxied" URL + * + * Note: the "proxied" URL is a relative url - it is assumed that the servlet path is /proxy + * + * @param url the URL to proxy + * @return the "proxied" url + */ + public static String createProxyUrl(String url) + { + String proxy = "/proxy"; + if (url != null && url.length() > 0) + { + int argIndex = url.lastIndexOf("?"); + if (argIndex == -1) + { + proxy += "?endpoint=" + url; + } + else + { + proxy += "?endpoint=" + url.substring(0, argIndex) + "&" + url.substring(argIndex + 1); + } + } + + return proxy; + } +} diff --git a/source/java/org/alfresco/web/scripts/WebScriptUtils.java b/source/java/org/alfresco/web/scripts/WebScriptUtils.java index 76270cafbb..6b99fb3faa 100644 --- a/source/java/org/alfresco/web/scripts/WebScriptUtils.java +++ b/source/java/org/alfresco/web/scripts/WebScriptUtils.java @@ -1,107 +1,107 @@ -package org.alfresco.web.scripts; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.alfresco.repo.jscript.ScriptUtils; -import org.alfresco.repo.web.scripts.RepositoryContainer; -import org.alfresco.service.cmr.admin.RepoUsage; -import org.alfresco.service.cmr.repository.StoreRef; -import org.springframework.extensions.webscripts.WebScript; - -/** - * Override of the JavaScript API ScriptUtils bean "utilsScript" to provide additional - * Remote API methods using objects not available to base Repository project. - *

- * See "web-scripts-application-context.xml" for bean definition. - * - * @since 4.2.0 - * @since 5.1 (Moved to Remote API project) - * @author Kevin Roast - */ -public class WebScriptUtils extends ScriptUtils -{ - protected RepositoryContainer repositoryContainer; - - public void setRepositoryContainer(RepositoryContainer repositoryContainer) - { - this.repositoryContainer = repositoryContainer; - } - - /** - * Searches for webscript components with the given family name. - * - * @param family the family - * - * @return An array of webscripts that match the given family name - */ - public Object[] findWebScripts(String family) - { - List values = new ArrayList(); - - for (WebScript webscript : this.repositoryContainer.getRegistry().getWebScripts()) - { - if (family != null) - { - Set familys = webscript.getDescription().getFamilys(); - if (familys != null && familys.contains(family)) - { - values.add(webscript.getDescription()); - } - } - else - { - values.add(webscript.getDescription()); - } - } - - return values.toArray(new Object[values.size()]); - } - - public String getHostAddress() - { - try - { - return InetAddress.getLocalHost().getHostAddress(); - } - catch (UnknownHostException e) - { - return "Unknown"; - } - } - - public String getHostName() - { - try - { - return InetAddress.getLocalHost().getHostName(); - } - catch (UnknownHostException e) - { - return "Unknown"; - } - } - - public RepoUsage getRestrictions() - { - return this.services.getRepoAdminService().getRestrictions(); - } - - public RepoUsage getUsage() - { - return this.services.getRepoAdminService().getUsage(); - } - - /** - * Gets the list of repository stores - * - * @return stores - */ - public List getStores() - { - return this.services.getNodeService().getStores(); - } -} +package org.alfresco.web.scripts; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.alfresco.repo.jscript.ScriptUtils; +import org.alfresco.repo.web.scripts.RepositoryContainer; +import org.alfresco.service.cmr.admin.RepoUsage; +import org.alfresco.service.cmr.repository.StoreRef; +import org.springframework.extensions.webscripts.WebScript; + +/** + * Override of the JavaScript API ScriptUtils bean "utilsScript" to provide additional + * Remote API methods using objects not available to base Repository project. + *

+ * See "web-scripts-application-context.xml" for bean definition. + * + * @since 4.2.0 + * @since 5.1 (Moved to Remote API project) + * @author Kevin Roast + */ +public class WebScriptUtils extends ScriptUtils +{ + protected RepositoryContainer repositoryContainer; + + public void setRepositoryContainer(RepositoryContainer repositoryContainer) + { + this.repositoryContainer = repositoryContainer; + } + + /** + * Searches for webscript components with the given family name. + * + * @param family the family + * + * @return An array of webscripts that match the given family name + */ + public Object[] findWebScripts(String family) + { + List values = new ArrayList(); + + for (WebScript webscript : this.repositoryContainer.getRegistry().getWebScripts()) + { + if (family != null) + { + Set familys = webscript.getDescription().getFamilys(); + if (familys != null && familys.contains(family)) + { + values.add(webscript.getDescription()); + } + } + else + { + values.add(webscript.getDescription()); + } + } + + return values.toArray(new Object[values.size()]); + } + + public String getHostAddress() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + return "Unknown"; + } + } + + public String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + return "Unknown"; + } + } + + public RepoUsage getRestrictions() + { + return this.services.getRepoAdminService().getRestrictions(); + } + + public RepoUsage getUsage() + { + return this.services.getRepoAdminService().getUsage(); + } + + /** + * Gets the list of repository stores + * + * @return stores + */ + public List getStores() + { + return this.services.getNodeService().getStores(); + } +} diff --git a/source/test-java/org/alfresco/opencmis/OpenCMISClientContext.java b/source/test-java/org/alfresco/opencmis/OpenCMISClientContext.java index 6ff0ca3aeb..0092a7ae86 100644 --- a/source/test-java/org/alfresco/opencmis/OpenCMISClientContext.java +++ b/source/test-java/org/alfresco/opencmis/OpenCMISClientContext.java @@ -1,77 +1,77 @@ -package org.alfresco.opencmis; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.apache.chemistry.opencmis.commons.SessionParameter; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; -import org.springframework.context.ApplicationContext; - -/** - * Encapsulates Chemistry OpenCMIS client connection details and creates a parameters file for running the - * TCK tests. - * - * @author steveglover - * - */ -public class OpenCMISClientContext -{ - private Map cmisParameters; - - public OpenCMISClientContext(BindingType bindingType, String url, String username, String password, Map parameters, ApplicationContext ctx) throws IOException - { - cmisParameters = new HashMap(); - cmisParameters.putAll(parameters); - cmisParameters.put(SessionParameter.BINDING_TYPE, bindingType.value()); - if(bindingType.equals(BindingType.ATOMPUB)) - { - cmisParameters.put(SessionParameter.ATOMPUB_URL, url); - } - else if(bindingType.equals(BindingType.BROWSER)) - { - cmisParameters.put(SessionParameter.BROWSER_URL, url); - } - cmisParameters.put(SessionParameter.USER, username); - cmisParameters.put(SessionParameter.PASSWORD, password); - - if (ctx != null) - { - Properties properties = (Properties)ctx.getBean("global-properties"); - cmisParameters.put(SessionParameter.CONNECT_TIMEOUT, properties.getProperty("opencmis.tck.connecttimeout")); - cmisParameters.put(SessionParameter.READ_TIMEOUT, properties.getProperty("opencmis.tck.readtimeout")); - } - createCMISParametersFile(); - } - - public OpenCMISClientContext(BindingType bindingType, String url, String username, String password, Map parameters) throws IOException - { - this(bindingType, url, username, password, parameters, null); - } - - protected void createCMISParametersFile() throws IOException - { - File f = File.createTempFile("OpenCMISTCKContext", "" + System.currentTimeMillis(), new File(System.getProperty("java.io.tmpdir"))); - f.deleteOnExit(); - FileWriter fw = new FileWriter(f); - for(String key : cmisParameters.keySet()) - { - fw.append(key); - fw.append("="); - fw.append(cmisParameters.get(key)); - fw.append("\n"); - } - fw.close(); - System.setProperty(JUnitHelper.JUNIT_PARAMETERS, f.getAbsolutePath()); - System.out.println("CMIS client parameters file: " + f.getAbsolutePath()); - } - - public Map getCMISParameters() - { - return cmisParameters; - } -} +package org.alfresco.opencmis; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.chemistry.opencmis.commons.SessionParameter; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; +import org.springframework.context.ApplicationContext; + +/** + * Encapsulates Chemistry OpenCMIS client connection details and creates a parameters file for running the + * TCK tests. + * + * @author steveglover + * + */ +public class OpenCMISClientContext +{ + private Map cmisParameters; + + public OpenCMISClientContext(BindingType bindingType, String url, String username, String password, Map parameters, ApplicationContext ctx) throws IOException + { + cmisParameters = new HashMap(); + cmisParameters.putAll(parameters); + cmisParameters.put(SessionParameter.BINDING_TYPE, bindingType.value()); + if(bindingType.equals(BindingType.ATOMPUB)) + { + cmisParameters.put(SessionParameter.ATOMPUB_URL, url); + } + else if(bindingType.equals(BindingType.BROWSER)) + { + cmisParameters.put(SessionParameter.BROWSER_URL, url); + } + cmisParameters.put(SessionParameter.USER, username); + cmisParameters.put(SessionParameter.PASSWORD, password); + + if (ctx != null) + { + Properties properties = (Properties)ctx.getBean("global-properties"); + cmisParameters.put(SessionParameter.CONNECT_TIMEOUT, properties.getProperty("opencmis.tck.connecttimeout")); + cmisParameters.put(SessionParameter.READ_TIMEOUT, properties.getProperty("opencmis.tck.readtimeout")); + } + createCMISParametersFile(); + } + + public OpenCMISClientContext(BindingType bindingType, String url, String username, String password, Map parameters) throws IOException + { + this(bindingType, url, username, password, parameters, null); + } + + protected void createCMISParametersFile() throws IOException + { + File f = File.createTempFile("OpenCMISTCKContext", "" + System.currentTimeMillis(), new File(System.getProperty("java.io.tmpdir"))); + f.deleteOnExit(); + FileWriter fw = new FileWriter(f); + for(String key : cmisParameters.keySet()) + { + fw.append(key); + fw.append("="); + fw.append(cmisParameters.get(key)); + fw.append("\n"); + } + fw.close(); + System.setProperty(JUnitHelper.JUNIT_PARAMETERS, f.getAbsolutePath()); + System.out.println("CMIS client parameters file: " + f.getAbsolutePath()); + } + + public Map getCMISParameters() + { + return cmisParameters; + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/LoginTest.java b/source/test-java/org/alfresco/repo/web/scripts/LoginTest.java index b30c0905fc..07eaba734e 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/LoginTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/LoginTest.java @@ -1,230 +1,230 @@ -package org.alfresco.repo.web.scripts; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.util.PropertyMap; -import org.json.JSONObject; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -/** - * Junit test for login / logout and validate web scripts - * - * testing uri /api/login - */ -public class LoginTest extends BaseWebScriptTest -{ - private MutableAuthenticationService authenticationService; - private AuthenticationComponent authenticationComponent; - private PersonService personService; - - private static final String USER_ONE = "AuthenticationTestOne"; - - protected void setUp() throws Exception - { - super.setUp(); - this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); - this.authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); - this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); - - this.authenticationComponent.setSystemUserAsCurrentUser(); - createUser(USER_ONE, USER_ONE); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - - private void createUser(String userName, String password) - { - if (this.authenticationService.authenticationExists(userName) == false) - { - this.authenticationService.createAuthentication(userName, password.toCharArray()); - - PropertyMap ppOne = new PropertyMap(4); - ppOne.put(ContentModel.PROP_USERNAME, userName); - ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); - ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); - ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); - ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); - - this.personService.createPerson(ppOne); - } - } - - private String parseTicket(String ticketResult) - { - int startTag = ticketResult.indexOf(""); - int endTag = ticketResult.indexOf(""); - if ((startTag != -1) && (endTag != -1)) - { - return ticketResult.substring(startTag+("".length()), endTag); - } - return ""; - } - - /** - * Positive test - login and retrieve a ticket via get - return xml, - * - via get method - * validate ticket - * logout - * fail to validate ticket - * fail to get ticket - */ - public void testAuthentication() throws Exception - { - /** - * Login via get method to return xml - */ - String loginURL = "/api/login?u=" + USER_ONE + "&pw=" + USER_ONE; - Response resp = sendRequest(new GetRequest(loginURL), Status.STATUS_OK); - String xmlFragment = resp.getContentAsString(); - - assertNotNull("xmlFragment"); - assertTrue("xmlFragment contains ticket", xmlFragment.contains("")); - String ticket = parseTicket(xmlFragment); - - String ticketURL = "/api/login/ticket/"+ticket; - - /** - * Negative test - validate as AuthenticationUtil.getAdminUserName() - should fail with a 404 - */ - setDefaultRunAs(AuthenticationUtil.getAdminUserName()); - sendRequest(new GetRequest(ticketURL), Status.STATUS_NOT_FOUND); - - /** - * Validate the ticket - should succeed - */ - setDefaultRunAs(USER_ONE); - - sendRequest(new GetRequest(ticketURL), Status.STATUS_OK); - - /** - * Logout - */ - sendRequest(new DeleteRequest(ticketURL), Status.STATUS_OK); - - /** - * Validate the ticket - should fail now - */ - sendRequest(new GetRequest(ticketURL), Status.STATUS_NOT_FOUND); - - } - - /** - * Positive test - login and retrieve a ticket, - * - via json method - */ - public void testAuthenticationGetJSON() throws Exception - { - /** - * Login via get method to return json - */ - String loginURL = "/api/login.json?u=" + USER_ONE + "&pw=" + USER_ONE ; - Response resp = sendRequest(new GetRequest(loginURL), Status.STATUS_OK); - JSONObject result = new JSONObject(resp.getContentAsString()); - JSONObject data = result.getJSONObject("data"); - String ticket = data.getString("ticket"); - assertNotNull("ticket is null", ticket); - - /** - * This is now testing the framework ... With a different format. - */ - String login2URL = "/api/login?u=" + USER_ONE + "&pw=" + USER_ONE + "&format=json"; - Response resp2 = sendRequest(new GetRequest(login2URL), Status.STATUS_OK); - JSONObject result2 = new JSONObject(resp2.getContentAsString()); - JSONObject data2 = result2.getJSONObject("data"); - String ticket2 = data2.getString("ticket"); - assertNotNull("ticket is null", ticket2); - - } - - /** - * Authenticate via a POST - * @throws Exception - */ - public void testPostLogin() throws Exception - { - String loginURL = "/api/login"; - /** - * logon via POST and JSON - */ - { - JSONObject req = new JSONObject(); - req.put("username", USER_ONE); - req.put("password", USER_ONE); - Response response = sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_OK); - - JSONObject result = new JSONObject(response.getContentAsString()); - JSONObject data = result.getJSONObject("data"); - String ticket = data.getString("ticket"); - assertNotNull("ticket null", ticket); - } - - /** - * Negative test - wrong password - */ - { - JSONObject req = new JSONObject(); - req.put("username", USER_ONE); - req.put("password", "blurb"); - sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_FORBIDDEN); - } - /** - * Negative test - missing username - */ - { - JSONObject req = new JSONObject(); - req.put("password", USER_ONE); - sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_BAD_REQUEST); - } - - /** - * Negative test - missing password - */ - { - JSONObject req = new JSONObject(); - req.put("username", USER_ONE); - sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_BAD_REQUEST); - } - } - - - /** - * Negative tests - wrong password - */ - public void testWrongPassword() throws Exception - { - /** - * Login via get method and wrong password, should get FORBIDDEN - */ - String loginURL = "/api/login?u=" + USER_ONE + "&pw=" + "crap"; - sendRequest(new GetRequest(loginURL), Status.STATUS_FORBIDDEN); - } - - /** - * Negative test - missing parameters - */ - public void testMissingParameters() throws Exception - { - /** - * Login via get method missing pw - */ - String loginURL = "/api/login?u=" + USER_ONE; - sendRequest(new GetRequest(loginURL), Status.STATUS_BAD_REQUEST); - - /** - * Login via get method missing u - */ - String login2URL = "/api/login?&pw=" + USER_ONE; - sendRequest(new GetRequest(login2URL), Status.STATUS_BAD_REQUEST); - - } -} +package org.alfresco.repo.web.scripts; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.util.PropertyMap; +import org.json.JSONObject; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +/** + * Junit test for login / logout and validate web scripts + * + * testing uri /api/login + */ +public class LoginTest extends BaseWebScriptTest +{ + private MutableAuthenticationService authenticationService; + private AuthenticationComponent authenticationComponent; + private PersonService personService; + + private static final String USER_ONE = "AuthenticationTestOne"; + + protected void setUp() throws Exception + { + super.setUp(); + this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); + this.authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); + this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); + + this.authenticationComponent.setSystemUserAsCurrentUser(); + createUser(USER_ONE, USER_ONE); + } + + protected void tearDown() throws Exception + { + super.tearDown(); + } + + private void createUser(String userName, String password) + { + if (this.authenticationService.authenticationExists(userName) == false) + { + this.authenticationService.createAuthentication(userName, password.toCharArray()); + + PropertyMap ppOne = new PropertyMap(4); + ppOne.put(ContentModel.PROP_USERNAME, userName); + ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); + ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); + ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); + ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + + this.personService.createPerson(ppOne); + } + } + + private String parseTicket(String ticketResult) + { + int startTag = ticketResult.indexOf(""); + int endTag = ticketResult.indexOf(""); + if ((startTag != -1) && (endTag != -1)) + { + return ticketResult.substring(startTag+("".length()), endTag); + } + return ""; + } + + /** + * Positive test - login and retrieve a ticket via get - return xml, + * - via get method + * validate ticket + * logout + * fail to validate ticket + * fail to get ticket + */ + public void testAuthentication() throws Exception + { + /** + * Login via get method to return xml + */ + String loginURL = "/api/login?u=" + USER_ONE + "&pw=" + USER_ONE; + Response resp = sendRequest(new GetRequest(loginURL), Status.STATUS_OK); + String xmlFragment = resp.getContentAsString(); + + assertNotNull("xmlFragment"); + assertTrue("xmlFragment contains ticket", xmlFragment.contains("")); + String ticket = parseTicket(xmlFragment); + + String ticketURL = "/api/login/ticket/"+ticket; + + /** + * Negative test - validate as AuthenticationUtil.getAdminUserName() - should fail with a 404 + */ + setDefaultRunAs(AuthenticationUtil.getAdminUserName()); + sendRequest(new GetRequest(ticketURL), Status.STATUS_NOT_FOUND); + + /** + * Validate the ticket - should succeed + */ + setDefaultRunAs(USER_ONE); + + sendRequest(new GetRequest(ticketURL), Status.STATUS_OK); + + /** + * Logout + */ + sendRequest(new DeleteRequest(ticketURL), Status.STATUS_OK); + + /** + * Validate the ticket - should fail now + */ + sendRequest(new GetRequest(ticketURL), Status.STATUS_NOT_FOUND); + + } + + /** + * Positive test - login and retrieve a ticket, + * - via json method + */ + public void testAuthenticationGetJSON() throws Exception + { + /** + * Login via get method to return json + */ + String loginURL = "/api/login.json?u=" + USER_ONE + "&pw=" + USER_ONE ; + Response resp = sendRequest(new GetRequest(loginURL), Status.STATUS_OK); + JSONObject result = new JSONObject(resp.getContentAsString()); + JSONObject data = result.getJSONObject("data"); + String ticket = data.getString("ticket"); + assertNotNull("ticket is null", ticket); + + /** + * This is now testing the framework ... With a different format. + */ + String login2URL = "/api/login?u=" + USER_ONE + "&pw=" + USER_ONE + "&format=json"; + Response resp2 = sendRequest(new GetRequest(login2URL), Status.STATUS_OK); + JSONObject result2 = new JSONObject(resp2.getContentAsString()); + JSONObject data2 = result2.getJSONObject("data"); + String ticket2 = data2.getString("ticket"); + assertNotNull("ticket is null", ticket2); + + } + + /** + * Authenticate via a POST + * @throws Exception + */ + public void testPostLogin() throws Exception + { + String loginURL = "/api/login"; + /** + * logon via POST and JSON + */ + { + JSONObject req = new JSONObject(); + req.put("username", USER_ONE); + req.put("password", USER_ONE); + Response response = sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_OK); + + JSONObject result = new JSONObject(response.getContentAsString()); + JSONObject data = result.getJSONObject("data"); + String ticket = data.getString("ticket"); + assertNotNull("ticket null", ticket); + } + + /** + * Negative test - wrong password + */ + { + JSONObject req = new JSONObject(); + req.put("username", USER_ONE); + req.put("password", "blurb"); + sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_FORBIDDEN); + } + /** + * Negative test - missing username + */ + { + JSONObject req = new JSONObject(); + req.put("password", USER_ONE); + sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_BAD_REQUEST); + } + + /** + * Negative test - missing password + */ + { + JSONObject req = new JSONObject(); + req.put("username", USER_ONE); + sendRequest(new PostRequest(loginURL, req.toString(), "application/json"), Status.STATUS_BAD_REQUEST); + } + } + + + /** + * Negative tests - wrong password + */ + public void testWrongPassword() throws Exception + { + /** + * Login via get method and wrong password, should get FORBIDDEN + */ + String loginURL = "/api/login?u=" + USER_ONE + "&pw=" + "crap"; + sendRequest(new GetRequest(loginURL), Status.STATUS_FORBIDDEN); + } + + /** + * Negative test - missing parameters + */ + public void testMissingParameters() throws Exception + { + /** + * Login via get method missing pw + */ + String loginURL = "/api/login?u=" + USER_ONE; + sendRequest(new GetRequest(loginURL), Status.STATUS_BAD_REQUEST); + + /** + * Login via get method missing u + */ + String login2URL = "/api/login?&pw=" + USER_ONE; + sendRequest(new GetRequest(login2URL), Status.STATUS_BAD_REQUEST); + + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/ReadOnlyTransactionInGetRestApiTest.java b/source/test-java/org/alfresco/repo/web/scripts/ReadOnlyTransactionInGetRestApiTest.java index e5c3093d08..e0a739a91d 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/ReadOnlyTransactionInGetRestApiTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/ReadOnlyTransactionInGetRestApiTest.java @@ -1,162 +1,162 @@ -package org.alfresco.repo.web.scripts; - -import java.util.List; - -import org.alfresco.repo.node.archive.NodeArchiveService; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.transaction.TransactionService; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -/** - * Set of tests that ensure GET REST APIs are run successfully in a read-only - * transaction (ALF-10179). - * - * Some webscripts have a side effect of creating a "container" these tests - * are to ensure this is handled gracefully in a way that allows the main - * transaction to be declared as readonly for performance reasons. - * - * @author Gavin Cornwell - * @since 4.0 - */ -public class ReadOnlyTransactionInGetRestApiTest extends BaseWebScriptTest -{ - private static final String TEST_SITE_NAME = "readOnlyTestSite"; - - private static final String URL_GET_SITE_BLOG = "/api/blog/site/" + TEST_SITE_NAME + "/blog"; - private static final String URL_GET_SITE_FORUM_POSTS = "/api/forum/site/" + TEST_SITE_NAME + "/discussions/posts"; - private static final String URL_GET_SITE_LINKS = "/api/links/site/" + TEST_SITE_NAME + "/links?page=1&pageSize=10"; - private static final String URL_GET_SITE_LINK = "/api/links/link/site/" + TEST_SITE_NAME + "/links/123456789"; - private static final String URL_GET_SITE_TAGS = "/api/tagscopes/site/" + TEST_SITE_NAME + "/tags"; - - private SiteService siteService; - private NodeService nodeService; - private TransactionService transactionService; - private NodeArchiveService nodeArchiveService; - - private NodeRef testSiteNodeRef; - private String testSiteNodeRefString; - - private boolean logEnabled = false; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - ApplicationContext appContext = getServer().getApplicationContext(); - - this.siteService = (SiteService)appContext.getBean("SiteService"); - this.nodeService = (NodeService)appContext.getBean("NodeService"); - this.transactionService = (TransactionService)appContext.getBean("TransactionService"); - this.nodeArchiveService = (NodeArchiveService)getServer().getApplicationContext().getBean("nodeArchiveService"); - - // set admin as current user - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - // delete the test site if it's still hanging around from previous runs - SiteInfo site = siteService.getSite(TEST_SITE_NAME); - if (site != null) - { - siteService.deleteSite(TEST_SITE_NAME); - nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(site.getNodeRef())); - } - - // create the test site, this should create a site but it won't have any containers created - SiteInfo siteInfo = this.siteService.createSite("collaboration", TEST_SITE_NAME, "Read Only Test Site", - "Test site for ReadOnlyTransactionRestApiTest", SiteVisibility.PUBLIC); - this.testSiteNodeRef = siteInfo.getNodeRef(); - this.testSiteNodeRefString = this.testSiteNodeRef.toString().replace("://", "/"); - - // ensure there are no containers present at the start of the test - List children = nodeService.getChildAssocs(this.testSiteNodeRef); - assertTrue("The test site should not have any containers", children.isEmpty()); - } - - /* (non-Javadoc) - * @see junit.framework.TestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - - SiteInfo site = siteService.getSite(TEST_SITE_NAME); - // use retrying transaction to delete the site - this.transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - // delete the test site - siteService.deleteSite(TEST_SITE_NAME); - - return null; - } - }); - nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(site.getNodeRef())); - - AuthenticationUtil.clearCurrentSecurityContext(); - } - - public void testGetSiteBlog() throws Exception - { - // TODO: Fixme - This REST API still requires a readwrite transaction to be successful - // Also add tests for all other blog GET REST APIs - - Response response = sendRequest(new GetRequest(URL_GET_SITE_BLOG), 200); - logResponse(response); - assertEquals(Status.STATUS_OK, response.getStatus()); - } - - public void testGetSiteForumPosts() throws Exception - { - Response response = sendRequest(new GetRequest(URL_GET_SITE_FORUM_POSTS), 200); - logResponse(response); - assertEquals(Status.STATUS_OK, response.getStatus()); - } - - public void testGetSiteLinks() throws Exception - { - Response response = sendRequest(new GetRequest(URL_GET_SITE_LINKS), 200); - logResponse(response); - assertEquals(Status.STATUS_OK, response.getStatus()); - } - - public void testGetSiteLink() throws Exception - { - Response response = sendRequest(new GetRequest(URL_GET_SITE_LINK), 404); - logResponse(response); - assertEquals(Status.STATUS_NOT_FOUND, response.getStatus()); - } - - public void testGetSiteTags() throws Exception - { - Response response = sendRequest(new GetRequest(URL_GET_SITE_TAGS), 200); - logResponse(response); - assertEquals(Status.STATUS_OK, response.getStatus()); - } - - private void logResponse(Response response) - { - if (this.logEnabled) - { - try - { - System.out.println(response.getContentAsString()); - } - catch (Exception e) - { - System.err.println("Unable to log response: " + e.toString()); - } - } - } -} +package org.alfresco.repo.web.scripts; + +import java.util.List; + +import org.alfresco.repo.node.archive.NodeArchiveService; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.transaction.TransactionService; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +/** + * Set of tests that ensure GET REST APIs are run successfully in a read-only + * transaction (ALF-10179). + * + * Some webscripts have a side effect of creating a "container" these tests + * are to ensure this is handled gracefully in a way that allows the main + * transaction to be declared as readonly for performance reasons. + * + * @author Gavin Cornwell + * @since 4.0 + */ +public class ReadOnlyTransactionInGetRestApiTest extends BaseWebScriptTest +{ + private static final String TEST_SITE_NAME = "readOnlyTestSite"; + + private static final String URL_GET_SITE_BLOG = "/api/blog/site/" + TEST_SITE_NAME + "/blog"; + private static final String URL_GET_SITE_FORUM_POSTS = "/api/forum/site/" + TEST_SITE_NAME + "/discussions/posts"; + private static final String URL_GET_SITE_LINKS = "/api/links/site/" + TEST_SITE_NAME + "/links?page=1&pageSize=10"; + private static final String URL_GET_SITE_LINK = "/api/links/link/site/" + TEST_SITE_NAME + "/links/123456789"; + private static final String URL_GET_SITE_TAGS = "/api/tagscopes/site/" + TEST_SITE_NAME + "/tags"; + + private SiteService siteService; + private NodeService nodeService; + private TransactionService transactionService; + private NodeArchiveService nodeArchiveService; + + private NodeRef testSiteNodeRef; + private String testSiteNodeRefString; + + private boolean logEnabled = false; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ApplicationContext appContext = getServer().getApplicationContext(); + + this.siteService = (SiteService)appContext.getBean("SiteService"); + this.nodeService = (NodeService)appContext.getBean("NodeService"); + this.transactionService = (TransactionService)appContext.getBean("TransactionService"); + this.nodeArchiveService = (NodeArchiveService)getServer().getApplicationContext().getBean("nodeArchiveService"); + + // set admin as current user + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + // delete the test site if it's still hanging around from previous runs + SiteInfo site = siteService.getSite(TEST_SITE_NAME); + if (site != null) + { + siteService.deleteSite(TEST_SITE_NAME); + nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(site.getNodeRef())); + } + + // create the test site, this should create a site but it won't have any containers created + SiteInfo siteInfo = this.siteService.createSite("collaboration", TEST_SITE_NAME, "Read Only Test Site", + "Test site for ReadOnlyTransactionRestApiTest", SiteVisibility.PUBLIC); + this.testSiteNodeRef = siteInfo.getNodeRef(); + this.testSiteNodeRefString = this.testSiteNodeRef.toString().replace("://", "/"); + + // ensure there are no containers present at the start of the test + List children = nodeService.getChildAssocs(this.testSiteNodeRef); + assertTrue("The test site should not have any containers", children.isEmpty()); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#tearDown() + */ + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + + SiteInfo site = siteService.getSite(TEST_SITE_NAME); + // use retrying transaction to delete the site + this.transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // delete the test site + siteService.deleteSite(TEST_SITE_NAME); + + return null; + } + }); + nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(site.getNodeRef())); + + AuthenticationUtil.clearCurrentSecurityContext(); + } + + public void testGetSiteBlog() throws Exception + { + // TODO: Fixme - This REST API still requires a readwrite transaction to be successful + // Also add tests for all other blog GET REST APIs + + Response response = sendRequest(new GetRequest(URL_GET_SITE_BLOG), 200); + logResponse(response); + assertEquals(Status.STATUS_OK, response.getStatus()); + } + + public void testGetSiteForumPosts() throws Exception + { + Response response = sendRequest(new GetRequest(URL_GET_SITE_FORUM_POSTS), 200); + logResponse(response); + assertEquals(Status.STATUS_OK, response.getStatus()); + } + + public void testGetSiteLinks() throws Exception + { + Response response = sendRequest(new GetRequest(URL_GET_SITE_LINKS), 200); + logResponse(response); + assertEquals(Status.STATUS_OK, response.getStatus()); + } + + public void testGetSiteLink() throws Exception + { + Response response = sendRequest(new GetRequest(URL_GET_SITE_LINK), 404); + logResponse(response); + assertEquals(Status.STATUS_NOT_FOUND, response.getStatus()); + } + + public void testGetSiteTags() throws Exception + { + Response response = sendRequest(new GetRequest(URL_GET_SITE_TAGS), 200); + logResponse(response); + assertEquals(Status.STATUS_OK, response.getStatus()); + } + + private void logResponse(Response response) + { + if (this.logEnabled) + { + try + { + System.out.println(response.getContentAsString()); + } + catch (Exception e) + { + System.err.println("Unable to log response: " + e.toString()); + } + } + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java b/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java index 5dbd1a0d45..a15b3b63b7 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java @@ -1,557 +1,557 @@ -package org.alfresco.repo.web.scripts.comment; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.Date; -import java.util.List; - -import javax.transaction.UserTransaction; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.node.archive.NodeArchiveService; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.permissions.PermissionReference; -import org.alfresco.repo.security.permissions.PermissionServiceSPI; -import org.alfresco.repo.security.permissions.impl.ModelDAO; -import org.alfresco.repo.security.permissions.impl.SimplePermissionEntry; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.PropertyMap; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; -import org.springframework.extensions.webscripts.WebScriptException; - -/** - * TODO: Fix the loose transaction handling. - */ -public class CommentsApiTest extends BaseWebScriptTest -{ - private static final String URL_POST_COMMENT = "api/node/{0}/{1}/{2}/comments"; - private static final String URL_DELETE_COMMENT = "api/comment/node/{0}/{1}/{2}?site={3}&itemtitle={4}&page={5}&pageParams={6}"; - private static final String JSON = "application/json"; - private static final String SITE_SHORT_NAME = "SomeTestSiteShortName"; - private static final String USER_ONE = "SomeTestUserOne"; - private static final String USER_TWO = "SomeTestUserTwo"; - - private static final String JSON_KEY_NODEREF = "nodeRef"; - private static final String JSON_KEY_ITEM = "item"; - - private String requestBodyJson = "{\"title\" : \"Test Title\", \"content\" : \"Test Comment\"}"; - - private FileFolderService fileFolderService; - private TransactionService transactionService; - private SearchService searchService; - private NodeService nodeService; - private NamespaceService namespaceService; - private VersionService versionService; - private PersonService personService; - private MutableAuthenticationService authenticationService; - private AuthenticationComponent authenticationComponent; - protected PermissionServiceSPI permissionService; - protected ModelDAO permissionModelDAO; - - private NodeRef rootNodeRef; - private NodeRef companyHomeNodeRef; - private NodeRef nodeRef; - private NodeRef sitePage; - - private static final String USER_TEST = "UserTest"; - - private UserTransaction txn; - - private String USER2 = "user2"; - private SiteService siteService; - private NodeArchiveService nodeArchiveService; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - ApplicationContext appContext = getServer().getApplicationContext(); - - fileFolderService = (FileFolderService)appContext.getBean("fileFolderService"); - transactionService = (TransactionService)appContext.getBean("transactionService"); - searchService = (SearchService)appContext.getBean("SearchService"); - nodeService = (NodeService)appContext.getBean("nodeService"); - namespaceService = (NamespaceService)appContext.getBean("namespaceService"); - versionService = (VersionService)appContext.getBean("versionService"); - personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); - authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); - authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); - permissionService = (PermissionServiceSPI) getServer().getApplicationContext().getBean("permissionService"); - permissionModelDAO = (ModelDAO) getServer().getApplicationContext().getBean("permissionsModelDAO"); - siteService = (SiteService)getServer().getApplicationContext().getBean("SiteService"); - personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); - nodeArchiveService = (NodeArchiveService)getServer().getApplicationContext().getBean("nodeArchiveService"); - - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - txn = transactionService.getUserTransaction(); - txn.begin(); - - rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); - List results = searchService.selectNodes(rootNodeRef, "/app:company_home", null, namespaceService, false); - if (results.size() == 0) - { - throw new AlfrescoRuntimeException("Can't find /app:company_home"); - } - - companyHomeNodeRef = results.get(0); - - results = searchService.selectNodes(rootNodeRef, "/app:company_home/cm:Commenty", null, namespaceService, false); - if (results.size() > 0) - { - fileFolderService.delete(results.get(0)); - } - - nodeRef = fileFolderService.create(companyHomeNodeRef, "Commenty", ContentModel.TYPE_CONTENT).getNodeRef(); - versionService.ensureVersioningEnabled(nodeRef, null); - nodeService.setProperty(nodeRef, ContentModel.PROP_AUTO_VERSION_PROPS, true); - - createUser(USER2); - createUser(USER_TEST); - - txn.commit(); - - AuthenticationUtil.clearCurrentSecurityContext(); - - // MNT-12082 - // Authenticate as admin - AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); - - // Create test site - // - only create the site if it doesn't already exist - SiteInfo siteInfo = siteService.getSite(SITE_SHORT_NAME); - if (siteInfo == null) - { - siteInfo = siteService.createSite("SomeTestSite", SITE_SHORT_NAME, "SiteTitle", "SiteDescription", SiteVisibility.PUBLIC); - } - - txn = transactionService.getUserTransaction(); - txn.begin(); - - // Create users - createUser(USER_ONE, SiteModel.SITE_CONSUMER); - createUser(USER_TWO, SiteModel.SITE_CONTRIBUTOR); - - // Create site page - sitePage = nodeService.createNode(siteInfo.getNodeRef(), - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "test"), - ContentModel.TYPE_CONTENT).getChildRef(); - - txn.commit(); - - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - - // admin user required to delete user - authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); - - // delete the discussions users - if(personService.personExists(USER_TEST)) - { - // delete invite site - personService.deletePerson(USER_TEST); - - // delete the users - } - if (authenticationService.authenticationExists(USER_TEST)) - { - authenticationService.deleteAuthentication(USER_TEST); - } - - AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); - - SiteInfo siteInfo = this.siteService.getSite(SITE_SHORT_NAME); - if (siteInfo != null) - { - // delete invite site - siteService.deleteSite(SITE_SHORT_NAME); - nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(siteInfo.getNodeRef())); - } - - // delete the users - deleteUser(USER_ONE); - deleteUser(USER_TWO); - } - - /** - * add a comment to given node ref - * - * @param nodeRef - * @param user - * @param status - * @return - * @throws Exception - */ - private Response addComment(NodeRef nodeRef, String user, int status) throws Exception - { - Response response = null; - - UserTransaction txn = transactionService.getUserTransaction(); - txn.begin(); - - // Not allowed if you're not an admin - AuthenticationUtil.setFullyAuthenticatedUser(user); - - // add comment and save response (comment nodeRef) - - StringBuilder body = new StringBuilder("{"); - body.append("\"itemTitle\" : \"Test Title\", "); - body.append("\"content\" : \"Test Comment\", "); - body.append("\"pageParams\" : \"{\\\"nodeRef\\\" : \\\""); - body.append(nodeRef.getStoreRef().getProtocol()); - body.append(":\\/\\/"); - body.append(nodeRef.getStoreRef().getIdentifier()); - body.append("\\/"); - body.append(nodeRef.getId()); - body.append("\\\"}"); - if (nodeRef.equals(sitePage)) - { - body.append("\",\"site\" : \""); - body.append(SITE_SHORT_NAME); - } - body.append("\"}"); - response = sendRequest( - new PostRequest(MessageFormat.format(URL_POST_COMMENT, new Object[] { nodeRef.getStoreRef().getProtocol(), - nodeRef.getStoreRef().getIdentifier(), nodeRef.getId() }), body.toString(), JSON), status); - - assertEquals(status, response.getStatus()); - - // Normally, webscripts are in their own transaction. The test infrastructure here forces us to have a transaction - // around the calls. if the WebScript fails, then we should rollback. - if (response.getStatus() == 500) - { - txn.rollback(); - } - else - { - txn.commit(); - } - - return response; - } - - private String getCurrentVersion(NodeRef nodeRef) throws Exception - { - String version = versionService.getCurrentVersion(nodeRef).getVersionLabel(); - return version; - } - - public void testCommentDoesNotVersion() throws Exception - { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - String versionBefore = getCurrentVersion(nodeRef); - addComment(nodeRef, AuthenticationUtil.getAdminUserName(), 200); - String versionAfter = getCurrentVersion(nodeRef); - assertEquals(versionBefore, versionAfter); - } - - /** - * MNT-9771 - * @throws Exception - */ - public void testCommentPermissions() throws Exception - { - authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); - UserTransaction txn = transactionService.getUserTransaction(); - txn.begin(); - - NodeRef contentForUserContributor = fileFolderService.create(companyHomeNodeRef, "CommentyContributor" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); - permissionService.setPermission(new SimplePermissionEntry(contentForUserContributor, getPermission(PermissionService.CONTRIBUTOR), USER_TEST, AccessStatus.ALLOWED)); - - NodeRef contentForUserConsumer = fileFolderService.create(companyHomeNodeRef, "CommentyConsumer" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); - permissionService.setPermission(new SimplePermissionEntry(contentForUserConsumer, getPermission(PermissionService.CONSUMER), USER_TEST, AccessStatus.ALLOWED)); - - //Contributor should be able to add comments - addComment(contentForUserContributor, USER_TEST, 200); - - txn.commit(); // Hack. Internally, the addComment starts and rolls back the next txn. - //Consumer shouldn't be able to add comments see MNT-9883 - addComment(contentForUserConsumer, USER_TEST, 500); - - txn = transactionService.getUserTransaction(); - txn.begin(); - nodeService.deleteNode(contentForUserContributor); - nodeService.deleteNode(contentForUserConsumer); - - txn.commit(); - } - - - private void createUser(String userName) - { - // if user with given user name doesn't already exist then create user - if (!authenticationService.authenticationExists(userName)) - { - // create user - authenticationService.createAuthentication(userName, "password".toCharArray()); - } - - if (!personService.personExists(userName)) - { - // create person properties - PropertyMap personProps = new PropertyMap(); - personProps.put(ContentModel.PROP_USERNAME, userName); - personProps.put(ContentModel.PROP_FIRSTNAME, "FirstNameTest"); - personProps.put(ContentModel.PROP_LASTNAME, "LastNameTest"); - personProps.put(ContentModel.PROP_EMAIL, "FirstNameTest.LastNameTest@test.com"); - personProps.put(ContentModel.PROP_JOBTITLE, "JobTitleTest"); - - // create person node for user - personService.createPerson(personProps); - } - } - - private PermissionReference getPermission(String permission) - { - return permissionModelDAO.getPermissionReference(null, permission); - } - - /** - * MNT-9771 - */ - public void testCommentDoesNotChangeModifier() throws Exception - { - permissionService.setPermission(nodeRef, USER2, PermissionService.ALL_PERMISSIONS, true); - String modifierBefore = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); - addComment(nodeRef, USER2, 200); - String modifierAfter = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); - assertEquals(modifierBefore, modifierAfter); - } - - /** - * MNT-15679 - */ - public void testDeleteCommentDoesNotChangeModifiedDate() throws Exception - { - // in site page - permissionService.setPermission(sitePage, USER_TWO, PermissionService.ALL_PERMISSIONS, true); - String modifierBefore = (String) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIER); - Date modifiedDateBefore = (Date) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIED); - - Response response1 = addComment(sitePage, USER_TWO, 200); - - JSONObject jsonResponse1 = parseResponseJSON(response1); - String nodeRefComment1 = getOrNull(jsonResponse1, JSON_KEY_NODEREF); - if (nodeRefComment1 != null) - { - NodeRef commentNodeRef1 = new NodeRef(nodeRefComment1); - deleteComment(commentNodeRef1, sitePage, USER_TWO, 200); - } - - Date modifiedDateAfter = (Date) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIED); - String modifierAfter = (String) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIER); - assertEquals(modifiedDateBefore.getTime(), modifiedDateAfter.getTime()); - assertEquals(modifierBefore, modifierAfter); - - // in repository - on nodeRef - permissionService.setPermission(nodeRef, USER2, PermissionService.ALL_PERMISSIONS, true); - modifierBefore = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); - modifiedDateBefore = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); - Response response2 = addComment(nodeRef, USER2, 200); - - JSONObject jsonResponse2 = parseResponseJSON(response2); - String nodeRefComment2 = getOrNull(jsonResponse2, JSON_KEY_NODEREF); - if (nodeRefComment2 != null) - { - NodeRef commentNodeRef2 = new NodeRef(nodeRefComment2); - deleteComment(commentNodeRef2, nodeRef, USER2, 200); - } - - modifiedDateAfter = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); - modifierAfter = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); - assertEquals(modifiedDateBefore.getTime(), modifiedDateAfter.getTime()); - assertEquals(modifierBefore, modifierAfter); - } - - /** - * MNT-12082 - */ - public void testConsumerCanNotComment() throws Exception - { - // Authenticate as consumer - authenticationService.authenticate(USER_ONE, USER_ONE.toCharArray()); - - String uri = MessageFormat.format(URL_POST_COMMENT, new Object[] {sitePage.getStoreRef().getProtocol(), sitePage.getStoreRef().getIdentifier(), sitePage.getId()}); - Response response = sendRequest(new PostRequest(uri, requestBodyJson, JSON), - Status.STATUS_INTERNAL_SERVER_ERROR); - assertEquals(Status.STATUS_INTERNAL_SERVER_ERROR, response.getStatus()); - } - - /** - * MNT-12082 - */ - public void testContributorCanComment() throws Exception - { - // Authenticate as contributor - authenticationService.authenticate(USER_TWO, USER_TWO.toCharArray()); - - String uri = MessageFormat.format(URL_POST_COMMENT, new Object[] {sitePage.getStoreRef().getProtocol(), sitePage.getStoreRef().getIdentifier(), sitePage.getId()}); - Response response = sendRequest(new PostRequest(uri, requestBodyJson, JSON), Status.STATUS_OK); - assertEquals(Status.STATUS_OK, response.getStatus()); - } - - private void createUser(String userName, String role) - { - // if user with given user name doesn't already exist then create user - if (authenticationService.authenticationExists(userName) == false) - { - authenticationService.createAuthentication(userName, userName.toCharArray()); - - // create person properties - PropertyMap personProps = new PropertyMap(); - personProps.put(ContentModel.PROP_USERNAME, userName); - personProps.put(ContentModel.PROP_FIRSTNAME, "FirstName123"); - personProps.put(ContentModel.PROP_LASTNAME, "LastName123"); - personProps.put(ContentModel.PROP_EMAIL, "FirstName123.LastName123@email.com"); - personProps.put(ContentModel.PROP_JOBTITLE, "JobTitle123"); - personProps.put(ContentModel.PROP_JOBTITLE, "Organisation123"); - - personService.createPerson(personProps); - } - - siteService.setMembership(SITE_SHORT_NAME, userName, role); - } - - private void deleteUser(String user) - { - personService.deletePerson(user); - if (authenticationService.authenticationExists(user)) - { - authenticationService.deleteAuthentication(user); - } - } - - - /** - * delete comment - * - * @param commentNodeRef - * @param parentNodeRef - * @param user - * @param status - * @throws Exception - */ - private void deleteComment(NodeRef commentNodeRef, NodeRef parentNodeRef, String user, int status) throws Exception - { - Response response = null; - - UserTransaction txn = transactionService.getUserTransaction(); - txn.begin(); - - // Not allowed if you're not an admin - AuthenticationUtil.setFullyAuthenticatedUser(user); - - String itemTitle = "Test Title"; - String page = "document-details"; - - StringBuilder pageParamsBuilder = new StringBuilder("{"); - pageParamsBuilder.append("\"nodeRef\" : \""); - pageParamsBuilder.append(parentNodeRef.toString()); - pageParamsBuilder.append("\", "); - pageParamsBuilder.append("}"); - String pageParams = pageParamsBuilder.toString(); - - String URL = MessageFormat.format(URL_DELETE_COMMENT, new Object[] { commentNodeRef.getStoreRef().getProtocol(), - commentNodeRef.getStoreRef().getIdentifier(), commentNodeRef.getId(), SITE_SHORT_NAME, itemTitle, page, pageParams }); - response = sendRequest(new DeleteRequest(URL), status); - assertEquals(status, response.getStatus()); - - // Normally, webscripts are in their own transaction. The test - // infrastructure here forces us to have a transaction - // around the calls. if the WebScript fails, then we should rollback. - if (response.getStatus() == 500) - { - txn.rollback(); - } - else - { - txn.commit(); - } - } - - /** - * returns value from JSON for a given key - * @param json - * @param key - * @return - */ - protected String getOrNull(JSONObject json, String key) - { - if (json != null && json.containsKey(key)) - { - return (String) json.get(key); - } - - JSONObject itemJsonObject = (JSONObject) json.get(JSON_KEY_ITEM); - if (itemJsonObject != null && itemJsonObject.containsKey(key)) - { - return (String) itemJsonObject.get(key); - } - return null; - } - - /** - * parse JSON - * @param response - * @return - */ - protected JSONObject parseResponseJSON(Response response) - { - JSONObject json = null; - String contentType = response.getContentType(); - if (contentType != null && contentType.indexOf(';') != -1) - { - contentType = contentType.substring(0, contentType.indexOf(';')); - } - if (MimetypeMap.MIMETYPE_JSON.equals(contentType)) - { - JSONParser parser = new JSONParser(); - try - { - json = (JSONObject) parser.parse(response.getContentAsString()); - } - catch (IOException io) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage()); - } - catch (ParseException pe) - { - throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage()); - } - } - return json; - } -} +package org.alfresco.repo.web.scripts.comment; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Date; +import java.util.List; + +import javax.transaction.UserTransaction; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.node.archive.NodeArchiveService; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.permissions.PermissionReference; +import org.alfresco.repo.security.permissions.PermissionServiceSPI; +import org.alfresco.repo.security.permissions.impl.ModelDAO; +import org.alfresco.repo.security.permissions.impl.SimplePermissionEntry; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.cmr.version.VersionService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.PropertyMap; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * TODO: Fix the loose transaction handling. + */ +public class CommentsApiTest extends BaseWebScriptTest +{ + private static final String URL_POST_COMMENT = "api/node/{0}/{1}/{2}/comments"; + private static final String URL_DELETE_COMMENT = "api/comment/node/{0}/{1}/{2}?site={3}&itemtitle={4}&page={5}&pageParams={6}"; + private static final String JSON = "application/json"; + private static final String SITE_SHORT_NAME = "SomeTestSiteShortName"; + private static final String USER_ONE = "SomeTestUserOne"; + private static final String USER_TWO = "SomeTestUserTwo"; + + private static final String JSON_KEY_NODEREF = "nodeRef"; + private static final String JSON_KEY_ITEM = "item"; + + private String requestBodyJson = "{\"title\" : \"Test Title\", \"content\" : \"Test Comment\"}"; + + private FileFolderService fileFolderService; + private TransactionService transactionService; + private SearchService searchService; + private NodeService nodeService; + private NamespaceService namespaceService; + private VersionService versionService; + private PersonService personService; + private MutableAuthenticationService authenticationService; + private AuthenticationComponent authenticationComponent; + protected PermissionServiceSPI permissionService; + protected ModelDAO permissionModelDAO; + + private NodeRef rootNodeRef; + private NodeRef companyHomeNodeRef; + private NodeRef nodeRef; + private NodeRef sitePage; + + private static final String USER_TEST = "UserTest"; + + private UserTransaction txn; + + private String USER2 = "user2"; + private SiteService siteService; + private NodeArchiveService nodeArchiveService; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ApplicationContext appContext = getServer().getApplicationContext(); + + fileFolderService = (FileFolderService)appContext.getBean("fileFolderService"); + transactionService = (TransactionService)appContext.getBean("transactionService"); + searchService = (SearchService)appContext.getBean("SearchService"); + nodeService = (NodeService)appContext.getBean("nodeService"); + namespaceService = (NamespaceService)appContext.getBean("namespaceService"); + versionService = (VersionService)appContext.getBean("versionService"); + personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); + authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); + authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); + permissionService = (PermissionServiceSPI) getServer().getApplicationContext().getBean("permissionService"); + permissionModelDAO = (ModelDAO) getServer().getApplicationContext().getBean("permissionsModelDAO"); + siteService = (SiteService)getServer().getApplicationContext().getBean("SiteService"); + personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); + nodeArchiveService = (NodeArchiveService)getServer().getApplicationContext().getBean("nodeArchiveService"); + + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + txn = transactionService.getUserTransaction(); + txn.begin(); + + rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + List results = searchService.selectNodes(rootNodeRef, "/app:company_home", null, namespaceService, false); + if (results.size() == 0) + { + throw new AlfrescoRuntimeException("Can't find /app:company_home"); + } + + companyHomeNodeRef = results.get(0); + + results = searchService.selectNodes(rootNodeRef, "/app:company_home/cm:Commenty", null, namespaceService, false); + if (results.size() > 0) + { + fileFolderService.delete(results.get(0)); + } + + nodeRef = fileFolderService.create(companyHomeNodeRef, "Commenty", ContentModel.TYPE_CONTENT).getNodeRef(); + versionService.ensureVersioningEnabled(nodeRef, null); + nodeService.setProperty(nodeRef, ContentModel.PROP_AUTO_VERSION_PROPS, true); + + createUser(USER2); + createUser(USER_TEST); + + txn.commit(); + + AuthenticationUtil.clearCurrentSecurityContext(); + + // MNT-12082 + // Authenticate as admin + AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); + + // Create test site + // - only create the site if it doesn't already exist + SiteInfo siteInfo = siteService.getSite(SITE_SHORT_NAME); + if (siteInfo == null) + { + siteInfo = siteService.createSite("SomeTestSite", SITE_SHORT_NAME, "SiteTitle", "SiteDescription", SiteVisibility.PUBLIC); + } + + txn = transactionService.getUserTransaction(); + txn.begin(); + + // Create users + createUser(USER_ONE, SiteModel.SITE_CONSUMER); + createUser(USER_TWO, SiteModel.SITE_CONTRIBUTOR); + + // Create site page + sitePage = nodeService.createNode(siteInfo.getNodeRef(), + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "test"), + ContentModel.TYPE_CONTENT).getChildRef(); + + txn.commit(); + + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + + // admin user required to delete user + authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + + // delete the discussions users + if(personService.personExists(USER_TEST)) + { + // delete invite site + personService.deletePerson(USER_TEST); + + // delete the users + } + if (authenticationService.authenticationExists(USER_TEST)) + { + authenticationService.deleteAuthentication(USER_TEST); + } + + AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); + + SiteInfo siteInfo = this.siteService.getSite(SITE_SHORT_NAME); + if (siteInfo != null) + { + // delete invite site + siteService.deleteSite(SITE_SHORT_NAME); + nodeArchiveService.purgeArchivedNode(nodeArchiveService.getArchivedNode(siteInfo.getNodeRef())); + } + + // delete the users + deleteUser(USER_ONE); + deleteUser(USER_TWO); + } + + /** + * add a comment to given node ref + * + * @param nodeRef + * @param user + * @param status + * @return + * @throws Exception + */ + private Response addComment(NodeRef nodeRef, String user, int status) throws Exception + { + Response response = null; + + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + + // Not allowed if you're not an admin + AuthenticationUtil.setFullyAuthenticatedUser(user); + + // add comment and save response (comment nodeRef) + + StringBuilder body = new StringBuilder("{"); + body.append("\"itemTitle\" : \"Test Title\", "); + body.append("\"content\" : \"Test Comment\", "); + body.append("\"pageParams\" : \"{\\\"nodeRef\\\" : \\\""); + body.append(nodeRef.getStoreRef().getProtocol()); + body.append(":\\/\\/"); + body.append(nodeRef.getStoreRef().getIdentifier()); + body.append("\\/"); + body.append(nodeRef.getId()); + body.append("\\\"}"); + if (nodeRef.equals(sitePage)) + { + body.append("\",\"site\" : \""); + body.append(SITE_SHORT_NAME); + } + body.append("\"}"); + response = sendRequest( + new PostRequest(MessageFormat.format(URL_POST_COMMENT, new Object[] { nodeRef.getStoreRef().getProtocol(), + nodeRef.getStoreRef().getIdentifier(), nodeRef.getId() }), body.toString(), JSON), status); + + assertEquals(status, response.getStatus()); + + // Normally, webscripts are in their own transaction. The test infrastructure here forces us to have a transaction + // around the calls. if the WebScript fails, then we should rollback. + if (response.getStatus() == 500) + { + txn.rollback(); + } + else + { + txn.commit(); + } + + return response; + } + + private String getCurrentVersion(NodeRef nodeRef) throws Exception + { + String version = versionService.getCurrentVersion(nodeRef).getVersionLabel(); + return version; + } + + public void testCommentDoesNotVersion() throws Exception + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + String versionBefore = getCurrentVersion(nodeRef); + addComment(nodeRef, AuthenticationUtil.getAdminUserName(), 200); + String versionAfter = getCurrentVersion(nodeRef); + assertEquals(versionBefore, versionAfter); + } + + /** + * MNT-9771 + * @throws Exception + */ + public void testCommentPermissions() throws Exception + { + authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + + NodeRef contentForUserContributor = fileFolderService.create(companyHomeNodeRef, "CommentyContributor" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); + permissionService.setPermission(new SimplePermissionEntry(contentForUserContributor, getPermission(PermissionService.CONTRIBUTOR), USER_TEST, AccessStatus.ALLOWED)); + + NodeRef contentForUserConsumer = fileFolderService.create(companyHomeNodeRef, "CommentyConsumer" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); + permissionService.setPermission(new SimplePermissionEntry(contentForUserConsumer, getPermission(PermissionService.CONSUMER), USER_TEST, AccessStatus.ALLOWED)); + + //Contributor should be able to add comments + addComment(contentForUserContributor, USER_TEST, 200); + + txn.commit(); // Hack. Internally, the addComment starts and rolls back the next txn. + //Consumer shouldn't be able to add comments see MNT-9883 + addComment(contentForUserConsumer, USER_TEST, 500); + + txn = transactionService.getUserTransaction(); + txn.begin(); + nodeService.deleteNode(contentForUserContributor); + nodeService.deleteNode(contentForUserConsumer); + + txn.commit(); + } + + + private void createUser(String userName) + { + // if user with given user name doesn't already exist then create user + if (!authenticationService.authenticationExists(userName)) + { + // create user + authenticationService.createAuthentication(userName, "password".toCharArray()); + } + + if (!personService.personExists(userName)) + { + // create person properties + PropertyMap personProps = new PropertyMap(); + personProps.put(ContentModel.PROP_USERNAME, userName); + personProps.put(ContentModel.PROP_FIRSTNAME, "FirstNameTest"); + personProps.put(ContentModel.PROP_LASTNAME, "LastNameTest"); + personProps.put(ContentModel.PROP_EMAIL, "FirstNameTest.LastNameTest@test.com"); + personProps.put(ContentModel.PROP_JOBTITLE, "JobTitleTest"); + + // create person node for user + personService.createPerson(personProps); + } + } + + private PermissionReference getPermission(String permission) + { + return permissionModelDAO.getPermissionReference(null, permission); + } + + /** + * MNT-9771 + */ + public void testCommentDoesNotChangeModifier() throws Exception + { + permissionService.setPermission(nodeRef, USER2, PermissionService.ALL_PERMISSIONS, true); + String modifierBefore = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); + addComment(nodeRef, USER2, 200); + String modifierAfter = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); + assertEquals(modifierBefore, modifierAfter); + } + + /** + * MNT-15679 + */ + public void testDeleteCommentDoesNotChangeModifiedDate() throws Exception + { + // in site page + permissionService.setPermission(sitePage, USER_TWO, PermissionService.ALL_PERMISSIONS, true); + String modifierBefore = (String) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIER); + Date modifiedDateBefore = (Date) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIED); + + Response response1 = addComment(sitePage, USER_TWO, 200); + + JSONObject jsonResponse1 = parseResponseJSON(response1); + String nodeRefComment1 = getOrNull(jsonResponse1, JSON_KEY_NODEREF); + if (nodeRefComment1 != null) + { + NodeRef commentNodeRef1 = new NodeRef(nodeRefComment1); + deleteComment(commentNodeRef1, sitePage, USER_TWO, 200); + } + + Date modifiedDateAfter = (Date) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIED); + String modifierAfter = (String) nodeService.getProperty(sitePage, ContentModel.PROP_MODIFIER); + assertEquals(modifiedDateBefore.getTime(), modifiedDateAfter.getTime()); + assertEquals(modifierBefore, modifierAfter); + + // in repository - on nodeRef + permissionService.setPermission(nodeRef, USER2, PermissionService.ALL_PERMISSIONS, true); + modifierBefore = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); + modifiedDateBefore = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); + Response response2 = addComment(nodeRef, USER2, 200); + + JSONObject jsonResponse2 = parseResponseJSON(response2); + String nodeRefComment2 = getOrNull(jsonResponse2, JSON_KEY_NODEREF); + if (nodeRefComment2 != null) + { + NodeRef commentNodeRef2 = new NodeRef(nodeRefComment2); + deleteComment(commentNodeRef2, nodeRef, USER2, 200); + } + + modifiedDateAfter = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); + modifierAfter = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); + assertEquals(modifiedDateBefore.getTime(), modifiedDateAfter.getTime()); + assertEquals(modifierBefore, modifierAfter); + } + + /** + * MNT-12082 + */ + public void testConsumerCanNotComment() throws Exception + { + // Authenticate as consumer + authenticationService.authenticate(USER_ONE, USER_ONE.toCharArray()); + + String uri = MessageFormat.format(URL_POST_COMMENT, new Object[] {sitePage.getStoreRef().getProtocol(), sitePage.getStoreRef().getIdentifier(), sitePage.getId()}); + Response response = sendRequest(new PostRequest(uri, requestBodyJson, JSON), + Status.STATUS_INTERNAL_SERVER_ERROR); + assertEquals(Status.STATUS_INTERNAL_SERVER_ERROR, response.getStatus()); + } + + /** + * MNT-12082 + */ + public void testContributorCanComment() throws Exception + { + // Authenticate as contributor + authenticationService.authenticate(USER_TWO, USER_TWO.toCharArray()); + + String uri = MessageFormat.format(URL_POST_COMMENT, new Object[] {sitePage.getStoreRef().getProtocol(), sitePage.getStoreRef().getIdentifier(), sitePage.getId()}); + Response response = sendRequest(new PostRequest(uri, requestBodyJson, JSON), Status.STATUS_OK); + assertEquals(Status.STATUS_OK, response.getStatus()); + } + + private void createUser(String userName, String role) + { + // if user with given user name doesn't already exist then create user + if (authenticationService.authenticationExists(userName) == false) + { + authenticationService.createAuthentication(userName, userName.toCharArray()); + + // create person properties + PropertyMap personProps = new PropertyMap(); + personProps.put(ContentModel.PROP_USERNAME, userName); + personProps.put(ContentModel.PROP_FIRSTNAME, "FirstName123"); + personProps.put(ContentModel.PROP_LASTNAME, "LastName123"); + personProps.put(ContentModel.PROP_EMAIL, "FirstName123.LastName123@email.com"); + personProps.put(ContentModel.PROP_JOBTITLE, "JobTitle123"); + personProps.put(ContentModel.PROP_JOBTITLE, "Organisation123"); + + personService.createPerson(personProps); + } + + siteService.setMembership(SITE_SHORT_NAME, userName, role); + } + + private void deleteUser(String user) + { + personService.deletePerson(user); + if (authenticationService.authenticationExists(user)) + { + authenticationService.deleteAuthentication(user); + } + } + + + /** + * delete comment + * + * @param commentNodeRef + * @param parentNodeRef + * @param user + * @param status + * @throws Exception + */ + private void deleteComment(NodeRef commentNodeRef, NodeRef parentNodeRef, String user, int status) throws Exception + { + Response response = null; + + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + + // Not allowed if you're not an admin + AuthenticationUtil.setFullyAuthenticatedUser(user); + + String itemTitle = "Test Title"; + String page = "document-details"; + + StringBuilder pageParamsBuilder = new StringBuilder("{"); + pageParamsBuilder.append("\"nodeRef\" : \""); + pageParamsBuilder.append(parentNodeRef.toString()); + pageParamsBuilder.append("\", "); + pageParamsBuilder.append("}"); + String pageParams = pageParamsBuilder.toString(); + + String URL = MessageFormat.format(URL_DELETE_COMMENT, new Object[] { commentNodeRef.getStoreRef().getProtocol(), + commentNodeRef.getStoreRef().getIdentifier(), commentNodeRef.getId(), SITE_SHORT_NAME, itemTitle, page, pageParams }); + response = sendRequest(new DeleteRequest(URL), status); + assertEquals(status, response.getStatus()); + + // Normally, webscripts are in their own transaction. The test + // infrastructure here forces us to have a transaction + // around the calls. if the WebScript fails, then we should rollback. + if (response.getStatus() == 500) + { + txn.rollback(); + } + else + { + txn.commit(); + } + } + + /** + * returns value from JSON for a given key + * @param json + * @param key + * @return + */ + protected String getOrNull(JSONObject json, String key) + { + if (json != null && json.containsKey(key)) + { + return (String) json.get(key); + } + + JSONObject itemJsonObject = (JSONObject) json.get(JSON_KEY_ITEM); + if (itemJsonObject != null && itemJsonObject.containsKey(key)) + { + return (String) itemJsonObject.get(key); + } + return null; + } + + /** + * parse JSON + * @param response + * @return + */ + protected JSONObject parseResponseJSON(Response response) + { + JSONObject json = null; + String contentType = response.getContentType(); + if (contentType != null && contentType.indexOf(';') != -1) + { + contentType = contentType.substring(0, contentType.indexOf(';')); + } + if (MimetypeMap.MIMETYPE_JSON.equals(contentType)) + { + JSONParser parser = new JSONParser(); + try + { + json = (JSONObject) parser.parse(response.getContentAsString()); + } + catch (IOException io) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage()); + } + catch (ParseException pe) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage()); + } + } + return json; + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/content/MimetypesGetTest.java b/source/test-java/org/alfresco/repo/web/scripts/content/MimetypesGetTest.java index c597f66bc8..fdfcfa1e72 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/content/MimetypesGetTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/content/MimetypesGetTest.java @@ -1,65 +1,65 @@ -package org.alfresco.repo.web.scripts.content; - -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.content.transform.ContentTransformerRegistry; -import org.alfresco.repo.content.transform.PdfBoxContentTransformer; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.springframework.context.ApplicationContext; - -/** - * Tests the {@link MimetypesGet} endpoint - */ -public class MimetypesGetTest extends BaseWebScriptTest -{ - - private ApplicationContext ctx; - private ContentTransformerRegistry contentTransformerRegistry; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - ctx = getServer().getApplicationContext(); - contentTransformerRegistry = (ContentTransformerRegistry) ctx.getBean("contentTransformerRegistry"); - } - - /** - * Tests the mimetypesGet.getTransformer method directly for - * varefication of label text - * - * @throws Exception - */ - public void testGetTransformer() throws Exception - { - MimetypesGet mimetypesGet = new MimetypesGet(); - mimetypesGet.setApplicationContext(ctx); - mimetypesGet.setContentTransformerRegistry(contentTransformerRegistry); - mimetypesGet.afterPropertiesSet(); - - // Test a Java transformer name - String transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_PDF, 1000, MimetypeMap.MIMETYPE_TEXT_PLAIN); - assertEquals(PdfBoxContentTransformer.class.getCanonicalName(), transformerName); - - // Test a generic proxy transformer name - transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_IMAGE_JPEG, 1000, MimetypeMap.MIMETYPE_IMAGE_PNG); - assertNotNull(transformerName); - assertTrue("Expected transformerName to contain 'Proxy' but was " + transformerName, - transformerName.contains("Proxy via")); - - boolean oodirectPresent = ctx.containsBean(MimetypesGet.OODIRECT_WORKER_BEAN); - boolean jodPresent = ctx.containsBean(MimetypesGet.JOD_WORKER_BEAN); - - // Test the office transformer name - transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_WORD, 1000, MimetypeMap.MIMETYPE_PDF); - assertNotNull(transformerName); - if (oodirectPresent) - { - assertEquals("Using a Direct Open Office Connection", transformerName); - } - else if (jodPresent) - { - assertEquals("Using JOD Converter / Open Office", transformerName); - } - } - -} +package org.alfresco.repo.web.scripts.content; + +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.transform.ContentTransformerRegistry; +import org.alfresco.repo.content.transform.PdfBoxContentTransformer; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.springframework.context.ApplicationContext; + +/** + * Tests the {@link MimetypesGet} endpoint + */ +public class MimetypesGetTest extends BaseWebScriptTest +{ + + private ApplicationContext ctx; + private ContentTransformerRegistry contentTransformerRegistry; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ctx = getServer().getApplicationContext(); + contentTransformerRegistry = (ContentTransformerRegistry) ctx.getBean("contentTransformerRegistry"); + } + + /** + * Tests the mimetypesGet.getTransformer method directly for + * varefication of label text + * + * @throws Exception + */ + public void testGetTransformer() throws Exception + { + MimetypesGet mimetypesGet = new MimetypesGet(); + mimetypesGet.setApplicationContext(ctx); + mimetypesGet.setContentTransformerRegistry(contentTransformerRegistry); + mimetypesGet.afterPropertiesSet(); + + // Test a Java transformer name + String transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_PDF, 1000, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertEquals(PdfBoxContentTransformer.class.getCanonicalName(), transformerName); + + // Test a generic proxy transformer name + transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_IMAGE_JPEG, 1000, MimetypeMap.MIMETYPE_IMAGE_PNG); + assertNotNull(transformerName); + assertTrue("Expected transformerName to contain 'Proxy' but was " + transformerName, + transformerName.contains("Proxy via")); + + boolean oodirectPresent = ctx.containsBean(MimetypesGet.OODIRECT_WORKER_BEAN); + boolean jodPresent = ctx.containsBean(MimetypesGet.JOD_WORKER_BEAN); + + // Test the office transformer name + transformerName = mimetypesGet.getTransformer(MimetypeMap.MIMETYPE_WORD, 1000, MimetypeMap.MIMETYPE_PDF); + assertNotNull(transformerName); + if (oodirectPresent) + { + assertEquals("Using a Direct Open Office Connection", transformerName); + } + else if (jodPresent) + { + assertEquals("Using JOD Converter / Open Office", transformerName); + } + } + +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/dictionary/DictionaryRestApiTest.java b/source/test-java/org/alfresco/repo/web/scripts/dictionary/DictionaryRestApiTest.java index 28617cae9e..5aca4a1fc7 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/dictionary/DictionaryRestApiTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/dictionary/DictionaryRestApiTest.java @@ -1,930 +1,930 @@ -package org.alfresco.repo.web.scripts.dictionary; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.json.JSONObject; -import org.json.JSONArray; - -/** - * Unit test for Dictionary REST API - * @author Saravanan Sellathurai - */ - -public class DictionaryRestApiTest extends BaseWebScriptTest -{ - private static final String URL_SITES = "/api/classes"; - private static final String URL_PROPERTIES = "/api/properties"; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - getServer(); - AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - AuthenticationUtil.clearCurrentSecurityContext(); - } - - private void validatePropertyDef(JSONObject result) throws Exception - { - assertEquals("cm:created", result.get("name")); - assertEquals("Created Date", result.get("title")); - assertEquals("Created Date", result.get("description")); - assertEquals("d:datetime", result.get("dataType")); - assertEquals(false, result.get("multiValued")); - assertEquals(true, result.get("mandatory")); - assertEquals(true, result.get("enforced")); - assertEquals(true, result.get("protected")); - assertEquals(true, result.get("indexed")); - assertEquals(true, result.get("indexedAtomically")); - assertEquals("/api/property/cm_created", result.get("url")); - - } - - private void validateChildAssociation(JSONObject result) throws Exception - { - assertEquals("cm:member", result.get("name")); - assertEquals(true, result.get("isChildAssociation")); - assertEquals(false, result.get("protected")); - - assertEquals("cm:authorityContainer", result.getJSONObject("source").get("class")); - assertEquals(false, result.getJSONObject("source").get("mandatory")); - assertEquals(true, result.getJSONObject("source").get("many")); - - assertEquals("cm:authority", result.getJSONObject("target").get("class")); - assertEquals(false, result.getJSONObject("target").get("mandatory")); - assertEquals(true, result.getJSONObject("target").get("many")); - - assertTrue(result.get("url").toString().startsWith("/api/classes/")); - assertTrue(result.get("url").toString().indexOf("/association/cm_member") > 0);; - } - - private void validateAssociation(JSONObject result) throws Exception - { - assertEquals("cm:workingcopylink", result.get("name")); - assertEquals(false, result.get("isChildAssociation")); - assertEquals(false, result.get("protected")); - - assertEquals("cm:checkedOut", result.getJSONObject("source").get("class")); - assertEquals(true, result.getJSONObject("source").get("mandatory")); - assertEquals(false, result.getJSONObject("source").get("many")); - - assertEquals("cm:workingcopy", result.getJSONObject("target").get("class")); - assertEquals(true, result.getJSONObject("target").get("mandatory")); - assertEquals(false, result.getJSONObject("target").get("many")); - - assertEquals("/api/classes/cm_checkedOut/association/cm_workingcopylink", result.get("url")); - } - private void validateAssociationDef(JSONObject result) throws Exception - { - assertEquals("cm:avatar", result.get("name")); - assertEquals("Avatar", result.get("title")); - assertEquals("The person's avatar image", result.get("description")); - assertEquals(false, result.get("isChildAssociation")); - assertEquals(false, result.get("protected")); - - assertEquals("cm:person", result.getJSONObject("source").get("class")); - assertEquals("cm:avatarOf", result.getJSONObject("source").get("role")); - assertEquals(false, result.getJSONObject("source").get("mandatory")); - assertEquals(false, result.getJSONObject("source").get("many")); - - assertEquals("cm:content", result.getJSONObject("target").get("class")); - assertEquals("cm:hasAvatar", result.getJSONObject("target").get("role")); - assertEquals(false, result.getJSONObject("target").get("mandatory")); - assertEquals(false, result.getJSONObject("target").get("many")); - - assertEquals("/api/classes/cm_person/association/cm_avatar", result.get("url")); - } - - private void validateTypeClass(JSONObject result) throws Exception - { - //cm:cmobject is of type =>type - assertEquals("cm:cmobject", result.get("name")); - assertEquals(false , result.get("isAspect")); - assertEquals("Object", result.get("title")); - assertEquals("", result.get("description")); - - assertEquals("sys:base", result.getJSONObject("parent").get("name")); - assertEquals("base", result.getJSONObject("parent").get("title")); - assertEquals("/api/classes/sys_base", result.getJSONObject("parent").get("url")); - - assertEquals("sys:referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("name")); - assertEquals("Referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("title")); - assertEquals("/api/classes/cm_cmobject/property/sys_referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("url")); - - assertEquals("cm:auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("name")); - assertEquals("Auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("title")); - assertEquals("/api/classes/cm_cmobject/property/cm_auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("url")); - - //assertEquals("cm:name", result.getJSONObject("properties").getJSONObject("cm:name").get("name")); - //assertEquals("Name", result.getJSONObject("properties").getJSONObject("cm:name").get("title")); - //assertEquals("/api/classes/cm_cmobject/property/cm_name", result.getJSONObject("properties").getJSONObject("cm:name").get("url")); - - //assertEquals(, result.getJSONObject("associations").length()); - //assertEquals(0, result.getJSONObject("childassociations").length()); - - assertEquals("/api/classes/cm_cmobject", result.get("url")); - - } - - private void validateAspectClass(JSONObject result) throws Exception - { - //cm:thumbnailed is of type =>aspect - assertEquals("cm:thumbnailed", result.get("name")); - assertEquals(true , result.get("isAspect")); - assertEquals("Thumbnailed", result.get("title")); - assertEquals("", result.get("description")); - assertEquals(0, result.getJSONObject("defaultAspects").length()); - - if (result.getJSONObject("properties").has("cm:automaticUpdate") == true) - { - assertEquals("cm:automaticUpdate", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("name")); - assertEquals("Automatic Update", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("title")); - assertEquals("/api/classes/cm_thumbnailed/property/cm_automaticUpdate", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("url")); - } - - //assertEquals(2, result.getJSONObject("associations").length()); - } - - private void validatePropertiesConformity(JSONArray classDefs) throws Exception - { - final int itemsToTest = 10; - for (int i = 0; (i < itemsToTest) && (i < classDefs.length()); ++i) - { - JSONObject classDef1 = classDefs.getJSONObject(i); - JSONArray propertyNames1 = classDef1.getJSONObject("properties").names(); - // properties of class obtained by api/classes - List propertyValues1 = Collections.emptyList(); - if (propertyNames1 != null) - { - propertyValues1 = new ArrayList(propertyNames1.length()); - for (int j = 0; j < propertyNames1.length(); j++) - { - propertyValues1.add(propertyNames1.getString(j)); - } - } - - String classUrl = classDef1.getString("url"); - assertTrue(classUrl.contains(URL_SITES)); - Response responseFromGetClassDef = sendRequest(new GetRequest(classUrl), 200); - JSONObject classDef2 = new JSONObject(responseFromGetClassDef.getContentAsString()); - assertTrue(classDef2.length() > 0); - assertEquals(200, responseFromGetClassDef.getStatus()); - assertEquals(classDef1.getString("name"), classDef2.getString("name")); - JSONArray propertyNames2 = classDef2.getJSONObject("properties").names(); - // properties of class obtained by api/classes/class - List propertyValues2 = Collections.emptyList(); - if (propertyNames2 != null) - { - propertyValues2 = new ArrayList(propertyNames2.length()); - for (int j = 0; j < propertyNames2.length(); j++) - { - propertyValues2.add(propertyNames2.getString(j)); - } - } - - Response responseFromGetPropertiesDef = sendRequest(new GetRequest(classUrl + "/properties"), 200); - JSONArray propertiesDefs = new JSONArray(responseFromGetPropertiesDef.getContentAsString()); - assertEquals(200, responseFromGetClassDef.getStatus()); - // properties of class obtained by api/classes/class/properties - List propertyValues3 = new ArrayList(propertiesDefs.length()); - for (int j = 0; j < propertiesDefs.length(); j++) - { - propertyValues3.add(propertiesDefs.getJSONObject(j).getString("name")); - } - - assertEquivalenceProperties(propertyValues1, propertyValues2); - assertEquivalenceProperties(propertyValues2, propertyValues3); - } - } - - private void assertEquivalenceProperties(List propertyValues1, List propertyValues2) - { - if ((propertyValues1.size() != propertyValues2.size()) || !propertyValues1.containsAll(propertyValues2)) - { - fail("Wrong properties in classes"); - } - } - - public void testGetPropertyDef() throws Exception - { - Response response = sendRequest(new GetRequest("/api/classes/cm_auditable/property/cm_created"), 200); - assertEquals(200,response.getStatus()); - JSONObject result = new JSONObject(response.getContentAsString()); - validatePropertyDef(result); - - assertEquals(result.length()>0, true); - response = sendRequest(new GetRequest("/api/classes/cm_hi/property/cm_welcome"), 404); - assertEquals(404,response.getStatus()); - - //invalid property name , returns a null JsonObject as such a property doesn't exist under cm_auditable - response = sendRequest(new GetRequest("/api/classes/cm_auditable/property/cm_welcome"), 200); - result = new JSONObject(response.getContentAsString()); - assertEquals(0, result.length()); - assertEquals(200,response.getStatus()); - } - - public void testGetPropertyDefs() throws Exception - { - //validate for a particular property cm_created in the class cm_auditable - GetRequest req = new GetRequest(URL_SITES + "/cm_auditable/properties"); - Map< String, String > arguments = new HashMap< String, String >(); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - Response response = sendRequest(req, 200); - assertEquals(200,response.getStatus()); - - JSONArray result = new JSONArray(response.getContentAsString()); - assertEquals(200,response.getStatus()); - assertEquals(5, result.length()); - - //validate with no parameter => returns an array of property definitions - arguments.clear(); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(200,response.getStatus()); - assertEquals(result.length()>0, true); - for(int i=0; i0, true); - for (int i = 0; i < result.length(); i++) - { - if(result.getJSONObject(i).get("name").equals("cm:created")) - { - validatePropertyDef(result.getJSONObject(i)); - } - - @SuppressWarnings("unused") - String title = ""; - if (result.getJSONObject(i).has("title") == true) - { - title = result.getJSONObject(i).getString("title"); - } - } - - // test /api/properties?name=cm:name&name=cm:title&name=cm:description - req = new GetRequest(URL_PROPERTIES + "?name=cm:name&name=cm:title&name=cm:description"); - response = sendRequest(req, 200); - assertEquals(200, response.getStatus()); - result = new JSONArray(response.getContentAsString()); - assertEquals(3, result.length()); - } - - public void testGetClassDetail() throws Exception - { - GetRequest req = new GetRequest(URL_SITES + "/cm_thumbnailed"); - Response response = sendRequest(req, 200); - JSONObject result = new JSONObject(response.getContentAsString()); - assertEquals(result.length()>0, true); - assertEquals(200,response.getStatus()); - validateAspectClass(result); - - req = new GetRequest(URL_SITES + "/cm_cmobject"); - response = sendRequest(req, 200); - result = new JSONObject(response.getContentAsString()); - assertEquals(result.length()>0, true); - assertEquals(200,response.getStatus()); - validateTypeClass(result); - - response = sendRequest(new GetRequest("/api/classes/cm_hi"), 404); - assertEquals(404,response.getStatus()); - } - - - public void testGetClassDetails() throws Exception - { - /** - * There are eight scenarios with getting class details , all are optional fields - * Classfilter namespaceprefix name Returns - * 1 yes yes yes single class - * 2 yes yes no Array of classes [returns array of classes of the particular namespaceprefix] - * 3 yes no no Array of classes [depends on classfilter, either type or aspect or all classes in the repo] - * 4 no no no Array of classes [returns all classes of both type and aspects in the entire repository] - * 5 no yes yes single class [returns a single class of a valid namespaceprefix:name combination] - * 6 no yes no Array of classes [returns an array of all aspects and types under particular namespaceprefix] - * 7 no no yes 404 error [since name alone doesn't makes any meaning] - * 8 yes no yes 404 error [since name alone doesn't makes any meaning] - * Test cases are provided for all the above scenarios - */ - - - //check for a aspect under cm with name thumbnailes [case-type:1] - GetRequest req = new GetRequest(URL_SITES); - Map< String, String > arguments = new HashMap< String, String >(); - arguments.put("cf", "aspect"); - arguments.put("nsp", "cm"); - arguments.put("n", "thumbnailed"); - req.setArgs(arguments); - Response response = sendRequest(req, 200); - JSONArray result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; iname, namespaceprefix [case-type:2] - arguments.clear(); - arguments.put("cf", "type"); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - // the above result has all the types under cm, so now check for the presence type cm:cmobject in the array of classes of all types - for(int i=0; iname [case-type:2] - arguments.clear(); - arguments.put("cf", "aspect"); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - // the above result has all the aspects under cm, so now check for the presence aspect cm:thumnailed in the array of classes of all aspects - for(int i=0; iname [case-type:2] - arguments.clear(); - arguments.put("cf", "all"); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; iname, namespaceprefix [case-type:3] - arguments.clear(); - arguments.put("cf", "type"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; iname, namespaceprefix [case-type:3] - arguments.clear(); - arguments.put("cf", "aspect"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i cm:cmobject] without classfilter option [case-type:5] - arguments.clear(); - arguments.put("nsp", "cm"); - arguments.put("n", "cmobject"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i cm:thumbnailed] without classfilter option [case-type:5] - arguments.clear(); - arguments.put("nsp", "cm"); - arguments.put("n", "thumbnailed"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i cm] without classfilter and name option [case-type:6] - arguments.clear(); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i cm] without classfilter and name option [case-type:6] - arguments.clear(); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i cm] without classfilter and name option [case-type:6] - arguments.clear(); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 200); - result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i returns 404 error - arguments.clear(); - arguments.put("n", "cmobject"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - - //check for a type under cm with name cmobject and no namespaceprefix [case-type:8] => returns 404 error - arguments.clear(); - arguments.put("cf", "type"); - arguments.put("n", "cmobject"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - // Test with wrong data - //check for all aspects under cm without option=>name - arguments.clear(); - arguments.put("cf", "aspects"); - arguments.put("nsp", "cm"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - //check for all types under cm without option=>name - arguments.clear(); - arguments.put("cf", "types"); - arguments.put("nsp", "cmd"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - //check for all dictionary data without option=>name and option=>namespaceprefix - arguments.clear(); - arguments.put("cf", "a�&llsara"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - //check for all aspect dictionary data without option=>name and option=>namespaceprefix - arguments.clear(); - arguments.put("cf", "aspectb"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - //check for all types dictionary data without option=>name and option=>namespaceprefix - arguments.clear(); - arguments.put("cf", "typesa"); - req.setArgs(arguments); - response = sendRequest(req, 404); - assertEquals(404,response.getStatus()); - - //check for all types dictionary data without option=>name and option=>namespaceprefix and option=>classfilter - arguments.clear(); - req.setArgs(arguments); - response = sendRequest(req, 200); - assertEquals(200,response.getStatus()); - } - - public void testSubClassDetails() throws Exception - { - GetRequest req = new GetRequest(URL_SITES + "/sys_base/subclasses"); - Map< String, String > arguments = new HashMap< String, String >(); - arguments.put("r", "true"); - req.setArgs(arguments); - Response response = sendRequest(req, 200); - assertEquals(200,response.getStatus()); - response = sendRequest(req, 200); - JSONArray result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i arguments = new HashMap< String, String >(); - arguments.put("af", "all"); - req.setArgs(arguments); - Response response = sendRequest(req, 200); - JSONArray result = new JSONArray(response.getContentAsString()); - assertEquals(result.length()>0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i0, true); - for(int i=0; i 0); - assertEquals(200, response.getStatus()); - validatePropertiesConformity(result); - } - -} +package org.alfresco.repo.web.scripts.dictionary; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONObject; +import org.json.JSONArray; + +/** + * Unit test for Dictionary REST API + * @author Saravanan Sellathurai + */ + +public class DictionaryRestApiTest extends BaseWebScriptTest +{ + private static final String URL_SITES = "/api/classes"; + private static final String URL_PROPERTIES = "/api/properties"; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + getServer(); + AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + AuthenticationUtil.clearCurrentSecurityContext(); + } + + private void validatePropertyDef(JSONObject result) throws Exception + { + assertEquals("cm:created", result.get("name")); + assertEquals("Created Date", result.get("title")); + assertEquals("Created Date", result.get("description")); + assertEquals("d:datetime", result.get("dataType")); + assertEquals(false, result.get("multiValued")); + assertEquals(true, result.get("mandatory")); + assertEquals(true, result.get("enforced")); + assertEquals(true, result.get("protected")); + assertEquals(true, result.get("indexed")); + assertEquals(true, result.get("indexedAtomically")); + assertEquals("/api/property/cm_created", result.get("url")); + + } + + private void validateChildAssociation(JSONObject result) throws Exception + { + assertEquals("cm:member", result.get("name")); + assertEquals(true, result.get("isChildAssociation")); + assertEquals(false, result.get("protected")); + + assertEquals("cm:authorityContainer", result.getJSONObject("source").get("class")); + assertEquals(false, result.getJSONObject("source").get("mandatory")); + assertEquals(true, result.getJSONObject("source").get("many")); + + assertEquals("cm:authority", result.getJSONObject("target").get("class")); + assertEquals(false, result.getJSONObject("target").get("mandatory")); + assertEquals(true, result.getJSONObject("target").get("many")); + + assertTrue(result.get("url").toString().startsWith("/api/classes/")); + assertTrue(result.get("url").toString().indexOf("/association/cm_member") > 0);; + } + + private void validateAssociation(JSONObject result) throws Exception + { + assertEquals("cm:workingcopylink", result.get("name")); + assertEquals(false, result.get("isChildAssociation")); + assertEquals(false, result.get("protected")); + + assertEquals("cm:checkedOut", result.getJSONObject("source").get("class")); + assertEquals(true, result.getJSONObject("source").get("mandatory")); + assertEquals(false, result.getJSONObject("source").get("many")); + + assertEquals("cm:workingcopy", result.getJSONObject("target").get("class")); + assertEquals(true, result.getJSONObject("target").get("mandatory")); + assertEquals(false, result.getJSONObject("target").get("many")); + + assertEquals("/api/classes/cm_checkedOut/association/cm_workingcopylink", result.get("url")); + } + private void validateAssociationDef(JSONObject result) throws Exception + { + assertEquals("cm:avatar", result.get("name")); + assertEquals("Avatar", result.get("title")); + assertEquals("The person's avatar image", result.get("description")); + assertEquals(false, result.get("isChildAssociation")); + assertEquals(false, result.get("protected")); + + assertEquals("cm:person", result.getJSONObject("source").get("class")); + assertEquals("cm:avatarOf", result.getJSONObject("source").get("role")); + assertEquals(false, result.getJSONObject("source").get("mandatory")); + assertEquals(false, result.getJSONObject("source").get("many")); + + assertEquals("cm:content", result.getJSONObject("target").get("class")); + assertEquals("cm:hasAvatar", result.getJSONObject("target").get("role")); + assertEquals(false, result.getJSONObject("target").get("mandatory")); + assertEquals(false, result.getJSONObject("target").get("many")); + + assertEquals("/api/classes/cm_person/association/cm_avatar", result.get("url")); + } + + private void validateTypeClass(JSONObject result) throws Exception + { + //cm:cmobject is of type =>type + assertEquals("cm:cmobject", result.get("name")); + assertEquals(false , result.get("isAspect")); + assertEquals("Object", result.get("title")); + assertEquals("", result.get("description")); + + assertEquals("sys:base", result.getJSONObject("parent").get("name")); + assertEquals("base", result.getJSONObject("parent").get("title")); + assertEquals("/api/classes/sys_base", result.getJSONObject("parent").get("url")); + + assertEquals("sys:referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("name")); + assertEquals("Referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("title")); + assertEquals("/api/classes/cm_cmobject/property/sys_referenceable", result.getJSONObject("defaultAspects").getJSONObject("sys:referenceable").get("url")); + + assertEquals("cm:auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("name")); + assertEquals("Auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("title")); + assertEquals("/api/classes/cm_cmobject/property/cm_auditable", result.getJSONObject("defaultAspects").getJSONObject("cm:auditable").get("url")); + + //assertEquals("cm:name", result.getJSONObject("properties").getJSONObject("cm:name").get("name")); + //assertEquals("Name", result.getJSONObject("properties").getJSONObject("cm:name").get("title")); + //assertEquals("/api/classes/cm_cmobject/property/cm_name", result.getJSONObject("properties").getJSONObject("cm:name").get("url")); + + //assertEquals(, result.getJSONObject("associations").length()); + //assertEquals(0, result.getJSONObject("childassociations").length()); + + assertEquals("/api/classes/cm_cmobject", result.get("url")); + + } + + private void validateAspectClass(JSONObject result) throws Exception + { + //cm:thumbnailed is of type =>aspect + assertEquals("cm:thumbnailed", result.get("name")); + assertEquals(true , result.get("isAspect")); + assertEquals("Thumbnailed", result.get("title")); + assertEquals("", result.get("description")); + assertEquals(0, result.getJSONObject("defaultAspects").length()); + + if (result.getJSONObject("properties").has("cm:automaticUpdate") == true) + { + assertEquals("cm:automaticUpdate", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("name")); + assertEquals("Automatic Update", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("title")); + assertEquals("/api/classes/cm_thumbnailed/property/cm_automaticUpdate", result.getJSONObject("properties").getJSONObject("cm:automaticUpdate").get("url")); + } + + //assertEquals(2, result.getJSONObject("associations").length()); + } + + private void validatePropertiesConformity(JSONArray classDefs) throws Exception + { + final int itemsToTest = 10; + for (int i = 0; (i < itemsToTest) && (i < classDefs.length()); ++i) + { + JSONObject classDef1 = classDefs.getJSONObject(i); + JSONArray propertyNames1 = classDef1.getJSONObject("properties").names(); + // properties of class obtained by api/classes + List propertyValues1 = Collections.emptyList(); + if (propertyNames1 != null) + { + propertyValues1 = new ArrayList(propertyNames1.length()); + for (int j = 0; j < propertyNames1.length(); j++) + { + propertyValues1.add(propertyNames1.getString(j)); + } + } + + String classUrl = classDef1.getString("url"); + assertTrue(classUrl.contains(URL_SITES)); + Response responseFromGetClassDef = sendRequest(new GetRequest(classUrl), 200); + JSONObject classDef2 = new JSONObject(responseFromGetClassDef.getContentAsString()); + assertTrue(classDef2.length() > 0); + assertEquals(200, responseFromGetClassDef.getStatus()); + assertEquals(classDef1.getString("name"), classDef2.getString("name")); + JSONArray propertyNames2 = classDef2.getJSONObject("properties").names(); + // properties of class obtained by api/classes/class + List propertyValues2 = Collections.emptyList(); + if (propertyNames2 != null) + { + propertyValues2 = new ArrayList(propertyNames2.length()); + for (int j = 0; j < propertyNames2.length(); j++) + { + propertyValues2.add(propertyNames2.getString(j)); + } + } + + Response responseFromGetPropertiesDef = sendRequest(new GetRequest(classUrl + "/properties"), 200); + JSONArray propertiesDefs = new JSONArray(responseFromGetPropertiesDef.getContentAsString()); + assertEquals(200, responseFromGetClassDef.getStatus()); + // properties of class obtained by api/classes/class/properties + List propertyValues3 = new ArrayList(propertiesDefs.length()); + for (int j = 0; j < propertiesDefs.length(); j++) + { + propertyValues3.add(propertiesDefs.getJSONObject(j).getString("name")); + } + + assertEquivalenceProperties(propertyValues1, propertyValues2); + assertEquivalenceProperties(propertyValues2, propertyValues3); + } + } + + private void assertEquivalenceProperties(List propertyValues1, List propertyValues2) + { + if ((propertyValues1.size() != propertyValues2.size()) || !propertyValues1.containsAll(propertyValues2)) + { + fail("Wrong properties in classes"); + } + } + + public void testGetPropertyDef() throws Exception + { + Response response = sendRequest(new GetRequest("/api/classes/cm_auditable/property/cm_created"), 200); + assertEquals(200,response.getStatus()); + JSONObject result = new JSONObject(response.getContentAsString()); + validatePropertyDef(result); + + assertEquals(result.length()>0, true); + response = sendRequest(new GetRequest("/api/classes/cm_hi/property/cm_welcome"), 404); + assertEquals(404,response.getStatus()); + + //invalid property name , returns a null JsonObject as such a property doesn't exist under cm_auditable + response = sendRequest(new GetRequest("/api/classes/cm_auditable/property/cm_welcome"), 200); + result = new JSONObject(response.getContentAsString()); + assertEquals(0, result.length()); + assertEquals(200,response.getStatus()); + } + + public void testGetPropertyDefs() throws Exception + { + //validate for a particular property cm_created in the class cm_auditable + GetRequest req = new GetRequest(URL_SITES + "/cm_auditable/properties"); + Map< String, String > arguments = new HashMap< String, String >(); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + Response response = sendRequest(req, 200); + assertEquals(200,response.getStatus()); + + JSONArray result = new JSONArray(response.getContentAsString()); + assertEquals(200,response.getStatus()); + assertEquals(5, result.length()); + + //validate with no parameter => returns an array of property definitions + arguments.clear(); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(200,response.getStatus()); + assertEquals(result.length()>0, true); + for(int i=0; i0, true); + for (int i = 0; i < result.length(); i++) + { + if(result.getJSONObject(i).get("name").equals("cm:created")) + { + validatePropertyDef(result.getJSONObject(i)); + } + + @SuppressWarnings("unused") + String title = ""; + if (result.getJSONObject(i).has("title") == true) + { + title = result.getJSONObject(i).getString("title"); + } + } + + // test /api/properties?name=cm:name&name=cm:title&name=cm:description + req = new GetRequest(URL_PROPERTIES + "?name=cm:name&name=cm:title&name=cm:description"); + response = sendRequest(req, 200); + assertEquals(200, response.getStatus()); + result = new JSONArray(response.getContentAsString()); + assertEquals(3, result.length()); + } + + public void testGetClassDetail() throws Exception + { + GetRequest req = new GetRequest(URL_SITES + "/cm_thumbnailed"); + Response response = sendRequest(req, 200); + JSONObject result = new JSONObject(response.getContentAsString()); + assertEquals(result.length()>0, true); + assertEquals(200,response.getStatus()); + validateAspectClass(result); + + req = new GetRequest(URL_SITES + "/cm_cmobject"); + response = sendRequest(req, 200); + result = new JSONObject(response.getContentAsString()); + assertEquals(result.length()>0, true); + assertEquals(200,response.getStatus()); + validateTypeClass(result); + + response = sendRequest(new GetRequest("/api/classes/cm_hi"), 404); + assertEquals(404,response.getStatus()); + } + + + public void testGetClassDetails() throws Exception + { + /** + * There are eight scenarios with getting class details , all are optional fields + * Classfilter namespaceprefix name Returns + * 1 yes yes yes single class + * 2 yes yes no Array of classes [returns array of classes of the particular namespaceprefix] + * 3 yes no no Array of classes [depends on classfilter, either type or aspect or all classes in the repo] + * 4 no no no Array of classes [returns all classes of both type and aspects in the entire repository] + * 5 no yes yes single class [returns a single class of a valid namespaceprefix:name combination] + * 6 no yes no Array of classes [returns an array of all aspects and types under particular namespaceprefix] + * 7 no no yes 404 error [since name alone doesn't makes any meaning] + * 8 yes no yes 404 error [since name alone doesn't makes any meaning] + * Test cases are provided for all the above scenarios + */ + + + //check for a aspect under cm with name thumbnailes [case-type:1] + GetRequest req = new GetRequest(URL_SITES); + Map< String, String > arguments = new HashMap< String, String >(); + arguments.put("cf", "aspect"); + arguments.put("nsp", "cm"); + arguments.put("n", "thumbnailed"); + req.setArgs(arguments); + Response response = sendRequest(req, 200); + JSONArray result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; iname, namespaceprefix [case-type:2] + arguments.clear(); + arguments.put("cf", "type"); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + // the above result has all the types under cm, so now check for the presence type cm:cmobject in the array of classes of all types + for(int i=0; iname [case-type:2] + arguments.clear(); + arguments.put("cf", "aspect"); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + // the above result has all the aspects under cm, so now check for the presence aspect cm:thumnailed in the array of classes of all aspects + for(int i=0; iname [case-type:2] + arguments.clear(); + arguments.put("cf", "all"); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; iname, namespaceprefix [case-type:3] + arguments.clear(); + arguments.put("cf", "type"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; iname, namespaceprefix [case-type:3] + arguments.clear(); + arguments.put("cf", "aspect"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i cm:cmobject] without classfilter option [case-type:5] + arguments.clear(); + arguments.put("nsp", "cm"); + arguments.put("n", "cmobject"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i cm:thumbnailed] without classfilter option [case-type:5] + arguments.clear(); + arguments.put("nsp", "cm"); + arguments.put("n", "thumbnailed"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i cm] without classfilter and name option [case-type:6] + arguments.clear(); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i cm] without classfilter and name option [case-type:6] + arguments.clear(); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i cm] without classfilter and name option [case-type:6] + arguments.clear(); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 200); + result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i returns 404 error + arguments.clear(); + arguments.put("n", "cmobject"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + + //check for a type under cm with name cmobject and no namespaceprefix [case-type:8] => returns 404 error + arguments.clear(); + arguments.put("cf", "type"); + arguments.put("n", "cmobject"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + // Test with wrong data + //check for all aspects under cm without option=>name + arguments.clear(); + arguments.put("cf", "aspects"); + arguments.put("nsp", "cm"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + //check for all types under cm without option=>name + arguments.clear(); + arguments.put("cf", "types"); + arguments.put("nsp", "cmd"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + //check for all dictionary data without option=>name and option=>namespaceprefix + arguments.clear(); + arguments.put("cf", "a�&llsara"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + //check for all aspect dictionary data without option=>name and option=>namespaceprefix + arguments.clear(); + arguments.put("cf", "aspectb"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + //check for all types dictionary data without option=>name and option=>namespaceprefix + arguments.clear(); + arguments.put("cf", "typesa"); + req.setArgs(arguments); + response = sendRequest(req, 404); + assertEquals(404,response.getStatus()); + + //check for all types dictionary data without option=>name and option=>namespaceprefix and option=>classfilter + arguments.clear(); + req.setArgs(arguments); + response = sendRequest(req, 200); + assertEquals(200,response.getStatus()); + } + + public void testSubClassDetails() throws Exception + { + GetRequest req = new GetRequest(URL_SITES + "/sys_base/subclasses"); + Map< String, String > arguments = new HashMap< String, String >(); + arguments.put("r", "true"); + req.setArgs(arguments); + Response response = sendRequest(req, 200); + assertEquals(200,response.getStatus()); + response = sendRequest(req, 200); + JSONArray result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i arguments = new HashMap< String, String >(); + arguments.put("af", "all"); + req.setArgs(arguments); + Response response = sendRequest(req, 200); + JSONArray result = new JSONArray(response.getContentAsString()); + assertEquals(result.length()>0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i0, true); + for(int i=0; i 0); + assertEquals(200, response.getStatus()); + validatePropertiesConformity(result); + } + +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/search/PersonSearchTest.java b/source/test-java/org/alfresco/repo/web/scripts/search/PersonSearchTest.java index 45714bd366..8e95f191ec 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/search/PersonSearchTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/search/PersonSearchTest.java @@ -1,118 +1,118 @@ -package org.alfresco.repo.web.scripts.search; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.util.PropertyMap; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -/** - * Unit test for PersonSearch Web Script. - * - * /alfresco/service/api/search/person?q=* - * @author Mark Rogers - */ -public class PersonSearchTest extends BaseWebScriptTest -{ - private static Log logger = LogFactory.getLog(PersonSearchTest.class); - - private MutableAuthenticationService authenticationService; - private AuthenticationComponent authenticationComponent; - private PersonService personService; - - private static final String USER_ONE = "PersonSearchTestOne"; - private static final String USER_TWO = "PersonSearchTestTwo"; - private static final String USER_THREE = "PersonSearchTestThree"; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - - this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); - this.authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); - this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); - this.authenticationComponent.setSystemUserAsCurrentUser(); - - // Create users - createUser(USER_ONE); - createUser(USER_TWO); - createUser(USER_THREE); - - // Do tests as user one - this.authenticationComponent.setCurrentUser(USER_ONE); - } - - private void createUser(String userName) - { - if (this.authenticationService.authenticationExists(userName) == false) - { - this.authenticationService.createAuthentication(userName, "PWD".toCharArray()); - - PropertyMap ppOne = new PropertyMap(4); - ppOne.put(ContentModel.PROP_USERNAME, userName); - ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); - ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); - ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); - ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); - - this.personService.createPerson(ppOne); - } - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); - } - - /** - * This is a basic sanity check of the search/person script. - */ - public void testSearch() throws Exception - { - /* - * Do the first query for default format and all results - */ - { - Response response = sendRequest(new GetRequest("/api/search/person?q=*"), Status.STATUS_OK); - logger.debug(response.getContentAsString()); - } - - /* - * Same search with HTML format - */ - { - Response response = sendRequest(new GetRequest("/api/search/person.html?q=*"), Status.STATUS_OK); - logger.debug(response.getContentAsString()); - } - - - /* - * Negative test - missing mandatory parameter - * - * Should really be a INVALID_REQUEST - */ - sendRequest(new GetRequest("/api/search/person?"), Status.STATUS_INTERNAL_SERVER_ERROR); - } - - public void testPortletSearch() throws Exception - { - Response response = sendRequest(new GetRequest("/api/search/person.portlet?q=*"), Status.STATUS_OK); - logger.debug(response.getContentAsString()); - } - - public void testAtomSearch() throws Exception - { - Response response = sendRequest(new GetRequest("/api/search/person.atom?q=*"), Status.STATUS_OK); - logger.debug(response.getContentAsString()); - } -} +package org.alfresco.repo.web.scripts.search; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.util.PropertyMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +/** + * Unit test for PersonSearch Web Script. + * + * /alfresco/service/api/search/person?q=* + * @author Mark Rogers + */ +public class PersonSearchTest extends BaseWebScriptTest +{ + private static Log logger = LogFactory.getLog(PersonSearchTest.class); + + private MutableAuthenticationService authenticationService; + private AuthenticationComponent authenticationComponent; + private PersonService personService; + + private static final String USER_ONE = "PersonSearchTestOne"; + private static final String USER_TWO = "PersonSearchTestTwo"; + private static final String USER_THREE = "PersonSearchTestThree"; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService"); + this.authenticationComponent = (AuthenticationComponent)getServer().getApplicationContext().getBean("authenticationComponent"); + this.personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); + this.authenticationComponent.setSystemUserAsCurrentUser(); + + // Create users + createUser(USER_ONE); + createUser(USER_TWO); + createUser(USER_THREE); + + // Do tests as user one + this.authenticationComponent.setCurrentUser(USER_ONE); + } + + private void createUser(String userName) + { + if (this.authenticationService.authenticationExists(userName) == false) + { + this.authenticationService.createAuthentication(userName, "PWD".toCharArray()); + + PropertyMap ppOne = new PropertyMap(4); + ppOne.put(ContentModel.PROP_USERNAME, userName); + ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); + ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); + ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); + ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + + this.personService.createPerson(ppOne); + } + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + } + + /** + * This is a basic sanity check of the search/person script. + */ + public void testSearch() throws Exception + { + /* + * Do the first query for default format and all results + */ + { + Response response = sendRequest(new GetRequest("/api/search/person?q=*"), Status.STATUS_OK); + logger.debug(response.getContentAsString()); + } + + /* + * Same search with HTML format + */ + { + Response response = sendRequest(new GetRequest("/api/search/person.html?q=*"), Status.STATUS_OK); + logger.debug(response.getContentAsString()); + } + + + /* + * Negative test - missing mandatory parameter + * + * Should really be a INVALID_REQUEST + */ + sendRequest(new GetRequest("/api/search/person?"), Status.STATUS_INTERNAL_SERVER_ERROR); + } + + public void testPortletSearch() throws Exception + { + Response response = sendRequest(new GetRequest("/api/search/person.portlet?q=*"), Status.STATUS_OK); + logger.debug(response.getContentAsString()); + } + + public void testAtomSearch() throws Exception + { + Response response = sendRequest(new GetRequest("/api/search/person.atom?q=*"), Status.STATUS_OK); + logger.debug(response.getContentAsString()); + } +} diff --git a/source/test-java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java b/source/test-java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java index ad5832552d..e9bdecb1ce 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java @@ -1,795 +1,795 @@ -package org.alfresco.repo.web.scripts.solr; - -import java.io.PrintWriter; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.solr.Acl; -import org.alfresco.repo.solr.AclChangeSet; -import org.alfresco.repo.solr.AclReaders; -import org.alfresco.repo.solr.SOLRTrackingComponent; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; -import org.alfresco.util.PropertyMap; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -/** - * Test the SOLR web scripts - * - * @since 4.0 - */ -public class SOLRWebScriptTest extends BaseWebScriptTest -{ - protected static final Log logger = LogFactory.getLog(SOLRWebScriptTest.class); - - private ApplicationContext ctx; - private SOLRTrackingComponent solrTrackingComponent; - private NodeDAO nodeDAO; - private TransactionService transactionService; - private NodeService nodeService; - private FileFolderService fileFolderService; - private RetryingTransactionHelper txnHelper; - private NamespaceService namespaceService; - - private String admin; - - private StoreRef storeRef; - private NodeRef rootNodeRef; - private NodeRef container3; - - private ArrayList contents = new ArrayList(100); - private List nodeIDs = new ArrayList(100); - - @Override - protected void setUp() throws Exception - { - super.setUp(); - ctx = getServer().getApplicationContext(); - - ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); - transactionService = serviceRegistry.getTransactionService(); - nodeService = serviceRegistry.getNodeService(); - fileFolderService = serviceRegistry.getFileFolderService(); - namespaceService = serviceRegistry.getNamespaceService(); - txnHelper = transactionService.getRetryingTransactionHelper(); - nodeDAO = (NodeDAO)ctx.getBean("nodeDAO"); - solrTrackingComponent = (SOLRTrackingComponent) ctx.getBean("solrTrackingComponent"); - - admin = AuthenticationUtil.getAdminUserName(); - - AuthenticationUtil.setFullyAuthenticatedUser(admin); - - storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".1." + System.currentTimeMillis()); - rootNodeRef = nodeService.getRootNode(storeRef); - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - } - - private JSONArray getTransactions(long fromCommitTime) throws Exception - { - String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime; - TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); - long startTime = System.currentTimeMillis(); - Response response = sendRequest(req, Status.STATUS_OK, admin); - long endTime = System.currentTimeMillis(); - - if(logger.isDebugEnabled()) - { - logger.debug(response.getContentAsString()); - } - JSONObject json = new JSONObject(response.getContentAsString()); - - JSONArray transactions = json.getJSONArray("transactions"); - - logger.debug("Got " + transactions.length() + " txns in " + (endTime - startTime) + " ms"); - - return transactions; - } - - public void testAclChangeSetsGet() throws Exception - { - String url = "/api/solr/aclchangesets?fromTime=" + 0L + "&fromId=" + 0L; - TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); - long startTime = System.currentTimeMillis(); - Response response = sendRequest(req, Status.STATUS_OK, admin); - long endTime = System.currentTimeMillis(); - - if(logger.isDebugEnabled()) - { - logger.debug(response.getContentAsString()); - } - JSONObject json = new JSONObject(response.getContentAsString()); - - JSONArray aclChangeSets = json.getJSONArray("aclChangeSets"); - - logger.debug("Got " + aclChangeSets.length() + " txns in " + (endTime - startTime) + " ms"); - } - - public void testAclsGet() throws Exception - { - List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, null, null, 100); - if (aclChangeSets.size() == 0) - { - return; // Can't test, but very unlikely - } - // Build JSON using these - JSONObject json = new JSONObject(); - JSONArray aclChangeSetIdsJSON = new JSONArray(); - int count = 0; - List aclChangeSetIds = new ArrayList(); - for (AclChangeSet aclChangeSet : aclChangeSets) - { - if (count >= 512) - { - break; - } - if (aclChangeSet.getAclCount() == 0) - { - continue; // No ACLs - } - Long aclChangeSetId = aclChangeSet.getId(); - aclChangeSetIdsJSON.put(aclChangeSetId); - aclChangeSetIds.add(aclChangeSetId); - count++; - } - json.put("aclChangeSetIds", aclChangeSetIdsJSON); - - String url = "/api/solr/acls"; - TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json"); - Response response = sendRequest(req, Status.STATUS_OK, admin); - if(logger.isDebugEnabled()) - { - logger.debug(response.getContentAsString()); - } - json = new JSONObject(response.getContentAsString()); - JSONArray acls = json.getJSONArray("acls"); - - // Check - List aclsCheck = solrTrackingComponent.getAcls(aclChangeSetIds, null, 512); - assertEquals("Script and API returned different number of results", aclsCheck.size(), acls.length()); - } - - public void testAclReadersGet() throws Exception - { - txnHelper.doInTransaction( - new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - aclReadersGetImpl(); - return null; - } - } - ); - } - - private void aclReadersGetImpl() throws Exception - { - List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, null, null, 1024); - List aclChangeSetIds = new ArrayList(50); - for (AclChangeSet aclChangeSet : aclChangeSets) - { - if (aclChangeSet.getAclCount() > 0) - { - aclChangeSetIds.add(aclChangeSet.getId()); - break; - } - } - if (aclChangeSetIds.size() == 0) - { - // No ACLs; not likely - } - List acls = solrTrackingComponent.getAcls(aclChangeSetIds, null, 1024); - List aclIds = new ArrayList(acls.size()); - JSONObject json = new JSONObject(); - JSONArray aclIdsJSON = new JSONArray(); - for (Acl acl : acls) - { - Long aclId = acl.getId(); - aclIds.add(aclId); - aclIdsJSON.put(aclId); - } - json.put("aclIds", aclIdsJSON); - - // Now get the readers - List aclsReaders = solrTrackingComponent.getAclsReaders(aclIds); - assertEquals("Should have same number of ACLs as supplied", aclIds.size(), aclsReaders.size()); - assertTrue("Must have *some* ACLs here", aclIds.size() > 0); - Map> readersByAclId = new HashMap>(); - for (AclReaders aclReaders : aclsReaders) - { - readersByAclId.put(aclReaders.getAclId(), aclReaders.getReaders()); - } - - Map> deniedByAclId = new HashMap>(); - for (AclReaders aclReaders : aclsReaders) - { - assertNotNull("AclReaders should not contain null denial set", aclReaders.getDenied()); - deniedByAclId.put(aclReaders.getAclId(), aclReaders.getDenied()); - } - - // Now query using the webscript - String url = "/api/solr/aclsReaders"; - TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json"); - Response response = sendRequest(req, Status.STATUS_OK, admin); - if(logger.isDebugEnabled()) - { - logger.debug(response.getContentAsString()); - } - json = new JSONObject(response.getContentAsString()); - JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders"); - // Check - assertEquals("Script and API returned different number of results", readersByAclId.size(), aclsReadersJSON.length()); - - // Iterate of the JSON and ensure that the list of ACL readers is correct - for (int i = 0; i < aclsReadersJSON.length(); i++) - { - // Choose an ACL and check the readers - JSONObject aclReadersJSON = aclsReadersJSON.getJSONObject(i); - Long aclIdJSON = aclReadersJSON.getLong("aclId"); - Set readersCheck = readersByAclId.get(aclIdJSON); - JSONArray readersJSON = aclReadersJSON.getJSONArray("readers"); - assertEquals("Readers list for ACL " + aclIdJSON + " is wrong. ", readersCheck.size(), readersJSON.length()); - for (int j = 0; j < readersJSON.length(); j++) - { - String readerJSON = readersJSON.getString(j); - assertTrue("Found reader not in check set: " + readerJSON, readersCheck.contains(readerJSON)); - } - - Set deniedCheck = deniedByAclId.get(aclIdJSON); - JSONArray deniedJSON = aclReadersJSON.getJSONArray("denied"); - assertEquals("Denied list for ACL " + aclIdJSON + " is wrong. ", deniedCheck.size(), deniedJSON.length()); - for (int j = 0; j < deniedJSON.length(); j++) - { - String denyJSON = deniedJSON.getString(j); - assertTrue("Found denied authority not in check set: " + denyJSON, deniedCheck.contains(denyJSON)); - } - } - } - - private JSONArray getNodes(GetNodesParameters parameters, int maxResults, int expectedNumNodes) throws Exception - { - StringBuilder url = new StringBuilder("/api/solr/nodes"); - - JSONObject json = new JSONObject(); - if(parameters.getTransactionIds() != null) - { - JSONArray array = new JSONArray(); - for(Long txnId : parameters.getTransactionIds()) - { - array.put(txnId); - } - json.put("txnIds", array); - } - - if(parameters.getFromNodeId() != null) - { - json.put("fromNodeId", parameters.getFromNodeId()); - } - - if(parameters.getToNodeId() != null) - { - json.put("toNodeId", parameters.getToNodeId()); - } - - if(parameters.getExcludeAspects() != null) - { - JSONArray array = new JSONArray(); - for(QName excludeAspect : parameters.getExcludeAspects()) - { - array.put(excludeAspect.toString()); - } - json.put("excludeAspects", array); - } - - if(parameters.getIncludeAspects() != null) - { - JSONArray array = new JSONArray(); - for(QName includeAspect : parameters.getIncludeAspects()) - { - array.put(includeAspect.toString()); - } - json.put("includeAspects", array); - } - - if(parameters.getStoreProtocol() != null) - { - json.put("storeProtocol", parameters.getStoreProtocol()); - } - - if(parameters.getStoreIdentifier() != null) - { - json.put("storeIdentifier", parameters.getStoreIdentifier()); - } - - json.put("maxResults", maxResults); - - TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url.toString(), json.toString(), "application/json"); - - long startTime = System.currentTimeMillis(); - Response response = sendRequest(req, Status.STATUS_OK, admin); - long endTime = System.currentTimeMillis(); - -// assertEquals("Expected application/json content type", "application/json[;charset=UTF-8]", response.getContentType()); - - if(logger.isDebugEnabled()) - { - logger.debug(response.getContentAsString()); - } - //logger.debug("getNodes: " + response.getContentAsString()); - JSONObject jsonResponse = new JSONObject(response.getContentAsString()); - jsonResponse.write(new PrintWriter(System.out)); - - JSONArray nodes = jsonResponse.getJSONArray("nodes"); - - //assertEquals("Node count is incorrect", nodes.length(), json.getInt("count")); - - logger.debug("Got " + nodes.length() + " nodes in " + (endTime - startTime) + " ms"); - - assertEquals("Number of returned node meta data results is incorrect", expectedNumNodes, nodes.length()); - - return nodes; - } - - private List getTransactionIds(JSONArray transactions) throws JSONException - { - List txnIds = new ArrayList(transactions.length()); - - int numTxns = transactions.length(); - for(int i = 0; i < numTxns; i++) - { - JSONObject txn = transactions.getJSONObject(i); - txnIds.add(txn.getLong("id")); - } - - return txnIds; - } - - public static String join(Collection s, String delimiter) - { - StringBuffer buffer = new StringBuffer(); - Iterator iter = s.iterator(); - while (iter.hasNext()) - { - buffer.append(iter.next()); - if (iter.hasNext()) - { - buffer.append(delimiter); - } - } - return buffer.toString(); - } - - private void buildTransactions3() - { - txnHelper.doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - PropertyMap props = new PropertyMap(); - props.put(ContentModel.PROP_NAME, "Container3"); - container3 = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - ContentModel.ASSOC_CHILDREN, - ContentModel.TYPE_FOLDER, - props).getChildRef(); - if(logger.isDebugEnabled()) - { - logger.debug("container3 = " + container3); - } - - for(int i = 0; i < 100; i++) - { - FileInfo content1Info = fileFolderService.create(container3, "Content" + i, ContentModel.TYPE_CONTENT); - NodeRef nodeRef = content1Info.getNodeRef(); - contents.add(nodeRef); - nodeIDs.add(Long.valueOf(getNodeID(nodeRef))); - - if(i % 2 == 1) - { - nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); - } - } - - return null; - } - }); - } - - private NodeRef container6; - - private void buildTransactions5() - { - txnHelper.doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - PropertyMap props = new PropertyMap(); - props.put(ContentModel.PROP_NAME, "Container6"); - container6 = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - ContentModel.ASSOC_CHILDREN, - ContentModel.TYPE_FOLDER, - props).getChildRef(); - - FileInfo contentInfo = fileFolderService.create(container6, "Content1", ContentModel.TYPE_CONTENT); - contents.add(contentInfo.getNodeRef()); - - Map aspectProperties = new HashMap(); - aspectProperties.put(ContentModel.PROP_AUTHOR, "steve"); - nodeService.addAspect(contentInfo.getNodeRef(), ContentModel.ASPECT_AUTHOR, aspectProperties); - - return null; - } - }); - } - - private JSONArray getNodesMetaData(List nodeIds, int maxResults, int numMetaDataNodes) throws Exception - { - StringBuilder url = new StringBuilder("/api/solr/metadata"); - - JSONObject json = new JSONObject(); - if(nodeIds != null && nodeIds.size() > 0) - { - JSONArray array = new JSONArray(); - for(Long nodeId : nodeIds) - { - array.put(nodeId); - } - json.put("nodeIds", array); - } - - json.put("maxResults", maxResults); - - TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url.toString(), json.toString(), "application/json"); - long startTime = System.currentTimeMillis(); - Response response = sendRequest(req, Status.STATUS_OK, admin); - long endTime = System.currentTimeMillis(); - - String content = response.getContentAsString(); - - if(logger.isDebugEnabled()) - { - logger.debug("nodesMetaData = " + content); - } - - JSONObject jsonResponse = null; - - try - { - jsonResponse = new JSONObject(content); - } - catch(JSONException e) - { - fail(e.getMessage()); - } - - JSONArray nodes = jsonResponse.getJSONArray("nodes"); - - logger.debug("Got metadata for " + nodes.length() + " nodes in " + (endTime - startTime) + " ms"); - - assertEquals("Number of returned nodes is incorrect", numMetaDataNodes, nodes.length()); - - return nodes; - } - - private void buildTransactions6() - { - txnHelper.doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - PropertyMap props = new PropertyMap(); - props.put(ContentModel.PROP_NAME, "Container6"); - NodeRef container6 = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - ContentModel.ASSOC_CHILDREN, - ContentModel.TYPE_FOLDER, - props).getChildRef(); - if(logger.isDebugEnabled()) - { - logger.debug("container6 = " + container6); - } - - for(int i = 0; i < 2000; i++) - { - FileInfo content1Info = fileFolderService.create(container6, "Content" + i, ContentModel.TYPE_CONTENT); - NodeRef nodeRef = content1Info.getNodeRef(); - contents.add(nodeRef); - - if(i % 2 == 1) - { - nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); - } - } - - return null; - } - }); - } - - public void testNodeMetaData() throws Exception - { - long fromCommitTime = System.currentTimeMillis(); - - buildTransactions5(); - - JSONArray transactions = getTransactions(fromCommitTime); - assertEquals("Number of transactions is incorrect", 1, transactions.length()); - - List transactionIds = getTransactionIds(transactions); - - GetNodesParameters params = new GetNodesParameters(); - params.setTransactionIds(transactionIds); - params.setStoreProtocol(storeRef.getProtocol()); - params.setStoreIdentifier(storeRef.getIdentifier()); - JSONArray nodes = getNodes(params, 0, 2); - - List nodeIds = new ArrayList(nodes.length()); - for(int i = 0; i < nodes.length(); i++) - { - JSONObject node = nodes.getJSONObject(i); - nodeIds.add(node.getLong("id")); - } - - JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2); - - // test second entry (second node created in buildTransactions) - NodeRef expectedNodeRef = contents.get(0); - - JSONObject node = nodesMetaData.getJSONObject(1); - NodeRef nodeRef = new NodeRef(node.getString("nodeRef")); - - assertEquals("NodeRef is incorrect", expectedNodeRef, nodeRef); - - JSONArray aspects = node.getJSONArray("aspects"); - JSONObject properties = node.getJSONObject("properties"); - Map propertyMap = getPropertyMap(properties); - - assertTrue("Expected author aspect", containsAspect(aspects, ContentModel.ASPECT_AUTHOR)); - assertTrue("Expected author property", containsProperty(propertyMap, ContentModel.PROP_AUTHOR, "steve")); - - JSONArray paths = node.getJSONArray("paths"); - List expectedPaths = nodeService.getPaths(expectedNodeRef, false); - for(int i = 0; i < paths.length(); i++) - { - JSONObject o = paths.getJSONObject(i); - String path = o.getString("path"); - String qname = o.has("qname") ? o.getString("qname") : null; - String expectedPath = expectedPaths.get(i).toString(); - assertEquals("Path element " + i + " is incorrect", expectedPath, path); - assertNull("qname should be null", qname); - } - } - - private NodeRef container7; - - private void buildTransactions7() - { - txnHelper.doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - PropertyMap props = new PropertyMap(); - props.put(ContentModel.PROP_NAME, "Container7"); - container7 = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - ContentModel.ASSOC_CHILDREN, - ContentModel.TYPE_FOLDER, - props).getChildRef(); - - FileInfo contentInfo = fileFolderService.create(container7, "Content1", ContentModel.TYPE_CONTENT); - contents.add(contentInfo.getNodeRef()); - - Map aspectProperties = new HashMap(); - aspectProperties.put(ContentModel.PROP_AUTHOR, "ste\"ve"); - nodeService.addAspect(contentInfo.getNodeRef(), ContentModel.ASPECT_AUTHOR, aspectProperties); - - return null; - } - }); - } - - public void testNodeMetaDataStringEscaping() throws Exception - { - long fromCommitTime = System.currentTimeMillis(); - - buildTransactions7(); - - JSONArray transactions = getTransactions(fromCommitTime); - assertEquals("Number of transactions is incorrect", 1, transactions.length()); - - List transactionIds = getTransactionIds(transactions); - - GetNodesParameters params = new GetNodesParameters(); - params.setTransactionIds(transactionIds); - params.setStoreProtocol(storeRef.getProtocol()); - params.setStoreIdentifier(storeRef.getIdentifier()); - JSONArray nodes = getNodes(params, 0, 2); - - List nodeIds = new ArrayList(nodes.length()); - for(int i = 0; i < nodes.length(); i++) - { - JSONObject node = nodes.getJSONObject(i); - nodeIds.add(node.getLong("id")); - } - - JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2); - - // test second entry (second node created in buildTransactions) - NodeRef expectedNodeRef = contents.get(0); - - JSONObject node = nodesMetaData.getJSONObject(1); - NodeRef nodeRef = new NodeRef(node.getString("nodeRef")); - - assertEquals("NodeRef is incorrect", expectedNodeRef, nodeRef); - - JSONArray aspects = node.getJSONArray("aspects"); - JSONObject properties = node.getJSONObject("properties"); - Map propertyMap = getPropertyMap(properties); - - assertTrue("Expected author aspect", containsAspect(aspects, ContentModel.ASPECT_AUTHOR)); - assertTrue("Expected author property", containsProperty(propertyMap, ContentModel.PROP_AUTHOR, "ste\"ve")); - } - - public void testNodeMetaDataManyNodes() throws Exception - { - long fromCommitTime = System.currentTimeMillis(); - - buildTransactions6(); - - JSONArray transactions = getTransactions(fromCommitTime); - assertEquals("Number of transactions is incorrect", 1, transactions.length()); - - List transactionIds = getTransactionIds(transactions); - - GetNodesParameters params = new GetNodesParameters(); - params.setStoreProtocol(storeRef.getProtocol()); - params.setStoreIdentifier(storeRef.getIdentifier()); - params.setTransactionIds(transactionIds); - JSONArray nodes = getNodes(params, 0, 2001); - - List nodeIds = new ArrayList(nodes.length()); - for(int i = 0; i < nodes.length(); i++) - { - JSONObject node = nodes.getJSONObject(i); - nodeIds.add(node.getLong("id")); - } - - // make sure caches are warm - time last call - @SuppressWarnings("unused") - JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); - nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); - - // sleep for a couple of seconds - try - { - Thread.sleep(2000); - } - catch(InterruptedException e) - { - // ignore - } - nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); - - nodesMetaData = getNodesMetaData(nodeIds, 1000, 1000); - nodesMetaData = getNodesMetaData(nodeIds, 600, 600); - nodesMetaData = getNodesMetaData(nodeIds, 300, 300); - nodesMetaData = getNodesMetaData(nodeIds, 100, 100); - nodesMetaData = getNodesMetaData(nodeIds, 50, 50); - - // clear out caches - nodeDAO.clear(); - - nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); - } - - private boolean containsAspect(JSONArray aspectsArray, QName aspect) throws Exception - { - if(aspect == null) - { - throw new IllegalArgumentException("aspect cannot be null"); - } - - boolean success = false; - for(int i = 0; i < aspectsArray.length(); i++) - { - String qName = aspectsArray.getString(i); - if(aspect.equals(QName.createQName(qName, namespaceService))) - { - success |= true; - break; - } - } - - return success; - } - - private Map getPropertyMap(JSONObject properties) throws Exception - { - Map propertyMap = new HashMap(properties.length()); - @SuppressWarnings("rawtypes") - Iterator propNames = properties.keys(); - while(propNames.hasNext()) - { - String propName = (String)propNames.next(); - String value = properties.getString(propName); - - propertyMap.put(QName.resolveToQName(namespaceService, propName), value); - } - - return propertyMap; - } - - private boolean containsProperty(Map propertyMap, QName propName, String propValue) throws Exception - { - if(propName == null) - { - throw new IllegalArgumentException("propName cannot be null"); - } - - String value = propertyMap.get(propName); - return (value == null ? false : value.equals(propValue)); - } - - public void DISABLED_testGetContent() throws Exception - { - long nodeId = -1l; - String propertyName = ContentModel.PROP_CONTENT.toString(); - - buildTransactions3(); - - String url = "/api/solr/content?nodeId=" + nodeId + "&propertyName=" + propertyName; - TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); - Response response = sendRequest(req, Status.STATUS_OK, admin); - if (logger.isDebugEnabled()) - { - logger.debug("content1 = " + response.getContentAsString()); - } - assertEquals("Content length is incorrect", "test content".length(), response.getContentLength()); - } - - private long getNodeID(NodeRef nodeRef) - { - Pair pair = nodeDAO.getNodePair(nodeRef); - assertNotNull("Can't find node " + nodeRef, pair); - return pair.getFirst(); - } +package org.alfresco.repo.web.scripts.solr; + +import java.io.PrintWriter; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.solr.Acl; +import org.alfresco.repo.solr.AclChangeSet; +import org.alfresco.repo.solr.AclReaders; +import org.alfresco.repo.solr.SOLRTrackingComponent; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; +import org.alfresco.util.PropertyMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +/** + * Test the SOLR web scripts + * + * @since 4.0 + */ +public class SOLRWebScriptTest extends BaseWebScriptTest +{ + protected static final Log logger = LogFactory.getLog(SOLRWebScriptTest.class); + + private ApplicationContext ctx; + private SOLRTrackingComponent solrTrackingComponent; + private NodeDAO nodeDAO; + private TransactionService transactionService; + private NodeService nodeService; + private FileFolderService fileFolderService; + private RetryingTransactionHelper txnHelper; + private NamespaceService namespaceService; + + private String admin; + + private StoreRef storeRef; + private NodeRef rootNodeRef; + private NodeRef container3; + + private ArrayList contents = new ArrayList(100); + private List nodeIDs = new ArrayList(100); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ctx = getServer().getApplicationContext(); + + ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); + transactionService = serviceRegistry.getTransactionService(); + nodeService = serviceRegistry.getNodeService(); + fileFolderService = serviceRegistry.getFileFolderService(); + namespaceService = serviceRegistry.getNamespaceService(); + txnHelper = transactionService.getRetryingTransactionHelper(); + nodeDAO = (NodeDAO)ctx.getBean("nodeDAO"); + solrTrackingComponent = (SOLRTrackingComponent) ctx.getBean("solrTrackingComponent"); + + admin = AuthenticationUtil.getAdminUserName(); + + AuthenticationUtil.setFullyAuthenticatedUser(admin); + + storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".1." + System.currentTimeMillis()); + rootNodeRef = nodeService.getRootNode(storeRef); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + } + + private JSONArray getTransactions(long fromCommitTime) throws Exception + { + String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime; + TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); + long startTime = System.currentTimeMillis(); + Response response = sendRequest(req, Status.STATUS_OK, admin); + long endTime = System.currentTimeMillis(); + + if(logger.isDebugEnabled()) + { + logger.debug(response.getContentAsString()); + } + JSONObject json = new JSONObject(response.getContentAsString()); + + JSONArray transactions = json.getJSONArray("transactions"); + + logger.debug("Got " + transactions.length() + " txns in " + (endTime - startTime) + " ms"); + + return transactions; + } + + public void testAclChangeSetsGet() throws Exception + { + String url = "/api/solr/aclchangesets?fromTime=" + 0L + "&fromId=" + 0L; + TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); + long startTime = System.currentTimeMillis(); + Response response = sendRequest(req, Status.STATUS_OK, admin); + long endTime = System.currentTimeMillis(); + + if(logger.isDebugEnabled()) + { + logger.debug(response.getContentAsString()); + } + JSONObject json = new JSONObject(response.getContentAsString()); + + JSONArray aclChangeSets = json.getJSONArray("aclChangeSets"); + + logger.debug("Got " + aclChangeSets.length() + " txns in " + (endTime - startTime) + " ms"); + } + + public void testAclsGet() throws Exception + { + List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, null, null, 100); + if (aclChangeSets.size() == 0) + { + return; // Can't test, but very unlikely + } + // Build JSON using these + JSONObject json = new JSONObject(); + JSONArray aclChangeSetIdsJSON = new JSONArray(); + int count = 0; + List aclChangeSetIds = new ArrayList(); + for (AclChangeSet aclChangeSet : aclChangeSets) + { + if (count >= 512) + { + break; + } + if (aclChangeSet.getAclCount() == 0) + { + continue; // No ACLs + } + Long aclChangeSetId = aclChangeSet.getId(); + aclChangeSetIdsJSON.put(aclChangeSetId); + aclChangeSetIds.add(aclChangeSetId); + count++; + } + json.put("aclChangeSetIds", aclChangeSetIdsJSON); + + String url = "/api/solr/acls"; + TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json"); + Response response = sendRequest(req, Status.STATUS_OK, admin); + if(logger.isDebugEnabled()) + { + logger.debug(response.getContentAsString()); + } + json = new JSONObject(response.getContentAsString()); + JSONArray acls = json.getJSONArray("acls"); + + // Check + List aclsCheck = solrTrackingComponent.getAcls(aclChangeSetIds, null, 512); + assertEquals("Script and API returned different number of results", aclsCheck.size(), acls.length()); + } + + public void testAclReadersGet() throws Exception + { + txnHelper.doInTransaction( + new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + aclReadersGetImpl(); + return null; + } + } + ); + } + + private void aclReadersGetImpl() throws Exception + { + List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, null, null, 1024); + List aclChangeSetIds = new ArrayList(50); + for (AclChangeSet aclChangeSet : aclChangeSets) + { + if (aclChangeSet.getAclCount() > 0) + { + aclChangeSetIds.add(aclChangeSet.getId()); + break; + } + } + if (aclChangeSetIds.size() == 0) + { + // No ACLs; not likely + } + List acls = solrTrackingComponent.getAcls(aclChangeSetIds, null, 1024); + List aclIds = new ArrayList(acls.size()); + JSONObject json = new JSONObject(); + JSONArray aclIdsJSON = new JSONArray(); + for (Acl acl : acls) + { + Long aclId = acl.getId(); + aclIds.add(aclId); + aclIdsJSON.put(aclId); + } + json.put("aclIds", aclIdsJSON); + + // Now get the readers + List aclsReaders = solrTrackingComponent.getAclsReaders(aclIds); + assertEquals("Should have same number of ACLs as supplied", aclIds.size(), aclsReaders.size()); + assertTrue("Must have *some* ACLs here", aclIds.size() > 0); + Map> readersByAclId = new HashMap>(); + for (AclReaders aclReaders : aclsReaders) + { + readersByAclId.put(aclReaders.getAclId(), aclReaders.getReaders()); + } + + Map> deniedByAclId = new HashMap>(); + for (AclReaders aclReaders : aclsReaders) + { + assertNotNull("AclReaders should not contain null denial set", aclReaders.getDenied()); + deniedByAclId.put(aclReaders.getAclId(), aclReaders.getDenied()); + } + + // Now query using the webscript + String url = "/api/solr/aclsReaders"; + TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json"); + Response response = sendRequest(req, Status.STATUS_OK, admin); + if(logger.isDebugEnabled()) + { + logger.debug(response.getContentAsString()); + } + json = new JSONObject(response.getContentAsString()); + JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders"); + // Check + assertEquals("Script and API returned different number of results", readersByAclId.size(), aclsReadersJSON.length()); + + // Iterate of the JSON and ensure that the list of ACL readers is correct + for (int i = 0; i < aclsReadersJSON.length(); i++) + { + // Choose an ACL and check the readers + JSONObject aclReadersJSON = aclsReadersJSON.getJSONObject(i); + Long aclIdJSON = aclReadersJSON.getLong("aclId"); + Set readersCheck = readersByAclId.get(aclIdJSON); + JSONArray readersJSON = aclReadersJSON.getJSONArray("readers"); + assertEquals("Readers list for ACL " + aclIdJSON + " is wrong. ", readersCheck.size(), readersJSON.length()); + for (int j = 0; j < readersJSON.length(); j++) + { + String readerJSON = readersJSON.getString(j); + assertTrue("Found reader not in check set: " + readerJSON, readersCheck.contains(readerJSON)); + } + + Set deniedCheck = deniedByAclId.get(aclIdJSON); + JSONArray deniedJSON = aclReadersJSON.getJSONArray("denied"); + assertEquals("Denied list for ACL " + aclIdJSON + " is wrong. ", deniedCheck.size(), deniedJSON.length()); + for (int j = 0; j < deniedJSON.length(); j++) + { + String denyJSON = deniedJSON.getString(j); + assertTrue("Found denied authority not in check set: " + denyJSON, deniedCheck.contains(denyJSON)); + } + } + } + + private JSONArray getNodes(GetNodesParameters parameters, int maxResults, int expectedNumNodes) throws Exception + { + StringBuilder url = new StringBuilder("/api/solr/nodes"); + + JSONObject json = new JSONObject(); + if(parameters.getTransactionIds() != null) + { + JSONArray array = new JSONArray(); + for(Long txnId : parameters.getTransactionIds()) + { + array.put(txnId); + } + json.put("txnIds", array); + } + + if(parameters.getFromNodeId() != null) + { + json.put("fromNodeId", parameters.getFromNodeId()); + } + + if(parameters.getToNodeId() != null) + { + json.put("toNodeId", parameters.getToNodeId()); + } + + if(parameters.getExcludeAspects() != null) + { + JSONArray array = new JSONArray(); + for(QName excludeAspect : parameters.getExcludeAspects()) + { + array.put(excludeAspect.toString()); + } + json.put("excludeAspects", array); + } + + if(parameters.getIncludeAspects() != null) + { + JSONArray array = new JSONArray(); + for(QName includeAspect : parameters.getIncludeAspects()) + { + array.put(includeAspect.toString()); + } + json.put("includeAspects", array); + } + + if(parameters.getStoreProtocol() != null) + { + json.put("storeProtocol", parameters.getStoreProtocol()); + } + + if(parameters.getStoreIdentifier() != null) + { + json.put("storeIdentifier", parameters.getStoreIdentifier()); + } + + json.put("maxResults", maxResults); + + TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url.toString(), json.toString(), "application/json"); + + long startTime = System.currentTimeMillis(); + Response response = sendRequest(req, Status.STATUS_OK, admin); + long endTime = System.currentTimeMillis(); + +// assertEquals("Expected application/json content type", "application/json[;charset=UTF-8]", response.getContentType()); + + if(logger.isDebugEnabled()) + { + logger.debug(response.getContentAsString()); + } + //logger.debug("getNodes: " + response.getContentAsString()); + JSONObject jsonResponse = new JSONObject(response.getContentAsString()); + jsonResponse.write(new PrintWriter(System.out)); + + JSONArray nodes = jsonResponse.getJSONArray("nodes"); + + //assertEquals("Node count is incorrect", nodes.length(), json.getInt("count")); + + logger.debug("Got " + nodes.length() + " nodes in " + (endTime - startTime) + " ms"); + + assertEquals("Number of returned node meta data results is incorrect", expectedNumNodes, nodes.length()); + + return nodes; + } + + private List getTransactionIds(JSONArray transactions) throws JSONException + { + List txnIds = new ArrayList(transactions.length()); + + int numTxns = transactions.length(); + for(int i = 0; i < numTxns; i++) + { + JSONObject txn = transactions.getJSONObject(i); + txnIds.add(txn.getLong("id")); + } + + return txnIds; + } + + public static String join(Collection s, String delimiter) + { + StringBuffer buffer = new StringBuffer(); + Iterator iter = s.iterator(); + while (iter.hasNext()) + { + buffer.append(iter.next()); + if (iter.hasNext()) + { + buffer.append(delimiter); + } + } + return buffer.toString(); + } + + private void buildTransactions3() + { + txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + PropertyMap props = new PropertyMap(); + props.put(ContentModel.PROP_NAME, "Container3"); + container3 = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_FOLDER, + props).getChildRef(); + if(logger.isDebugEnabled()) + { + logger.debug("container3 = " + container3); + } + + for(int i = 0; i < 100; i++) + { + FileInfo content1Info = fileFolderService.create(container3, "Content" + i, ContentModel.TYPE_CONTENT); + NodeRef nodeRef = content1Info.getNodeRef(); + contents.add(nodeRef); + nodeIDs.add(Long.valueOf(getNodeID(nodeRef))); + + if(i % 2 == 1) + { + nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); + } + } + + return null; + } + }); + } + + private NodeRef container6; + + private void buildTransactions5() + { + txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + PropertyMap props = new PropertyMap(); + props.put(ContentModel.PROP_NAME, "Container6"); + container6 = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_FOLDER, + props).getChildRef(); + + FileInfo contentInfo = fileFolderService.create(container6, "Content1", ContentModel.TYPE_CONTENT); + contents.add(contentInfo.getNodeRef()); + + Map aspectProperties = new HashMap(); + aspectProperties.put(ContentModel.PROP_AUTHOR, "steve"); + nodeService.addAspect(contentInfo.getNodeRef(), ContentModel.ASPECT_AUTHOR, aspectProperties); + + return null; + } + }); + } + + private JSONArray getNodesMetaData(List nodeIds, int maxResults, int numMetaDataNodes) throws Exception + { + StringBuilder url = new StringBuilder("/api/solr/metadata"); + + JSONObject json = new JSONObject(); + if(nodeIds != null && nodeIds.size() > 0) + { + JSONArray array = new JSONArray(); + for(Long nodeId : nodeIds) + { + array.put(nodeId); + } + json.put("nodeIds", array); + } + + json.put("maxResults", maxResults); + + TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url.toString(), json.toString(), "application/json"); + long startTime = System.currentTimeMillis(); + Response response = sendRequest(req, Status.STATUS_OK, admin); + long endTime = System.currentTimeMillis(); + + String content = response.getContentAsString(); + + if(logger.isDebugEnabled()) + { + logger.debug("nodesMetaData = " + content); + } + + JSONObject jsonResponse = null; + + try + { + jsonResponse = new JSONObject(content); + } + catch(JSONException e) + { + fail(e.getMessage()); + } + + JSONArray nodes = jsonResponse.getJSONArray("nodes"); + + logger.debug("Got metadata for " + nodes.length() + " nodes in " + (endTime - startTime) + " ms"); + + assertEquals("Number of returned nodes is incorrect", numMetaDataNodes, nodes.length()); + + return nodes; + } + + private void buildTransactions6() + { + txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + PropertyMap props = new PropertyMap(); + props.put(ContentModel.PROP_NAME, "Container6"); + NodeRef container6 = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_FOLDER, + props).getChildRef(); + if(logger.isDebugEnabled()) + { + logger.debug("container6 = " + container6); + } + + for(int i = 0; i < 2000; i++) + { + FileInfo content1Info = fileFolderService.create(container6, "Content" + i, ContentModel.TYPE_CONTENT); + NodeRef nodeRef = content1Info.getNodeRef(); + contents.add(nodeRef); + + if(i % 2 == 1) + { + nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null); + } + } + + return null; + } + }); + } + + public void testNodeMetaData() throws Exception + { + long fromCommitTime = System.currentTimeMillis(); + + buildTransactions5(); + + JSONArray transactions = getTransactions(fromCommitTime); + assertEquals("Number of transactions is incorrect", 1, transactions.length()); + + List transactionIds = getTransactionIds(transactions); + + GetNodesParameters params = new GetNodesParameters(); + params.setTransactionIds(transactionIds); + params.setStoreProtocol(storeRef.getProtocol()); + params.setStoreIdentifier(storeRef.getIdentifier()); + JSONArray nodes = getNodes(params, 0, 2); + + List nodeIds = new ArrayList(nodes.length()); + for(int i = 0; i < nodes.length(); i++) + { + JSONObject node = nodes.getJSONObject(i); + nodeIds.add(node.getLong("id")); + } + + JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2); + + // test second entry (second node created in buildTransactions) + NodeRef expectedNodeRef = contents.get(0); + + JSONObject node = nodesMetaData.getJSONObject(1); + NodeRef nodeRef = new NodeRef(node.getString("nodeRef")); + + assertEquals("NodeRef is incorrect", expectedNodeRef, nodeRef); + + JSONArray aspects = node.getJSONArray("aspects"); + JSONObject properties = node.getJSONObject("properties"); + Map propertyMap = getPropertyMap(properties); + + assertTrue("Expected author aspect", containsAspect(aspects, ContentModel.ASPECT_AUTHOR)); + assertTrue("Expected author property", containsProperty(propertyMap, ContentModel.PROP_AUTHOR, "steve")); + + JSONArray paths = node.getJSONArray("paths"); + List expectedPaths = nodeService.getPaths(expectedNodeRef, false); + for(int i = 0; i < paths.length(); i++) + { + JSONObject o = paths.getJSONObject(i); + String path = o.getString("path"); + String qname = o.has("qname") ? o.getString("qname") : null; + String expectedPath = expectedPaths.get(i).toString(); + assertEquals("Path element " + i + " is incorrect", expectedPath, path); + assertNull("qname should be null", qname); + } + } + + private NodeRef container7; + + private void buildTransactions7() + { + txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + PropertyMap props = new PropertyMap(); + props.put(ContentModel.PROP_NAME, "Container7"); + container7 = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + ContentModel.ASSOC_CHILDREN, + ContentModel.TYPE_FOLDER, + props).getChildRef(); + + FileInfo contentInfo = fileFolderService.create(container7, "Content1", ContentModel.TYPE_CONTENT); + contents.add(contentInfo.getNodeRef()); + + Map aspectProperties = new HashMap(); + aspectProperties.put(ContentModel.PROP_AUTHOR, "ste\"ve"); + nodeService.addAspect(contentInfo.getNodeRef(), ContentModel.ASPECT_AUTHOR, aspectProperties); + + return null; + } + }); + } + + public void testNodeMetaDataStringEscaping() throws Exception + { + long fromCommitTime = System.currentTimeMillis(); + + buildTransactions7(); + + JSONArray transactions = getTransactions(fromCommitTime); + assertEquals("Number of transactions is incorrect", 1, transactions.length()); + + List transactionIds = getTransactionIds(transactions); + + GetNodesParameters params = new GetNodesParameters(); + params.setTransactionIds(transactionIds); + params.setStoreProtocol(storeRef.getProtocol()); + params.setStoreIdentifier(storeRef.getIdentifier()); + JSONArray nodes = getNodes(params, 0, 2); + + List nodeIds = new ArrayList(nodes.length()); + for(int i = 0; i < nodes.length(); i++) + { + JSONObject node = nodes.getJSONObject(i); + nodeIds.add(node.getLong("id")); + } + + JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2); + + // test second entry (second node created in buildTransactions) + NodeRef expectedNodeRef = contents.get(0); + + JSONObject node = nodesMetaData.getJSONObject(1); + NodeRef nodeRef = new NodeRef(node.getString("nodeRef")); + + assertEquals("NodeRef is incorrect", expectedNodeRef, nodeRef); + + JSONArray aspects = node.getJSONArray("aspects"); + JSONObject properties = node.getJSONObject("properties"); + Map propertyMap = getPropertyMap(properties); + + assertTrue("Expected author aspect", containsAspect(aspects, ContentModel.ASPECT_AUTHOR)); + assertTrue("Expected author property", containsProperty(propertyMap, ContentModel.PROP_AUTHOR, "ste\"ve")); + } + + public void testNodeMetaDataManyNodes() throws Exception + { + long fromCommitTime = System.currentTimeMillis(); + + buildTransactions6(); + + JSONArray transactions = getTransactions(fromCommitTime); + assertEquals("Number of transactions is incorrect", 1, transactions.length()); + + List transactionIds = getTransactionIds(transactions); + + GetNodesParameters params = new GetNodesParameters(); + params.setStoreProtocol(storeRef.getProtocol()); + params.setStoreIdentifier(storeRef.getIdentifier()); + params.setTransactionIds(transactionIds); + JSONArray nodes = getNodes(params, 0, 2001); + + List nodeIds = new ArrayList(nodes.length()); + for(int i = 0; i < nodes.length(); i++) + { + JSONObject node = nodes.getJSONObject(i); + nodeIds.add(node.getLong("id")); + } + + // make sure caches are warm - time last call + @SuppressWarnings("unused") + JSONArray nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); + nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); + + // sleep for a couple of seconds + try + { + Thread.sleep(2000); + } + catch(InterruptedException e) + { + // ignore + } + nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); + + nodesMetaData = getNodesMetaData(nodeIds, 1000, 1000); + nodesMetaData = getNodesMetaData(nodeIds, 600, 600); + nodesMetaData = getNodesMetaData(nodeIds, 300, 300); + nodesMetaData = getNodesMetaData(nodeIds, 100, 100); + nodesMetaData = getNodesMetaData(nodeIds, 50, 50); + + // clear out caches + nodeDAO.clear(); + + nodesMetaData = getNodesMetaData(nodeIds, 0, 2001); + } + + private boolean containsAspect(JSONArray aspectsArray, QName aspect) throws Exception + { + if(aspect == null) + { + throw new IllegalArgumentException("aspect cannot be null"); + } + + boolean success = false; + for(int i = 0; i < aspectsArray.length(); i++) + { + String qName = aspectsArray.getString(i); + if(aspect.equals(QName.createQName(qName, namespaceService))) + { + success |= true; + break; + } + } + + return success; + } + + private Map getPropertyMap(JSONObject properties) throws Exception + { + Map propertyMap = new HashMap(properties.length()); + @SuppressWarnings("rawtypes") + Iterator propNames = properties.keys(); + while(propNames.hasNext()) + { + String propName = (String)propNames.next(); + String value = properties.getString(propName); + + propertyMap.put(QName.resolveToQName(namespaceService, propName), value); + } + + return propertyMap; + } + + private boolean containsProperty(Map propertyMap, QName propName, String propValue) throws Exception + { + if(propName == null) + { + throw new IllegalArgumentException("propName cannot be null"); + } + + String value = propertyMap.get(propName); + return (value == null ? false : value.equals(propValue)); + } + + public void DISABLED_testGetContent() throws Exception + { + long nodeId = -1l; + String propertyName = ContentModel.PROP_CONTENT.toString(); + + buildTransactions3(); + + String url = "/api/solr/content?nodeId=" + nodeId + "&propertyName=" + propertyName; + TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url); + Response response = sendRequest(req, Status.STATUS_OK, admin); + if (logger.isDebugEnabled()) + { + logger.debug("content1 = " + response.getContentAsString()); + } + assertEquals("Content length is incorrect", "test content".length(), response.getContentLength()); + } + + private long getNodeID(NodeRef nodeRef) + { + Pair pair = nodeDAO.getNodePair(nodeRef); + assertNotNull("Can't find node " + nodeRef, pair); + return pair.getFirst(); + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceRestApiTest.java b/source/test-java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceRestApiTest.java index 816f94a0da..e0276e1e71 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceRestApiTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceRestApiTest.java @@ -1,288 +1,288 @@ -package org.alfresco.repo.web.scripts.subscriptions; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.util.PropertyMap; -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.PutRequest; -import org.springframework.extensions.webscripts.TestWebScriptServer.Response; - -/** - * Subscription Service REST API tests - */ -public class SubscriptionServiceRestApiTest extends BaseWebScriptTest -{ - public static final String USER_BOB = "bob"; - public static final String USER_TOM = "tom"; - public static final String USER_LISA = "lisa"; - - private static final String URL_FOLLOW = "/api/subscriptions/{userid}/follow"; - private static final String URL_UNFOLLOW = "/api/subscriptions/{userid}/unfollow"; - private static final String URL_FOLLOWERS = "/api/subscriptions/{userid}/followers"; - private static final String URL_FOLLOWERS_COUNT = "/api/subscriptions/{userid}/followers/count"; - private static final String URL_FOLLOWING = "/api/subscriptions/{userid}/following"; - private static final String URL_FOLLOWING_COUNT = "/api/subscriptions/{userid}/following/count"; - private static final String URL_FOLLOWS = "/api/subscriptions/{userid}/follows"; - private static final String URL_PRIVATE = "/api/subscriptions/{userid}/private"; - - protected PersonService personService; - - @Override - public void setUp() throws Exception - { - // Get the required services - personService = (PersonService) getServer().getApplicationContext().getBean("PersonService"); - - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); - - createPerson(USER_BOB); - createPerson(USER_TOM); - createPerson(USER_LISA); - } - - @Override - protected void tearDown() throws Exception - { - deletePerson(USER_BOB); - deletePerson(USER_TOM); - deletePerson(USER_LISA); - } - - protected void deletePerson(String userId) - { - personService.deletePerson(userId); - } - - protected NodeRef createPerson(String userId) - { - deletePerson(userId); - - PropertyMap properties = new PropertyMap(5); - properties.put(ContentModel.PROP_USERNAME, userId); - properties.put(ContentModel.PROP_FIRSTNAME, userId); - properties.put(ContentModel.PROP_LASTNAME, "Test"); - properties.put(ContentModel.PROP_EMAIL, userId + "@test.demo.alfresco.com"); - - return personService.createPerson(properties); - } - - protected String getUrl(String urlPattern, String user) - { - return urlPattern.replaceFirst("\\{userid\\}", user); - } - - protected void follow(String user1, String user2) throws Exception - { - JSONArray jsonUsers = new JSONArray(); - jsonUsers.put(user2); - - String url = getUrl(URL_FOLLOW, user1); - sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), Status.STATUS_NO_CONTENT); - } - - protected void unfollow(String user1, String user2) throws Exception - { - JSONArray jsonUsers = new JSONArray(); - jsonUsers.put(user2); - - String url = getUrl(URL_UNFOLLOW, user1); - sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), Status.STATUS_NO_CONTENT); - } - - protected boolean follows(String user1, String user2) throws Exception - { - JSONArray jsonUsers = new JSONArray(); - jsonUsers.put(user2); - - String url = getUrl(URL_FOLLOWS, user1); - Response response = sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), - Status.STATUS_OK); - - JSONArray resultArray = new JSONArray(response.getContentAsString()); - assertEquals(1, resultArray.length()); - - JSONObject resultObject = resultArray.getJSONObject(0); - assertTrue(resultObject.has(user2)); - - return resultObject.getBoolean(user2); - } - - protected int getFollowingCount(String user) throws Exception - { - String url = getUrl(URL_FOLLOWING_COUNT, user); - Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("count")); - - return resultObject.getInt("count"); - } - - protected int getFollowersCount(String user) throws Exception - { - String url = getUrl(URL_FOLLOWERS_COUNT, user); - Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("count")); - - return resultObject.getInt("count"); - } - - protected List getFollowing(String user) throws Exception - { - String url = getUrl(URL_FOLLOWING, user); - Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("people")); - - List result = new ArrayList(); - JSONArray people = resultObject.getJSONArray("people"); - - for (int i = 0; i < people.length(); i++) - { - JSONObject person = people.getJSONObject(i); - assertTrue(person.has("userName")); - assertTrue(person.has("firstName")); - assertTrue(person.has("lastName")); - - result.add(person.getString("userName")); - } - - return result; - } - - protected List getFollowers(String user) throws Exception - { - String url = getUrl(URL_FOLLOWERS, user); - Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("people")); - - List result = new ArrayList(); - JSONArray people = resultObject.getJSONArray("people"); - - for (int i = 0; i < people.length(); i++) - { - JSONObject person = people.getJSONObject(i); - assertTrue(person.has("userName")); - assertTrue(person.has("firstName")); - assertTrue(person.has("lastName")); - - result.add(person.getString("userName")); - } - - return result; - } - - protected boolean isSubscriptionListPrivate(String user) throws Exception - { - String url = getUrl(URL_PRIVATE, user); - Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("private")); - - return resultObject.getBoolean("private"); - } - - protected void setSubscriptionListPrivate(String user, boolean setPrivate) throws Exception - { - JSONObject privateObject = new JSONObject(); - privateObject.put("private", setPrivate); - - String url = getUrl(URL_PRIVATE, user); - Response response = sendRequest(new PutRequest(url, privateObject.toString(), "application/json"), - Status.STATUS_OK); - - JSONObject resultObject = new JSONObject(response.getContentAsString()); - assertTrue(resultObject.has("private")); - assertEquals(setPrivate, resultObject.getBoolean("private")); - } - - public void testFollow() throws Exception - { - String userId1 = USER_BOB; - String userId2 = USER_TOM; - String userId3 = USER_LISA; - - // check follows first - if (follows(userId1, userId2)) - { - unfollow(userId1, userId2); - } - assertFalse(follows(userId1, userId2)); - - // count the people user 1 is following - int count = getFollowingCount(userId1); - assertTrue(count >= 0); - - // user 1 follows user 2 -- twice (the second follow request should be - // ignored) - follow(userId1, userId2); - follow(userId1, userId2); - assertEquals(count + 1, getFollowingCount(userId1)); - assertTrue(follows(userId1, userId2)); - - // user 1 follows user 3 - follow(userId1, userId3); - assertEquals(count + 2, getFollowingCount(userId1)); - assertTrue(follows(userId1, userId3)); - - // get following list of user 1 - List following = getFollowing(userId1); - assertNotNull(following); - assertTrue(following.contains(userId2)); - assertTrue(following.contains(userId3)); - - // count followers of user 2 - int followerCount = getFollowersCount(userId2); - assertTrue(followerCount > 0); - - // get followers of user 2 - List followers = getFollowers(userId2); - assertNotNull(followers); - assertTrue(followers.contains(userId1)); - - // unfollow - unfollow(userId1, userId2); - assertEquals(count + 1, getFollowingCount(userId1)); - assertFalse(follows(userId1, userId2)); - assertTrue(follows(userId1, userId3)); - - unfollow(userId1, userId3); - assertEquals(count, getFollowingCount(userId1)); - assertFalse(follows(userId1, userId3)); - } - - public void testPrivateList() throws Exception - { - final String userId1 = USER_BOB; - - assertFalse(isSubscriptionListPrivate(userId1)); - - setSubscriptionListPrivate(userId1, false); - assertFalse(isSubscriptionListPrivate(userId1)); - - setSubscriptionListPrivate(userId1, true); - assertTrue(isSubscriptionListPrivate(userId1)); - - setSubscriptionListPrivate(userId1, false); - assertFalse(isSubscriptionListPrivate(userId1)); - - setSubscriptionListPrivate(userId1, true); - assertTrue(isSubscriptionListPrivate(userId1)); - } -} +package org.alfresco.repo.web.scripts.subscriptions; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.util.PropertyMap; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PutRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; + +/** + * Subscription Service REST API tests + */ +public class SubscriptionServiceRestApiTest extends BaseWebScriptTest +{ + public static final String USER_BOB = "bob"; + public static final String USER_TOM = "tom"; + public static final String USER_LISA = "lisa"; + + private static final String URL_FOLLOW = "/api/subscriptions/{userid}/follow"; + private static final String URL_UNFOLLOW = "/api/subscriptions/{userid}/unfollow"; + private static final String URL_FOLLOWERS = "/api/subscriptions/{userid}/followers"; + private static final String URL_FOLLOWERS_COUNT = "/api/subscriptions/{userid}/followers/count"; + private static final String URL_FOLLOWING = "/api/subscriptions/{userid}/following"; + private static final String URL_FOLLOWING_COUNT = "/api/subscriptions/{userid}/following/count"; + private static final String URL_FOLLOWS = "/api/subscriptions/{userid}/follows"; + private static final String URL_PRIVATE = "/api/subscriptions/{userid}/private"; + + protected PersonService personService; + + @Override + public void setUp() throws Exception + { + // Get the required services + personService = (PersonService) getServer().getApplicationContext().getBean("PersonService"); + + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); + + createPerson(USER_BOB); + createPerson(USER_TOM); + createPerson(USER_LISA); + } + + @Override + protected void tearDown() throws Exception + { + deletePerson(USER_BOB); + deletePerson(USER_TOM); + deletePerson(USER_LISA); + } + + protected void deletePerson(String userId) + { + personService.deletePerson(userId); + } + + protected NodeRef createPerson(String userId) + { + deletePerson(userId); + + PropertyMap properties = new PropertyMap(5); + properties.put(ContentModel.PROP_USERNAME, userId); + properties.put(ContentModel.PROP_FIRSTNAME, userId); + properties.put(ContentModel.PROP_LASTNAME, "Test"); + properties.put(ContentModel.PROP_EMAIL, userId + "@test.demo.alfresco.com"); + + return personService.createPerson(properties); + } + + protected String getUrl(String urlPattern, String user) + { + return urlPattern.replaceFirst("\\{userid\\}", user); + } + + protected void follow(String user1, String user2) throws Exception + { + JSONArray jsonUsers = new JSONArray(); + jsonUsers.put(user2); + + String url = getUrl(URL_FOLLOW, user1); + sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), Status.STATUS_NO_CONTENT); + } + + protected void unfollow(String user1, String user2) throws Exception + { + JSONArray jsonUsers = new JSONArray(); + jsonUsers.put(user2); + + String url = getUrl(URL_UNFOLLOW, user1); + sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), Status.STATUS_NO_CONTENT); + } + + protected boolean follows(String user1, String user2) throws Exception + { + JSONArray jsonUsers = new JSONArray(); + jsonUsers.put(user2); + + String url = getUrl(URL_FOLLOWS, user1); + Response response = sendRequest(new PostRequest(url, jsonUsers.toString(), "application/json"), + Status.STATUS_OK); + + JSONArray resultArray = new JSONArray(response.getContentAsString()); + assertEquals(1, resultArray.length()); + + JSONObject resultObject = resultArray.getJSONObject(0); + assertTrue(resultObject.has(user2)); + + return resultObject.getBoolean(user2); + } + + protected int getFollowingCount(String user) throws Exception + { + String url = getUrl(URL_FOLLOWING_COUNT, user); + Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("count")); + + return resultObject.getInt("count"); + } + + protected int getFollowersCount(String user) throws Exception + { + String url = getUrl(URL_FOLLOWERS_COUNT, user); + Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("count")); + + return resultObject.getInt("count"); + } + + protected List getFollowing(String user) throws Exception + { + String url = getUrl(URL_FOLLOWING, user); + Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("people")); + + List result = new ArrayList(); + JSONArray people = resultObject.getJSONArray("people"); + + for (int i = 0; i < people.length(); i++) + { + JSONObject person = people.getJSONObject(i); + assertTrue(person.has("userName")); + assertTrue(person.has("firstName")); + assertTrue(person.has("lastName")); + + result.add(person.getString("userName")); + } + + return result; + } + + protected List getFollowers(String user) throws Exception + { + String url = getUrl(URL_FOLLOWERS, user); + Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("people")); + + List result = new ArrayList(); + JSONArray people = resultObject.getJSONArray("people"); + + for (int i = 0; i < people.length(); i++) + { + JSONObject person = people.getJSONObject(i); + assertTrue(person.has("userName")); + assertTrue(person.has("firstName")); + assertTrue(person.has("lastName")); + + result.add(person.getString("userName")); + } + + return result; + } + + protected boolean isSubscriptionListPrivate(String user) throws Exception + { + String url = getUrl(URL_PRIVATE, user); + Response response = sendRequest(new GetRequest(url), Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("private")); + + return resultObject.getBoolean("private"); + } + + protected void setSubscriptionListPrivate(String user, boolean setPrivate) throws Exception + { + JSONObject privateObject = new JSONObject(); + privateObject.put("private", setPrivate); + + String url = getUrl(URL_PRIVATE, user); + Response response = sendRequest(new PutRequest(url, privateObject.toString(), "application/json"), + Status.STATUS_OK); + + JSONObject resultObject = new JSONObject(response.getContentAsString()); + assertTrue(resultObject.has("private")); + assertEquals(setPrivate, resultObject.getBoolean("private")); + } + + public void testFollow() throws Exception + { + String userId1 = USER_BOB; + String userId2 = USER_TOM; + String userId3 = USER_LISA; + + // check follows first + if (follows(userId1, userId2)) + { + unfollow(userId1, userId2); + } + assertFalse(follows(userId1, userId2)); + + // count the people user 1 is following + int count = getFollowingCount(userId1); + assertTrue(count >= 0); + + // user 1 follows user 2 -- twice (the second follow request should be + // ignored) + follow(userId1, userId2); + follow(userId1, userId2); + assertEquals(count + 1, getFollowingCount(userId1)); + assertTrue(follows(userId1, userId2)); + + // user 1 follows user 3 + follow(userId1, userId3); + assertEquals(count + 2, getFollowingCount(userId1)); + assertTrue(follows(userId1, userId3)); + + // get following list of user 1 + List following = getFollowing(userId1); + assertNotNull(following); + assertTrue(following.contains(userId2)); + assertTrue(following.contains(userId3)); + + // count followers of user 2 + int followerCount = getFollowersCount(userId2); + assertTrue(followerCount > 0); + + // get followers of user 2 + List followers = getFollowers(userId2); + assertNotNull(followers); + assertTrue(followers.contains(userId1)); + + // unfollow + unfollow(userId1, userId2); + assertEquals(count + 1, getFollowingCount(userId1)); + assertFalse(follows(userId1, userId2)); + assertTrue(follows(userId1, userId3)); + + unfollow(userId1, userId3); + assertEquals(count, getFollowingCount(userId1)); + assertFalse(follows(userId1, userId3)); + } + + public void testPrivateList() throws Exception + { + final String userId1 = USER_BOB; + + assertFalse(isSubscriptionListPrivate(userId1)); + + setSubscriptionListPrivate(userId1, false); + assertFalse(isSubscriptionListPrivate(userId1)); + + setSubscriptionListPrivate(userId1, true); + assertTrue(isSubscriptionListPrivate(userId1)); + + setSubscriptionListPrivate(userId1, false); + assertFalse(isSubscriptionListPrivate(userId1)); + + setSubscriptionListPrivate(userId1, true); + assertTrue(isSubscriptionListPrivate(userId1)); + } +} diff --git a/source/test-java/org/alfresco/repo/web/util/AbstractJettyComponent.java b/source/test-java/org/alfresco/repo/web/util/AbstractJettyComponent.java index 0b82cae28d..2dc292cb2b 100644 --- a/source/test-java/org/alfresco/repo/web/util/AbstractJettyComponent.java +++ b/source/test-java/org/alfresco/repo/web/util/AbstractJettyComponent.java @@ -1,239 +1,239 @@ -package org.alfresco.repo.web.util; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.Date; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.BaseApplicationContextHelper; -import org.alfresco.util.TempFileProvider; -import org.alfresco.util.WebApplicationContextLoader; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.jetty.security.HashLoginService; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; -import org.springframework.beans.BeanUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.web.context.ConfigurableWebApplicationContext; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.GenericWebApplicationContext; - -/** - * Manages an embedded jetty server, hooking it up to the repository spring context. - * - * @author steveglover - * - */ -public abstract class AbstractJettyComponent implements JettyComponent -{ - protected static final Log logger = LogFactory.getLog(AbstractJettyComponent.class); - - public static final int JETTY_STOP_PORT = 8079; - public static final String JETTY_LOCAL_IP = "127.0.0.1"; - - protected int port = 8081; - protected String contextPath = "/alfresco"; - protected String publicApiServletName = "api"; - protected String[] configLocations; - protected String[] classLocations; - protected static Server server; - - private WebAppContext webAppContext; - - public AbstractJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) - { - this.configLocations = configLocations; - this.classLocations = classLocations; - this.port = port; - this.contextPath = contextPath; - server = new Server(port); - } - - public int getPort() - { - return port; - } - - /* - * Creates a web application context wrapping a Spring application context (adapted from core spring code in - * org.springframework.web.context.ContextLoader) - */ - protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) - { - GenericWebApplicationContext wac = (GenericWebApplicationContext) BeanUtils.instantiateClass(GenericWebApplicationContext.class); - - // Assign the best possible id value. - wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + contextPath); - - wac.setParent(parent); - wac.setServletContext(sc); - wac.refresh(); - - return wac; - } - - public ConfigurableApplicationContext getApplicationContext() - { - return (ConfigurableApplicationContext)webAppContext.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); - } - - protected abstract void configureWebAppContext(WebAppContext webAppContext); - - public void start() - { - if(logger.isDebugEnabled()) - { - logger.debug("["+new Date()+"] startJetty: starting embedded Jetty server ..."); - } - - try - { - if(logger.isDebugEnabled()) - { - logger.debug("["+new Date()+"] startJetty"); - } - - this.webAppContext = new WebAppContext(); - webAppContext.setContextPath(contextPath); - - configure(webAppContext); - - server.setHandler(webAppContext); - - // for clean shutdown, add monitor thread - - // from: http://ptrthomas.wordpress.com/2009/01/24/how-to-start-and-stop-jetty-revisited/ - // adapted from: http://jetty.codehaus.org/jetty/jetty-6/xref/org/mortbay/start/Monitor.html - Thread monitor = new MonitorThread(); - monitor.start(); - - configureWebAppContext(webAppContext); - - server.start(); - - if(logger.isDebugEnabled()) - { - logger.debug("["+new Date()+"] startJetty: ... embedded Jetty server started on port " + port); - } - } - catch (Exception e) - { - logger.error("["+new Date()+"] startJetty: ... failed to start embedded Jetty server on port " + port + ", " + e); - } - } - - protected void configure(WebAppContext webAppContext) - { - try - { - ClassLoader classLoader = BaseApplicationContextHelper.buildClassLoader(classLocations); - webAppContext.setClassLoader(classLoader); - } - catch (IOException e) - { - throw new ExceptionInInitializerError(e); - } - - webAppContext.addEventListener(new ServletContextListener() - { - public void contextInitialized(ServletContextEvent sce) - { - // create a Spring web application context, wrapping and providing access to - // the application context - try - { - ServletContext servletContext = sce.getServletContext(); - - // initialise web application context - WebApplicationContextLoader.getApplicationContext(servletContext, configLocations, classLocations); - - if(logger.isDebugEnabled()) - { - logger.debug("contextInitialized "+sce); - } - } - catch(Throwable t) - { - logger.error("Failed to start Jetty server: " + t); - throw new AlfrescoRuntimeException("Failed to start Jetty server", t); - } - } - - public void contextDestroyed(ServletContextEvent sce) - { - if(logger.isDebugEnabled()) - { - logger.debug("contextDestroyed "+sce); - } - } - }); - - // with a login-config in web.xml, jetty seems to require this in order to start successfully - webAppContext.getSecurityHandler().setLoginService(new HashLoginService()); - - // arbitrary temporary file location - File tmp = new File(TempFileProvider.getSystemTempDir(), String.valueOf(System.currentTimeMillis())); - webAppContext.setResourceBase(tmp.getAbsolutePath()); - } - - public void shutdown() - { - try - { - server.stop(); - } - catch(Exception e) - { - throw new AlfrescoRuntimeException("", e); - } - } - - private static class MonitorThread extends Thread - { - private ServerSocket socket; - - public MonitorThread() - { - setDaemon(true); - setName("StopMonitor"); - try - { - socket = new ServerSocket(JETTY_STOP_PORT, 1, InetAddress.getByName(JETTY_LOCAL_IP)); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - } - - @Override - public void run() - { - Socket accept; - try - { - accept = socket.accept(); - BufferedReader reader = new BufferedReader(new InputStreamReader(accept.getInputStream())); - reader.readLine(); - server.stop(); - accept.close(); - socket.close(); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - } - } -} +package org.alfresco.repo.web.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Date; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.util.BaseApplicationContextHelper; +import org.alfresco.util.TempFileProvider; +import org.alfresco.util.WebApplicationContextLoader; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.jetty.security.HashLoginService; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; +import org.springframework.beans.BeanUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.web.context.ConfigurableWebApplicationContext; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; + +/** + * Manages an embedded jetty server, hooking it up to the repository spring context. + * + * @author steveglover + * + */ +public abstract class AbstractJettyComponent implements JettyComponent +{ + protected static final Log logger = LogFactory.getLog(AbstractJettyComponent.class); + + public static final int JETTY_STOP_PORT = 8079; + public static final String JETTY_LOCAL_IP = "127.0.0.1"; + + protected int port = 8081; + protected String contextPath = "/alfresco"; + protected String publicApiServletName = "api"; + protected String[] configLocations; + protected String[] classLocations; + protected static Server server; + + private WebAppContext webAppContext; + + public AbstractJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) + { + this.configLocations = configLocations; + this.classLocations = classLocations; + this.port = port; + this.contextPath = contextPath; + server = new Server(port); + } + + public int getPort() + { + return port; + } + + /* + * Creates a web application context wrapping a Spring application context (adapted from core spring code in + * org.springframework.web.context.ContextLoader) + */ + protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) + { + GenericWebApplicationContext wac = (GenericWebApplicationContext) BeanUtils.instantiateClass(GenericWebApplicationContext.class); + + // Assign the best possible id value. + wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + contextPath); + + wac.setParent(parent); + wac.setServletContext(sc); + wac.refresh(); + + return wac; + } + + public ConfigurableApplicationContext getApplicationContext() + { + return (ConfigurableApplicationContext)webAppContext.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); + } + + protected abstract void configureWebAppContext(WebAppContext webAppContext); + + public void start() + { + if(logger.isDebugEnabled()) + { + logger.debug("["+new Date()+"] startJetty: starting embedded Jetty server ..."); + } + + try + { + if(logger.isDebugEnabled()) + { + logger.debug("["+new Date()+"] startJetty"); + } + + this.webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); + + configure(webAppContext); + + server.setHandler(webAppContext); + + // for clean shutdown, add monitor thread + + // from: http://ptrthomas.wordpress.com/2009/01/24/how-to-start-and-stop-jetty-revisited/ + // adapted from: http://jetty.codehaus.org/jetty/jetty-6/xref/org/mortbay/start/Monitor.html + Thread monitor = new MonitorThread(); + monitor.start(); + + configureWebAppContext(webAppContext); + + server.start(); + + if(logger.isDebugEnabled()) + { + logger.debug("["+new Date()+"] startJetty: ... embedded Jetty server started on port " + port); + } + } + catch (Exception e) + { + logger.error("["+new Date()+"] startJetty: ... failed to start embedded Jetty server on port " + port + ", " + e); + } + } + + protected void configure(WebAppContext webAppContext) + { + try + { + ClassLoader classLoader = BaseApplicationContextHelper.buildClassLoader(classLocations); + webAppContext.setClassLoader(classLoader); + } + catch (IOException e) + { + throw new ExceptionInInitializerError(e); + } + + webAppContext.addEventListener(new ServletContextListener() + { + public void contextInitialized(ServletContextEvent sce) + { + // create a Spring web application context, wrapping and providing access to + // the application context + try + { + ServletContext servletContext = sce.getServletContext(); + + // initialise web application context + WebApplicationContextLoader.getApplicationContext(servletContext, configLocations, classLocations); + + if(logger.isDebugEnabled()) + { + logger.debug("contextInitialized "+sce); + } + } + catch(Throwable t) + { + logger.error("Failed to start Jetty server: " + t); + throw new AlfrescoRuntimeException("Failed to start Jetty server", t); + } + } + + public void contextDestroyed(ServletContextEvent sce) + { + if(logger.isDebugEnabled()) + { + logger.debug("contextDestroyed "+sce); + } + } + }); + + // with a login-config in web.xml, jetty seems to require this in order to start successfully + webAppContext.getSecurityHandler().setLoginService(new HashLoginService()); + + // arbitrary temporary file location + File tmp = new File(TempFileProvider.getSystemTempDir(), String.valueOf(System.currentTimeMillis())); + webAppContext.setResourceBase(tmp.getAbsolutePath()); + } + + public void shutdown() + { + try + { + server.stop(); + } + catch(Exception e) + { + throw new AlfrescoRuntimeException("", e); + } + } + + private static class MonitorThread extends Thread + { + private ServerSocket socket; + + public MonitorThread() + { + setDaemon(true); + setName("StopMonitor"); + try + { + socket = new ServerSocket(JETTY_STOP_PORT, 1, InetAddress.getByName(JETTY_LOCAL_IP)); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + } + + @Override + public void run() + { + Socket accept; + try + { + accept = socket.accept(); + BufferedReader reader = new BufferedReader(new InputStreamReader(accept.getInputStream())); + reader.readLine(); + server.stop(); + accept.close(); + socket.close(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + } + } +} diff --git a/source/test-java/org/alfresco/repo/web/util/HttpRangeProcessorTest.java b/source/test-java/org/alfresco/repo/web/util/HttpRangeProcessorTest.java index ddb02f5bc7..68d6abb1be 100644 --- a/source/test-java/org/alfresco/repo/web/util/HttpRangeProcessorTest.java +++ b/source/test-java/org/alfresco/repo/web/util/HttpRangeProcessorTest.java @@ -1,74 +1,74 @@ -package org.alfresco.repo.web.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.service.cmr.repository.ContentReader; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.mock.web.MockHttpServletResponse; - -/** - * Tests for the HttpRangeProcessor class. - * - * @author Ray Gauss II - */ -@RunWith(MockitoJUnitRunner.class) -public class HttpRangeProcessorTest -{ - private HttpRangeProcessor httpRangeProcessor; - private @Mock ContentReader reader; - - @Before - public void setUp() throws Exception - { - httpRangeProcessor = new HttpRangeProcessor(null); - when(reader.getMimetype()).thenReturn("image/jpeg"); - when(reader.getSize()).thenReturn(19133L); - when(reader.getContentInputStream()).thenReturn(this.getClass().getResourceAsStream("/test.jpg")); - } - - @Test - public void testValidRange() throws IOException - { - testRange("700-800", HttpServletResponse.SC_PARTIAL_CONTENT); - } - - @Test - public void testStartOnlyRange() throws IOException - { - testRange("19000-", HttpServletResponse.SC_PARTIAL_CONTENT); - } - - @Test - public void testNegativeRange() throws IOException - { - testRange("800-700", HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); - } - - @Test - public void testBeyondLengthRange() throws IOException - { - testRange("20000-", HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); - } - - protected void testRange(String range, int expectedStatus) throws IOException - { - MockHttpServletResponse response = new MockHttpServletResponse(); - - boolean result = httpRangeProcessor.processRange(response, reader, range, null, null, null, null); - - assertTrue(result); - assertEquals(expectedStatus, response.getStatus()); - reader.getContentInputStream().close(); - } - -} +package org.alfresco.repo.web.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.service.cmr.repository.ContentReader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.mock.web.MockHttpServletResponse; + +/** + * Tests for the HttpRangeProcessor class. + * + * @author Ray Gauss II + */ +@RunWith(MockitoJUnitRunner.class) +public class HttpRangeProcessorTest +{ + private HttpRangeProcessor httpRangeProcessor; + private @Mock ContentReader reader; + + @Before + public void setUp() throws Exception + { + httpRangeProcessor = new HttpRangeProcessor(null); + when(reader.getMimetype()).thenReturn("image/jpeg"); + when(reader.getSize()).thenReturn(19133L); + when(reader.getContentInputStream()).thenReturn(this.getClass().getResourceAsStream("/test.jpg")); + } + + @Test + public void testValidRange() throws IOException + { + testRange("700-800", HttpServletResponse.SC_PARTIAL_CONTENT); + } + + @Test + public void testStartOnlyRange() throws IOException + { + testRange("19000-", HttpServletResponse.SC_PARTIAL_CONTENT); + } + + @Test + public void testNegativeRange() throws IOException + { + testRange("800-700", HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); + } + + @Test + public void testBeyondLengthRange() throws IOException + { + testRange("20000-", HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); + } + + protected void testRange(String range, int expectedStatus) throws IOException + { + MockHttpServletResponse response = new MockHttpServletResponse(); + + boolean result = httpRangeProcessor.processRange(response, reader, range, null, null, null, null); + + assertTrue(result); + assertEquals(expectedStatus, response.getStatus()); + reader.getContentInputStream().close(); + } + +} diff --git a/source/test-java/org/alfresco/repo/web/util/JettyComponent.java b/source/test-java/org/alfresco/repo/web/util/JettyComponent.java index 5ceac2d79b..a31385a94e 100644 --- a/source/test-java/org/alfresco/repo/web/util/JettyComponent.java +++ b/source/test-java/org/alfresco/repo/web/util/JettyComponent.java @@ -1,11 +1,11 @@ -package org.alfresco.repo.web.util; - -import org.springframework.context.ConfigurableApplicationContext; - -public interface JettyComponent -{ - int getPort(); - ConfigurableApplicationContext getApplicationContext(); - void start(); - void shutdown(); -} +package org.alfresco.repo.web.util; + +import org.springframework.context.ConfigurableApplicationContext; + +public interface JettyComponent +{ + int getPort(); + ConfigurableApplicationContext getApplicationContext(); + void start(); + void shutdown(); +} diff --git a/source/test-java/org/alfresco/repo/web/util/PagingCursorTest.java b/source/test-java/org/alfresco/repo/web/util/PagingCursorTest.java index 2e51b7bd74..5cdd6b8bb2 100644 --- a/source/test-java/org/alfresco/repo/web/util/PagingCursorTest.java +++ b/source/test-java/org/alfresco/repo/web/util/PagingCursorTest.java @@ -1,317 +1,317 @@ -package org.alfresco.repo.web.util; - -import junit.framework.TestCase; - -import org.alfresco.repo.web.util.PagingCursor.Page; -import org.alfresco.repo.web.util.PagingCursor.Rows; - - -/** - * Test Paged and Row Based Cursors - * - * @author davidc - */ -public class PagingCursorTest extends TestCase -{ - protected PagingCursor pageCursor; - - @Override - protected void setUp() throws Exception - { - pageCursor = new PagingCursor(); - } - - public void testZeroBasedBooleans() - { - assertFalse(pageCursor.isZeroBasedPage()); - pageCursor.setZeroBasedPage(true); - assertTrue(pageCursor.isZeroBasedPage()); - assertTrue(pageCursor.isZeroBasedRow()); - pageCursor.setZeroBasedRow(false); - assertFalse(pageCursor.isZeroBasedRow()); - } - - public void testZeroRowsPageCursor() - { - Page page = pageCursor.createPageCursor(0, 10, 1); - assertNotNull(page); - assertEquals(0, page.getTotalRows()); - assertEquals(0, page.getTotalPages()); - assertEquals(10, page.getRowsPerPage()); - assertFalse(page.isInRange()); - assertEquals(1, page.getCurrentPage()); - assertEquals(-1, page.getFirstPage()); - assertEquals(-1, page.getLastPage()); - assertEquals(-1, page.getPreviousPage()); - assertEquals(-1, page.getNextPage()); - assertEquals(-1, page.getStartRow()); - assertEquals(-1, page.getEndRow()); - } - - public void testOutOfBoundsPageCursor() - { - Page page1 = pageCursor.createPageCursor(1, 1, 1); - assertNotNull(page1); - assertTrue(page1.isInRange()); - Page page2 = pageCursor.createPageCursor(1, 1, 2); - assertNotNull(page2); - assertFalse(page2.isInRange()); - Page page3 = pageCursor.createPageCursor(1, 2, 1); - assertNotNull(page3); - assertTrue(page3.isInRange()); - Page page4 = pageCursor.createPageCursor(10, 2, 5); - assertNotNull(page4); - assertTrue(page4.isInRange()); - Page page5 = pageCursor.createPageCursor(10, 2, 6); - assertNotNull(page5); - assertFalse(page5.isInRange()); - Page page6 = pageCursor.createPageCursor(11, 2, 5); - assertNotNull(page6); - assertTrue(page6.isInRange()); - Page page7 = pageCursor.createPageCursor(11, 2, 6); - assertNotNull(page7); - assertTrue(page7.isInRange()); - Page page8 = pageCursor.createPageCursor(11, 2, 0); - assertNotNull(page8); - assertFalse(page8.isInRange()); - - pageCursor.setZeroBasedPage(true); - Page page10 = pageCursor.createPageCursor(1, 1, 0); - assertNotNull(page10); - assertTrue(page10.isInRange()); - Page page11 = pageCursor.createPageCursor(1, 1, 1); - assertNotNull(page11); - assertFalse(page11.isInRange()); - Page page12 = pageCursor.createPageCursor(1, 2, 0); - assertNotNull(page12); - assertTrue(page12.isInRange()); - Page page13 = pageCursor.createPageCursor(10, 2, 4); - assertNotNull(page13); - assertTrue(page13.isInRange()); - Page page14 = pageCursor.createPageCursor(10, 2, 5); - assertNotNull(page14); - assertFalse(page14.isInRange()); - Page page15 = pageCursor.createPageCursor(11, 2, 4); - assertNotNull(page15); - assertTrue(page15.isInRange()); - Page page16 = pageCursor.createPageCursor(11, 2, 5); - assertNotNull(page16); - assertTrue(page16.isInRange()); - Page page17 = pageCursor.createPageCursor(11, 2, -1); - assertNotNull(page17); - assertFalse(page17.isInRange()); - } - - public void testTotalPageCursor() - { - Page page1 = pageCursor.createPageCursor(10, 1, 1); - assertEquals(10, page1.getTotalRows()); - assertEquals(10, page1.getTotalPages()); - Page page2 = pageCursor.createPageCursor(10, 10, 1); - assertEquals(10, page2.getTotalRows()); - assertEquals(1, page2.getTotalPages()); - Page page3 = pageCursor.createPageCursor(9, 10, 1); - assertEquals(9, page3.getTotalRows()); - assertEquals(1, page3.getTotalPages()); - Page page4 = pageCursor.createPageCursor(11, 10, 1); - assertEquals(11, page4.getTotalRows()); - assertEquals(2, page4.getTotalPages()); - Page page5 = pageCursor.createPageCursor(20, 10, 1); - assertEquals(20, page5.getTotalRows()); - assertEquals(2, page5.getTotalPages()); - } - - public void testPagingPageCursor() - { - Page page1 = pageCursor.createPageCursor(10, 1, 1); - assertEquals(1, page1.getCurrentPage()); - assertEquals(1, page1.getFirstPage()); - assertEquals(10, page1.getLastPage()); - assertEquals(-1, page1.getPreviousPage()); - assertEquals(2, page1.getNextPage()); - assertEquals(0, page1.getStartRow()); - assertEquals(0, page1.getEndRow()); - Page page2 = pageCursor.createPageCursor(10, 1, 2); - assertEquals(2, page2.getCurrentPage()); - assertEquals(1, page2.getFirstPage()); - assertEquals(10, page2.getLastPage()); - assertEquals(1, page2.getPreviousPage()); - assertEquals(3, page2.getNextPage()); - assertEquals(1, page2.getStartRow()); - assertEquals(1, page2.getEndRow()); - Page page3 = pageCursor.createPageCursor(10, 10, 1); - assertEquals(1, page3.getCurrentPage()); - assertEquals(1, page3.getFirstPage()); - assertEquals(1, page3.getLastPage()); - assertEquals(-1, page3.getPreviousPage()); - assertEquals(-1, page3.getNextPage()); - assertEquals(0, page3.getStartRow()); - assertEquals(9, page3.getEndRow()); - Page page4 = pageCursor.createPageCursor(9, 10, 1); - assertEquals(1, page4.getCurrentPage()); - assertEquals(1, page4.getFirstPage()); - assertEquals(1, page4.getLastPage()); - assertEquals(-1, page4.getPreviousPage()); - assertEquals(-1, page4.getNextPage()); - assertEquals(0, page4.getStartRow()); - assertEquals(8, page4.getEndRow()); - Page page5 = pageCursor.createPageCursor(11, 10, 1); - assertEquals(1, page5.getCurrentPage()); - assertEquals(1, page5.getFirstPage()); - assertEquals(2, page5.getLastPage()); - assertEquals(-1, page5.getPreviousPage()); - assertEquals(2, page5.getNextPage()); - assertEquals(0, page5.getStartRow()); - assertEquals(9, page5.getEndRow()); - Page page6 = pageCursor.createPageCursor(20, 10, 1); - assertEquals(1, page6.getCurrentPage()); - assertEquals(1, page6.getFirstPage()); - assertEquals(2, page6.getLastPage()); - assertEquals(-1, page6.getPreviousPage()); - assertEquals(2, page6.getNextPage()); - assertEquals(0, page6.getStartRow()); - assertEquals(9, page6.getEndRow()); - Page page7 = pageCursor.createPageCursor(20, 10, 2); - assertEquals(2, page7.getCurrentPage()); - assertEquals(1, page7.getFirstPage()); - assertEquals(2, page7.getLastPage()); - assertEquals(1, page7.getPreviousPage()); - assertEquals(-1, page7.getNextPage()); - assertEquals(10, page7.getStartRow()); - assertEquals(19, page7.getEndRow()); - Page page8 = pageCursor.createPageCursor(11, 10, 2); - assertEquals(2, page8.getCurrentPage()); - assertEquals(1, page8.getFirstPage()); - assertEquals(2, page8.getLastPage()); - assertEquals(1, page8.getPreviousPage()); - assertEquals(-1, page8.getNextPage()); - assertEquals(10, page8.getStartRow()); - assertEquals(10, page8.getEndRow()); - } - - public void testUnlimitedPageCursor() - { - Page page1 = pageCursor.createPageCursor(100, 0, 1); - assertTrue(page1.isInRange()); - assertEquals(1, page1.getCurrentPage()); - assertEquals(1, page1.getFirstPage()); - assertEquals(1, page1.getLastPage()); - assertEquals(-1, page1.getPreviousPage()); - assertEquals(-1, page1.getNextPage()); - assertEquals(0, page1.getStartRow()); - assertEquals(99, page1.getEndRow()); - Page page2 = pageCursor.createPageCursor(100, 0, 2); - assertFalse(page2.isInRange()); - } - - public void testScrollPageCursor() - { - int count = 0; - long[] coll = new long[100]; - - Page page = pageCursor.createPageCursor(100, 10, 1); - while (page.isInRange()) - { - for (long i = page.getStartRow(); i <= page.getEndRow(); i++) - { - coll[(int)i] = i; - count++; - } - page = pageCursor.createPageCursor(100, 10, page.getNextPage()); - } - - assertEquals(100, count); - for (int test = 0; test < count; test++) - { - assertEquals(test, coll[test]); - } - } - - public void testZeroRowsIndexCursor() - { - Rows rows = pageCursor.createRowsCursor(0, 10, 0); - assertNotNull(rows); - assertEquals(0, rows.getTotalRows()); - assertFalse(rows.isInRange()); - assertEquals(10, rows.getMaxRows()); - assertEquals(-1, rows.getStartRow()); - assertEquals(-1, rows.getEndRow()); - assertEquals(-1, rows.getNextSkipRows()); - } - - public void testOutOfBoundsRowsCursor() - { - Rows rows1 = pageCursor.createRowsCursor(1, 1, 0); - assertNotNull(rows1); - assertTrue(rows1.isInRange()); - Rows rows2 = pageCursor.createRowsCursor(1, 1, 1); - assertNotNull(rows2); - assertFalse(rows2.isInRange()); - Rows rows3 = pageCursor.createRowsCursor(1, -1, 0); - assertNotNull(rows3); - assertTrue(rows3.isInRange()); - } - - public void testTotalRowsCursor() - { - Rows rows1 = pageCursor.createRowsCursor(10, 1, 1); - assertEquals(10, rows1.getTotalRows()); - } - - public void testPagingRowsCursor() - { - Rows rows1 = pageCursor.createRowsCursor(10, 1, 0); - assertEquals(0, rows1.getStartRow()); - assertEquals(0, rows1.getEndRow()); - assertEquals(1, rows1.getNextSkipRows()); - Rows rows2 = pageCursor.createRowsCursor(10, 7, 0); - assertEquals(0, rows2.getStartRow()); - assertEquals(6, rows2.getEndRow()); - assertEquals(7, rows2.getNextSkipRows()); - Rows rows3 = pageCursor.createRowsCursor(10, 7, 7); - assertEquals(7, rows3.getStartRow()); - assertEquals(9, rows3.getEndRow()); - assertEquals(-1, rows3.getNextSkipRows()); - Rows rows4 = pageCursor.createRowsCursor(10, 10, 0); - assertEquals(0, rows4.getStartRow()); - assertEquals(9, rows4.getEndRow()); - assertEquals(-1, rows4.getNextSkipRows()); - Rows rows5 = pageCursor.createRowsCursor(10, 11, 0); - assertEquals(0, rows5.getStartRow()); - assertEquals(9, rows5.getEndRow()); - assertEquals(-1, rows5.getNextSkipRows()); - } - - public void testUnlimitedRowsCursor() - { - Rows rows1 = pageCursor.createRowsCursor(100, 0, 0); - assertTrue(rows1.isInRange()); - assertEquals(0, rows1.getStartRow()); - assertEquals(99, rows1.getEndRow()); - assertEquals(-1, rows1.getNextSkipRows()); - } - - public void testScrollRowsCursor() - { - int count = 0; - long[] coll = new long[100]; - - Rows rows = pageCursor.createRowsCursor(100, 10, 0); - while (rows.isInRange()) - { - for (long i = rows.getStartRow(); i <= rows.getEndRow(); i++) - { - coll[(int)i] = i; - count++; - } - rows = pageCursor.createRowsCursor(100, 10, rows.getNextSkipRows()); - } - - assertEquals(100, count); - for (int test = 0; test < count; test++) - { - assertEquals(test, coll[test]); - } - } - -} +package org.alfresco.repo.web.util; + +import junit.framework.TestCase; + +import org.alfresco.repo.web.util.PagingCursor.Page; +import org.alfresco.repo.web.util.PagingCursor.Rows; + + +/** + * Test Paged and Row Based Cursors + * + * @author davidc + */ +public class PagingCursorTest extends TestCase +{ + protected PagingCursor pageCursor; + + @Override + protected void setUp() throws Exception + { + pageCursor = new PagingCursor(); + } + + public void testZeroBasedBooleans() + { + assertFalse(pageCursor.isZeroBasedPage()); + pageCursor.setZeroBasedPage(true); + assertTrue(pageCursor.isZeroBasedPage()); + assertTrue(pageCursor.isZeroBasedRow()); + pageCursor.setZeroBasedRow(false); + assertFalse(pageCursor.isZeroBasedRow()); + } + + public void testZeroRowsPageCursor() + { + Page page = pageCursor.createPageCursor(0, 10, 1); + assertNotNull(page); + assertEquals(0, page.getTotalRows()); + assertEquals(0, page.getTotalPages()); + assertEquals(10, page.getRowsPerPage()); + assertFalse(page.isInRange()); + assertEquals(1, page.getCurrentPage()); + assertEquals(-1, page.getFirstPage()); + assertEquals(-1, page.getLastPage()); + assertEquals(-1, page.getPreviousPage()); + assertEquals(-1, page.getNextPage()); + assertEquals(-1, page.getStartRow()); + assertEquals(-1, page.getEndRow()); + } + + public void testOutOfBoundsPageCursor() + { + Page page1 = pageCursor.createPageCursor(1, 1, 1); + assertNotNull(page1); + assertTrue(page1.isInRange()); + Page page2 = pageCursor.createPageCursor(1, 1, 2); + assertNotNull(page2); + assertFalse(page2.isInRange()); + Page page3 = pageCursor.createPageCursor(1, 2, 1); + assertNotNull(page3); + assertTrue(page3.isInRange()); + Page page4 = pageCursor.createPageCursor(10, 2, 5); + assertNotNull(page4); + assertTrue(page4.isInRange()); + Page page5 = pageCursor.createPageCursor(10, 2, 6); + assertNotNull(page5); + assertFalse(page5.isInRange()); + Page page6 = pageCursor.createPageCursor(11, 2, 5); + assertNotNull(page6); + assertTrue(page6.isInRange()); + Page page7 = pageCursor.createPageCursor(11, 2, 6); + assertNotNull(page7); + assertTrue(page7.isInRange()); + Page page8 = pageCursor.createPageCursor(11, 2, 0); + assertNotNull(page8); + assertFalse(page8.isInRange()); + + pageCursor.setZeroBasedPage(true); + Page page10 = pageCursor.createPageCursor(1, 1, 0); + assertNotNull(page10); + assertTrue(page10.isInRange()); + Page page11 = pageCursor.createPageCursor(1, 1, 1); + assertNotNull(page11); + assertFalse(page11.isInRange()); + Page page12 = pageCursor.createPageCursor(1, 2, 0); + assertNotNull(page12); + assertTrue(page12.isInRange()); + Page page13 = pageCursor.createPageCursor(10, 2, 4); + assertNotNull(page13); + assertTrue(page13.isInRange()); + Page page14 = pageCursor.createPageCursor(10, 2, 5); + assertNotNull(page14); + assertFalse(page14.isInRange()); + Page page15 = pageCursor.createPageCursor(11, 2, 4); + assertNotNull(page15); + assertTrue(page15.isInRange()); + Page page16 = pageCursor.createPageCursor(11, 2, 5); + assertNotNull(page16); + assertTrue(page16.isInRange()); + Page page17 = pageCursor.createPageCursor(11, 2, -1); + assertNotNull(page17); + assertFalse(page17.isInRange()); + } + + public void testTotalPageCursor() + { + Page page1 = pageCursor.createPageCursor(10, 1, 1); + assertEquals(10, page1.getTotalRows()); + assertEquals(10, page1.getTotalPages()); + Page page2 = pageCursor.createPageCursor(10, 10, 1); + assertEquals(10, page2.getTotalRows()); + assertEquals(1, page2.getTotalPages()); + Page page3 = pageCursor.createPageCursor(9, 10, 1); + assertEquals(9, page3.getTotalRows()); + assertEquals(1, page3.getTotalPages()); + Page page4 = pageCursor.createPageCursor(11, 10, 1); + assertEquals(11, page4.getTotalRows()); + assertEquals(2, page4.getTotalPages()); + Page page5 = pageCursor.createPageCursor(20, 10, 1); + assertEquals(20, page5.getTotalRows()); + assertEquals(2, page5.getTotalPages()); + } + + public void testPagingPageCursor() + { + Page page1 = pageCursor.createPageCursor(10, 1, 1); + assertEquals(1, page1.getCurrentPage()); + assertEquals(1, page1.getFirstPage()); + assertEquals(10, page1.getLastPage()); + assertEquals(-1, page1.getPreviousPage()); + assertEquals(2, page1.getNextPage()); + assertEquals(0, page1.getStartRow()); + assertEquals(0, page1.getEndRow()); + Page page2 = pageCursor.createPageCursor(10, 1, 2); + assertEquals(2, page2.getCurrentPage()); + assertEquals(1, page2.getFirstPage()); + assertEquals(10, page2.getLastPage()); + assertEquals(1, page2.getPreviousPage()); + assertEquals(3, page2.getNextPage()); + assertEquals(1, page2.getStartRow()); + assertEquals(1, page2.getEndRow()); + Page page3 = pageCursor.createPageCursor(10, 10, 1); + assertEquals(1, page3.getCurrentPage()); + assertEquals(1, page3.getFirstPage()); + assertEquals(1, page3.getLastPage()); + assertEquals(-1, page3.getPreviousPage()); + assertEquals(-1, page3.getNextPage()); + assertEquals(0, page3.getStartRow()); + assertEquals(9, page3.getEndRow()); + Page page4 = pageCursor.createPageCursor(9, 10, 1); + assertEquals(1, page4.getCurrentPage()); + assertEquals(1, page4.getFirstPage()); + assertEquals(1, page4.getLastPage()); + assertEquals(-1, page4.getPreviousPage()); + assertEquals(-1, page4.getNextPage()); + assertEquals(0, page4.getStartRow()); + assertEquals(8, page4.getEndRow()); + Page page5 = pageCursor.createPageCursor(11, 10, 1); + assertEquals(1, page5.getCurrentPage()); + assertEquals(1, page5.getFirstPage()); + assertEquals(2, page5.getLastPage()); + assertEquals(-1, page5.getPreviousPage()); + assertEquals(2, page5.getNextPage()); + assertEquals(0, page5.getStartRow()); + assertEquals(9, page5.getEndRow()); + Page page6 = pageCursor.createPageCursor(20, 10, 1); + assertEquals(1, page6.getCurrentPage()); + assertEquals(1, page6.getFirstPage()); + assertEquals(2, page6.getLastPage()); + assertEquals(-1, page6.getPreviousPage()); + assertEquals(2, page6.getNextPage()); + assertEquals(0, page6.getStartRow()); + assertEquals(9, page6.getEndRow()); + Page page7 = pageCursor.createPageCursor(20, 10, 2); + assertEquals(2, page7.getCurrentPage()); + assertEquals(1, page7.getFirstPage()); + assertEquals(2, page7.getLastPage()); + assertEquals(1, page7.getPreviousPage()); + assertEquals(-1, page7.getNextPage()); + assertEquals(10, page7.getStartRow()); + assertEquals(19, page7.getEndRow()); + Page page8 = pageCursor.createPageCursor(11, 10, 2); + assertEquals(2, page8.getCurrentPage()); + assertEquals(1, page8.getFirstPage()); + assertEquals(2, page8.getLastPage()); + assertEquals(1, page8.getPreviousPage()); + assertEquals(-1, page8.getNextPage()); + assertEquals(10, page8.getStartRow()); + assertEquals(10, page8.getEndRow()); + } + + public void testUnlimitedPageCursor() + { + Page page1 = pageCursor.createPageCursor(100, 0, 1); + assertTrue(page1.isInRange()); + assertEquals(1, page1.getCurrentPage()); + assertEquals(1, page1.getFirstPage()); + assertEquals(1, page1.getLastPage()); + assertEquals(-1, page1.getPreviousPage()); + assertEquals(-1, page1.getNextPage()); + assertEquals(0, page1.getStartRow()); + assertEquals(99, page1.getEndRow()); + Page page2 = pageCursor.createPageCursor(100, 0, 2); + assertFalse(page2.isInRange()); + } + + public void testScrollPageCursor() + { + int count = 0; + long[] coll = new long[100]; + + Page page = pageCursor.createPageCursor(100, 10, 1); + while (page.isInRange()) + { + for (long i = page.getStartRow(); i <= page.getEndRow(); i++) + { + coll[(int)i] = i; + count++; + } + page = pageCursor.createPageCursor(100, 10, page.getNextPage()); + } + + assertEquals(100, count); + for (int test = 0; test < count; test++) + { + assertEquals(test, coll[test]); + } + } + + public void testZeroRowsIndexCursor() + { + Rows rows = pageCursor.createRowsCursor(0, 10, 0); + assertNotNull(rows); + assertEquals(0, rows.getTotalRows()); + assertFalse(rows.isInRange()); + assertEquals(10, rows.getMaxRows()); + assertEquals(-1, rows.getStartRow()); + assertEquals(-1, rows.getEndRow()); + assertEquals(-1, rows.getNextSkipRows()); + } + + public void testOutOfBoundsRowsCursor() + { + Rows rows1 = pageCursor.createRowsCursor(1, 1, 0); + assertNotNull(rows1); + assertTrue(rows1.isInRange()); + Rows rows2 = pageCursor.createRowsCursor(1, 1, 1); + assertNotNull(rows2); + assertFalse(rows2.isInRange()); + Rows rows3 = pageCursor.createRowsCursor(1, -1, 0); + assertNotNull(rows3); + assertTrue(rows3.isInRange()); + } + + public void testTotalRowsCursor() + { + Rows rows1 = pageCursor.createRowsCursor(10, 1, 1); + assertEquals(10, rows1.getTotalRows()); + } + + public void testPagingRowsCursor() + { + Rows rows1 = pageCursor.createRowsCursor(10, 1, 0); + assertEquals(0, rows1.getStartRow()); + assertEquals(0, rows1.getEndRow()); + assertEquals(1, rows1.getNextSkipRows()); + Rows rows2 = pageCursor.createRowsCursor(10, 7, 0); + assertEquals(0, rows2.getStartRow()); + assertEquals(6, rows2.getEndRow()); + assertEquals(7, rows2.getNextSkipRows()); + Rows rows3 = pageCursor.createRowsCursor(10, 7, 7); + assertEquals(7, rows3.getStartRow()); + assertEquals(9, rows3.getEndRow()); + assertEquals(-1, rows3.getNextSkipRows()); + Rows rows4 = pageCursor.createRowsCursor(10, 10, 0); + assertEquals(0, rows4.getStartRow()); + assertEquals(9, rows4.getEndRow()); + assertEquals(-1, rows4.getNextSkipRows()); + Rows rows5 = pageCursor.createRowsCursor(10, 11, 0); + assertEquals(0, rows5.getStartRow()); + assertEquals(9, rows5.getEndRow()); + assertEquals(-1, rows5.getNextSkipRows()); + } + + public void testUnlimitedRowsCursor() + { + Rows rows1 = pageCursor.createRowsCursor(100, 0, 0); + assertTrue(rows1.isInRange()); + assertEquals(0, rows1.getStartRow()); + assertEquals(99, rows1.getEndRow()); + assertEquals(-1, rows1.getNextSkipRows()); + } + + public void testScrollRowsCursor() + { + int count = 0; + long[] coll = new long[100]; + + Rows rows = pageCursor.createRowsCursor(100, 10, 0); + while (rows.isInRange()) + { + for (long i = rows.getStartRow(); i <= rows.getEndRow(); i++) + { + coll[(int)i] = i; + count++; + } + rows = pageCursor.createRowsCursor(100, 10, rows.getNextSkipRows()); + } + + assertEquals(100, count); + for (int test = 0; test < count; test++) + { + assertEquals(test, coll[test]); + } + } + +} diff --git a/source/test-java/org/alfresco/repo/web/util/paging/PagingTest.java b/source/test-java/org/alfresco/repo/web/util/paging/PagingTest.java index a231e67bba..0d868d9f4a 100644 --- a/source/test-java/org/alfresco/repo/web/util/paging/PagingTest.java +++ b/source/test-java/org/alfresco/repo/web/util/paging/PagingTest.java @@ -1,347 +1,347 @@ -package org.alfresco.repo.web.util.paging; - -import junit.framework.TestCase; - - -/** - * Test Paged and Window Based Cursors - * - * @author davidc - */ -public class PagingTest extends TestCase -{ - protected Paging paging; - - @Override - protected void setUp() throws Exception - { - paging = new Paging(); - } - - public void testZeroBasedBooleans() - { - assertFalse(paging.isZeroBasedPage()); - paging.setZeroBasedPage(true); - assertTrue(paging.isZeroBasedPage()); - assertTrue(paging.isZeroBasedRow()); - paging.setZeroBasedRow(false); - assertFalse(paging.isZeroBasedRow()); - } - - public void testCreatePage() - { - Page page = paging.createPage(1, 10); - assertNotNull(page); - assertEquals(Paging.PageType.PAGE, page.getType()); - assertFalse(page.isZeroBasedIdx()); - assertEquals(1, page.getNumber()); - assertEquals(10, page.getSize()); - - Page window = paging.createWindow(1, 10); - assertNotNull(window); - assertEquals(Paging.PageType.WINDOW, window.getType()); - assertTrue(window.isZeroBasedIdx()); - assertEquals(1, window.getNumber()); - assertEquals(10, window.getSize()); - } - - public void testZeroRowsPage() - { - Cursor cursor = paging.createCursor(0, paging.createPage(1, 10)); - assertNotNull(cursor); - assertEquals(0, cursor.getTotalRows()); - assertEquals(0, cursor.getTotalPages()); - assertEquals(10, cursor.getPageSize()); - assertFalse(cursor.isInRange()); - assertEquals(1, cursor.getCurrentPage()); - assertEquals(-1, cursor.getFirstPage()); - assertEquals(-1, cursor.getLastPage()); - assertEquals(-1, cursor.getPrevPage()); - assertEquals(-1, cursor.getNextPage()); - assertEquals(0, cursor.getStartRow()); - assertEquals(-1, cursor.getEndRow()); - assertEquals(0, cursor.getRowCount()); - } - - public void testOutOfBoundsPage() - { - Cursor cursor1 = paging.createCursor(1, paging.createPage(1, 1)); - assertNotNull(cursor1); - assertTrue(cursor1.isInRange()); - Cursor cursor2 = paging.createCursor(1, paging.createPage(2, 1)); - assertNotNull(cursor2); - assertFalse(cursor2.isInRange()); - Cursor cursor3 = paging.createCursor(1, paging.createPage(1, 2)); - assertNotNull(cursor3); - assertTrue(cursor3.isInRange()); - Cursor cursor4 = paging.createCursor(10, paging.createPage(5, 2)); - assertNotNull(cursor4); - assertTrue(cursor4.isInRange()); - Cursor cursor5 = paging.createCursor(10, paging.createPage(6, 2)); - assertNotNull(cursor5); - assertFalse(cursor5.isInRange()); - Cursor cursor6 = paging.createCursor(11, paging.createPage(5, 2)); - assertNotNull(cursor6); - assertTrue(cursor6.isInRange()); - Cursor cursor7 = paging.createCursor(11, paging.createPage(6, 2)); - assertNotNull(cursor7); - assertTrue(cursor7.isInRange()); - Cursor cursor8 = paging.createCursor(11, paging.createPage(0, 2)); - assertNotNull(cursor8); - assertFalse(cursor8.isInRange()); - - paging.setZeroBasedPage(true); - Cursor cursor10 = paging.createCursor(1, paging.createPage(0, 1)); - assertNotNull(cursor10); - assertTrue(cursor10.isInRange()); - Cursor cursor11 = paging.createCursor(1, paging.createPage(1, 1)); - assertNotNull(cursor11); - assertFalse(cursor11.isInRange()); - Cursor cursor12 = paging.createCursor(1, paging.createPage(0, 2)); - assertNotNull(cursor12); - assertTrue(cursor12.isInRange()); - Cursor cursor13 = paging.createCursor(10, paging.createPage(4, 2)); - assertNotNull(cursor13); - assertTrue(cursor13.isInRange()); - Cursor cursor14 = paging.createCursor(10, paging.createPage(5, 2)); - assertNotNull(cursor14); - assertFalse(cursor14.isInRange()); - Cursor cursor15 = paging.createCursor(11, paging.createPage(4, 2)); - assertNotNull(cursor15); - assertTrue(cursor15.isInRange()); - Cursor cursor16 = paging.createCursor(11, paging.createPage(5, 2)); - assertNotNull(cursor16); - assertTrue(cursor16.isInRange()); - Cursor cursor17 = paging.createCursor(11, paging.createPage(-1, 2)); - assertNotNull(cursor17); - assertFalse(cursor17.isInRange()); - } - - public void testTotalPage() - { - Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1)); - assertEquals(10, cursor1.getTotalRows()); - assertEquals(10, cursor1.getTotalPages()); - Cursor cursor2 = paging.createCursor(10, paging.createPage(1, 10)); - assertEquals(10, cursor2.getTotalRows()); - assertEquals(1, cursor2.getTotalPages()); - Cursor cursor3 = paging.createCursor(9, paging.createPage(1, 10)); - assertEquals(9, cursor3.getTotalRows()); - assertEquals(1, cursor3.getTotalPages()); - Cursor cursor4 = paging.createCursor(11, paging.createPage(1, 10)); - assertEquals(11, cursor4.getTotalRows()); - assertEquals(2, cursor4.getTotalPages()); - Cursor cursor5 = paging.createCursor(20, paging.createPage(1, 10)); - assertEquals(20, cursor5.getTotalRows()); - assertEquals(2, cursor5.getTotalPages()); - } - - public void testCursorPage() - { - Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1)); - assertEquals(1, cursor1.getCurrentPage()); - assertEquals(1, cursor1.getFirstPage()); - assertEquals(10, cursor1.getLastPage()); - assertEquals(-1, cursor1.getPrevPage()); - assertEquals(2, cursor1.getNextPage()); - assertEquals(0, cursor1.getStartRow()); - assertEquals(0, cursor1.getEndRow()); - assertEquals(1, cursor1.getRowCount()); - Cursor cursor2 = paging.createCursor(10, paging.createPage(2, 1)); - assertEquals(2, cursor2.getCurrentPage()); - assertEquals(1, cursor2.getFirstPage()); - assertEquals(10, cursor2.getLastPage()); - assertEquals(1, cursor2.getPrevPage()); - assertEquals(3, cursor2.getNextPage()); - assertEquals(1, cursor2.getStartRow()); - assertEquals(1, cursor2.getEndRow()); - assertEquals(1, cursor2.getRowCount()); - Cursor cursor3 = paging.createCursor(10, paging.createPage(1, 10)); - assertEquals(1, cursor3.getCurrentPage()); - assertEquals(1, cursor3.getFirstPage()); - assertEquals(1, cursor3.getLastPage()); - assertEquals(-1, cursor3.getPrevPage()); - assertEquals(-1, cursor3.getNextPage()); - assertEquals(0, cursor3.getStartRow()); - assertEquals(9, cursor3.getEndRow()); - assertEquals(10, cursor3.getRowCount()); - Cursor cursor4 = paging.createCursor(9, paging.createPage(1, 10)); - assertEquals(1, cursor4.getCurrentPage()); - assertEquals(1, cursor4.getFirstPage()); - assertEquals(1, cursor4.getLastPage()); - assertEquals(-1, cursor4.getPrevPage()); - assertEquals(-1, cursor4.getNextPage()); - assertEquals(0, cursor4.getStartRow()); - assertEquals(8, cursor4.getEndRow()); - assertEquals(9, cursor4.getRowCount()); - Cursor cursor5 = paging.createCursor(11, paging.createPage(1, 10)); - assertEquals(1, cursor5.getCurrentPage()); - assertEquals(1, cursor5.getFirstPage()); - assertEquals(2, cursor5.getLastPage()); - assertEquals(-1, cursor5.getPrevPage()); - assertEquals(2, cursor5.getNextPage()); - assertEquals(0, cursor5.getStartRow()); - assertEquals(9, cursor5.getEndRow()); - assertEquals(10, cursor5.getRowCount()); - Cursor cursor6 = paging.createCursor(20, paging.createPage(1, 10)); - assertEquals(1, cursor6.getCurrentPage()); - assertEquals(1, cursor6.getFirstPage()); - assertEquals(2, cursor6.getLastPage()); - assertEquals(-1, cursor6.getPrevPage()); - assertEquals(2, cursor6.getNextPage()); - assertEquals(0, cursor6.getStartRow()); - assertEquals(9, cursor6.getEndRow()); - assertEquals(10, cursor6.getRowCount()); - Cursor cursor7 = paging.createCursor(20, paging.createPage(2, 10)); - assertEquals(2, cursor7.getCurrentPage()); - assertEquals(1, cursor7.getFirstPage()); - assertEquals(2, cursor7.getLastPage()); - assertEquals(1, cursor7.getPrevPage()); - assertEquals(-1, cursor7.getNextPage()); - assertEquals(10, cursor7.getStartRow()); - assertEquals(19, cursor7.getEndRow()); - assertEquals(10, cursor7.getRowCount()); - Cursor cursor8 = paging.createCursor(11, paging.createPage(2, 10)); - assertEquals(2, cursor8.getCurrentPage()); - assertEquals(1, cursor8.getFirstPage()); - assertEquals(2, cursor8.getLastPage()); - assertEquals(1, cursor8.getPrevPage()); - assertEquals(-1, cursor8.getNextPage()); - assertEquals(10, cursor8.getStartRow()); - assertEquals(10, cursor8.getEndRow()); - assertEquals(1, cursor8.getRowCount()); - } - - public void testUnlimitedPage() - { - Cursor cursor1 = paging.createCursor(100, paging.createPage(1, -1)); - assertTrue(cursor1.isInRange()); - assertEquals(1, cursor1.getCurrentPage()); - assertEquals(1, cursor1.getFirstPage()); - assertEquals(1, cursor1.getLastPage()); - assertEquals(-1, cursor1.getPrevPage()); - assertEquals(-1, cursor1.getNextPage()); - assertEquals(0, cursor1.getStartRow()); - assertEquals(99, cursor1.getEndRow()); - Cursor cursor2 = paging.createCursor(100, paging.createPage(2, -1)); - assertFalse(cursor2.isInRange()); - } - - public void testScrollPage() - { - int count = 0; - long[] coll = new long[100]; - - Cursor cursor = paging.createCursor(coll.length, paging.createPage(1, 10)); - while (cursor.isInRange()) - { - for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) - { - coll[(int)i] = i; - count++; - } - cursor = paging.createCursor(coll.length, paging.createPage(cursor.getNextPage(), cursor.getPageSize())); - } - - assertEquals(100, count); - for (int test = 0; test < count; test++) - { - assertEquals(test, coll[test]); - } - } - - public void testZeroRowsWindow() - { - Cursor rows = paging.createCursor(0, paging.createWindow(0, 10)); - assertNotNull(rows); - assertEquals(0, rows.getTotalRows()); - assertFalse(rows.isInRange()); - assertEquals(10, rows.getPageSize()); - assertEquals(0, rows.getStartRow()); - assertEquals(-1, rows.getEndRow()); - assertEquals(0, rows.getRowCount()); - assertEquals(-1, rows.getNextPage()); - } - - public void testOutOfBoundsWindow() - { - Cursor cursor1 = paging.createCursor(1, paging.createWindow(0, 1)); - assertNotNull(cursor1); - assertTrue(cursor1.isInRange()); - Cursor cursor2 = paging.createCursor(1, paging.createWindow(1, 1)); - assertNotNull(cursor2); - assertFalse(cursor2.isInRange()); - Cursor cursor3 = paging.createCursor(1, paging.createWindow(0, -1)); - assertNotNull(cursor3); - assertTrue(cursor3.isInRange()); - } - - public void testTotalWindow() - { - Cursor cursor1 = paging.createCursor(10, paging.createWindow(1, 1)); - assertEquals(10, cursor1.getTotalRows()); - } - - public void testCursorWindow() - { - Cursor cursor1 = paging.createCursor(10, paging.createWindow(0, 1)); - assertEquals(0, cursor1.getStartRow()); - assertEquals(0, cursor1.getEndRow()); - assertEquals(1, cursor1.getRowCount()); - assertEquals(1, cursor1.getNextPage()); - Cursor cursor2 = paging.createCursor(10, paging.createWindow(0, 7)); - assertEquals(0, cursor2.getStartRow()); - assertEquals(6, cursor2.getEndRow()); - assertEquals(7, cursor2.getRowCount()); - assertEquals(7, cursor2.getNextPage()); - Cursor cursor3 = paging.createCursor(10, paging.createWindow(7, 7)); - assertEquals(7, cursor3.getStartRow()); - assertEquals(9, cursor3.getEndRow()); - assertEquals(3, cursor3.getRowCount()); - assertEquals(-1, cursor3.getNextPage()); - Cursor cursor4 = paging.createCursor(10, paging.createWindow(0, 10)); - assertEquals(0, cursor4.getStartRow()); - assertEquals(9, cursor4.getEndRow()); - assertEquals(10, cursor4.getRowCount()); - assertEquals(-1, cursor4.getNextPage()); - Cursor cursor5 = paging.createCursor(10, paging.createWindow(0, 11)); - assertEquals(0, cursor5.getStartRow()); - assertEquals(9, cursor5.getEndRow()); - assertEquals(10, cursor5.getRowCount()); - assertEquals(-1, cursor5.getNextPage()); - } - - public void testUnlimitedWindow() - { - Cursor cursor1 = paging.createCursor(100, paging.createWindow(0, -1)); - assertTrue(cursor1.isInRange()); - assertEquals(0, cursor1.getStartRow()); - assertEquals(99, cursor1.getEndRow()); - assertEquals(100, cursor1.getRowCount()); - assertEquals(-1, cursor1.getNextPage()); - } - - public void testScrollWindow() - { - int count = 0; - long[] coll = new long[100]; - - Cursor cursor = paging.createCursor(coll.length, paging.createWindow(0, 10)); - while (cursor.isInRange()) - { - for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) - { - coll[(int)i] = i; - count++; - } - cursor = paging.createCursor(coll.length, paging.createWindow(cursor.getNextPage(), cursor.getPageSize())); - } - - assertEquals(100, count); - for (int test = 0; test < count; test++) - { - assertEquals(test, coll[test]); - } - } - -} +package org.alfresco.repo.web.util.paging; + +import junit.framework.TestCase; + + +/** + * Test Paged and Window Based Cursors + * + * @author davidc + */ +public class PagingTest extends TestCase +{ + protected Paging paging; + + @Override + protected void setUp() throws Exception + { + paging = new Paging(); + } + + public void testZeroBasedBooleans() + { + assertFalse(paging.isZeroBasedPage()); + paging.setZeroBasedPage(true); + assertTrue(paging.isZeroBasedPage()); + assertTrue(paging.isZeroBasedRow()); + paging.setZeroBasedRow(false); + assertFalse(paging.isZeroBasedRow()); + } + + public void testCreatePage() + { + Page page = paging.createPage(1, 10); + assertNotNull(page); + assertEquals(Paging.PageType.PAGE, page.getType()); + assertFalse(page.isZeroBasedIdx()); + assertEquals(1, page.getNumber()); + assertEquals(10, page.getSize()); + + Page window = paging.createWindow(1, 10); + assertNotNull(window); + assertEquals(Paging.PageType.WINDOW, window.getType()); + assertTrue(window.isZeroBasedIdx()); + assertEquals(1, window.getNumber()); + assertEquals(10, window.getSize()); + } + + public void testZeroRowsPage() + { + Cursor cursor = paging.createCursor(0, paging.createPage(1, 10)); + assertNotNull(cursor); + assertEquals(0, cursor.getTotalRows()); + assertEquals(0, cursor.getTotalPages()); + assertEquals(10, cursor.getPageSize()); + assertFalse(cursor.isInRange()); + assertEquals(1, cursor.getCurrentPage()); + assertEquals(-1, cursor.getFirstPage()); + assertEquals(-1, cursor.getLastPage()); + assertEquals(-1, cursor.getPrevPage()); + assertEquals(-1, cursor.getNextPage()); + assertEquals(0, cursor.getStartRow()); + assertEquals(-1, cursor.getEndRow()); + assertEquals(0, cursor.getRowCount()); + } + + public void testOutOfBoundsPage() + { + Cursor cursor1 = paging.createCursor(1, paging.createPage(1, 1)); + assertNotNull(cursor1); + assertTrue(cursor1.isInRange()); + Cursor cursor2 = paging.createCursor(1, paging.createPage(2, 1)); + assertNotNull(cursor2); + assertFalse(cursor2.isInRange()); + Cursor cursor3 = paging.createCursor(1, paging.createPage(1, 2)); + assertNotNull(cursor3); + assertTrue(cursor3.isInRange()); + Cursor cursor4 = paging.createCursor(10, paging.createPage(5, 2)); + assertNotNull(cursor4); + assertTrue(cursor4.isInRange()); + Cursor cursor5 = paging.createCursor(10, paging.createPage(6, 2)); + assertNotNull(cursor5); + assertFalse(cursor5.isInRange()); + Cursor cursor6 = paging.createCursor(11, paging.createPage(5, 2)); + assertNotNull(cursor6); + assertTrue(cursor6.isInRange()); + Cursor cursor7 = paging.createCursor(11, paging.createPage(6, 2)); + assertNotNull(cursor7); + assertTrue(cursor7.isInRange()); + Cursor cursor8 = paging.createCursor(11, paging.createPage(0, 2)); + assertNotNull(cursor8); + assertFalse(cursor8.isInRange()); + + paging.setZeroBasedPage(true); + Cursor cursor10 = paging.createCursor(1, paging.createPage(0, 1)); + assertNotNull(cursor10); + assertTrue(cursor10.isInRange()); + Cursor cursor11 = paging.createCursor(1, paging.createPage(1, 1)); + assertNotNull(cursor11); + assertFalse(cursor11.isInRange()); + Cursor cursor12 = paging.createCursor(1, paging.createPage(0, 2)); + assertNotNull(cursor12); + assertTrue(cursor12.isInRange()); + Cursor cursor13 = paging.createCursor(10, paging.createPage(4, 2)); + assertNotNull(cursor13); + assertTrue(cursor13.isInRange()); + Cursor cursor14 = paging.createCursor(10, paging.createPage(5, 2)); + assertNotNull(cursor14); + assertFalse(cursor14.isInRange()); + Cursor cursor15 = paging.createCursor(11, paging.createPage(4, 2)); + assertNotNull(cursor15); + assertTrue(cursor15.isInRange()); + Cursor cursor16 = paging.createCursor(11, paging.createPage(5, 2)); + assertNotNull(cursor16); + assertTrue(cursor16.isInRange()); + Cursor cursor17 = paging.createCursor(11, paging.createPage(-1, 2)); + assertNotNull(cursor17); + assertFalse(cursor17.isInRange()); + } + + public void testTotalPage() + { + Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1)); + assertEquals(10, cursor1.getTotalRows()); + assertEquals(10, cursor1.getTotalPages()); + Cursor cursor2 = paging.createCursor(10, paging.createPage(1, 10)); + assertEquals(10, cursor2.getTotalRows()); + assertEquals(1, cursor2.getTotalPages()); + Cursor cursor3 = paging.createCursor(9, paging.createPage(1, 10)); + assertEquals(9, cursor3.getTotalRows()); + assertEquals(1, cursor3.getTotalPages()); + Cursor cursor4 = paging.createCursor(11, paging.createPage(1, 10)); + assertEquals(11, cursor4.getTotalRows()); + assertEquals(2, cursor4.getTotalPages()); + Cursor cursor5 = paging.createCursor(20, paging.createPage(1, 10)); + assertEquals(20, cursor5.getTotalRows()); + assertEquals(2, cursor5.getTotalPages()); + } + + public void testCursorPage() + { + Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1)); + assertEquals(1, cursor1.getCurrentPage()); + assertEquals(1, cursor1.getFirstPage()); + assertEquals(10, cursor1.getLastPage()); + assertEquals(-1, cursor1.getPrevPage()); + assertEquals(2, cursor1.getNextPage()); + assertEquals(0, cursor1.getStartRow()); + assertEquals(0, cursor1.getEndRow()); + assertEquals(1, cursor1.getRowCount()); + Cursor cursor2 = paging.createCursor(10, paging.createPage(2, 1)); + assertEquals(2, cursor2.getCurrentPage()); + assertEquals(1, cursor2.getFirstPage()); + assertEquals(10, cursor2.getLastPage()); + assertEquals(1, cursor2.getPrevPage()); + assertEquals(3, cursor2.getNextPage()); + assertEquals(1, cursor2.getStartRow()); + assertEquals(1, cursor2.getEndRow()); + assertEquals(1, cursor2.getRowCount()); + Cursor cursor3 = paging.createCursor(10, paging.createPage(1, 10)); + assertEquals(1, cursor3.getCurrentPage()); + assertEquals(1, cursor3.getFirstPage()); + assertEquals(1, cursor3.getLastPage()); + assertEquals(-1, cursor3.getPrevPage()); + assertEquals(-1, cursor3.getNextPage()); + assertEquals(0, cursor3.getStartRow()); + assertEquals(9, cursor3.getEndRow()); + assertEquals(10, cursor3.getRowCount()); + Cursor cursor4 = paging.createCursor(9, paging.createPage(1, 10)); + assertEquals(1, cursor4.getCurrentPage()); + assertEquals(1, cursor4.getFirstPage()); + assertEquals(1, cursor4.getLastPage()); + assertEquals(-1, cursor4.getPrevPage()); + assertEquals(-1, cursor4.getNextPage()); + assertEquals(0, cursor4.getStartRow()); + assertEquals(8, cursor4.getEndRow()); + assertEquals(9, cursor4.getRowCount()); + Cursor cursor5 = paging.createCursor(11, paging.createPage(1, 10)); + assertEquals(1, cursor5.getCurrentPage()); + assertEquals(1, cursor5.getFirstPage()); + assertEquals(2, cursor5.getLastPage()); + assertEquals(-1, cursor5.getPrevPage()); + assertEquals(2, cursor5.getNextPage()); + assertEquals(0, cursor5.getStartRow()); + assertEquals(9, cursor5.getEndRow()); + assertEquals(10, cursor5.getRowCount()); + Cursor cursor6 = paging.createCursor(20, paging.createPage(1, 10)); + assertEquals(1, cursor6.getCurrentPage()); + assertEquals(1, cursor6.getFirstPage()); + assertEquals(2, cursor6.getLastPage()); + assertEquals(-1, cursor6.getPrevPage()); + assertEquals(2, cursor6.getNextPage()); + assertEquals(0, cursor6.getStartRow()); + assertEquals(9, cursor6.getEndRow()); + assertEquals(10, cursor6.getRowCount()); + Cursor cursor7 = paging.createCursor(20, paging.createPage(2, 10)); + assertEquals(2, cursor7.getCurrentPage()); + assertEquals(1, cursor7.getFirstPage()); + assertEquals(2, cursor7.getLastPage()); + assertEquals(1, cursor7.getPrevPage()); + assertEquals(-1, cursor7.getNextPage()); + assertEquals(10, cursor7.getStartRow()); + assertEquals(19, cursor7.getEndRow()); + assertEquals(10, cursor7.getRowCount()); + Cursor cursor8 = paging.createCursor(11, paging.createPage(2, 10)); + assertEquals(2, cursor8.getCurrentPage()); + assertEquals(1, cursor8.getFirstPage()); + assertEquals(2, cursor8.getLastPage()); + assertEquals(1, cursor8.getPrevPage()); + assertEquals(-1, cursor8.getNextPage()); + assertEquals(10, cursor8.getStartRow()); + assertEquals(10, cursor8.getEndRow()); + assertEquals(1, cursor8.getRowCount()); + } + + public void testUnlimitedPage() + { + Cursor cursor1 = paging.createCursor(100, paging.createPage(1, -1)); + assertTrue(cursor1.isInRange()); + assertEquals(1, cursor1.getCurrentPage()); + assertEquals(1, cursor1.getFirstPage()); + assertEquals(1, cursor1.getLastPage()); + assertEquals(-1, cursor1.getPrevPage()); + assertEquals(-1, cursor1.getNextPage()); + assertEquals(0, cursor1.getStartRow()); + assertEquals(99, cursor1.getEndRow()); + Cursor cursor2 = paging.createCursor(100, paging.createPage(2, -1)); + assertFalse(cursor2.isInRange()); + } + + public void testScrollPage() + { + int count = 0; + long[] coll = new long[100]; + + Cursor cursor = paging.createCursor(coll.length, paging.createPage(1, 10)); + while (cursor.isInRange()) + { + for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) + { + coll[(int)i] = i; + count++; + } + cursor = paging.createCursor(coll.length, paging.createPage(cursor.getNextPage(), cursor.getPageSize())); + } + + assertEquals(100, count); + for (int test = 0; test < count; test++) + { + assertEquals(test, coll[test]); + } + } + + public void testZeroRowsWindow() + { + Cursor rows = paging.createCursor(0, paging.createWindow(0, 10)); + assertNotNull(rows); + assertEquals(0, rows.getTotalRows()); + assertFalse(rows.isInRange()); + assertEquals(10, rows.getPageSize()); + assertEquals(0, rows.getStartRow()); + assertEquals(-1, rows.getEndRow()); + assertEquals(0, rows.getRowCount()); + assertEquals(-1, rows.getNextPage()); + } + + public void testOutOfBoundsWindow() + { + Cursor cursor1 = paging.createCursor(1, paging.createWindow(0, 1)); + assertNotNull(cursor1); + assertTrue(cursor1.isInRange()); + Cursor cursor2 = paging.createCursor(1, paging.createWindow(1, 1)); + assertNotNull(cursor2); + assertFalse(cursor2.isInRange()); + Cursor cursor3 = paging.createCursor(1, paging.createWindow(0, -1)); + assertNotNull(cursor3); + assertTrue(cursor3.isInRange()); + } + + public void testTotalWindow() + { + Cursor cursor1 = paging.createCursor(10, paging.createWindow(1, 1)); + assertEquals(10, cursor1.getTotalRows()); + } + + public void testCursorWindow() + { + Cursor cursor1 = paging.createCursor(10, paging.createWindow(0, 1)); + assertEquals(0, cursor1.getStartRow()); + assertEquals(0, cursor1.getEndRow()); + assertEquals(1, cursor1.getRowCount()); + assertEquals(1, cursor1.getNextPage()); + Cursor cursor2 = paging.createCursor(10, paging.createWindow(0, 7)); + assertEquals(0, cursor2.getStartRow()); + assertEquals(6, cursor2.getEndRow()); + assertEquals(7, cursor2.getRowCount()); + assertEquals(7, cursor2.getNextPage()); + Cursor cursor3 = paging.createCursor(10, paging.createWindow(7, 7)); + assertEquals(7, cursor3.getStartRow()); + assertEquals(9, cursor3.getEndRow()); + assertEquals(3, cursor3.getRowCount()); + assertEquals(-1, cursor3.getNextPage()); + Cursor cursor4 = paging.createCursor(10, paging.createWindow(0, 10)); + assertEquals(0, cursor4.getStartRow()); + assertEquals(9, cursor4.getEndRow()); + assertEquals(10, cursor4.getRowCount()); + assertEquals(-1, cursor4.getNextPage()); + Cursor cursor5 = paging.createCursor(10, paging.createWindow(0, 11)); + assertEquals(0, cursor5.getStartRow()); + assertEquals(9, cursor5.getEndRow()); + assertEquals(10, cursor5.getRowCount()); + assertEquals(-1, cursor5.getNextPage()); + } + + public void testUnlimitedWindow() + { + Cursor cursor1 = paging.createCursor(100, paging.createWindow(0, -1)); + assertTrue(cursor1.isInRange()); + assertEquals(0, cursor1.getStartRow()); + assertEquals(99, cursor1.getEndRow()); + assertEquals(100, cursor1.getRowCount()); + assertEquals(-1, cursor1.getNextPage()); + } + + public void testScrollWindow() + { + int count = 0; + long[] coll = new long[100]; + + Cursor cursor = paging.createCursor(coll.length, paging.createWindow(0, 10)); + while (cursor.isInRange()) + { + for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) + { + coll[(int)i] = i; + count++; + } + cursor = paging.createCursor(coll.length, paging.createWindow(cursor.getNextPage(), cursor.getPageSize())); + } + + assertEquals(100, count); + for (int test = 0; test < count; test++) + { + assertEquals(test, coll[test]); + } + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS10TCKTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS10TCKTest.java index 79df8ca284..7c7a5ee062 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS10TCKTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS10TCKTest.java @@ -1,5 +1,5 @@ -package org.alfresco.rest.api.tests; - -public abstract class AbstractEnterpriseOpenCMIS10TCKTest extends AbstractEnterpriseOpenCMISTCKTest -{ -} +package org.alfresco.rest.api.tests; + +public abstract class AbstractEnterpriseOpenCMIS10TCKTest extends AbstractEnterpriseOpenCMISTCKTest +{ +} diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS11TCKTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS11TCKTest.java index 914efe6df1..eac24580d2 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS11TCKTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMIS11TCKTest.java @@ -1,133 +1,133 @@ -package org.alfresco.rest.api.tests; - -import java.util.Map; - -import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; -import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; -import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; -import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; -import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; -import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; -import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; -import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; -import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; -import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; -import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersionDeleteTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningSmokeTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningStateCreateTest; -import org.junit.Test; - -public abstract class AbstractEnterpriseOpenCMIS11TCKTest extends AbstractEnterpriseOpenCMISTCKTest -{ - @Test - public void testCMISTCKBasics() throws Exception - { - BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); - JUnitHelper.run(basicsTestGroup); - } - - @Test - public void testCMISTCKCRUD() throws Exception - { - CRUDTestGroup crudTestGroup = new CRUDTestGroup(); - JUnitHelper.run(crudTestGroup); - } - - @Test - public void testCMISTCKVersioning() throws Exception - { - OverrideVersioningTestGroup versioningTestGroup = new OverrideVersioningTestGroup(); - JUnitHelper.run(versioningTestGroup); - } - - @Test - public void testCMISTCKFiling() throws Exception - { - FilingTestGroup filingTestGroup = new FilingTestGroup(); - JUnitHelper.run(filingTestGroup); - } - - @Test - public void testCMISTCKControl() throws Exception - { - ControlTestGroup controlTestGroup = new ControlTestGroup(); - JUnitHelper.run(controlTestGroup); - } - - @Test - public void testCMISTCKQuery() throws Exception - { - OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); - JUnitHelper.run(queryTestGroup); - } - - class OverrideVersioningTestGroup extends AbstractSessionTestGroup - { - @Override - public void init(Map parameters) throws Exception - { - super.init(parameters); - - setName("Versioning Test Group"); - setDescription("Versioning tests."); - - addTest(new VersioningSmokeTest()); - addTest(new VersionDeleteTest()); - addTest(new VersioningStateCreateTest()); - // relies on Solr being available -// addTest(new CheckedOutTest()); - } - } - -// class OverrideCRUDTestGroup extends AbstractSessionTestGroup -// { -// @Override -// public void init(Map parameters) throws Exception -// { -// super.init(parameters); -// -// setName("CRUD Test Group"); -// setDescription("Create, Read, Update, and Delete tests."); -// -// addTest(new CreateAndDeleteFolderTest()); -// addTest(new CreateAndDeleteDocumentTest()); -// addTest(new CreateBigDocument()); -// addTest(new CreateDocumentWithoutContent()); -// addTest(new NameCharsetTest()); -// addTest(new CreateAndDeleteRelationshipTest()); -// addTest(new CreateAndDeleteItemTest()); -// addTest(new UpdateSmokeTest()); -// // TCK fails because we support only 1 object in bulk update at present -// // See ACE-34 -// //addTest(new BulkUpdatePropertiesTest()); -// addTest(new SetAndDeleteContentTest()); -// addTest(new ChangeTokenTest()); -// addTest(new ContentRangesTest()); -// addTest(new CopyTest()); -// addTest(new MoveTest()); -// addTest(new DeleteTreeTest()); -// addTest(new OperationContextTest()); -// } -// } - - public class OverrideQueryTestGroup extends AbstractSessionTestGroup - { - @Override - public void init(Map parameters) throws Exception - { - super.init(parameters); - - setName("Query Test Group"); - setDescription("Query and content changes tests."); - - addTest(new QuerySmokeTest()); - // The test fails on Lucene see MNT-11223 -// addTest(new QueryRootFolderTest()); - addTest(new QueryForObjectCustom()); - addTest(new QueryLikeTestCustom()); - addTest(new QueryInFolderTestCustom()); - addTest(new ContentChangesSmokeTest()); - } - } -} +package org.alfresco.rest.api.tests; + +import java.util.Map; + +import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; +import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; +import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; +import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; +import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; +import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; +import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; +import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; +import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; +import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; +import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersionDeleteTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningSmokeTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningStateCreateTest; +import org.junit.Test; + +public abstract class AbstractEnterpriseOpenCMIS11TCKTest extends AbstractEnterpriseOpenCMISTCKTest +{ + @Test + public void testCMISTCKBasics() throws Exception + { + BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); + JUnitHelper.run(basicsTestGroup); + } + + @Test + public void testCMISTCKCRUD() throws Exception + { + CRUDTestGroup crudTestGroup = new CRUDTestGroup(); + JUnitHelper.run(crudTestGroup); + } + + @Test + public void testCMISTCKVersioning() throws Exception + { + OverrideVersioningTestGroup versioningTestGroup = new OverrideVersioningTestGroup(); + JUnitHelper.run(versioningTestGroup); + } + + @Test + public void testCMISTCKFiling() throws Exception + { + FilingTestGroup filingTestGroup = new FilingTestGroup(); + JUnitHelper.run(filingTestGroup); + } + + @Test + public void testCMISTCKControl() throws Exception + { + ControlTestGroup controlTestGroup = new ControlTestGroup(); + JUnitHelper.run(controlTestGroup); + } + + @Test + public void testCMISTCKQuery() throws Exception + { + OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); + JUnitHelper.run(queryTestGroup); + } + + class OverrideVersioningTestGroup extends AbstractSessionTestGroup + { + @Override + public void init(Map parameters) throws Exception + { + super.init(parameters); + + setName("Versioning Test Group"); + setDescription("Versioning tests."); + + addTest(new VersioningSmokeTest()); + addTest(new VersionDeleteTest()); + addTest(new VersioningStateCreateTest()); + // relies on Solr being available +// addTest(new CheckedOutTest()); + } + } + +// class OverrideCRUDTestGroup extends AbstractSessionTestGroup +// { +// @Override +// public void init(Map parameters) throws Exception +// { +// super.init(parameters); +// +// setName("CRUD Test Group"); +// setDescription("Create, Read, Update, and Delete tests."); +// +// addTest(new CreateAndDeleteFolderTest()); +// addTest(new CreateAndDeleteDocumentTest()); +// addTest(new CreateBigDocument()); +// addTest(new CreateDocumentWithoutContent()); +// addTest(new NameCharsetTest()); +// addTest(new CreateAndDeleteRelationshipTest()); +// addTest(new CreateAndDeleteItemTest()); +// addTest(new UpdateSmokeTest()); +// // TCK fails because we support only 1 object in bulk update at present +// // See ACE-34 +// //addTest(new BulkUpdatePropertiesTest()); +// addTest(new SetAndDeleteContentTest()); +// addTest(new ChangeTokenTest()); +// addTest(new ContentRangesTest()); +// addTest(new CopyTest()); +// addTest(new MoveTest()); +// addTest(new DeleteTreeTest()); +// addTest(new OperationContextTest()); +// } +// } + + public class OverrideQueryTestGroup extends AbstractSessionTestGroup + { + @Override + public void init(Map parameters) throws Exception + { + super.init(parameters); + + setName("Query Test Group"); + setDescription("Query and content changes tests."); + + addTest(new QuerySmokeTest()); + // The test fails on Lucene see MNT-11223 +// addTest(new QueryRootFolderTest()); + addTest(new QueryForObjectCustom()); + addTest(new QueryLikeTestCustom()); + addTest(new QueryInFolderTestCustom()); + addTest(new ContentChangesSmokeTest()); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMISTCKTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMISTCKTest.java index faf6ebcf9c..00a186e3b0 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMISTCKTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractEnterpriseOpenCMISTCKTest.java @@ -1,43 +1,43 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.opencmis.OpenCMISClientContext; -import org.alfresco.repo.dictionary.DictionaryDAO; -import org.alfresco.repo.dictionary.M2Aspect; -import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.M2Property; -import org.alfresco.service.namespace.QName; -import org.springframework.context.ApplicationContext; - -/** - * Base class for Chemistry OpenCMIS TCK tests. - * - * @author steveglover - * - */ -public abstract class AbstractEnterpriseOpenCMISTCKTest extends EnterpriseTestApi -{ - protected static OpenCMISClientContext clientContext; - - @Override - protected TestFixture getTestFixture() throws Exception - { - return EnterprisePublicApiTestFixture.getInstance(); - } - - protected void overrideVersionableAspectProperties(ApplicationContext ctx) - { - final DictionaryDAO dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); - dictionaryDAO.removeModel(QName.createQName("cm:contentmodel")); - M2Model contentModel = M2Model.createModel(getClass().getClassLoader().getResourceAsStream("alfresco/model/contentModel.xml")); - - M2Aspect versionableAspect = contentModel.getAspect("cm:versionable"); - M2Property prop = versionableAspect.getProperty("cm:initialVersion"); - prop.setDefaultValue(Boolean.FALSE.toString()); - prop = versionableAspect.getProperty("cm:autoVersion"); - prop.setDefaultValue(Boolean.FALSE.toString()); - prop = versionableAspect.getProperty("cm:autoVersionOnUpdateProps"); - prop.setDefaultValue(Boolean.FALSE.toString()); - - dictionaryDAO.putModel(contentModel); - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.opencmis.OpenCMISClientContext; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.M2Aspect; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.repo.dictionary.M2Property; +import org.alfresco.service.namespace.QName; +import org.springframework.context.ApplicationContext; + +/** + * Base class for Chemistry OpenCMIS TCK tests. + * + * @author steveglover + * + */ +public abstract class AbstractEnterpriseOpenCMISTCKTest extends EnterpriseTestApi +{ + protected static OpenCMISClientContext clientContext; + + @Override + protected TestFixture getTestFixture() throws Exception + { + return EnterprisePublicApiTestFixture.getInstance(); + } + + protected void overrideVersionableAspectProperties(ApplicationContext ctx) + { + final DictionaryDAO dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); + dictionaryDAO.removeModel(QName.createQName("cm:contentmodel")); + M2Model contentModel = M2Model.createModel(getClass().getClassLoader().getResourceAsStream("alfresco/model/contentModel.xml")); + + M2Aspect versionableAspect = contentModel.getAspect("cm:versionable"); + M2Property prop = versionableAspect.getProperty("cm:initialVersion"); + prop.setDefaultValue(Boolean.FALSE.toString()); + prop = versionableAspect.getProperty("cm:autoVersion"); + prop.setDefaultValue(Boolean.FALSE.toString()); + prop = versionableAspect.getProperty("cm:autoVersionOnUpdateProps"); + prop.setDefaultValue(Boolean.FALSE.toString()); + + dictionaryDAO.putModel(contentModel); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractTestApi.java b/source/test-java/org/alfresco/rest/api/tests/AbstractTestApi.java index 4dd1dd7e29..eedc13aa13 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractTestApi.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractTestApi.java @@ -1,206 +1,206 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.text.Collator; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.client.AuthenticatedHttp; -import org.alfresco.rest.api.tests.client.AuthenticationDetailsProvider; -import org.alfresco.rest.api.tests.client.HttpClientProvider; -import org.alfresco.rest.api.tests.client.PublicApiClient; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiHttpClient; -import org.alfresco.rest.api.tests.client.UserAuthenticationDetailsProviderImpl; -import org.alfresco.rest.api.tests.client.UserData; -import org.alfresco.rest.api.tests.client.UserDataService; -import org.alfresco.rest.api.tests.client.data.ExpectedComparison; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.springframework.context.ApplicationContext; - -public abstract class AbstractTestApi -{ - private static final Log logger = LogFactory.getLog(AbstractTestApi.class); - - protected RepoService repoService; - protected ApplicationContext applicationContext; - - protected PublicApiHttpClient httpClient; - protected PublicApiClient publicApiClient; - protected RetryingTransactionHelper transactionHelper; - protected Collator collator = Collator.getInstance(); - - public RepoService getRepoService() - { - return repoService; - } - - @Before - public void setupTests() throws Exception - { - TestFixture testFixture = getTestFixture(false); - this.applicationContext = testFixture.getApplicationContext(); - this.repoService = testFixture.getRepoService(); - this.transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); - - HttpClientProvider httpClientProvider = (HttpClientProvider)applicationContext.getBean("httpClientProvider"); - - UserDataService userDataService = new UserDataService() - { - @Override - public UserData findUserByUserName(String userName) - { - UserData userData = new UserData(); - TestPerson person = getRepoService().getPerson(userName.toLowerCase()); - userData.setUserName(person.getId()); - userData.setPassword(person.getPassword()); - userData.setId(person.getId()); - return userData; - } - }; - AuthenticationDetailsProvider authenticationDetailsProvider = new UserAuthenticationDetailsProviderImpl(userDataService, "admin", "admin"); - AuthenticatedHttp authenticatedHttp = new AuthenticatedHttp(httpClientProvider, authenticationDetailsProvider); - this.httpClient = new PublicApiHttpClient("localhost", TestFixture.PORT, TestFixture.CONTEXT_PATH, - TestFixture.PUBLIC_API_SERVLET_NAME, authenticatedHttp); - this.publicApiClient = new PublicApiClient(httpClient, userDataService); - } - - protected void log(String msg) - { - log(msg, null); - } - - protected void log(String msg, Throwable t) - { - if(logger.isDebugEnabled()) - { - logger.debug(msg, t); - } - } - - protected Paging getPaging(Integer skipCount, Integer maxItems) - { - return new Paging(skipCount, maxItems, null); - } - - protected Paging getPaging(Integer skipCount, Integer maxItems, int total, Integer expectedTotal) - { - ExpectedPaging expectedPaging = ExpectedPaging.getExpectedPaging(skipCount, maxItems, total, expectedTotal); - return new Paging(skipCount, maxItems, expectedPaging); - } - - protected void check(ExpectedComparison expected, T actual) - { - assertNotNull(expected); - assertNotNull(actual); - - expected.expected(actual); - } - - protected String stripCMISSuffix(String nodeId) - { - String ret = null; - - int idx = nodeId.indexOf(";"); - if(idx != -1) - { - ret = nodeId.substring(0, idx); - } - else - { - ret = nodeId; - } - - return ret; - } - - protected Map createParams(Paging paging, Map otherParams) - { - Map params = new HashMap(2); - if(paging != null) - { - if(paging.getSkipCount() != null) - { - params.put("skipCount", String.valueOf(paging.getSkipCount())); - } - if(paging.getMaxItems() != null) - { - params.put("maxItems", String.valueOf(paging.getMaxItems())); - } - } - if(otherParams != null) - { - params.putAll(otherParams); - } - return params; - } - - protected void checkList(List expected, ExpectedPaging expectedPaging, ListResponse actual) - { - assertNotNull(expectedPaging); - assertNotNull(actual); - - log("Expected paging " + expectedPaging.toString()); - - for(T1 expectedEntry : expected) - { - log("Expected entry " + expectedEntry.toString()); - } - - log("Actual paging " + actual.getPaging().toString()); - - for(Object actualEntry : actual.getList()) - { - log("Actual entry " + actualEntry.toString()); - } - - assertEquals(expectedPaging, actual.getPaging()); - assertEquals(expected.size(), actual.getList().size()); - - for(int i = 0; i < expected.size(); i++) - { - ExpectedComparison expectedEntry = (ExpectedComparison)expected.get(i); - T actualEntry = actual.getList().get(i); - assertNotNull(actualEntry); - assertNotNull(expectedEntry); - expectedEntry.expected(actualEntry); - } - } - - protected List sublist(List list, int skipCount, int maxItems) - { - List ret = null; - - int size = list.size(); - int start = skipCount; - int end = Math.min(skipCount + maxItems, size); - - if(start > size) - { - ret = Collections.emptyList(); - } - else - { - ret = list.subList(start, end); - } - - return ret; - } - - protected abstract TestFixture getTestFixture() throws Exception; - - /** - * @param createTestData The created instance can optionally create test data if required - */ - protected abstract TestFixture getTestFixture(boolean createTestData) throws Exception; -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.text.Collator; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.client.AuthenticatedHttp; +import org.alfresco.rest.api.tests.client.AuthenticationDetailsProvider; +import org.alfresco.rest.api.tests.client.HttpClientProvider; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient; +import org.alfresco.rest.api.tests.client.UserAuthenticationDetailsProviderImpl; +import org.alfresco.rest.api.tests.client.UserData; +import org.alfresco.rest.api.tests.client.UserDataService; +import org.alfresco.rest.api.tests.client.data.ExpectedComparison; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.springframework.context.ApplicationContext; + +public abstract class AbstractTestApi +{ + private static final Log logger = LogFactory.getLog(AbstractTestApi.class); + + protected RepoService repoService; + protected ApplicationContext applicationContext; + + protected PublicApiHttpClient httpClient; + protected PublicApiClient publicApiClient; + protected RetryingTransactionHelper transactionHelper; + protected Collator collator = Collator.getInstance(); + + public RepoService getRepoService() + { + return repoService; + } + + @Before + public void setupTests() throws Exception + { + TestFixture testFixture = getTestFixture(false); + this.applicationContext = testFixture.getApplicationContext(); + this.repoService = testFixture.getRepoService(); + this.transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); + + HttpClientProvider httpClientProvider = (HttpClientProvider)applicationContext.getBean("httpClientProvider"); + + UserDataService userDataService = new UserDataService() + { + @Override + public UserData findUserByUserName(String userName) + { + UserData userData = new UserData(); + TestPerson person = getRepoService().getPerson(userName.toLowerCase()); + userData.setUserName(person.getId()); + userData.setPassword(person.getPassword()); + userData.setId(person.getId()); + return userData; + } + }; + AuthenticationDetailsProvider authenticationDetailsProvider = new UserAuthenticationDetailsProviderImpl(userDataService, "admin", "admin"); + AuthenticatedHttp authenticatedHttp = new AuthenticatedHttp(httpClientProvider, authenticationDetailsProvider); + this.httpClient = new PublicApiHttpClient("localhost", TestFixture.PORT, TestFixture.CONTEXT_PATH, + TestFixture.PUBLIC_API_SERVLET_NAME, authenticatedHttp); + this.publicApiClient = new PublicApiClient(httpClient, userDataService); + } + + protected void log(String msg) + { + log(msg, null); + } + + protected void log(String msg, Throwable t) + { + if(logger.isDebugEnabled()) + { + logger.debug(msg, t); + } + } + + protected Paging getPaging(Integer skipCount, Integer maxItems) + { + return new Paging(skipCount, maxItems, null); + } + + protected Paging getPaging(Integer skipCount, Integer maxItems, int total, Integer expectedTotal) + { + ExpectedPaging expectedPaging = ExpectedPaging.getExpectedPaging(skipCount, maxItems, total, expectedTotal); + return new Paging(skipCount, maxItems, expectedPaging); + } + + protected void check(ExpectedComparison expected, T actual) + { + assertNotNull(expected); + assertNotNull(actual); + + expected.expected(actual); + } + + protected String stripCMISSuffix(String nodeId) + { + String ret = null; + + int idx = nodeId.indexOf(";"); + if(idx != -1) + { + ret = nodeId.substring(0, idx); + } + else + { + ret = nodeId; + } + + return ret; + } + + protected Map createParams(Paging paging, Map otherParams) + { + Map params = new HashMap(2); + if(paging != null) + { + if(paging.getSkipCount() != null) + { + params.put("skipCount", String.valueOf(paging.getSkipCount())); + } + if(paging.getMaxItems() != null) + { + params.put("maxItems", String.valueOf(paging.getMaxItems())); + } + } + if(otherParams != null) + { + params.putAll(otherParams); + } + return params; + } + + protected void checkList(List expected, ExpectedPaging expectedPaging, ListResponse actual) + { + assertNotNull(expectedPaging); + assertNotNull(actual); + + log("Expected paging " + expectedPaging.toString()); + + for(T1 expectedEntry : expected) + { + log("Expected entry " + expectedEntry.toString()); + } + + log("Actual paging " + actual.getPaging().toString()); + + for(Object actualEntry : actual.getList()) + { + log("Actual entry " + actualEntry.toString()); + } + + assertEquals(expectedPaging, actual.getPaging()); + assertEquals(expected.size(), actual.getList().size()); + + for(int i = 0; i < expected.size(); i++) + { + ExpectedComparison expectedEntry = (ExpectedComparison)expected.get(i); + T actualEntry = actual.getList().get(i); + assertNotNull(actualEntry); + assertNotNull(expectedEntry); + expectedEntry.expected(actualEntry); + } + } + + protected List sublist(List list, int skipCount, int maxItems) + { + List ret = null; + + int size = list.size(); + int start = skipCount; + int end = Math.min(skipCount + maxItems, size); + + if(start > size) + { + ret = Collections.emptyList(); + } + else + { + ret = list.subList(start, end); + } + + return ret; + } + + protected abstract TestFixture getTestFixture() throws Exception; + + /** + * @param createTestData The created instance can optionally create test data if required + */ + protected abstract TestFixture getTestFixture(boolean createTestData) throws Exception; +} diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractTestFixture.java b/source/test-java/org/alfresco/rest/api/tests/AbstractTestFixture.java index 5536d5c970..7dd17e893e 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractTestFixture.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractTestFixture.java @@ -1,236 +1,236 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.TreeMap; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.web.util.JettyComponent; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.springframework.context.ApplicationContext; - -public abstract class AbstractTestFixture implements TestFixture -{ - public static final int DEFAULT_NUM_MEMBERS_PER_SITE = 4; - - public static final String TEST_DOMAIN_PREFIX = "acme"; - - protected List people = new ArrayList(10); - protected TreeMap networks = new TreeMap(); - protected TreeMap sites = new TreeMap(); - - protected String[] configLocations; - protected final String[] classLocations; - protected int port = 8081; - protected String contextPath = "/alfresco"; - protected String servletName = "api"; - protected String hostname = "localhost"; - protected JettyComponent jetty; - protected boolean cleanup; - protected Random random = new Random(); - protected RepoService repoService; - protected RetryingTransactionHelper transactionHelper; - protected int numMembersPerSite; - protected ApplicationContext applicationContext; - - public ApplicationContext getApplicationContext() - { - return applicationContext; - } - - protected AbstractTestFixture(String[] configLocations, String[] classLocations, int port, String contextPath, String servletName, - int numMembersPerSite, boolean cleanup) - { - this.configLocations = configLocations; - this.classLocations = classLocations; - this.port = port; - this.contextPath = contextPath; - this.servletName = servletName; - this.numMembersPerSite = numMembersPerSite; - this.cleanup = cleanup; - } - - public JettyComponent getJettyComponent() - { - return jetty; - } - - public int getPort() - { - return port; - } - - protected abstract JettyComponent makeJettyComponent(); - protected abstract void populateTestData(); - protected abstract RepoService makeRepoService() throws Exception; - - public void setup() throws Exception - { - setup(true); - } - - public void setup(boolean createTestData) throws Exception - { - this.jetty = makeJettyComponent(); - this.jetty.start(); - this.applicationContext = jetty.getApplicationContext(); - this.repoService = makeRepoService(); - this.transactionHelper = (RetryingTransactionHelper)repoService.getApplicationContext().getBean("retryingTransactionHelper"); - - if (createTestData) - { - populateTestData(); - createTestData(); - } - } - - public RepoService getRepoService() - { - return repoService; - } - - public TestNetwork getNetwork(String name) - { - return networks.get(name); - } - - public Iterator getNetworksIt() - { - return networks.values().iterator(); - } - - public TreeMap getNetworks() - { - return networks; - } - - public Iterator networksIterator() - { - return networks.values().iterator(); - } - - public TestNetwork getRandomNetwork() - { - if (networks.isEmpty()) - { - populateTestData(); - createTestData(); - } - int r = random.nextInt(networks.size()); - List a = new ArrayList(); - a.addAll(networks.values()); - return a.get(r); - } - - protected void addNetwork(TestNetwork network) - { - networks.put(network.getId(), network); - } - - public void addPerson(PersonInfo personInfo) - { - people.add(personInfo); - } - - public void addSite(SiteInformation siteInfo) - { - sites.put(siteInfo.getShortName(), siteInfo); - } - - public TreeMap getSites() - { - return sites; - } - - public void createTestData() - { - for(final TestNetwork testAccount : getNetworks().values()) - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public Void execute() throws Throwable - { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - testAccount.create(); - - for(PersonInfo testPerson : people) - { - testAccount.createUser(testPerson); - } - - return null; - } - }, false, true); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public Void execute() throws Throwable - { - // clear fully authenticated user ("admin") - affects site creation (which uses this to setup perms) - AuthenticationUtil.clearCurrentSecurityContext(); - - if(testAccount.getPersonIds().size() > 0) - { - // use a fixed sample size of account members (so we have some left over for tests) - List people = testAccount.peopleSample(testAccount.getPersonIds().size()); - - String tenantDomain = testAccount.getId(); - - int i = 0; - for(final SiteInformation site : getSites().values()) - { - final Iterator peopleIterator = RepoService.getWrappingIterator(i++, people); - - final String siteCreator = peopleIterator.next(); - assertNotNull(siteCreator); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - final TestSite testSite = testAccount.createSite(site); - - // invite some members to the site, leave at least one non-site member - for(int j = 0; j < numMembersPerSite; j++) - { - String siteMember = peopleIterator.next(); - assertNotNull(siteMember); - testSite.inviteToSite(siteMember, SiteRole.SiteContributor); - } - - return null; - } - }, siteCreator, tenantDomain); - } - } - - return null; - } - }, false, true); - } - } - - public void shutdown() - { - if(cleanup) - { - repoService.shutdown(); - } - - this.jetty.shutdown(); - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.TreeMap; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.web.util.JettyComponent; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.springframework.context.ApplicationContext; + +public abstract class AbstractTestFixture implements TestFixture +{ + public static final int DEFAULT_NUM_MEMBERS_PER_SITE = 4; + + public static final String TEST_DOMAIN_PREFIX = "acme"; + + protected List people = new ArrayList(10); + protected TreeMap networks = new TreeMap(); + protected TreeMap sites = new TreeMap(); + + protected String[] configLocations; + protected final String[] classLocations; + protected int port = 8081; + protected String contextPath = "/alfresco"; + protected String servletName = "api"; + protected String hostname = "localhost"; + protected JettyComponent jetty; + protected boolean cleanup; + protected Random random = new Random(); + protected RepoService repoService; + protected RetryingTransactionHelper transactionHelper; + protected int numMembersPerSite; + protected ApplicationContext applicationContext; + + public ApplicationContext getApplicationContext() + { + return applicationContext; + } + + protected AbstractTestFixture(String[] configLocations, String[] classLocations, int port, String contextPath, String servletName, + int numMembersPerSite, boolean cleanup) + { + this.configLocations = configLocations; + this.classLocations = classLocations; + this.port = port; + this.contextPath = contextPath; + this.servletName = servletName; + this.numMembersPerSite = numMembersPerSite; + this.cleanup = cleanup; + } + + public JettyComponent getJettyComponent() + { + return jetty; + } + + public int getPort() + { + return port; + } + + protected abstract JettyComponent makeJettyComponent(); + protected abstract void populateTestData(); + protected abstract RepoService makeRepoService() throws Exception; + + public void setup() throws Exception + { + setup(true); + } + + public void setup(boolean createTestData) throws Exception + { + this.jetty = makeJettyComponent(); + this.jetty.start(); + this.applicationContext = jetty.getApplicationContext(); + this.repoService = makeRepoService(); + this.transactionHelper = (RetryingTransactionHelper)repoService.getApplicationContext().getBean("retryingTransactionHelper"); + + if (createTestData) + { + populateTestData(); + createTestData(); + } + } + + public RepoService getRepoService() + { + return repoService; + } + + public TestNetwork getNetwork(String name) + { + return networks.get(name); + } + + public Iterator getNetworksIt() + { + return networks.values().iterator(); + } + + public TreeMap getNetworks() + { + return networks; + } + + public Iterator networksIterator() + { + return networks.values().iterator(); + } + + public TestNetwork getRandomNetwork() + { + if (networks.isEmpty()) + { + populateTestData(); + createTestData(); + } + int r = random.nextInt(networks.size()); + List a = new ArrayList(); + a.addAll(networks.values()); + return a.get(r); + } + + protected void addNetwork(TestNetwork network) + { + networks.put(network.getId(), network); + } + + public void addPerson(PersonInfo personInfo) + { + people.add(personInfo); + } + + public void addSite(SiteInformation siteInfo) + { + sites.put(siteInfo.getShortName(), siteInfo); + } + + public TreeMap getSites() + { + return sites; + } + + public void createTestData() + { + for(final TestNetwork testAccount : getNetworks().values()) + { + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public Void execute() throws Throwable + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + testAccount.create(); + + for(PersonInfo testPerson : people) + { + testAccount.createUser(testPerson); + } + + return null; + } + }, false, true); + + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public Void execute() throws Throwable + { + // clear fully authenticated user ("admin") - affects site creation (which uses this to setup perms) + AuthenticationUtil.clearCurrentSecurityContext(); + + if(testAccount.getPersonIds().size() > 0) + { + // use a fixed sample size of account members (so we have some left over for tests) + List people = testAccount.peopleSample(testAccount.getPersonIds().size()); + + String tenantDomain = testAccount.getId(); + + int i = 0; + for(final SiteInformation site : getSites().values()) + { + final Iterator peopleIterator = RepoService.getWrappingIterator(i++, people); + + final String siteCreator = peopleIterator.next(); + assertNotNull(siteCreator); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + final TestSite testSite = testAccount.createSite(site); + + // invite some members to the site, leave at least one non-site member + for(int j = 0; j < numMembersPerSite; j++) + { + String siteMember = peopleIterator.next(); + assertNotNull(siteMember); + testSite.inviteToSite(siteMember, SiteRole.SiteContributor); + } + + return null; + } + }, siteCreator, tenantDomain); + } + } + + return null; + } + }, false, true); + } + } + + public void shutdown() + { + if(cleanup) + { + repoService.shutdown(); + } + + this.jetty.shutdown(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/ApiTest.java b/source/test-java/org/alfresco/rest/api/tests/ApiTest.java index 2ce014b699..a79789f34c 100644 --- a/source/test-java/org/alfresco/rest/api/tests/ApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/ApiTest.java @@ -1,54 +1,54 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.rest.DeletedNodesTest; -import org.junit.AfterClass; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -/** - * Public API tests. - * - * @author steveglover - * @author janv - * @author Jamal Kaabi-Mofrad - * @author Gethin James - * - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - NodeApiTest.class, - NodeAssociationsApiTest.class, - QueriesApiTest.class, - RenditionsTest.class, - SharedLinkApiTest.class, - ActivitiesPostingTest.class, - DeletedNodesTest.class, - AuthenticationsTest.class, - TestSites.class, - TestNodeComments.class, - TestCMIS.class, - TestFavouriteSites.class, - TestSiteContainers.class, - TestNodeRatings.class, - TestUserPreferences.class, - TestTags.class, - TestNetworks.class, - TestActivities.class, - TestPeople.class, - TestSiteMembers.class, - TestPersonSites.class, - TestSiteMembershipRequests.class, - TestFavourites.class, - TestRemovePermissions.class, - TestPublicApi128.class, - TestPublicApiCaching.class, - ModulePackagesApiTest.class -}) -public class ApiTest -{ - @AfterClass - public static void after() throws Exception - { -// EnterprisePublicApiTestFixture.cleanup(); - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.rest.DeletedNodesTest; +import org.junit.AfterClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Public API tests. + * + * @author steveglover + * @author janv + * @author Jamal Kaabi-Mofrad + * @author Gethin James + * + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + NodeApiTest.class, + NodeAssociationsApiTest.class, + QueriesApiTest.class, + RenditionsTest.class, + SharedLinkApiTest.class, + ActivitiesPostingTest.class, + DeletedNodesTest.class, + AuthenticationsTest.class, + TestSites.class, + TestNodeComments.class, + TestCMIS.class, + TestFavouriteSites.class, + TestSiteContainers.class, + TestNodeRatings.class, + TestUserPreferences.class, + TestTags.class, + TestNetworks.class, + TestActivities.class, + TestPeople.class, + TestSiteMembers.class, + TestPersonSites.class, + TestSiteMembershipRequests.class, + TestFavourites.class, + TestRemovePermissions.class, + TestPublicApi128.class, + TestPublicApiCaching.class, + ModulePackagesApiTest.class +}) +public class ApiTest +{ + @AfterClass + public static void after() throws Exception + { +// EnterprisePublicApiTestFixture.cleanup(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/CMISTCKJettyComponent.java b/source/test-java/org/alfresco/rest/api/tests/CMISTCKJettyComponent.java index 48e8307c64..23e0c87d25 100644 --- a/source/test-java/org/alfresco/rest/api/tests/CMISTCKJettyComponent.java +++ b/source/test-java/org/alfresco/rest/api/tests/CMISTCKJettyComponent.java @@ -1,31 +1,31 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.repo.web.util.AbstractJettyComponent; -import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.webapp.WebAppContext; - -/** - * Manages an embedded jetty server, hooking it up to the repository spring context and providing access to the Chemistry OpenCMIS servlet. - * - * @author steveglover - * - */ -public class CMISTCKJettyComponent extends AbstractJettyComponent -{ - public CMISTCKJettyComponent(int port, String contextPath, String servletName, String[] configLocations, String[] classLocations) - { - super(port, contextPath, configLocations, classLocations); - } - - @Override - protected void configureWebAppContext(WebAppContext webAppContext) - { - super.configure(webAppContext); - - // the Chemistry OpenCMIS servlet - ServletHolder servletHolder = new ServletHolder(CmisAtomPubServlet.class); - servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); - webAppContext.addServlet(servletHolder, "/cmisatom/*"); - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.repo.web.util.AbstractJettyComponent; +import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * Manages an embedded jetty server, hooking it up to the repository spring context and providing access to the Chemistry OpenCMIS servlet. + * + * @author steveglover + * + */ +public class CMISTCKJettyComponent extends AbstractJettyComponent +{ + public CMISTCKJettyComponent(int port, String contextPath, String servletName, String[] configLocations, String[] classLocations) + { + super(port, contextPath, configLocations, classLocations); + } + + @Override + protected void configureWebAppContext(WebAppContext webAppContext) + { + super.configure(webAppContext); + + // the Chemistry OpenCMIS servlet + ServletHolder servletHolder = new ServletHolder(CmisAtomPubServlet.class); + servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); + webAppContext.addServlet(servletHolder, "/cmisatom/*"); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/Cleanup.java b/source/test-java/org/alfresco/rest/api/tests/Cleanup.java index a54fc1f4c4..a27df34f24 100644 --- a/source/test-java/org/alfresco/rest/api/tests/Cleanup.java +++ b/source/test-java/org/alfresco/rest/api/tests/Cleanup.java @@ -1,13 +1,13 @@ -package org.alfresco.rest.api.tests; - -import org.junit.After; - -public class Cleanup -{ - @After - public void after() throws Exception - { -// PublicApiTestFixture fixture = PublicApiTestFixture.getInstance(); -// fixture.shutdown(); - } -} +package org.alfresco.rest.api.tests; + +import org.junit.After; + +public class Cleanup +{ + @After + public void after() throws Exception + { +// PublicApiTestFixture fixture = PublicApiTestFixture.getInstance(); +// fixture.shutdown(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/CloudPersonInfo.java b/source/test-java/org/alfresco/rest/api/tests/CloudPersonInfo.java index a24f373968..9645be7078 100644 --- a/source/test-java/org/alfresco/rest/api/tests/CloudPersonInfo.java +++ b/source/test-java/org/alfresco/rest/api/tests/CloudPersonInfo.java @@ -1,23 +1,23 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.rest.api.tests.client.data.Company; - -public class CloudPersonInfo extends PersonInfo -{ - private boolean networkAdmin; - - public CloudPersonInfo(String firstName, String lastName, String username, - String password, boolean networkAdmin, Company company, String skype, - String location, String tel, String mob, String instantmsg, - String google) - { - super(firstName, lastName, username, password, company, skype, location, tel, mob, instantmsg, google); - if(username == null) - this.networkAdmin = networkAdmin; - } - - public boolean isNetworkAdmin() - { - return networkAdmin; - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.rest.api.tests.client.data.Company; + +public class CloudPersonInfo extends PersonInfo +{ + private boolean networkAdmin; + + public CloudPersonInfo(String firstName, String lastName, String username, + String password, boolean networkAdmin, Company company, String skype, + String location, String tel, String mob, String instantmsg, + String google) + { + super(firstName, lastName, username, password, company, skype, location, tel, mob, instantmsg, google); + if(username == null) + this.networkAdmin = networkAdmin; + } + + public boolean isNetworkAdmin() + { + return networkAdmin; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/EnterpriseJettyComponent.java b/source/test-java/org/alfresco/rest/api/tests/EnterpriseJettyComponent.java index 095e04ed33..1a326ea783 100644 --- a/source/test-java/org/alfresco/rest/api/tests/EnterpriseJettyComponent.java +++ b/source/test-java/org/alfresco/rest/api/tests/EnterpriseJettyComponent.java @@ -1,31 +1,31 @@ -package org.alfresco.rest.api.tests; - -import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.webapp.WebAppContext; - -/** - * Manages an embedded jetty server, hooking it up to the repository spring context and providing - * authenticated, tenant-based access through the tenant servlet. - * - * @author steveglover - * - */ -public class EnterpriseJettyComponent extends PublicApiJettyComponent -{ - public EnterpriseJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) - { - super(port, contextPath, configLocations, classLocations); - } - - @Override - protected void configureWebAppContext(WebAppContext webAppContext) - { - super.configureWebAppContext(webAppContext); - - // the tenant servlet with alfresco managed authentication - ServletHolder servletHolder = new ServletHolder(CmisAtomPubServlet.class); - servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); - webAppContext.addServlet(servletHolder, "/cmisatom/*"); - } -} +package org.alfresco.rest.api.tests; + +import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * Manages an embedded jetty server, hooking it up to the repository spring context and providing + * authenticated, tenant-based access through the tenant servlet. + * + * @author steveglover + * + */ +public class EnterpriseJettyComponent extends PublicApiJettyComponent +{ + public EnterpriseJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) + { + super(port, contextPath, configLocations, classLocations); + } + + @Override + protected void configureWebAppContext(WebAppContext webAppContext) + { + super.configureWebAppContext(webAppContext); + + // the tenant servlet with alfresco managed authentication + ServletHolder servletHolder = new ServletHolder(CmisAtomPubServlet.class); + servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); + webAppContext.addServlet(servletHolder, "/cmisatom/*"); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/EnterprisePublicApiTestFixture.java b/source/test-java/org/alfresco/rest/api/tests/EnterprisePublicApiTestFixture.java index 065be71769..5afa11dbe8 100644 --- a/source/test-java/org/alfresco/rest/api/tests/EnterprisePublicApiTestFixture.java +++ b/source/test-java/org/alfresco/rest/api/tests/EnterprisePublicApiTestFixture.java @@ -1,55 +1,55 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.repo.web.util.JettyComponent; - -public class EnterprisePublicApiTestFixture extends EnterpriseTestFixture -{ - public final static String[] CONFIG_LOCATIONS = new String[] - { - "classpath:alfresco/application-context.xml", - "classpath:alfresco/web-scripts-application-context.xml", - "classpath:alfresco/web-scripts-application-context-test.xml", - "rest-api-test-context.xml", - "testcmis-model-context.xml" - }; - - public final static String[] CLASS_LOCATIONS = new String[] {"classpath*:/publicapi/lucene/"}; - - private static EnterprisePublicApiTestFixture instance; - - /* - * Note: synchronized for multi-threaded test access - */ - public synchronized static EnterprisePublicApiTestFixture getInstance(boolean createTestData) throws Exception - { - if(instance == null) - { - instance = new EnterprisePublicApiTestFixture(); - instance.setup(createTestData); - } - return instance; - } - - public static EnterprisePublicApiTestFixture getInstance() throws Exception - { - return getInstance(true); - } - - private EnterprisePublicApiTestFixture() - { - super(CONFIG_LOCATIONS, CLASS_LOCATIONS, PORT, CONTEXT_PATH, PUBLIC_API_SERVLET_NAME, DEFAULT_NUM_MEMBERS_PER_SITE, false); - } - - @Override - protected JettyComponent makeJettyComponent() - { - JettyComponent jettyComponent = new EnterpriseJettyComponent(port, contextPath, configLocations, classLocations); - return jettyComponent; - } - - @Override - protected RepoService makeRepoService() throws Exception - { - return new RepoService(applicationContext); - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.repo.web.util.JettyComponent; + +public class EnterprisePublicApiTestFixture extends EnterpriseTestFixture +{ + public final static String[] CONFIG_LOCATIONS = new String[] + { + "classpath:alfresco/application-context.xml", + "classpath:alfresco/web-scripts-application-context.xml", + "classpath:alfresco/web-scripts-application-context-test.xml", + "rest-api-test-context.xml", + "testcmis-model-context.xml" + }; + + public final static String[] CLASS_LOCATIONS = new String[] {"classpath*:/publicapi/lucene/"}; + + private static EnterprisePublicApiTestFixture instance; + + /* + * Note: synchronized for multi-threaded test access + */ + public synchronized static EnterprisePublicApiTestFixture getInstance(boolean createTestData) throws Exception + { + if(instance == null) + { + instance = new EnterprisePublicApiTestFixture(); + instance.setup(createTestData); + } + return instance; + } + + public static EnterprisePublicApiTestFixture getInstance() throws Exception + { + return getInstance(true); + } + + private EnterprisePublicApiTestFixture() + { + super(CONFIG_LOCATIONS, CLASS_LOCATIONS, PORT, CONTEXT_PATH, PUBLIC_API_SERVLET_NAME, DEFAULT_NUM_MEMBERS_PER_SITE, false); + } + + @Override + protected JettyComponent makeJettyComponent() + { + JettyComponent jettyComponent = new EnterpriseJettyComponent(port, contextPath, configLocations, classLocations); + return jettyComponent; + } + + @Override + protected RepoService makeRepoService() throws Exception + { + return new RepoService(applicationContext); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestApi.java b/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestApi.java index 0f8fca4419..d58a1865cb 100644 --- a/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestApi.java +++ b/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestApi.java @@ -1,16 +1,16 @@ -package org.alfresco.rest.api.tests; - -public class EnterpriseTestApi extends AbstractTestApi -{ - @Override - protected TestFixture getTestFixture() throws Exception - { - return EnterprisePublicApiTestFixture.getInstance(); - } - - @Override - protected TestFixture getTestFixture(boolean createTestData) throws Exception - { - return EnterprisePublicApiTestFixture.getInstance(createTestData); - } -} +package org.alfresco.rest.api.tests; + +public class EnterpriseTestApi extends AbstractTestApi +{ + @Override + protected TestFixture getTestFixture() throws Exception + { + return EnterprisePublicApiTestFixture.getInstance(); + } + + @Override + protected TestFixture getTestFixture(boolean createTestData) throws Exception + { + return EnterprisePublicApiTestFixture.getInstance(createTestData); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestFixture.java b/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestFixture.java index 349d8cd97a..69245a73c9 100644 --- a/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestFixture.java +++ b/source/test-java/org/alfresco/rest/api/tests/EnterpriseTestFixture.java @@ -1,49 +1,49 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.service.cmr.site.SiteVisibility; - -public abstract class EnterpriseTestFixture extends AbstractTestFixture -{ - public static final String WITH_AVATAR = "withAvatar"; //If you set PersonInfo instantmsg to WITH_AVATAR, an avatar gets created. - public EnterpriseTestFixture(String[] configLocations, String[] classLocations, int port, String contextPath, - String servletName, int numMembersPerSite, boolean cleanup) - { - super(configLocations, classLocations, port, contextPath, servletName, numMembersPerSite, cleanup); - } - - @Override - protected void populateTestData() - { - for(int i = 1; i <= 2; i++) - { - TestNetwork network = repoService.createNetworkWithAlias(TEST_DOMAIN_PREFIX + "00" + i, true); - addNetwork(network); - } - - // 5 public sites - for(int i = 0; i < 5; i++) - { - SiteInformation siteInfo = new SiteInformation("testSite" + i, "Public Test Site" + i, "Public Test Site" + i, SiteVisibility.PUBLIC); - addSite(siteInfo); - } - - // 5 private sites - for(int i = 5; i < 10; i++) - { - SiteInformation siteInfo = new SiteInformation("testSite" + i, "Private Test Site" + i, "Private Test Site" + i, SiteVisibility.PRIVATE); - addSite(siteInfo); - } - - addPerson(new PersonInfo("David", "Smith", "david.smith", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - addPerson(new PersonInfo("Bob", "Jones", "bob.jones", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - addPerson(new PersonInfo("Bill", "Grainger", "bill.grainger", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); - addPerson(new PersonInfo("Jill", "Fry", "jill.fry", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - addPerson(new PersonInfo("Elvis", "Presley", "elvis.presley", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); - addPerson(new PersonInfo("John", "Lennon", "john.lennon", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); - addPerson(new PersonInfo("George", "Harrison", "george.harrison", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - addPerson(new PersonInfo("David", "Bowie", "david.bowie", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - addPerson(new PersonInfo("Ford", "Prefect", "ford.prefect", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.service.cmr.site.SiteVisibility; + +public abstract class EnterpriseTestFixture extends AbstractTestFixture +{ + public static final String WITH_AVATAR = "withAvatar"; //If you set PersonInfo instantmsg to WITH_AVATAR, an avatar gets created. + public EnterpriseTestFixture(String[] configLocations, String[] classLocations, int port, String contextPath, + String servletName, int numMembersPerSite, boolean cleanup) + { + super(configLocations, classLocations, port, contextPath, servletName, numMembersPerSite, cleanup); + } + + @Override + protected void populateTestData() + { + for(int i = 1; i <= 2; i++) + { + TestNetwork network = repoService.createNetworkWithAlias(TEST_DOMAIN_PREFIX + "00" + i, true); + addNetwork(network); + } + + // 5 public sites + for(int i = 0; i < 5; i++) + { + SiteInformation siteInfo = new SiteInformation("testSite" + i, "Public Test Site" + i, "Public Test Site" + i, SiteVisibility.PUBLIC); + addSite(siteInfo); + } + + // 5 private sites + for(int i = 5; i < 10; i++) + { + SiteInformation siteInfo = new SiteInformation("testSite" + i, "Private Test Site" + i, "Private Test Site" + i, SiteVisibility.PRIVATE); + addSite(siteInfo); + } + + addPerson(new PersonInfo("David", "Smith", "david.smith", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + addPerson(new PersonInfo("Bob", "Jones", "bob.jones", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + addPerson(new PersonInfo("Bill", "Grainger", "bill.grainger", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); + addPerson(new PersonInfo("Jill", "Fry", "jill.fry", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + addPerson(new PersonInfo("Elvis", "Presley", "elvis.presley", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); + addPerson(new PersonInfo("John", "Lennon", "john.lennon", "password", null, "skype", "location", "telephone", "mob", WITH_AVATAR, "google")); + addPerson(new PersonInfo("George", "Harrison", "george.harrison", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + addPerson(new PersonInfo("David", "Bowie", "david.bowie", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + addPerson(new PersonInfo("Ford", "Prefect", "ford.prefect", "password", null, "skype", "location", "telephone", "mob", "instant", "google")); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java b/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java index e212910c37..b6b8f8b872 100644 --- a/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java +++ b/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java @@ -1,98 +1,98 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.rest.api.tests.client.data.Company; - -public class PersonInfo -{ - protected Company company; - protected String firstName; - protected String lastName; - protected String username; - protected String password; - protected String skype; - protected String location; - protected String tel; - protected String mob; - protected String instantmsg; - protected String google; - protected boolean networkAdmin; - - public PersonInfo(String firstName, String lastName, String username, - String password, Company company, String skype, - String location, String tel, String mob, String instantmsg, - String google) - { - super(); - if(username == null) - { - throw new IllegalArgumentException(); - } - this.company = company; - this.networkAdmin = false; - this.firstName = firstName; - this.lastName = lastName; - this.username = username; - this.password = password; - this.skype = skype; - this.location = location; - this.tel = tel; - this.mob = mob; - this.instantmsg = instantmsg; - this.google = google; - } - - public boolean isNetworkAdmin() - { - return networkAdmin; - } - - public Company getCompany() - { - return company; - } - - public String getFirstName() - { - return firstName; - } - - public String getLastName() - { - return lastName; - } - - public String getUsername() - { - return username; - } - - public String getPassword() - { - return password; - } - - public String getSkype() { - return skype; - } - - public String getLocation() { - return location; - } - - public String getTel() { - return tel; - } - - public String getMob() { - return mob; - } - - public String getInstantmsg() { - return instantmsg; - } - - public String getGoogle() { - return google; - } - -} +package org.alfresco.rest.api.tests; + +import org.alfresco.rest.api.tests.client.data.Company; + +public class PersonInfo +{ + protected Company company; + protected String firstName; + protected String lastName; + protected String username; + protected String password; + protected String skype; + protected String location; + protected String tel; + protected String mob; + protected String instantmsg; + protected String google; + protected boolean networkAdmin; + + public PersonInfo(String firstName, String lastName, String username, + String password, Company company, String skype, + String location, String tel, String mob, String instantmsg, + String google) + { + super(); + if(username == null) + { + throw new IllegalArgumentException(); + } + this.company = company; + this.networkAdmin = false; + this.firstName = firstName; + this.lastName = lastName; + this.username = username; + this.password = password; + this.skype = skype; + this.location = location; + this.tel = tel; + this.mob = mob; + this.instantmsg = instantmsg; + this.google = google; + } + + public boolean isNetworkAdmin() + { + return networkAdmin; + } + + public Company getCompany() + { + return company; + } + + public String getFirstName() + { + return firstName; + } + + public String getLastName() + { + return lastName; + } + + public String getUsername() + { + return username; + } + + public String getPassword() + { + return password; + } + + public String getSkype() { + return skype; + } + + public String getLocation() { + return location; + } + + public String getTel() { + return tel; + } + + public String getMob() { + return mob; + } + + public String getInstantmsg() { + return instantmsg; + } + + public String getGoogle() { + return google; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/PublicApiDateFormat.java b/source/test-java/org/alfresco/rest/api/tests/PublicApiDateFormat.java index b08bda5b87..a1510161a6 100644 --- a/source/test-java/org/alfresco/rest/api/tests/PublicApiDateFormat.java +++ b/source/test-java/org/alfresco/rest/api/tests/PublicApiDateFormat.java @@ -1,27 +1,27 @@ -package org.alfresco.rest.api.tests; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; - -public class PublicApiDateFormat -{ - private static DateFormat dateFormat; - - private PublicApiDateFormat() - { - } - - // The date format to use when checking dates coming back from the rest api - static - { - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - TimeZone gmt = TimeZone.getTimeZone("UTC"); - dateFormat.setTimeZone(gmt); - } - - public static DateFormat getDateFormat() - { - return dateFormat; - } -} +package org.alfresco.rest.api.tests; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.TimeZone; + +public class PublicApiDateFormat +{ + private static DateFormat dateFormat; + + private PublicApiDateFormat() + { + } + + // The date format to use when checking dates coming back from the rest api + static + { + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + TimeZone gmt = TimeZone.getTimeZone("UTC"); + dateFormat.setTimeZone(gmt); + } + + public static DateFormat getDateFormat() + { + return dateFormat; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/PublicApiJettyComponent.java b/source/test-java/org/alfresco/rest/api/tests/PublicApiJettyComponent.java index 1decd3ed45..48db9f094f 100644 --- a/source/test-java/org/alfresco/rest/api/tests/PublicApiJettyComponent.java +++ b/source/test-java/org/alfresco/rest/api/tests/PublicApiJettyComponent.java @@ -1,85 +1,85 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.repo.web.util.AbstractJettyComponent; -import org.alfresco.rest.api.PublicApiWebScriptServlet; -import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.webapp.WebAppContext; - -/** - * Manages an embedded jetty server, hooking it up to the repository spring context and providing - * authenticated, tenant-based access through the tenant servlet. - * - * @author steveglover - * - */ -public class PublicApiJettyComponent extends AbstractJettyComponent -{ - public PublicApiJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) - { - super(port, contextPath, configLocations, classLocations); - } - - @Override - protected void configureWebAppContext(WebAppContext webAppContext) - { -// ServletContext servletContext = webAppContext.getServletContext(); - - // the tenant servlet with alfresco managed authentication - ServletHolder servletHolder = new ServletHolder(PublicApiWebScriptServlet.class); - servletHolder.setInitParameter("authenticator", "publicapi.authenticator"); - webAppContext.addServlet(servletHolder, "/" + publicApiServletName + "/*"); - -// DependencyInjectedFilter apiFilter = (DependencyInjectedFilter)getApplicationContext().getBean("publicAPICMISFilter"); -// BeanProxyFilter filter = new BeanProxyFilter(servletContext, apiFilter); -// FilterHolder filterHolder = new FilterHolder(filter); -// webAppContext.addFilter(filterHolder, "/" + publicApiServletName + "/*", null); - - // the tenant servlet with alfresco managed authentication - servletHolder = new ServletHolder(CmisAtomPubServlet.class); - servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); - webAppContext.addServlet(servletHolder, "/cmisatom/*"); - } - -// private static class BeanProxyFilter implements Filter -// { -// private DependencyInjectedFilter filter; -// private ServletContext context; -// -// private BeanProxyFilter(ServletContext context, DependencyInjectedFilter filter) -// { -// this.context = context; -// this.filter = filter; -// } -// -// /** -// * Initialize the filter. -// * -// * @param args -// * FilterConfig -// * @throws ServletException -// * the servlet exception -// * @exception ServletException -// */ -// public void init(FilterConfig args) throws ServletException -// { -// } -// -// /* (non-Javadoc) -// * @see javax.servlet.Filter#destroy() -// */ -// public void destroy() -// { -// this.filter = null; -// } -// -// /* (non-Javadoc) -// * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) -// */ -// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, -// ServletException -// { -// this.filter.doFilter(this.context, request, response, chain); -// } -// } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.repo.web.util.AbstractJettyComponent; +import org.alfresco.rest.api.PublicApiWebScriptServlet; +import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * Manages an embedded jetty server, hooking it up to the repository spring context and providing + * authenticated, tenant-based access through the tenant servlet. + * + * @author steveglover + * + */ +public class PublicApiJettyComponent extends AbstractJettyComponent +{ + public PublicApiJettyComponent(int port, String contextPath, String[] configLocations, String[] classLocations) + { + super(port, contextPath, configLocations, classLocations); + } + + @Override + protected void configureWebAppContext(WebAppContext webAppContext) + { +// ServletContext servletContext = webAppContext.getServletContext(); + + // the tenant servlet with alfresco managed authentication + ServletHolder servletHolder = new ServletHolder(PublicApiWebScriptServlet.class); + servletHolder.setInitParameter("authenticator", "publicapi.authenticator"); + webAppContext.addServlet(servletHolder, "/" + publicApiServletName + "/*"); + +// DependencyInjectedFilter apiFilter = (DependencyInjectedFilter)getApplicationContext().getBean("publicAPICMISFilter"); +// BeanProxyFilter filter = new BeanProxyFilter(servletContext, apiFilter); +// FilterHolder filterHolder = new FilterHolder(filter); +// webAppContext.addFilter(filterHolder, "/" + publicApiServletName + "/*", null); + + // the tenant servlet with alfresco managed authentication + servletHolder = new ServletHolder(CmisAtomPubServlet.class); + servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler"); + webAppContext.addServlet(servletHolder, "/cmisatom/*"); + } + +// private static class BeanProxyFilter implements Filter +// { +// private DependencyInjectedFilter filter; +// private ServletContext context; +// +// private BeanProxyFilter(ServletContext context, DependencyInjectedFilter filter) +// { +// this.context = context; +// this.filter = filter; +// } +// +// /** +// * Initialize the filter. +// * +// * @param args +// * FilterConfig +// * @throws ServletException +// * the servlet exception +// * @exception ServletException +// */ +// public void init(FilterConfig args) throws ServletException +// { +// } +// +// /* (non-Javadoc) +// * @see javax.servlet.Filter#destroy() +// */ +// public void destroy() +// { +// this.filter = null; +// } +// +// /* (non-Javadoc) +// * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) +// */ +// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, +// ServletException +// { +// this.filter.doFilter(this.context, request, response, chain); +// } +// } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/PublicApiTestContext.java b/source/test-java/org/alfresco/rest/api/tests/PublicApiTestContext.java index e648cf0280..1556689d07 100644 --- a/source/test-java/org/alfresco/rest/api/tests/PublicApiTestContext.java +++ b/source/test-java/org/alfresco/rest/api/tests/PublicApiTestContext.java @@ -1,131 +1,131 @@ -package org.alfresco.rest.api.tests; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.util.ApplicationContextHelper; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.webscripts.TestWebScriptServer; - -/** - * Helper for Cloud Tests - */ -public class PublicApiTestContext -{ - private ApplicationContext applicationContext; - private BaseWebScriptTest test; - - private List usersToBeTidied = new ArrayList(); - private List invalidDomainsToBeTidied = new ArrayList(); - - private MutableAuthenticationService authenticationService; - private RetryingTransactionHelper transactionHelper; - - public PublicApiTestContext() - { - init(ApplicationContextHelper.getApplicationContext()); - } - - public PublicApiTestContext(ApplicationContext context) - { - init(context); - } - - public PublicApiTestContext(BaseWebScriptTest test) - { - this.test = test; - this.test.setCustomContext("cloud-test-context.xml"); - init(test.getServer().getApplicationContext()); - } - - private void init(ApplicationContext context) - { - applicationContext = context; - transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); - authenticationService = (MutableAuthenticationService)applicationContext.getBean("authenticationService"); - } - - public ApplicationContext getApplicationContext() - { - return applicationContext; - } - - public TestWebScriptServer getTestServer() - { - return test.getServer(); - } - - public String createUserName(String alias, String tenant) - { - StringBuilder sb = new StringBuilder(); - sb.append(alias); - if(tenant != null && !tenant.equals(TenantService.DEFAULT_DOMAIN)) - { - sb.append("@"); - sb.append(tenant); - } - return sb.toString(); - } - - public void addUser(String user) - { - usersToBeTidied.add(user); - } - - public void addInvalidDomain(String domain) - { - invalidDomainsToBeTidied.add(domain); - } - - public void removeInvalidDomain(String domain) - { - invalidDomainsToBeTidied.remove(domain); - } - - public void cleanup() - { - RunAsWork work = new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public Void execute() throws Throwable - { - return null; - } - }); - return null; - } - }; - AuthenticationUtil.runAs(work, AuthenticationUtil.getSystemUserName()); - - for (final String user : this.usersToBeTidied) - { - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - if (authenticationService.authenticationExists(user)) - { - authenticationService.deleteAuthentication(user); - } - return null; - } - }); - } - usersToBeTidied.clear(); - - // finally clear authentication - AuthenticationUtil.clearCurrentSecurityContext(); - } -} +package org.alfresco.rest.api.tests; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.util.ApplicationContextHelper; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.webscripts.TestWebScriptServer; + +/** + * Helper for Cloud Tests + */ +public class PublicApiTestContext +{ + private ApplicationContext applicationContext; + private BaseWebScriptTest test; + + private List usersToBeTidied = new ArrayList(); + private List invalidDomainsToBeTidied = new ArrayList(); + + private MutableAuthenticationService authenticationService; + private RetryingTransactionHelper transactionHelper; + + public PublicApiTestContext() + { + init(ApplicationContextHelper.getApplicationContext()); + } + + public PublicApiTestContext(ApplicationContext context) + { + init(context); + } + + public PublicApiTestContext(BaseWebScriptTest test) + { + this.test = test; + this.test.setCustomContext("cloud-test-context.xml"); + init(test.getServer().getApplicationContext()); + } + + private void init(ApplicationContext context) + { + applicationContext = context; + transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); + authenticationService = (MutableAuthenticationService)applicationContext.getBean("authenticationService"); + } + + public ApplicationContext getApplicationContext() + { + return applicationContext; + } + + public TestWebScriptServer getTestServer() + { + return test.getServer(); + } + + public String createUserName(String alias, String tenant) + { + StringBuilder sb = new StringBuilder(); + sb.append(alias); + if(tenant != null && !tenant.equals(TenantService.DEFAULT_DOMAIN)) + { + sb.append("@"); + sb.append(tenant); + } + return sb.toString(); + } + + public void addUser(String user) + { + usersToBeTidied.add(user); + } + + public void addInvalidDomain(String domain) + { + invalidDomainsToBeTidied.add(domain); + } + + public void removeInvalidDomain(String domain) + { + invalidDomainsToBeTidied.remove(domain); + } + + public void cleanup() + { + RunAsWork work = new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public Void execute() throws Throwable + { + return null; + } + }); + return null; + } + }; + AuthenticationUtil.runAs(work, AuthenticationUtil.getSystemUserName()); + + for (final String user : this.usersToBeTidied) + { + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + if (authenticationService.authenticationExists(user)) + { + authenticationService.deleteAuthentication(user); + } + return null; + } + }); + } + usersToBeTidied.clear(); + + // finally clear authentication + AuthenticationUtil.clearCurrentSecurityContext(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/RepoService.java b/source/test-java/org/alfresco/rest/api/tests/RepoService.java index 5a67673c19..f09f31f4b2 100644 --- a/source/test-java/org/alfresco/rest/api/tests/RepoService.java +++ b/source/test-java/org/alfresco/rest/api/tests/RepoService.java @@ -1,1939 +1,1939 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.sql.SQLException; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.alfresco.model.ContentModel; -import org.alfresco.opencmis.CMISConnector; -import org.alfresco.opencmis.CMISNodeInfoImpl; -import org.alfresco.query.PageDetails; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.activities.feed.FeedGenerator; -import org.alfresco.repo.activities.feed.cleanup.FeedCleaner; -import org.alfresco.repo.activities.post.lookup.PostLookup; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.content.cleanup.ContentStoreCleaner; -import org.alfresco.repo.domain.activities.ActivityFeedEntity; -import org.alfresco.repo.domain.activities.ActivityPostDAO; -import org.alfresco.repo.forum.CommentService; -import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl; -import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; -import org.alfresco.repo.model.filefolder.HiddenAspect; -import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility; -import org.alfresco.repo.node.index.NodeIndexer; -import org.alfresco.repo.security.authentication.AuthenticationException; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.site.SiteDoesNotExistException; -import org.alfresco.repo.tenant.Network; -import org.alfresco.repo.tenant.NetworksService; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.version.VersionModel; -import org.alfresco.repo.web.scripts.invitation.InvitationWebScriptTest; -import org.alfresco.rest.api.Activities; -import org.alfresco.rest.api.impl.node.ratings.RatingScheme; -import org.alfresco.rest.api.tests.client.data.Activity; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.Company; -import org.alfresco.rest.api.tests.client.data.FavouriteDocument; -import org.alfresco.rest.api.tests.client.data.FavouriteFolder; -import org.alfresco.rest.api.tests.client.data.FavouriteSite; -import org.alfresco.rest.api.tests.client.data.MemberOfSite; -import org.alfresco.rest.api.tests.client.data.NetworkImpl; -import org.alfresco.rest.api.tests.client.data.NodeRating; -import org.alfresco.rest.api.tests.client.data.NodeRating.Aggregate; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.PersonNetwork; -import org.alfresco.rest.api.tests.client.data.SiteContainer; -import org.alfresco.rest.api.tests.client.data.SiteImpl; -import org.alfresco.rest.api.tests.client.data.SiteMember; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.alfresco.service.cmr.activities.ActivityService; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.favourites.FavouritesService; -import org.alfresco.service.cmr.invitation.Invitation; -import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; -import org.alfresco.service.cmr.invitation.InvitationService; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockType; -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.preference.PreferenceService; -import org.alfresco.service.cmr.rating.Rating; -import org.alfresco.service.cmr.rating.RatingService; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.cmr.tagging.TaggingService; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionHistory; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.version.VersionType; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.FileFilterMode.Client; -import org.alfresco.util.GUID; -import org.alfresco.util.Pair; -import org.alfresco.util.registry.NamedObjectRegistry; -import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; -import org.apache.chemistry.opencmis.commons.data.Properties; -import org.apache.chemistry.opencmis.commons.data.PropertyData; -import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONException; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.quartz.JobExecutionException; -import org.quartz.Scheduler; -import org.springframework.context.ApplicationContext; -import org.springframework.scheduling.quartz.JobDetailBean; - -import com.google.common.collect.AbstractIterator; - -/** - * A convenient proxy into the repository services to support the tests. - * - * @author steveglover - * - */ -public class RepoService -{ - private static final Log logger = LogFactory.getLog(RepoService.class); - - protected static final String TEST_SITE_PRESET = "testSitePreset"; - - private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; - private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); - - protected ApplicationContext applicationContext; - - protected MutableAuthenticationService authenticationService; - protected DictionaryService dictionaryService; - protected SiteService siteService; - protected ActivityService activityService; - protected PostLookup postLookup; - protected FeedGenerator feedGenerator; - protected FileFolderService fileFolderService; - protected ContentService contentService; - protected CommentService commentService; - protected NodeService nodeService; - protected PreferenceService preferenceService; - protected TaggingService taggingService; - protected RatingService ratingService; - protected TenantService tenantService; - protected TenantAdminService tenantAdminService; - protected ActivityPostDAO postDAO; - protected JobDetailBean feedGeneratorJobDetail; - protected JobDetailBean postLookupJobDetail; - protected JobDetailBean feedCleanerJobDetail; - protected JobDetailBean postCleanerJobDetail; - protected JobDetailBean feedNotifierJobDetail; - protected ContentStoreCleaner contentStoreCleaner; - protected FeedCleaner feedCleaner; - protected PersonService personService; - protected NamedObjectRegistry nodeRatingSchemeRegistry; - protected VersionService versionService; - protected CheckOutCheckInService cociService; - protected FavouritesService favouritesService; - protected InvitationService invitationService; - protected LockService lockService; - protected CMISConnector cmisConnector; - protected NodeIndexer nodeIndexer; - protected HiddenAspect hiddenAspect; - protected NetworksService networksService; - protected NamespaceService namespaceService; - protected RetryingTransactionHelper transactionHelper; - - protected Activities activities; - - protected PublicApiTestContext publicApiContext; - - protected Random random = new Random(System.currentTimeMillis()); - - protected static int numNetworks = 0; - - /* - * Represents the "system" tenant/network - */ - protected TestNetwork systemNetwork; - - /* - * A map of user names (stored in the map in lower case) and TestPersons - */ - protected Map allPeople = new HashMap(); - - // Needed for CGLIB to create proxy, see CloudRepoService - public RepoService() - { - } - - @SuppressWarnings("unchecked") - public RepoService(ApplicationContext applicationContext) throws Exception - { - this.applicationContext = applicationContext; - this.publicApiContext = new PublicApiTestContext(applicationContext); - this.authenticationService = (MutableAuthenticationService)applicationContext.getBean("AuthenticationService"); - this.siteService = (SiteService)applicationContext.getBean("SiteService"); - this.activityService = (ActivityService)applicationContext.getBean("activityService"); - this.fileFolderService = (FileFolderService)applicationContext.getBean("FileFolderService"); - this.contentService = (ContentService)applicationContext.getBean("ContentService"); - this.commentService = (CommentService)applicationContext.getBean("CommentService"); - this.nodeService = (NodeService)applicationContext.getBean("NodeService"); - this.preferenceService = (PreferenceService)applicationContext.getBean("PreferenceService"); - this.taggingService = (TaggingService)applicationContext.getBean("TaggingService"); - this.ratingService = (RatingService)applicationContext.getBean("RatingService"); - this.tenantService = (TenantService)applicationContext.getBean("tenantService"); - this.tenantAdminService = (TenantAdminService)applicationContext.getBean("tenantAdminService"); - this.personService = (PersonService)applicationContext.getBean("PersonService"); - this.contentStoreCleaner = (ContentStoreCleaner)applicationContext.getBean("contentStoreCleaner"); - this.postDAO = (ActivityPostDAO)applicationContext.getBean("postDAO"); - this.nodeRatingSchemeRegistry = (NamedObjectRegistry)applicationContext.getBean("nodeRatingSchemeRegistry"); - this.cociService = (CheckOutCheckInService)applicationContext.getBean("CheckoutCheckinService"); - this.favouritesService = (FavouritesService)applicationContext.getBean("FavouritesService"); - this.dictionaryService = (DictionaryService)applicationContext.getBean("dictionaryService"); - this.invitationService = (InvitationService)applicationContext.getBean("InvitationService"); - this.lockService = (LockService)applicationContext.getBean("LockService"); - this.cmisConnector = (CMISConnector)applicationContext.getBean("CMISConnector"); - this.nodeIndexer = (NodeIndexer)applicationContext.getBean("nodeIndexer"); - this.activities = (Activities)applicationContext.getBean("activities"); - this.hiddenAspect = (HiddenAspect)applicationContext.getBean("hiddenAspect"); - this.networksService = (NetworksService)applicationContext.getBean("networksService"); - this.namespaceService = (NamespaceService)applicationContext.getBean("namespaceService"); - this.transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); - - Scheduler scheduler = (Scheduler)applicationContext.getBean("schedulerFactory"); - - JobDetailBean contentStoreCleanerJobDetail = (JobDetailBean)applicationContext.getBean("contentStoreCleanerJobDetail"); - scheduler.pauseJob(contentStoreCleanerJobDetail.getName(), contentStoreCleanerJobDetail.getGroup()); - - ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory)applicationContext.getBean("ActivitiesFeed"); - ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext(); - this.postLookup = (PostLookup)activitiesFeedCtx.getBean("postLookup"); - this.feedGenerator = (FeedGenerator)activitiesFeedCtx.getBean("feedGenerator"); - this.feedGeneratorJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedGeneratorJobDetail"); - this.postLookupJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("postLookupJobDetail"); - this.feedCleanerJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedCleanerJobDetail"); - this.postCleanerJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("postCleanerJobDetail"); - this.feedNotifierJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedNotifierJobDetail"); - this.feedCleaner = (FeedCleaner)activitiesFeedCtx.getBean("feedCleaner"); - - // Pause activities jobs so that we aren't competing with their scheduled versions - scheduler.pauseJob(feedGeneratorJobDetail.getName(), feedGeneratorJobDetail.getGroup()); - scheduler.pauseJob(postLookupJobDetail.getName(), postLookupJobDetail.getGroup()); - scheduler.pauseJob(feedCleanerJobDetail.getName(), feedCleanerJobDetail.getGroup()); - scheduler.pauseJob(postCleanerJobDetail.getName(), postCleanerJobDetail.getGroup()); - scheduler.pauseJob(feedNotifierJobDetail.getName(), feedNotifierJobDetail.getGroup()); - - this.systemNetwork = new TestNetwork(TenantService.DEFAULT_DOMAIN, true); - } - - public TestNetwork getSystemNetwork() - { - return systemNetwork; - } - - public PublicApiTestContext getPublicApiContext() - { - return publicApiContext; - } - - public void addPerson(TestPerson person) - { - allPeople.put(person.getId().toLowerCase(), person); - } - - public NodeService getNodeService() - { - return nodeService; - } - - public TestPerson getPerson(String username) - { - return allPeople.get(username.toLowerCase()); - } - - public void disableInTxnIndexing() - { - nodeIndexer.setDisabled(true); - } - - public int getClientVisibilityMask(Client client, Visibility visibility) - { - return hiddenAspect.getClientVisibilityMask(client, visibility); - } - - public ApplicationContext getApplicationContext() - { - return applicationContext; - } - - public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) - { - return nodeService.createAssociation(sourceRef, targetRef, assocTypeQName); - } - - public String toPrefixString(QName qname) - { - return qname.toPrefixString(namespaceService); - } - - public Invitation approveSiteInvitation(String personId, String siteId) - { - Invitation ret = null; - - List invitations = invitationService.listPendingInvitationsForInvitee(personId); - for(Invitation invitation : invitations) - { - if(invitation.getResourceName().equals(siteId)) - { - ret = invitationService.approve(invitation.getInviteId(), "I accept you"); - } - } - - return ret; - } - - public void moveNode(NodeRef nodeToMoveRef, NodeRef newParentNodeRef) throws FileExistsException, FileNotFoundException - { - fileFolderService.move(nodeToMoveRef, newParentNodeRef, GUID.generate()); - } - - public void deleteNode(NodeRef nodeRef) - { - nodeService.deleteNode(nodeRef); - } - - public void lockNode(NodeRef nodeRef) - { - lockService.lock(nodeRef, LockType.NODE_LOCK); - } - - public void unlockNode(NodeRef nodeRef) - { - lockService.unlock(nodeRef); - } - - public NodeRef addUserDescription(final String personId, final TestNetwork network, final String personDescription) - { - return AuthenticationUtil.runAsSystem(new RunAsWork() - { - //@Override - public NodeRef doWork() throws Exception - { - NodeRef userRef = personService.getPersonOrNull(personId); - if (userRef == null) - { - throw new AuthenticationException("User name does not exist: " + personId); - } - - ContentWriter writer = contentService.getWriter(userRef, ContentModel.PROP_PERSONDESC, true); - writer.setMimetype(MimetypeMap.MIMETYPE_HTML); - writer.putContent(personDescription); - - log("Updated person description " + personId + (network != null ? " in network " + network : "")); - return userRef; - } - }); - } - - public TestPerson createUser(final PersonInfo personInfo, final String username, final TestNetwork network) - { - return getOrCreateUser(personInfo, username, network, true); - } - - public TestPerson getOrCreateUser(final PersonInfo personInfo, final String username, final TestNetwork network) - { - return getOrCreateUser(personInfo, username, network, false); - } - - // TODO review delete person - public TestPerson getOrCreateUser(final PersonInfo personInfo, final String username, final TestNetwork network, final boolean deletePerson) - { - return AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public TestPerson doWork() throws Exception - { - - final TestPerson testPerson = new TestPerson(personInfo.getFirstName(), personInfo.getLastName(), username, personInfo.getPassword(), - personInfo.getCompany(), network, personInfo.getSkype(), personInfo.getLocation(), personInfo.getTel(), - personInfo.getMob(), personInfo.getInstantmsg(), personInfo.getGoogle()); - - final Map props = testPerson.getProperties(); - - // short-circuit for default "admin" - if (! username.equalsIgnoreCase("admin")) - { - NodeRef personNodeRef = personService.getPersonOrNull(username); - - if ((personNodeRef != null) && deletePerson) - { - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - personService.deletePerson(testPerson.getId()); - return null; - } - }); - } - - if (personNodeRef == null) - { - personNodeRef = personService.createPerson(props); - - // create authentication to represent user - authenticationService.createAuthentication(username, personInfo.getPassword().toCharArray()); - - if (EnterpriseTestFixture.WITH_AVATAR.equals(personInfo.getInstantmsg())) - { - InvitationWebScriptTest.makeAvatar(nodeService, personNodeRef); - log("Made avatar for " + testPerson.getId() + (network != null ? " in network " + network : "")); - } - } - } - log("Username " + testPerson.getId() + (network != null ? " in network " + network : "")); - - publicApiContext.addUser(testPerson.getId()); - addPerson(testPerson); - - return testPerson; - } - }); - } - - public TestSite createSite(TestNetwork network, final SiteInformation site) - { - SiteInfo siteInfo = null; - - if(siteService.hasSite(site.getShortName())) - { - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - siteService.deleteSite(site.getShortName()); - return null; - } - }); - } - - siteInfo = siteService.createSite(TEST_SITE_PRESET, site.getShortName(), site.getTitle(), site.getDescription(), site.getSiteVisibility()); - siteService.createContainer(site.getShortName(), "documentLibrary", ContentModel.TYPE_FOLDER, null); - - final TestSite testSite = new TestSite(network, siteInfo); - - log("Created site " + testSite + (network != null ? " in network " + network : "")); - - return testSite; - } - - public Invitation rejectSiteInvitation(String personId, String siteId) - { - Invitation ret = null; - - List invitations = invitationService.listPendingInvitationsForInvitee(personId); - for(Invitation invitation : invitations) - { - if(invitation.getResourceName().equals(siteId)) - { - ret = invitationService.reject(invitation.getInviteId(), "I reject you"); - } - } - - return ret; - } - - public List getModeratedSiteInvitations(String networkId, String runAsUserId, final String inviteeId, final String siteId) - { - List invitations = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - InvitationSearchCriteriaImpl searchCriteria = new InvitationSearchCriteriaImpl(); - searchCriteria.setInvitee(inviteeId); - if(siteId != null) - { - searchCriteria.setResourceName(siteId); - } - searchCriteria.setResourceType(Invitation.ResourceType.WEB_SITE); - searchCriteria.setInvitationType(InvitationType.MODERATED); - List invitations = invitationService.searchInvitation(searchCriteria); - return invitations; - } - }, runAsUserId, networkId); - return invitations; - } - - public Version getCurrentVersion(NodeRef nodeRef) - { - return versionService.getCurrentVersion(nodeRef); - } - - protected void log(String msg) - { - if(logger.isDebugEnabled()) - { - logger.debug(msg); - } - } - - public SiteInfo getSiteInfo(String siteId) - { - return siteService.getSite(siteId); - } - - public boolean isCheckedOut(NodeRef nodeRef) - { - return cociService.isCheckedOut(nodeRef); - } - - public Serializable getProperty(NodeRef nodeRef, QName propertyName) - { - Serializable value = nodeService.getProperty(nodeRef, propertyName); - return value; - } - - public Set getAspects(NodeRef nodeRef) - { - Set aspects = nodeService.getAspects(nodeRef); - return aspects; - } - - public ContentReader getContent(NodeRef nodeRef, QName propertyQName) - { - ContentReader reader = contentService.getReader(nodeRef, propertyQName); - return reader; - } - - private void cleanupContent() - { -// eagerCleaner.setEagerOrphanCleanup(false); - - log("Cleaning up feeds..."); - - // fire the cleaner - feedCleaner.setMaxAgeMins(1); - feedCleaner.setMaxFeedSize(1); - try - { - feedCleaner.execute(); - } - catch(JobExecutionException e) - { - // TODO - } - - log("...done"); - - log("Cleaning up content..."); - - // fire the cleaner - contentStoreCleaner.setProtectDays(0); - contentStoreCleaner.execute(); - - log("...done"); - } - - public void shutdown() - { - cleanupContent(); - publicApiContext.cleanup(); - } - - public Version createVersion(NodeRef nodeRef, String history, boolean majorVersion) - { - Map props = new HashMap(2, 1.0f); - props.put(Version.PROP_DESCRIPTION, history); - props.put(VersionModel.PROP_VERSION_TYPE, majorVersion ? VersionType.MAJOR : VersionType.MINOR); - return versionService.createVersion(nodeRef, props); - } - - public VersionHistory getVersionHistory(NodeRef nodeRef) - { - return versionService.getVersionHistory(nodeRef); - } - - public Pair splitSiteNetwork(String siteNetwork) - { - int idx = siteNetwork.indexOf("@"); - String siteId = siteNetwork; - String networkId = null; - if(idx > -1) - { - siteId = siteNetwork.substring(0, idx - 1); - networkId = siteNetwork.substring(idx + 1); - } - return new Pair(siteId, networkId); - } - - private Map parseActivitySummary(ActivityFeedEntity entity) - { - String activityType = entity.getActivityType(); - String activitySummary = entity.getActivitySummary(); - JSONObject json = (JSONObject)JSONValue.parse(activitySummary); - return Activity.getActivitySummary(json, activityType); - } - - public List getActivities(String personId, String siteId, boolean excludeUser, boolean excludeOthers) - { - List feedEntities = activityService.getUserFeedEntries(personId, siteId, excludeUser, excludeOthers, 0); - List activities = new ArrayList(feedEntities.size()); - for(ActivityFeedEntity entity : feedEntities) - { - String siteNetwork = entity.getSiteNetwork(); - Pair pair = splitSiteNetwork(siteNetwork); - siteId = pair.getFirst(); - String networkId = pair.getSecond(); - String postDateStr = PublicApiDateFormat.getDateFormat().format(entity.getPostDate()); - Activity activity = new Activity(entity.getId(), networkId, siteId, entity.getFeedUserId(), entity.getPostUserId(), postDateStr, entity.getActivityType(), parseActivitySummary(entity)); - activities.add(activity); - } - - return activities; - } - - public Rating getRating(NodeRef targetNode, String scheme) - { - return ratingService.getRatingByCurrentUser(targetNode, scheme); - } - - public List getRatings(NodeRef targetNode) - { - return ratingService.getRatingsByCurrentUser(targetNode); - } - - public RatingScheme getApiRatingScheme(String ratingSchemeName) - { - return nodeRatingSchemeRegistry.getNamedObject(ratingSchemeName); - } - - @SuppressWarnings("unchecked") - public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException - { - Map activitySummary = activities.getActivitySummary(entity); - JSONObject json = new JSONObject(); - for(String key : activitySummary.keySet()) - { - Object value = activitySummary.get(key); - if(value instanceof NodeRef) - { - value = ((NodeRef)value).getId(); - } - json.put(key, value); - } - return json; - } - - public void checkSiteMember(final TestPerson person, final TestSite site, SiteRole siteRole) throws Exception - { - assertTrue(siteService.isMember(site.getSiteId(), person.getId())); - assertEquals(siteRole.toString(), siteService.getMembersRole(site.getSiteId(), person.getId())); - } - - public void addFavouriteSite(final String username, final String siteShortName) - { - SiteInfo siteInfo = siteService.getSite(siteShortName); - if(siteInfo != null) - { - favouritesService.addFavourite(username, siteInfo.getNodeRef()); - } - else - { - throw new SiteDoesNotExistException(siteShortName); - } - } - - private PagingResults getFavouriteSites(String userName, PagingRequest pagingRequest) - { - final Collator collator = Collator.getInstance(); - - final Set sortedFavouriteSites = new TreeSet(new Comparator() - { - @Override - public int compare(SiteInfo o1, SiteInfo o2) - { - return collator.compare(o1.getTitle(), o2.getTitle()); - } - }); - - Map prefs = preferenceService.getPreferences(userName, FAVOURITE_SITES_PREFIX); - for(String key : prefs.keySet()) - { - boolean isFavourite = false; - Serializable s = prefs.get(key); - if(s instanceof Boolean) - { - isFavourite = (Boolean)s; - } - if(isFavourite) - { - String siteShortName = key.substring(FAVOURITE_SITES_PREFIX_LENGTH); - SiteInfo siteInfo = siteService.getSite(siteShortName); - if(siteInfo != null) - { - sortedFavouriteSites.add(siteInfo); - } - } - } - - int totalSize = sortedFavouriteSites.size(); - final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); - - final List page = new ArrayList(pageDetails.getPageSize()); - Iterator it = sortedFavouriteSites.iterator(); - for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) - { - SiteInfo favouriteSite = it.next(); - - if(counter < pageDetails.getSkipCount()) - { - continue; - } - - if(counter > pageDetails.getEnd() - 1) - { - break; - } - - page.add(favouriteSite); - } - - return new PagingResults() - { - @Override - public List getPage() - { - return page; - } - - @Override - public boolean hasMoreItems() - { - return pageDetails.hasMoreItems(); - } - - @Override - public Pair getTotalResultCount() - { - Integer total = Integer.valueOf(sortedFavouriteSites.size()); - return new Pair(total, total); - } - - @Override - public String getQueryExecutionId() - { - return null; - } - }; - } - - public List getFavouriteSites(TestPerson user) - { - List favouriteSites = new ArrayList(); - - PagingResults pagingResults = getFavouriteSites(user.getId(), new PagingRequest(0, Integer.MAX_VALUE)); - for(SiteInfo siteInfo : pagingResults.getPage()) - { - String siteId = siteInfo.getShortName(); - String siteGuid = siteInfo.getNodeRef().getId(); - - TestSite site = user.getDefaultAccount().getSite(siteId); - FavouriteSite favouriteSite = null; - if(site.isMember(user.getId())) - { - favouriteSite = new FavouriteSite(site); - } - else - { - favouriteSite = new FavouriteSite(null, siteId, siteGuid, null, null, null, null, null); - } - favouriteSites.add(favouriteSite); - } - - return favouriteSites; - } - - public void addPreference(final String username, final String Key, final Serializable value) - { - Map preferences = new HashMap(1); - preferences.put(Key, value); - preferenceService.setPreferences(username, preferences); - } - - public List getSiteMemberships(String personId) - { - List sites = siteService.listSites(personId); - List memberships = new ArrayList(); - for(SiteInfo siteInfo : sites) - { - String roleStr = siteService.getMembersRole(siteInfo.getShortName(), personId); - SiteRole role = SiteRole.valueOf(roleStr); - SiteImpl site = new SiteImpl(siteInfo, role, true); - memberships.add(new MemberOfSite(site, role)); - } - return memberships; - } - - public void generateFeed() throws JobExecutionException, SQLException - { - // process all outstanding activity posts - transactionHelper.doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - postLookup.execute(); - return null; - } - }, false, true); - - Long maxSequence = getMaxActivitySeq(); - while(maxSequence != null) - { - feedGenerator.execute(); - - maxSequence = getMaxActivitySeq(); - } - } - - private Long getMaxActivitySeq() throws SQLException - { - Long maxSequence = transactionHelper.doInTransaction(new RetryingTransactionCallback() - { - @Override - public Long execute() throws Throwable - { - return postDAO.getMaxActivitySeq(); - } - }, true, true); - - return maxSequence; - } - - public Tag addTag(NodeRef nodeRef, String tag) - { - NodeRef tagNodeRef = taggingService.addTag(nodeRef, tag); - return new Tag(nodeRef.getId(), tagNodeRef.getId(), tag); - } - - public List getTags() - { - Set tags = new TreeSet(); - for(String tag : taggingService.getTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE)) - { - tags.add(new Tag(null, taggingService.getTagNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tag).getId(), tag)); - } - return new ArrayList(tags); - } - - public List getTags(NodeRef nodeRef) - { - Set tags = new TreeSet(); - for(String tag : taggingService.getTags(nodeRef)) - { - tags.add(new Tag(null, taggingService.getTagNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tag).getId(), tag)); - } - return new ArrayList(tags); - } - - /* - * Get (CMIS) node properties - */ - private Properties getProperties(NodeRef nodeRef) - { - CMISNodeInfoImpl nodeInfo = cmisConnector.createNodeInfo(nodeRef); - final Properties properties = cmisConnector.getNodeProperties(nodeInfo, null); - // fake the title property, which CMIS doesn't give us - String title = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE); - final PropertyStringImpl titleProp = new PropertyStringImpl(ContentModel.PROP_TITLE.toString(), title); - Properties wrapProperties = new Properties() - { - @Override - public List getExtensions() - { - return properties.getExtensions(); - } - - @Override - public void setExtensions(List extensions) - { - properties.setExtensions(extensions); - } - - @Override - public Map> getProperties() - { - Map> updatedProperties = new HashMap>(properties.getProperties()); - updatedProperties.put(titleProp.getId(), titleProp); - return updatedProperties; - } - - @Override - public List> getPropertyList() - { - List> propertyList = new ArrayList>(properties.getPropertyList()); - propertyList.add(titleProp); - return propertyList; - } - }; - return wrapProperties; - } - - public FavouriteDocument getDocument(String networkId, final NodeRef nodeRef) - { - return TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public FavouriteDocument doWork() throws Exception - { - FavouriteDocument document = null; - - QName type = nodeService.getType(nodeRef); - if(dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) - { - Properties properties = getProperties(nodeRef); - document = FavouriteDocument.getDocument(nodeRef.getId(), nodeRef.getId(), properties); - } - else - { - throw new IllegalArgumentException("Not a document node"); - } - - return document; - } - }, networkId); - } - - public FavouriteFolder getFolder(String networkId, final NodeRef nodeRef) - { - return TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public FavouriteFolder doWork() throws Exception - { - FavouriteFolder folder = null; - - QName type = nodeService.getType(nodeRef); - if(dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER)) - { - Properties properties = getProperties(nodeRef); - folder = FavouriteFolder.getFolder(nodeRef.getId(), nodeRef.getId(), properties); - } - else - { - throw new IllegalArgumentException("Not a folder node"); - } - - return folder; - } - }, networkId); - } - - public List getNodeRatings(String personId, String networkId, final NodeRef nodeRef) - { - List ratings = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List ratings = new ArrayList(); - - { - Rating likesRating = ratingService.getRatingByCurrentUser(nodeRef, "likesRatingScheme"); - Object myRating = null; - String ratedAt = null; - if(likesRating != null) - { - myRating = likesRating.getScore() == 1.0f ? Boolean.TRUE : Boolean.FALSE; - Date rateTime = likesRating.getAppliedAt(); - ratedAt = PublicApiDateFormat.getDateFormat().format(rateTime); - } - int ratingsCount = ratingService.getRatingsCount(nodeRef, "likesRatingScheme"); - Aggregate aggregate = new Aggregate(ratingsCount, null); - ratings.add(new NodeRating(nodeRef.getId(), "likes", ratedAt, myRating, aggregate)); - } - - { - Rating fiveStarRating = ratingService.getRatingByCurrentUser(nodeRef, "fiveStarRatingScheme"); - Object myRating = null; - String ratedAt = null; - if(fiveStarRating != null) - { - myRating = fiveStarRating.getScore(); - Date rateTime = fiveStarRating.getAppliedAt(); - ratedAt = PublicApiDateFormat.getDateFormat().format(rateTime); - } - int ratingsCount = ratingService.getRatingsCount(nodeRef, "fiveStarRatingScheme"); - float averageRating = ratingService.getAverageRating(nodeRef, "fiveStarRatingScheme"); - Aggregate aggregate = new Aggregate(ratingsCount, averageRating == -1 ? null : averageRating); - ratings.add(new NodeRating(nodeRef.getId(), "fiveStar", ratedAt, myRating, aggregate)); - } - - return ratings; - } - - }, personId, networkId); - - Collections.sort(ratings); - - return ratings; - } - - public int numRatingSchemes() - { - return ratingService.getRatingSchemes().size(); - } - - public NodeRef addToDocumentLibrary(TestSite site, String name, QName type) - { - NodeRef documentLibraryContainerNodeRef = siteService.getContainer(site.getSiteId(), "documentLibrary"); - NodeRef nodeRef = fileFolderService.create(documentLibraryContainerNodeRef, name, type).getNodeRef(); - return nodeRef; - } - - public String getSiteNetwork(final String siteShortName, String tenantDomain) - { - return TenantUtil.runAsTenant(new TenantRunAsWork() - { - @Override - public String doWork() throws Exception - { - return tenantService.getName(siteShortName); - } - }, tenantDomain); - } - - public void postActivity(final String activityType, final String siteId, final JSONObject activityData) throws JobExecutionException - { - activityService.postActivity(activityType, siteId, "documentlibrary", activityData.toString()); - } - - public NodeRef createDocument(final NodeRef parentNodeRef, final String name, final String content) - { - NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_CONTENT).getNodeRef(); - ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - writer.putContent(content); - - return nodeRef; - } - - public NodeRef createDocument(final NodeRef parentNodeRef, final String name, final String title, final String description, final String content) - { - NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_CONTENT).getNodeRef(); - ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - writer.putContent(content); - nodeService.setProperty(nodeRef, ContentModel.PROP_TITLE, title); - nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, description); - - return nodeRef; - } - - public NodeRef createFolder(final NodeRef parentNodeRef, final String name) - { - NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_FOLDER).getNodeRef(); - return nodeRef; - } - - public NodeRef createFolder(final NodeRef parentNodeRef, final String name, final String title, final String description) - { - NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_FOLDER).getNodeRef(); - nodeService.setProperty(nodeRef, ContentModel.PROP_TITLE, title); - nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, description); - - return nodeRef; - } - - public NodeRef createCmObject(final NodeRef parentNodeRef, final String name) - { - QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)); - NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, ContentModel.TYPE_CMOBJECT).getChildRef(); - - return nodeRef; - } - - public NodeRef createObjectOfCustomType(final NodeRef parentNodeRef, final String name, final String typeName) - { - QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)); - QName typeQName = QName.createQName(typeName); - NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, typeQName).getChildRef(); - - return nodeRef; - } - - public Visibility getVisibility(Client client, NodeRef nodeRef) - { - return hiddenAspect.getVisibility(client, nodeRef); - } - - public void addAspect(NodeRef nodeRef, QName aspectTypeQName, Map aspectProperties) - { - nodeService.addAspect(nodeRef, aspectTypeQName, aspectProperties); - } - - public NodeRef createComment(NodeRef nodeRef, final Comment comment) - { - NodeRef commentNodeRef = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false); - comment.setId(commentNodeRef.getId()); - Date created = (Date)nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATED); - comment.setCreatedAt(PublicApiDateFormat.getDateFormat().format(created)); - TestPerson person = getPerson((String)nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATOR)); - comment.setCreatedBy(person); - return commentNodeRef; - } - - public TestNetwork createNetworkWithAlias(String alias, boolean enabled) - { - String networkId = alias + "-" + System.currentTimeMillis(); - TestNetwork network = new TestNetwork(networkId, enabled); - return network; - } - - public TestNetwork createNetwork(String networkId, boolean enabled) - { - TestNetwork network = new TestNetwork(networkId, enabled); - return network; - } - - public class TestSite extends SiteImpl - { - private static final long serialVersionUID = 5317623044880374281L; - - private TestNetwork account; - private SiteInfo siteInfo; - - public TestSite(TestNetwork account, SiteInfo siteInfo) - { - this(account, siteInfo.getShortName(), siteInfo.getNodeRef().getId(), siteInfo.getTitle(), siteInfo.getDescription(), siteInfo.getVisibility()); - this.account = account; - this.siteInfo = siteInfo; - } - - public TestSite(TestNetwork account, String siteId, String guid, String title, String description, SiteVisibility siteVisibility) - { - super((account == null ? null : account.getId()), siteId, guid); - setTitle(title); - setDescription(description); - setVisibility(siteVisibility.toString()); - this.siteInfo = siteService.getSite(siteId); - } - - public SiteInfo getSiteInfo() - { - return siteInfo; - } - public NodeRef getContainerNodeRef(String containerId) - { - return siteService.getContainer(siteId, containerId); - } - - public NodeRef createContainer(String containerName) - { - return siteService.createContainer(getSiteId(), containerName, ContentModel.TYPE_FOLDER, null); - } - - public void inviteToSite(final String toInvite, final SiteRole siteRole) - { - siteService.setMembership(getSiteId(), toInvite, siteRole.toString()); - log(toInvite + " invited to site " + getSiteId()); - } - - public TestNetwork getAccount() - { - return account; - } - - public Map getMembers(final String roleFilter) - { - Map members = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() - { - @Override - public Map doWork() throws Exception - { - Map members = siteService.listMembers(getSiteId(), null, roleFilter, 0); - return members; - } - }, getAccount().getId()); - return members; - } - - public List getMembers() - { - Map members = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() - { - @Override - public Map doWork() throws Exception - { - // get all site members - Map members = siteService.listMembers(getSiteId(), null, null, 0); - return members; - } - }, getAccount().getId()); - List ret = new ArrayList(members.size()); - for(String userId : members.keySet()) - { - String role = members.get(userId); - TestPerson person = RepoService.this.getPerson(userId); - SiteMember sm = new SiteMember(userId, person, getSiteId(), role); - ret.add(sm); - } - Collections.sort(ret); - return ret; - } - - public boolean isMember(final String personId) - { - Boolean isMember = TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Boolean doWork() throws Exception - { - return siteService.isMember(getSiteId(), personId); - } - }, getAccount().getId()); - return isMember; - } - - public SiteRole getMember(String personId) - { - return SiteRole.valueOf(siteService.getMembersRole(getSiteId(), personId)); - } - - public void updateMember(String personId, SiteRole role) - { - siteService.setMembership(getSiteId(), personId, role.toString()); - } - - public void removeMember(String personId) - { - if(siteService.isMember(getSiteId(), personId)) - { - siteService.removeMembership(getSiteId(), personId); - } - } - - public void setSiteVisibility(SiteVisibility siteVisibility) - { - this.visibility = siteVisibility.toString(); - siteInfo.setVisibility(siteVisibility); - siteService.updateSite(siteInfo); - } - - @Override - public String toString() { - return "TestSite [siteid=" + getSiteId() + ", title=" + getTitle() - + ", description=" + getDescription() + ", siteVisibility=" - + getVisibility() + "]"; - } - } - - public static Iterator getWrappingIterator(final int startIdx, final List list) - { - return new AbstractIterator() - { - private int idx = Math.max(0, Math.min(startIdx, list.size() - 1)); - - @Override - protected T computeNext() - { - T o = list.get(idx); - - idx++; - if(idx >= list.size()) - { - idx = 0; - } - - return o; - } - }; - } - - public class TestNetwork extends NetworkImpl implements Comparable - { - private static final long serialVersionUID = -107881141652228471L; - - protected Map people = new TreeMap(); - protected TreeMap sites = new TreeMap(); - protected Set publicSites = new TreeSet(); - - public TestNetwork(String domain, boolean enabled) - { - super(domain, enabled); - } - - public void create() - { - if(!getId().equals(TenantService.DEFAULT_DOMAIN) && !tenantAdminService.existsTenant(getId())) - { - tenantAdminService.createTenant(getId(), "admin".toCharArray()); - numNetworks++; - log("Created network " + getId()); - } - } - - public TestSite createSite(SiteVisibility siteVisibility) - { - String shortName = "TESTSITE" + GUID.generate(); - SiteInformation siteInfo = new SiteInformation(shortName, shortName, shortName, siteVisibility); - return createSite(siteInfo); - } - - public TestSite createSite(final SiteInformation site) - { - TestSite testSite = RepoService.this.createSite(this, site); - addSite(testSite); - - return testSite; - } - - public TestPerson createUser() - { - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo("FirstName", "LastName", username, "password", null, "skype", "location", - "telephone", "mob", "instant", "google"); - TestPerson person = createUser(personInfo); - return person; - } - - public NodeRef addUserDescription(final String personId, final String personDescription) - { - NodeRef personRef = TenantUtil.runAsTenant(new TenantRunAsWork() - { - public NodeRef doWork() throws Exception - { - return RepoService.this.addUserDescription(personId, TestNetwork.this, personDescription); - } - }, getId()); - - return personRef; - } - - public TestPerson createUser(final PersonInfo personInfo) - { - final String username = publicApiContext.createUserName(personInfo.getUsername(), getId()); - TestPerson testPerson = TenantUtil.runAsTenant(new TenantRunAsWork() - { - public TestPerson doWork() throws Exception - { - TestPerson person = RepoService.this.createUser(personInfo, username, TestNetwork.this); - - return person; - } - }, getId()); - addPerson(testPerson); - return testPerson; - } - - public List peopleSample(int sampleSize) - { - final List p = new ArrayList(); - - if(sampleSize < 0) - { - p.addAll(people.keySet()); - } - else - { - int startIdx = random.nextInt(people.size()); - List peopleList = new ArrayList(people.keySet()); - Iterator it = getWrappingIterator(startIdx, peopleList); - - for(int i = 0; i < sampleSize && it.hasNext(); i++) - { - p.add(it.next()); - } - } - - return p; - } - - // Return a site of which person is not a member - public TestSite getSiteNonMember(final String personId) - { - return TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite ret = null; - SiteInfo match = null; - for(SiteInfo info : siteService.listSites(null, null)) - { - boolean isMember = siteService.isMember(info.getShortName(), personId); - if(!isMember) - { - match = info; - break; - } - } - - if(match != null) - { - ret = new TestSite(TestNetwork.this, match); - } - - return ret; - } - }, getId()); - } - - public void addSite(TestSite site) - { - sites.put(site.getSiteId(), site); - if(site.getVisibility().equals(SiteVisibility.PUBLIC.toString())) - { - publicSites.add(site); - } - } - - public Set getPublicSites() - { - return publicSites; - } - - public TestSite getSite(final String siteShortName) - { - TestSite site = TenantUtil.runAsTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - SiteInfo siteInfo = siteService.getSite(siteShortName); - return new TestSite(TestNetwork.this, siteInfo); - } - }, getId()); - return site; - } - - /* - * List sites in this account that person can see - */ - public List getSites(String personId) - { - List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List results = siteService.listSites(null, null); - TreeMap ret = new TreeMap(); - for(SiteInfo siteInfo : results) - { - TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); - ret.put(site.getSiteId(), site); - } - - return new ArrayList(ret.values()); - } - }, personId, getId()); - return sites; - } - - public List getAllSites() - { - List sites = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List results = siteService.listSites(null, null); - TreeMap ret = new TreeMap(); - for(SiteInfo siteInfo : results) - { - TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); - ret.put(site.getSiteId(), site); - } - - return new ArrayList(ret.values()); - } - }, getId()); - return sites; - } - - public List getSiteContainers(final String siteId, TestPerson runAs) - { - List siteContainers = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - PagingResults results = siteService.listContainers(siteId, new PagingRequest(0, Integer.MAX_VALUE)); - List ret = new ArrayList(results.getPage().size()); - for(FileInfo fileInfo : results.getPage()) - { - SiteContainer siteContainer = new SiteContainer(siteId, fileInfo.getName(), fileInfo.getNodeRef().getId()); - ret.add(siteContainer); - } - - return ret; - } - }, runAs.getId(), getId()); - - return siteContainers; - } - - public Map getSitesForUser(String username) - { - if(username == null) - { - username = AuthenticationUtil.getAdminUserName(); - } - List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List results = siteService.listSites(null, null); - return results; - } - }, username, getId()); - TreeMap ret = new TreeMap(); - for(SiteInfo siteInfo : sites) - { - TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); - ret.put(site.getSiteId(), site); - } - return ret; - } - - public List getSiteMemberships(String username) - { - if(username == null) - { - username = AuthenticationUtil.getAdminUserName(); - } - final String userId = username; - List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List sites = siteService.listSites(userId); - Set personSites = new TreeSet(); - for(SiteInfo siteInfo : sites) - { - TestSite site = getSite(siteInfo.getShortName()); - String role = siteService.getMembersRole(siteInfo.getShortName(), userId); - MemberOfSite ms = new MemberOfSite(site, SiteRole.valueOf(role)); - personSites.add(ms); - } - - return new ArrayList(personSites); - } - }, userId, getId()); - return sites; - } - - public Map getSites(SiteVisibility siteVisibility) - { - Map ret = new HashMap(); - for(String key : getSitesForUser(null).keySet()) - { - TestSite site = getSitesForUser(null).get(key); - if(site.getVisibility().equals(siteVisibility.toString())) - { - ret.put(key, site); - } - } - return ret; - } - - public void addPerson(TestPerson person) - { - people.put(person.getId(), person); - } - - public List getPersonIds() - { - return new ArrayList(people.keySet()); - } - - public List getPeople() - { - return new ArrayList(people.values()); - } - - public int compareTo(TestNetwork o) - { - return getId().compareTo(o.getId()); - } - - public void addExternalUser(String personId) - { - throw new UnsupportedOperationException(); - } - - public TestSite homeSite(TestPerson person) - { - throw new UnsupportedOperationException(); - } - - public void inviteUser(final String user) - { - throw new UnsupportedOperationException(); - } - - public Collection getHomeSites() - { - throw new UnsupportedOperationException(); - } - - public Long getAccountId() - { - throw new UnsupportedOperationException(); - } - - public void setAccountId(Long accountId) - { - throw new UnsupportedOperationException(); - } - - public int getType() - { - throw new UnsupportedOperationException(); - } - - public void addNetworkAdmin(String email) - { - throw new UnsupportedOperationException(); - } - - public Set getNetworkAdmins() - { - throw new UnsupportedOperationException(); - } - - public Set getNonNetworkAdmins() - { - throw new UnsupportedOperationException(); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((getId() == null) ? 0 : getId().hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - { - return true; - } - - if(obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - TestNetwork other = (TestNetwork) obj; - return getId().equals(other.getId()); - } - - public TestSite getSite(SiteVisibility siteVisibility) - { - TestSite ret = null; - for(TestSite site : getSitesForUser(null).values()) - { - if(site.getVisibility().equals(siteVisibility)) - { - ret = site; - break; - } - } - return ret; - } - - @Override - public String toString() - { - return "TestNetwork [people=" + people + ", sites=" + sites - + ", publicSites=" + publicSites + "]"; - } - } - - public static class SiteMembership implements Comparable - { - private TestSite site; - private SiteRole role; - - public SiteMembership(TestSite site, SiteRole role) - { - super(); - if(site == null) - { - throw new IllegalArgumentException(); - } - if(role == null) - { - throw new IllegalArgumentException(); - } - this.site = site; - this.role = role; - } - - public TestSite getSite() - { - return site; - } - - public SiteRole getRole() - { - return role; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((role == null) ? 0 : role.hashCode()); - result = prime * result + ((site == null) ? 0 : site.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - SiteMembership other = (SiteMembership) obj; - if (role != other.role) - { - return false; - } - - return site.equals(other.site); - } - - @Override - public int compareTo(SiteMembership siteMembership) - { - int ret = site.getSiteId().compareTo(siteMembership.getSite().getSiteId()); - if(ret == 0) - { - // arbitrary sorting on site role - ret = role.compareTo(siteMembership.getRole()); - } - return ret; - } - } - - // order by last name, first name, role - public class TestPerson extends Person - { - private static final long serialVersionUID = 4038390056182705588L; - - protected boolean enabled; - protected String password; - protected TestNetwork defaultAccount; - protected TreeMap siteMemberships = new TreeMap(); - - public TestPerson(String firstName, String lastName, String username, String password, Company company, TestNetwork defaultAccount, String skype, String location, String tel, - String mob, String instantmsg, String google) - { - super(username, username, true, firstName, lastName, company, skype, location, tel, mob, instantmsg, google, null); - this.password = password; - this.enabled = true; - this.defaultAccount = defaultAccount; - } - - public boolean isNetworkAdmin() - { - return false; // cloud only - } - - public String getDefaultDomain() - { - return defaultAccount == null ? null : defaultAccount.getId(); - } - - public boolean isEnabled() - { - return enabled; - } - - public void addSiteMembership(TestSite site, SiteRole siteRole) - { - siteMemberships.put(site, siteRole); - } - - public TestNetwork getDefaultAccount() - { - return defaultAccount; - } - - public String getPassword() - { - return password; - } - - public List getNetworkMemberships() - { - String personId = getId(); - String runAsNetworkId = Person.getNetworkId(personId); - return TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List members = new ArrayList(); - PagingResults networks = networksService.getNetworks(new PagingRequest(0, Integer.MAX_VALUE)); - for(Network network : networks.getPage()) - { - NetworkImpl restNetwork = new NetworkImpl(network); - PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork); - members.add(personNetwork); - } - return members; - } - }, personId, runAsNetworkId); - } - - @Override - public String toString() - { - return "TestPerson [enabled=" + enabled + ", password=" + password - + ", defaultAccount=" + defaultAccount.getId() + ", siteMemberships=" + siteMemberships - + ", getId()=" + getId() + ", getFirstName()=" - + getFirstName() + ", getCompany()=" + getCompany() - + ", getLastName()=" + getLastName() + "]"; - } - } - - public static class SiteInformation implements Comparable - { - private String shortName; - private String title; - private String sitePreset; - private String description; - private SiteVisibility siteVisibility; - - public SiteInformation(String shortName, String title, String description, SiteVisibility siteVisibility) - { - super(); - if(shortName == null) - { - throw new IllegalArgumentException(); - } - this.shortName = shortName; - this.title = title; - this.description = description; - this.siteVisibility = siteVisibility; - } - - public String getShortName() - { - return shortName; - } - - public String getTitle() - { - return title; - } - - public String getSitePreset() - { - return sitePreset; - } - - public String getDescription() - { - return description; - } - - public SiteVisibility getSiteVisibility() - { - return siteVisibility; - } - - public boolean equals(Object other) - { - if(this == other) - { - return true; - } - - if(!(other instanceof SiteInformation)) - { - return false; - } - - SiteInformation site = (SiteInformation)other; - return shortName == site.getShortName(); - } - - @Override - public int compareTo(SiteInformation site) - { - return shortName.compareTo(site.getShortName()); - } - - public int hashCode() - { - return getShortName().hashCode(); - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.sql.SQLException; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.CMISConnector; +import org.alfresco.opencmis.CMISNodeInfoImpl; +import org.alfresco.query.PageDetails; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.activities.feed.FeedGenerator; +import org.alfresco.repo.activities.feed.cleanup.FeedCleaner; +import org.alfresco.repo.activities.post.lookup.PostLookup; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.cleanup.ContentStoreCleaner; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.forum.CommentService; +import org.alfresco.repo.invitation.InvitationSearchCriteriaImpl; +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.model.filefolder.HiddenAspect; +import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility; +import org.alfresco.repo.node.index.NodeIndexer; +import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.site.SiteDoesNotExistException; +import org.alfresco.repo.tenant.Network; +import org.alfresco.repo.tenant.NetworksService; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.version.VersionModel; +import org.alfresco.repo.web.scripts.invitation.InvitationWebScriptTest; +import org.alfresco.rest.api.Activities; +import org.alfresco.rest.api.impl.node.ratings.RatingScheme; +import org.alfresco.rest.api.tests.client.data.Activity; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.Company; +import org.alfresco.rest.api.tests.client.data.FavouriteDocument; +import org.alfresco.rest.api.tests.client.data.FavouriteFolder; +import org.alfresco.rest.api.tests.client.data.FavouriteSite; +import org.alfresco.rest.api.tests.client.data.MemberOfSite; +import org.alfresco.rest.api.tests.client.data.NetworkImpl; +import org.alfresco.rest.api.tests.client.data.NodeRating; +import org.alfresco.rest.api.tests.client.data.NodeRating.Aggregate; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.PersonNetwork; +import org.alfresco.rest.api.tests.client.data.SiteContainer; +import org.alfresco.rest.api.tests.client.data.SiteImpl; +import org.alfresco.rest.api.tests.client.data.SiteMember; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.favourites.FavouritesService; +import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.InvitationSearchCriteria.InvitationType; +import org.alfresco.service.cmr.invitation.InvitationService; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockType; +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.preference.PreferenceService; +import org.alfresco.service.cmr.rating.Rating; +import org.alfresco.service.cmr.rating.RatingService; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.cmr.tagging.TaggingService; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionHistory; +import org.alfresco.service.cmr.version.VersionService; +import org.alfresco.service.cmr.version.VersionType; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.FileFilterMode.Client; +import org.alfresco.util.GUID; +import org.alfresco.util.Pair; +import org.alfresco.util.registry.NamedObjectRegistry; +import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; +import org.apache.chemistry.opencmis.commons.data.Properties; +import org.apache.chemistry.opencmis.commons.data.PropertyData; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.quartz.JobExecutionException; +import org.quartz.Scheduler; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.quartz.JobDetailBean; + +import com.google.common.collect.AbstractIterator; + +/** + * A convenient proxy into the repository services to support the tests. + * + * @author steveglover + * + */ +public class RepoService +{ + private static final Log logger = LogFactory.getLog(RepoService.class); + + protected static final String TEST_SITE_PRESET = "testSitePreset"; + + private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; + private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); + + protected ApplicationContext applicationContext; + + protected MutableAuthenticationService authenticationService; + protected DictionaryService dictionaryService; + protected SiteService siteService; + protected ActivityService activityService; + protected PostLookup postLookup; + protected FeedGenerator feedGenerator; + protected FileFolderService fileFolderService; + protected ContentService contentService; + protected CommentService commentService; + protected NodeService nodeService; + protected PreferenceService preferenceService; + protected TaggingService taggingService; + protected RatingService ratingService; + protected TenantService tenantService; + protected TenantAdminService tenantAdminService; + protected ActivityPostDAO postDAO; + protected JobDetailBean feedGeneratorJobDetail; + protected JobDetailBean postLookupJobDetail; + protected JobDetailBean feedCleanerJobDetail; + protected JobDetailBean postCleanerJobDetail; + protected JobDetailBean feedNotifierJobDetail; + protected ContentStoreCleaner contentStoreCleaner; + protected FeedCleaner feedCleaner; + protected PersonService personService; + protected NamedObjectRegistry nodeRatingSchemeRegistry; + protected VersionService versionService; + protected CheckOutCheckInService cociService; + protected FavouritesService favouritesService; + protected InvitationService invitationService; + protected LockService lockService; + protected CMISConnector cmisConnector; + protected NodeIndexer nodeIndexer; + protected HiddenAspect hiddenAspect; + protected NetworksService networksService; + protected NamespaceService namespaceService; + protected RetryingTransactionHelper transactionHelper; + + protected Activities activities; + + protected PublicApiTestContext publicApiContext; + + protected Random random = new Random(System.currentTimeMillis()); + + protected static int numNetworks = 0; + + /* + * Represents the "system" tenant/network + */ + protected TestNetwork systemNetwork; + + /* + * A map of user names (stored in the map in lower case) and TestPersons + */ + protected Map allPeople = new HashMap(); + + // Needed for CGLIB to create proxy, see CloudRepoService + public RepoService() + { + } + + @SuppressWarnings("unchecked") + public RepoService(ApplicationContext applicationContext) throws Exception + { + this.applicationContext = applicationContext; + this.publicApiContext = new PublicApiTestContext(applicationContext); + this.authenticationService = (MutableAuthenticationService)applicationContext.getBean("AuthenticationService"); + this.siteService = (SiteService)applicationContext.getBean("SiteService"); + this.activityService = (ActivityService)applicationContext.getBean("activityService"); + this.fileFolderService = (FileFolderService)applicationContext.getBean("FileFolderService"); + this.contentService = (ContentService)applicationContext.getBean("ContentService"); + this.commentService = (CommentService)applicationContext.getBean("CommentService"); + this.nodeService = (NodeService)applicationContext.getBean("NodeService"); + this.preferenceService = (PreferenceService)applicationContext.getBean("PreferenceService"); + this.taggingService = (TaggingService)applicationContext.getBean("TaggingService"); + this.ratingService = (RatingService)applicationContext.getBean("RatingService"); + this.tenantService = (TenantService)applicationContext.getBean("tenantService"); + this.tenantAdminService = (TenantAdminService)applicationContext.getBean("tenantAdminService"); + this.personService = (PersonService)applicationContext.getBean("PersonService"); + this.contentStoreCleaner = (ContentStoreCleaner)applicationContext.getBean("contentStoreCleaner"); + this.postDAO = (ActivityPostDAO)applicationContext.getBean("postDAO"); + this.nodeRatingSchemeRegistry = (NamedObjectRegistry)applicationContext.getBean("nodeRatingSchemeRegistry"); + this.cociService = (CheckOutCheckInService)applicationContext.getBean("CheckoutCheckinService"); + this.favouritesService = (FavouritesService)applicationContext.getBean("FavouritesService"); + this.dictionaryService = (DictionaryService)applicationContext.getBean("dictionaryService"); + this.invitationService = (InvitationService)applicationContext.getBean("InvitationService"); + this.lockService = (LockService)applicationContext.getBean("LockService"); + this.cmisConnector = (CMISConnector)applicationContext.getBean("CMISConnector"); + this.nodeIndexer = (NodeIndexer)applicationContext.getBean("nodeIndexer"); + this.activities = (Activities)applicationContext.getBean("activities"); + this.hiddenAspect = (HiddenAspect)applicationContext.getBean("hiddenAspect"); + this.networksService = (NetworksService)applicationContext.getBean("networksService"); + this.namespaceService = (NamespaceService)applicationContext.getBean("namespaceService"); + this.transactionHelper = (RetryingTransactionHelper)applicationContext.getBean("retryingTransactionHelper"); + + Scheduler scheduler = (Scheduler)applicationContext.getBean("schedulerFactory"); + + JobDetailBean contentStoreCleanerJobDetail = (JobDetailBean)applicationContext.getBean("contentStoreCleanerJobDetail"); + scheduler.pauseJob(contentStoreCleanerJobDetail.getName(), contentStoreCleanerJobDetail.getGroup()); + + ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory)applicationContext.getBean("ActivitiesFeed"); + ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext(); + this.postLookup = (PostLookup)activitiesFeedCtx.getBean("postLookup"); + this.feedGenerator = (FeedGenerator)activitiesFeedCtx.getBean("feedGenerator"); + this.feedGeneratorJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedGeneratorJobDetail"); + this.postLookupJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("postLookupJobDetail"); + this.feedCleanerJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedCleanerJobDetail"); + this.postCleanerJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("postCleanerJobDetail"); + this.feedNotifierJobDetail = (JobDetailBean)activitiesFeedCtx.getBean("feedNotifierJobDetail"); + this.feedCleaner = (FeedCleaner)activitiesFeedCtx.getBean("feedCleaner"); + + // Pause activities jobs so that we aren't competing with their scheduled versions + scheduler.pauseJob(feedGeneratorJobDetail.getName(), feedGeneratorJobDetail.getGroup()); + scheduler.pauseJob(postLookupJobDetail.getName(), postLookupJobDetail.getGroup()); + scheduler.pauseJob(feedCleanerJobDetail.getName(), feedCleanerJobDetail.getGroup()); + scheduler.pauseJob(postCleanerJobDetail.getName(), postCleanerJobDetail.getGroup()); + scheduler.pauseJob(feedNotifierJobDetail.getName(), feedNotifierJobDetail.getGroup()); + + this.systemNetwork = new TestNetwork(TenantService.DEFAULT_DOMAIN, true); + } + + public TestNetwork getSystemNetwork() + { + return systemNetwork; + } + + public PublicApiTestContext getPublicApiContext() + { + return publicApiContext; + } + + public void addPerson(TestPerson person) + { + allPeople.put(person.getId().toLowerCase(), person); + } + + public NodeService getNodeService() + { + return nodeService; + } + + public TestPerson getPerson(String username) + { + return allPeople.get(username.toLowerCase()); + } + + public void disableInTxnIndexing() + { + nodeIndexer.setDisabled(true); + } + + public int getClientVisibilityMask(Client client, Visibility visibility) + { + return hiddenAspect.getClientVisibilityMask(client, visibility); + } + + public ApplicationContext getApplicationContext() + { + return applicationContext; + } + + public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) + { + return nodeService.createAssociation(sourceRef, targetRef, assocTypeQName); + } + + public String toPrefixString(QName qname) + { + return qname.toPrefixString(namespaceService); + } + + public Invitation approveSiteInvitation(String personId, String siteId) + { + Invitation ret = null; + + List invitations = invitationService.listPendingInvitationsForInvitee(personId); + for(Invitation invitation : invitations) + { + if(invitation.getResourceName().equals(siteId)) + { + ret = invitationService.approve(invitation.getInviteId(), "I accept you"); + } + } + + return ret; + } + + public void moveNode(NodeRef nodeToMoveRef, NodeRef newParentNodeRef) throws FileExistsException, FileNotFoundException + { + fileFolderService.move(nodeToMoveRef, newParentNodeRef, GUID.generate()); + } + + public void deleteNode(NodeRef nodeRef) + { + nodeService.deleteNode(nodeRef); + } + + public void lockNode(NodeRef nodeRef) + { + lockService.lock(nodeRef, LockType.NODE_LOCK); + } + + public void unlockNode(NodeRef nodeRef) + { + lockService.unlock(nodeRef); + } + + public NodeRef addUserDescription(final String personId, final TestNetwork network, final String personDescription) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + //@Override + public NodeRef doWork() throws Exception + { + NodeRef userRef = personService.getPersonOrNull(personId); + if (userRef == null) + { + throw new AuthenticationException("User name does not exist: " + personId); + } + + ContentWriter writer = contentService.getWriter(userRef, ContentModel.PROP_PERSONDESC, true); + writer.setMimetype(MimetypeMap.MIMETYPE_HTML); + writer.putContent(personDescription); + + log("Updated person description " + personId + (network != null ? " in network " + network : "")); + return userRef; + } + }); + } + + public TestPerson createUser(final PersonInfo personInfo, final String username, final TestNetwork network) + { + return getOrCreateUser(personInfo, username, network, true); + } + + public TestPerson getOrCreateUser(final PersonInfo personInfo, final String username, final TestNetwork network) + { + return getOrCreateUser(personInfo, username, network, false); + } + + // TODO review delete person + public TestPerson getOrCreateUser(final PersonInfo personInfo, final String username, final TestNetwork network, final boolean deletePerson) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public TestPerson doWork() throws Exception + { + + final TestPerson testPerson = new TestPerson(personInfo.getFirstName(), personInfo.getLastName(), username, personInfo.getPassword(), + personInfo.getCompany(), network, personInfo.getSkype(), personInfo.getLocation(), personInfo.getTel(), + personInfo.getMob(), personInfo.getInstantmsg(), personInfo.getGoogle()); + + final Map props = testPerson.getProperties(); + + // short-circuit for default "admin" + if (! username.equalsIgnoreCase("admin")) + { + NodeRef personNodeRef = personService.getPersonOrNull(username); + + if ((personNodeRef != null) && deletePerson) + { + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + personService.deletePerson(testPerson.getId()); + return null; + } + }); + } + + if (personNodeRef == null) + { + personNodeRef = personService.createPerson(props); + + // create authentication to represent user + authenticationService.createAuthentication(username, personInfo.getPassword().toCharArray()); + + if (EnterpriseTestFixture.WITH_AVATAR.equals(personInfo.getInstantmsg())) + { + InvitationWebScriptTest.makeAvatar(nodeService, personNodeRef); + log("Made avatar for " + testPerson.getId() + (network != null ? " in network " + network : "")); + } + } + } + log("Username " + testPerson.getId() + (network != null ? " in network " + network : "")); + + publicApiContext.addUser(testPerson.getId()); + addPerson(testPerson); + + return testPerson; + } + }); + } + + public TestSite createSite(TestNetwork network, final SiteInformation site) + { + SiteInfo siteInfo = null; + + if(siteService.hasSite(site.getShortName())) + { + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + siteService.deleteSite(site.getShortName()); + return null; + } + }); + } + + siteInfo = siteService.createSite(TEST_SITE_PRESET, site.getShortName(), site.getTitle(), site.getDescription(), site.getSiteVisibility()); + siteService.createContainer(site.getShortName(), "documentLibrary", ContentModel.TYPE_FOLDER, null); + + final TestSite testSite = new TestSite(network, siteInfo); + + log("Created site " + testSite + (network != null ? " in network " + network : "")); + + return testSite; + } + + public Invitation rejectSiteInvitation(String personId, String siteId) + { + Invitation ret = null; + + List invitations = invitationService.listPendingInvitationsForInvitee(personId); + for(Invitation invitation : invitations) + { + if(invitation.getResourceName().equals(siteId)) + { + ret = invitationService.reject(invitation.getInviteId(), "I reject you"); + } + } + + return ret; + } + + public List getModeratedSiteInvitations(String networkId, String runAsUserId, final String inviteeId, final String siteId) + { + List invitations = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + InvitationSearchCriteriaImpl searchCriteria = new InvitationSearchCriteriaImpl(); + searchCriteria.setInvitee(inviteeId); + if(siteId != null) + { + searchCriteria.setResourceName(siteId); + } + searchCriteria.setResourceType(Invitation.ResourceType.WEB_SITE); + searchCriteria.setInvitationType(InvitationType.MODERATED); + List invitations = invitationService.searchInvitation(searchCriteria); + return invitations; + } + }, runAsUserId, networkId); + return invitations; + } + + public Version getCurrentVersion(NodeRef nodeRef) + { + return versionService.getCurrentVersion(nodeRef); + } + + protected void log(String msg) + { + if(logger.isDebugEnabled()) + { + logger.debug(msg); + } + } + + public SiteInfo getSiteInfo(String siteId) + { + return siteService.getSite(siteId); + } + + public boolean isCheckedOut(NodeRef nodeRef) + { + return cociService.isCheckedOut(nodeRef); + } + + public Serializable getProperty(NodeRef nodeRef, QName propertyName) + { + Serializable value = nodeService.getProperty(nodeRef, propertyName); + return value; + } + + public Set getAspects(NodeRef nodeRef) + { + Set aspects = nodeService.getAspects(nodeRef); + return aspects; + } + + public ContentReader getContent(NodeRef nodeRef, QName propertyQName) + { + ContentReader reader = contentService.getReader(nodeRef, propertyQName); + return reader; + } + + private void cleanupContent() + { +// eagerCleaner.setEagerOrphanCleanup(false); + + log("Cleaning up feeds..."); + + // fire the cleaner + feedCleaner.setMaxAgeMins(1); + feedCleaner.setMaxFeedSize(1); + try + { + feedCleaner.execute(); + } + catch(JobExecutionException e) + { + // TODO + } + + log("...done"); + + log("Cleaning up content..."); + + // fire the cleaner + contentStoreCleaner.setProtectDays(0); + contentStoreCleaner.execute(); + + log("...done"); + } + + public void shutdown() + { + cleanupContent(); + publicApiContext.cleanup(); + } + + public Version createVersion(NodeRef nodeRef, String history, boolean majorVersion) + { + Map props = new HashMap(2, 1.0f); + props.put(Version.PROP_DESCRIPTION, history); + props.put(VersionModel.PROP_VERSION_TYPE, majorVersion ? VersionType.MAJOR : VersionType.MINOR); + return versionService.createVersion(nodeRef, props); + } + + public VersionHistory getVersionHistory(NodeRef nodeRef) + { + return versionService.getVersionHistory(nodeRef); + } + + public Pair splitSiteNetwork(String siteNetwork) + { + int idx = siteNetwork.indexOf("@"); + String siteId = siteNetwork; + String networkId = null; + if(idx > -1) + { + siteId = siteNetwork.substring(0, idx - 1); + networkId = siteNetwork.substring(idx + 1); + } + return new Pair(siteId, networkId); + } + + private Map parseActivitySummary(ActivityFeedEntity entity) + { + String activityType = entity.getActivityType(); + String activitySummary = entity.getActivitySummary(); + JSONObject json = (JSONObject)JSONValue.parse(activitySummary); + return Activity.getActivitySummary(json, activityType); + } + + public List getActivities(String personId, String siteId, boolean excludeUser, boolean excludeOthers) + { + List feedEntities = activityService.getUserFeedEntries(personId, siteId, excludeUser, excludeOthers, 0); + List activities = new ArrayList(feedEntities.size()); + for(ActivityFeedEntity entity : feedEntities) + { + String siteNetwork = entity.getSiteNetwork(); + Pair pair = splitSiteNetwork(siteNetwork); + siteId = pair.getFirst(); + String networkId = pair.getSecond(); + String postDateStr = PublicApiDateFormat.getDateFormat().format(entity.getPostDate()); + Activity activity = new Activity(entity.getId(), networkId, siteId, entity.getFeedUserId(), entity.getPostUserId(), postDateStr, entity.getActivityType(), parseActivitySummary(entity)); + activities.add(activity); + } + + return activities; + } + + public Rating getRating(NodeRef targetNode, String scheme) + { + return ratingService.getRatingByCurrentUser(targetNode, scheme); + } + + public List getRatings(NodeRef targetNode) + { + return ratingService.getRatingsByCurrentUser(targetNode); + } + + public RatingScheme getApiRatingScheme(String ratingSchemeName) + { + return nodeRatingSchemeRegistry.getNamedObject(ratingSchemeName); + } + + @SuppressWarnings("unchecked") + public Map getActivitySummary(ActivityFeedEntity entity) throws JSONException + { + Map activitySummary = activities.getActivitySummary(entity); + JSONObject json = new JSONObject(); + for(String key : activitySummary.keySet()) + { + Object value = activitySummary.get(key); + if(value instanceof NodeRef) + { + value = ((NodeRef)value).getId(); + } + json.put(key, value); + } + return json; + } + + public void checkSiteMember(final TestPerson person, final TestSite site, SiteRole siteRole) throws Exception + { + assertTrue(siteService.isMember(site.getSiteId(), person.getId())); + assertEquals(siteRole.toString(), siteService.getMembersRole(site.getSiteId(), person.getId())); + } + + public void addFavouriteSite(final String username, final String siteShortName) + { + SiteInfo siteInfo = siteService.getSite(siteShortName); + if(siteInfo != null) + { + favouritesService.addFavourite(username, siteInfo.getNodeRef()); + } + else + { + throw new SiteDoesNotExistException(siteShortName); + } + } + + private PagingResults getFavouriteSites(String userName, PagingRequest pagingRequest) + { + final Collator collator = Collator.getInstance(); + + final Set sortedFavouriteSites = new TreeSet(new Comparator() + { + @Override + public int compare(SiteInfo o1, SiteInfo o2) + { + return collator.compare(o1.getTitle(), o2.getTitle()); + } + }); + + Map prefs = preferenceService.getPreferences(userName, FAVOURITE_SITES_PREFIX); + for(String key : prefs.keySet()) + { + boolean isFavourite = false; + Serializable s = prefs.get(key); + if(s instanceof Boolean) + { + isFavourite = (Boolean)s; + } + if(isFavourite) + { + String siteShortName = key.substring(FAVOURITE_SITES_PREFIX_LENGTH); + SiteInfo siteInfo = siteService.getSite(siteShortName); + if(siteInfo != null) + { + sortedFavouriteSites.add(siteInfo); + } + } + } + + int totalSize = sortedFavouriteSites.size(); + final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); + + final List page = new ArrayList(pageDetails.getPageSize()); + Iterator it = sortedFavouriteSites.iterator(); + for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) + { + SiteInfo favouriteSite = it.next(); + + if(counter < pageDetails.getSkipCount()) + { + continue; + } + + if(counter > pageDetails.getEnd() - 1) + { + break; + } + + page.add(favouriteSite); + } + + return new PagingResults() + { + @Override + public List getPage() + { + return page; + } + + @Override + public boolean hasMoreItems() + { + return pageDetails.hasMoreItems(); + } + + @Override + public Pair getTotalResultCount() + { + Integer total = Integer.valueOf(sortedFavouriteSites.size()); + return new Pair(total, total); + } + + @Override + public String getQueryExecutionId() + { + return null; + } + }; + } + + public List getFavouriteSites(TestPerson user) + { + List favouriteSites = new ArrayList(); + + PagingResults pagingResults = getFavouriteSites(user.getId(), new PagingRequest(0, Integer.MAX_VALUE)); + for(SiteInfo siteInfo : pagingResults.getPage()) + { + String siteId = siteInfo.getShortName(); + String siteGuid = siteInfo.getNodeRef().getId(); + + TestSite site = user.getDefaultAccount().getSite(siteId); + FavouriteSite favouriteSite = null; + if(site.isMember(user.getId())) + { + favouriteSite = new FavouriteSite(site); + } + else + { + favouriteSite = new FavouriteSite(null, siteId, siteGuid, null, null, null, null, null); + } + favouriteSites.add(favouriteSite); + } + + return favouriteSites; + } + + public void addPreference(final String username, final String Key, final Serializable value) + { + Map preferences = new HashMap(1); + preferences.put(Key, value); + preferenceService.setPreferences(username, preferences); + } + + public List getSiteMemberships(String personId) + { + List sites = siteService.listSites(personId); + List memberships = new ArrayList(); + for(SiteInfo siteInfo : sites) + { + String roleStr = siteService.getMembersRole(siteInfo.getShortName(), personId); + SiteRole role = SiteRole.valueOf(roleStr); + SiteImpl site = new SiteImpl(siteInfo, role, true); + memberships.add(new MemberOfSite(site, role)); + } + return memberships; + } + + public void generateFeed() throws JobExecutionException, SQLException + { + // process all outstanding activity posts + transactionHelper.doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + postLookup.execute(); + return null; + } + }, false, true); + + Long maxSequence = getMaxActivitySeq(); + while(maxSequence != null) + { + feedGenerator.execute(); + + maxSequence = getMaxActivitySeq(); + } + } + + private Long getMaxActivitySeq() throws SQLException + { + Long maxSequence = transactionHelper.doInTransaction(new RetryingTransactionCallback() + { + @Override + public Long execute() throws Throwable + { + return postDAO.getMaxActivitySeq(); + } + }, true, true); + + return maxSequence; + } + + public Tag addTag(NodeRef nodeRef, String tag) + { + NodeRef tagNodeRef = taggingService.addTag(nodeRef, tag); + return new Tag(nodeRef.getId(), tagNodeRef.getId(), tag); + } + + public List getTags() + { + Set tags = new TreeSet(); + for(String tag : taggingService.getTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE)) + { + tags.add(new Tag(null, taggingService.getTagNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tag).getId(), tag)); + } + return new ArrayList(tags); + } + + public List getTags(NodeRef nodeRef) + { + Set tags = new TreeSet(); + for(String tag : taggingService.getTags(nodeRef)) + { + tags.add(new Tag(null, taggingService.getTagNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tag).getId(), tag)); + } + return new ArrayList(tags); + } + + /* + * Get (CMIS) node properties + */ + private Properties getProperties(NodeRef nodeRef) + { + CMISNodeInfoImpl nodeInfo = cmisConnector.createNodeInfo(nodeRef); + final Properties properties = cmisConnector.getNodeProperties(nodeInfo, null); + // fake the title property, which CMIS doesn't give us + String title = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE); + final PropertyStringImpl titleProp = new PropertyStringImpl(ContentModel.PROP_TITLE.toString(), title); + Properties wrapProperties = new Properties() + { + @Override + public List getExtensions() + { + return properties.getExtensions(); + } + + @Override + public void setExtensions(List extensions) + { + properties.setExtensions(extensions); + } + + @Override + public Map> getProperties() + { + Map> updatedProperties = new HashMap>(properties.getProperties()); + updatedProperties.put(titleProp.getId(), titleProp); + return updatedProperties; + } + + @Override + public List> getPropertyList() + { + List> propertyList = new ArrayList>(properties.getPropertyList()); + propertyList.add(titleProp); + return propertyList; + } + }; + return wrapProperties; + } + + public FavouriteDocument getDocument(String networkId, final NodeRef nodeRef) + { + return TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public FavouriteDocument doWork() throws Exception + { + FavouriteDocument document = null; + + QName type = nodeService.getType(nodeRef); + if(dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) + { + Properties properties = getProperties(nodeRef); + document = FavouriteDocument.getDocument(nodeRef.getId(), nodeRef.getId(), properties); + } + else + { + throw new IllegalArgumentException("Not a document node"); + } + + return document; + } + }, networkId); + } + + public FavouriteFolder getFolder(String networkId, final NodeRef nodeRef) + { + return TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public FavouriteFolder doWork() throws Exception + { + FavouriteFolder folder = null; + + QName type = nodeService.getType(nodeRef); + if(dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER)) + { + Properties properties = getProperties(nodeRef); + folder = FavouriteFolder.getFolder(nodeRef.getId(), nodeRef.getId(), properties); + } + else + { + throw new IllegalArgumentException("Not a folder node"); + } + + return folder; + } + }, networkId); + } + + public List getNodeRatings(String personId, String networkId, final NodeRef nodeRef) + { + List ratings = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List ratings = new ArrayList(); + + { + Rating likesRating = ratingService.getRatingByCurrentUser(nodeRef, "likesRatingScheme"); + Object myRating = null; + String ratedAt = null; + if(likesRating != null) + { + myRating = likesRating.getScore() == 1.0f ? Boolean.TRUE : Boolean.FALSE; + Date rateTime = likesRating.getAppliedAt(); + ratedAt = PublicApiDateFormat.getDateFormat().format(rateTime); + } + int ratingsCount = ratingService.getRatingsCount(nodeRef, "likesRatingScheme"); + Aggregate aggregate = new Aggregate(ratingsCount, null); + ratings.add(new NodeRating(nodeRef.getId(), "likes", ratedAt, myRating, aggregate)); + } + + { + Rating fiveStarRating = ratingService.getRatingByCurrentUser(nodeRef, "fiveStarRatingScheme"); + Object myRating = null; + String ratedAt = null; + if(fiveStarRating != null) + { + myRating = fiveStarRating.getScore(); + Date rateTime = fiveStarRating.getAppliedAt(); + ratedAt = PublicApiDateFormat.getDateFormat().format(rateTime); + } + int ratingsCount = ratingService.getRatingsCount(nodeRef, "fiveStarRatingScheme"); + float averageRating = ratingService.getAverageRating(nodeRef, "fiveStarRatingScheme"); + Aggregate aggregate = new Aggregate(ratingsCount, averageRating == -1 ? null : averageRating); + ratings.add(new NodeRating(nodeRef.getId(), "fiveStar", ratedAt, myRating, aggregate)); + } + + return ratings; + } + + }, personId, networkId); + + Collections.sort(ratings); + + return ratings; + } + + public int numRatingSchemes() + { + return ratingService.getRatingSchemes().size(); + } + + public NodeRef addToDocumentLibrary(TestSite site, String name, QName type) + { + NodeRef documentLibraryContainerNodeRef = siteService.getContainer(site.getSiteId(), "documentLibrary"); + NodeRef nodeRef = fileFolderService.create(documentLibraryContainerNodeRef, name, type).getNodeRef(); + return nodeRef; + } + + public String getSiteNetwork(final String siteShortName, String tenantDomain) + { + return TenantUtil.runAsTenant(new TenantRunAsWork() + { + @Override + public String doWork() throws Exception + { + return tenantService.getName(siteShortName); + } + }, tenantDomain); + } + + public void postActivity(final String activityType, final String siteId, final JSONObject activityData) throws JobExecutionException + { + activityService.postActivity(activityType, siteId, "documentlibrary", activityData.toString()); + } + + public NodeRef createDocument(final NodeRef parentNodeRef, final String name, final String content) + { + NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_CONTENT).getNodeRef(); + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + writer.putContent(content); + + return nodeRef; + } + + public NodeRef createDocument(final NodeRef parentNodeRef, final String name, final String title, final String description, final String content) + { + NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_CONTENT).getNodeRef(); + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + writer.putContent(content); + nodeService.setProperty(nodeRef, ContentModel.PROP_TITLE, title); + nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, description); + + return nodeRef; + } + + public NodeRef createFolder(final NodeRef parentNodeRef, final String name) + { + NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_FOLDER).getNodeRef(); + return nodeRef; + } + + public NodeRef createFolder(final NodeRef parentNodeRef, final String name, final String title, final String description) + { + NodeRef nodeRef = fileFolderService.create(parentNodeRef, name, ContentModel.TYPE_FOLDER).getNodeRef(); + nodeService.setProperty(nodeRef, ContentModel.PROP_TITLE, title); + nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, description); + + return nodeRef; + } + + public NodeRef createCmObject(final NodeRef parentNodeRef, final String name) + { + QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)); + NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, ContentModel.TYPE_CMOBJECT).getChildRef(); + + return nodeRef; + } + + public NodeRef createObjectOfCustomType(final NodeRef parentNodeRef, final String name, final String typeName) + { + QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)); + QName typeQName = QName.createQName(typeName); + NodeRef nodeRef = nodeService.createNode(parentNodeRef, ContentModel.ASSOC_CONTAINS, assocQName, typeQName).getChildRef(); + + return nodeRef; + } + + public Visibility getVisibility(Client client, NodeRef nodeRef) + { + return hiddenAspect.getVisibility(client, nodeRef); + } + + public void addAspect(NodeRef nodeRef, QName aspectTypeQName, Map aspectProperties) + { + nodeService.addAspect(nodeRef, aspectTypeQName, aspectProperties); + } + + public NodeRef createComment(NodeRef nodeRef, final Comment comment) + { + NodeRef commentNodeRef = commentService.createComment(nodeRef, comment.getTitle(), comment.getContent(), false); + comment.setId(commentNodeRef.getId()); + Date created = (Date)nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATED); + comment.setCreatedAt(PublicApiDateFormat.getDateFormat().format(created)); + TestPerson person = getPerson((String)nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATOR)); + comment.setCreatedBy(person); + return commentNodeRef; + } + + public TestNetwork createNetworkWithAlias(String alias, boolean enabled) + { + String networkId = alias + "-" + System.currentTimeMillis(); + TestNetwork network = new TestNetwork(networkId, enabled); + return network; + } + + public TestNetwork createNetwork(String networkId, boolean enabled) + { + TestNetwork network = new TestNetwork(networkId, enabled); + return network; + } + + public class TestSite extends SiteImpl + { + private static final long serialVersionUID = 5317623044880374281L; + + private TestNetwork account; + private SiteInfo siteInfo; + + public TestSite(TestNetwork account, SiteInfo siteInfo) + { + this(account, siteInfo.getShortName(), siteInfo.getNodeRef().getId(), siteInfo.getTitle(), siteInfo.getDescription(), siteInfo.getVisibility()); + this.account = account; + this.siteInfo = siteInfo; + } + + public TestSite(TestNetwork account, String siteId, String guid, String title, String description, SiteVisibility siteVisibility) + { + super((account == null ? null : account.getId()), siteId, guid); + setTitle(title); + setDescription(description); + setVisibility(siteVisibility.toString()); + this.siteInfo = siteService.getSite(siteId); + } + + public SiteInfo getSiteInfo() + { + return siteInfo; + } + public NodeRef getContainerNodeRef(String containerId) + { + return siteService.getContainer(siteId, containerId); + } + + public NodeRef createContainer(String containerName) + { + return siteService.createContainer(getSiteId(), containerName, ContentModel.TYPE_FOLDER, null); + } + + public void inviteToSite(final String toInvite, final SiteRole siteRole) + { + siteService.setMembership(getSiteId(), toInvite, siteRole.toString()); + log(toInvite + " invited to site " + getSiteId()); + } + + public TestNetwork getAccount() + { + return account; + } + + public Map getMembers(final String roleFilter) + { + Map members = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() + { + @Override + public Map doWork() throws Exception + { + Map members = siteService.listMembers(getSiteId(), null, roleFilter, 0); + return members; + } + }, getAccount().getId()); + return members; + } + + public List getMembers() + { + Map members = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() + { + @Override + public Map doWork() throws Exception + { + // get all site members + Map members = siteService.listMembers(getSiteId(), null, null, 0); + return members; + } + }, getAccount().getId()); + List ret = new ArrayList(members.size()); + for(String userId : members.keySet()) + { + String role = members.get(userId); + TestPerson person = RepoService.this.getPerson(userId); + SiteMember sm = new SiteMember(userId, person, getSiteId(), role); + ret.add(sm); + } + Collections.sort(ret); + return ret; + } + + public boolean isMember(final String personId) + { + Boolean isMember = TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + return siteService.isMember(getSiteId(), personId); + } + }, getAccount().getId()); + return isMember; + } + + public SiteRole getMember(String personId) + { + return SiteRole.valueOf(siteService.getMembersRole(getSiteId(), personId)); + } + + public void updateMember(String personId, SiteRole role) + { + siteService.setMembership(getSiteId(), personId, role.toString()); + } + + public void removeMember(String personId) + { + if(siteService.isMember(getSiteId(), personId)) + { + siteService.removeMembership(getSiteId(), personId); + } + } + + public void setSiteVisibility(SiteVisibility siteVisibility) + { + this.visibility = siteVisibility.toString(); + siteInfo.setVisibility(siteVisibility); + siteService.updateSite(siteInfo); + } + + @Override + public String toString() { + return "TestSite [siteid=" + getSiteId() + ", title=" + getTitle() + + ", description=" + getDescription() + ", siteVisibility=" + + getVisibility() + "]"; + } + } + + public static Iterator getWrappingIterator(final int startIdx, final List list) + { + return new AbstractIterator() + { + private int idx = Math.max(0, Math.min(startIdx, list.size() - 1)); + + @Override + protected T computeNext() + { + T o = list.get(idx); + + idx++; + if(idx >= list.size()) + { + idx = 0; + } + + return o; + } + }; + } + + public class TestNetwork extends NetworkImpl implements Comparable + { + private static final long serialVersionUID = -107881141652228471L; + + protected Map people = new TreeMap(); + protected TreeMap sites = new TreeMap(); + protected Set publicSites = new TreeSet(); + + public TestNetwork(String domain, boolean enabled) + { + super(domain, enabled); + } + + public void create() + { + if(!getId().equals(TenantService.DEFAULT_DOMAIN) && !tenantAdminService.existsTenant(getId())) + { + tenantAdminService.createTenant(getId(), "admin".toCharArray()); + numNetworks++; + log("Created network " + getId()); + } + } + + public TestSite createSite(SiteVisibility siteVisibility) + { + String shortName = "TESTSITE" + GUID.generate(); + SiteInformation siteInfo = new SiteInformation(shortName, shortName, shortName, siteVisibility); + return createSite(siteInfo); + } + + public TestSite createSite(final SiteInformation site) + { + TestSite testSite = RepoService.this.createSite(this, site); + addSite(testSite); + + return testSite; + } + + public TestPerson createUser() + { + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo("FirstName", "LastName", username, "password", null, "skype", "location", + "telephone", "mob", "instant", "google"); + TestPerson person = createUser(personInfo); + return person; + } + + public NodeRef addUserDescription(final String personId, final String personDescription) + { + NodeRef personRef = TenantUtil.runAsTenant(new TenantRunAsWork() + { + public NodeRef doWork() throws Exception + { + return RepoService.this.addUserDescription(personId, TestNetwork.this, personDescription); + } + }, getId()); + + return personRef; + } + + public TestPerson createUser(final PersonInfo personInfo) + { + final String username = publicApiContext.createUserName(personInfo.getUsername(), getId()); + TestPerson testPerson = TenantUtil.runAsTenant(new TenantRunAsWork() + { + public TestPerson doWork() throws Exception + { + TestPerson person = RepoService.this.createUser(personInfo, username, TestNetwork.this); + + return person; + } + }, getId()); + addPerson(testPerson); + return testPerson; + } + + public List peopleSample(int sampleSize) + { + final List p = new ArrayList(); + + if(sampleSize < 0) + { + p.addAll(people.keySet()); + } + else + { + int startIdx = random.nextInt(people.size()); + List peopleList = new ArrayList(people.keySet()); + Iterator it = getWrappingIterator(startIdx, peopleList); + + for(int i = 0; i < sampleSize && it.hasNext(); i++) + { + p.add(it.next()); + } + } + + return p; + } + + // Return a site of which person is not a member + public TestSite getSiteNonMember(final String personId) + { + return TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite ret = null; + SiteInfo match = null; + for(SiteInfo info : siteService.listSites(null, null)) + { + boolean isMember = siteService.isMember(info.getShortName(), personId); + if(!isMember) + { + match = info; + break; + } + } + + if(match != null) + { + ret = new TestSite(TestNetwork.this, match); + } + + return ret; + } + }, getId()); + } + + public void addSite(TestSite site) + { + sites.put(site.getSiteId(), site); + if(site.getVisibility().equals(SiteVisibility.PUBLIC.toString())) + { + publicSites.add(site); + } + } + + public Set getPublicSites() + { + return publicSites; + } + + public TestSite getSite(final String siteShortName) + { + TestSite site = TenantUtil.runAsTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + SiteInfo siteInfo = siteService.getSite(siteShortName); + return new TestSite(TestNetwork.this, siteInfo); + } + }, getId()); + return site; + } + + /* + * List sites in this account that person can see + */ + public List getSites(String personId) + { + List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List results = siteService.listSites(null, null); + TreeMap ret = new TreeMap(); + for(SiteInfo siteInfo : results) + { + TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); + ret.put(site.getSiteId(), site); + } + + return new ArrayList(ret.values()); + } + }, personId, getId()); + return sites; + } + + public List getAllSites() + { + List sites = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List results = siteService.listSites(null, null); + TreeMap ret = new TreeMap(); + for(SiteInfo siteInfo : results) + { + TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); + ret.put(site.getSiteId(), site); + } + + return new ArrayList(ret.values()); + } + }, getId()); + return sites; + } + + public List getSiteContainers(final String siteId, TestPerson runAs) + { + List siteContainers = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + PagingResults results = siteService.listContainers(siteId, new PagingRequest(0, Integer.MAX_VALUE)); + List ret = new ArrayList(results.getPage().size()); + for(FileInfo fileInfo : results.getPage()) + { + SiteContainer siteContainer = new SiteContainer(siteId, fileInfo.getName(), fileInfo.getNodeRef().getId()); + ret.add(siteContainer); + } + + return ret; + } + }, runAs.getId(), getId()); + + return siteContainers; + } + + public Map getSitesForUser(String username) + { + if(username == null) + { + username = AuthenticationUtil.getAdminUserName(); + } + List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List results = siteService.listSites(null, null); + return results; + } + }, username, getId()); + TreeMap ret = new TreeMap(); + for(SiteInfo siteInfo : sites) + { + TestSite site = new TestSite(TestNetwork.this, siteInfo/*, null*/); + ret.put(site.getSiteId(), site); + } + return ret; + } + + public List getSiteMemberships(String username) + { + if(username == null) + { + username = AuthenticationUtil.getAdminUserName(); + } + final String userId = username; + List sites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List sites = siteService.listSites(userId); + Set personSites = new TreeSet(); + for(SiteInfo siteInfo : sites) + { + TestSite site = getSite(siteInfo.getShortName()); + String role = siteService.getMembersRole(siteInfo.getShortName(), userId); + MemberOfSite ms = new MemberOfSite(site, SiteRole.valueOf(role)); + personSites.add(ms); + } + + return new ArrayList(personSites); + } + }, userId, getId()); + return sites; + } + + public Map getSites(SiteVisibility siteVisibility) + { + Map ret = new HashMap(); + for(String key : getSitesForUser(null).keySet()) + { + TestSite site = getSitesForUser(null).get(key); + if(site.getVisibility().equals(siteVisibility.toString())) + { + ret.put(key, site); + } + } + return ret; + } + + public void addPerson(TestPerson person) + { + people.put(person.getId(), person); + } + + public List getPersonIds() + { + return new ArrayList(people.keySet()); + } + + public List getPeople() + { + return new ArrayList(people.values()); + } + + public int compareTo(TestNetwork o) + { + return getId().compareTo(o.getId()); + } + + public void addExternalUser(String personId) + { + throw new UnsupportedOperationException(); + } + + public TestSite homeSite(TestPerson person) + { + throw new UnsupportedOperationException(); + } + + public void inviteUser(final String user) + { + throw new UnsupportedOperationException(); + } + + public Collection getHomeSites() + { + throw new UnsupportedOperationException(); + } + + public Long getAccountId() + { + throw new UnsupportedOperationException(); + } + + public void setAccountId(Long accountId) + { + throw new UnsupportedOperationException(); + } + + public int getType() + { + throw new UnsupportedOperationException(); + } + + public void addNetworkAdmin(String email) + { + throw new UnsupportedOperationException(); + } + + public Set getNetworkAdmins() + { + throw new UnsupportedOperationException(); + } + + public Set getNonNetworkAdmins() + { + throw new UnsupportedOperationException(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((getId() == null) ? 0 : getId().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + { + return true; + } + + if(obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + TestNetwork other = (TestNetwork) obj; + return getId().equals(other.getId()); + } + + public TestSite getSite(SiteVisibility siteVisibility) + { + TestSite ret = null; + for(TestSite site : getSitesForUser(null).values()) + { + if(site.getVisibility().equals(siteVisibility)) + { + ret = site; + break; + } + } + return ret; + } + + @Override + public String toString() + { + return "TestNetwork [people=" + people + ", sites=" + sites + + ", publicSites=" + publicSites + "]"; + } + } + + public static class SiteMembership implements Comparable + { + private TestSite site; + private SiteRole role; + + public SiteMembership(TestSite site, SiteRole role) + { + super(); + if(site == null) + { + throw new IllegalArgumentException(); + } + if(role == null) + { + throw new IllegalArgumentException(); + } + this.site = site; + this.role = role; + } + + public TestSite getSite() + { + return site; + } + + public SiteRole getRole() + { + return role; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((role == null) ? 0 : role.hashCode()); + result = prime * result + ((site == null) ? 0 : site.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + SiteMembership other = (SiteMembership) obj; + if (role != other.role) + { + return false; + } + + return site.equals(other.site); + } + + @Override + public int compareTo(SiteMembership siteMembership) + { + int ret = site.getSiteId().compareTo(siteMembership.getSite().getSiteId()); + if(ret == 0) + { + // arbitrary sorting on site role + ret = role.compareTo(siteMembership.getRole()); + } + return ret; + } + } + + // order by last name, first name, role + public class TestPerson extends Person + { + private static final long serialVersionUID = 4038390056182705588L; + + protected boolean enabled; + protected String password; + protected TestNetwork defaultAccount; + protected TreeMap siteMemberships = new TreeMap(); + + public TestPerson(String firstName, String lastName, String username, String password, Company company, TestNetwork defaultAccount, String skype, String location, String tel, + String mob, String instantmsg, String google) + { + super(username, username, true, firstName, lastName, company, skype, location, tel, mob, instantmsg, google, null); + this.password = password; + this.enabled = true; + this.defaultAccount = defaultAccount; + } + + public boolean isNetworkAdmin() + { + return false; // cloud only + } + + public String getDefaultDomain() + { + return defaultAccount == null ? null : defaultAccount.getId(); + } + + public boolean isEnabled() + { + return enabled; + } + + public void addSiteMembership(TestSite site, SiteRole siteRole) + { + siteMemberships.put(site, siteRole); + } + + public TestNetwork getDefaultAccount() + { + return defaultAccount; + } + + public String getPassword() + { + return password; + } + + public List getNetworkMemberships() + { + String personId = getId(); + String runAsNetworkId = Person.getNetworkId(personId); + return TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List members = new ArrayList(); + PagingResults networks = networksService.getNetworks(new PagingRequest(0, Integer.MAX_VALUE)); + for(Network network : networks.getPage()) + { + NetworkImpl restNetwork = new NetworkImpl(network); + PersonNetwork personNetwork = new PersonNetwork(network.getIsHomeNetwork(), restNetwork); + members.add(personNetwork); + } + return members; + } + }, personId, runAsNetworkId); + } + + @Override + public String toString() + { + return "TestPerson [enabled=" + enabled + ", password=" + password + + ", defaultAccount=" + defaultAccount.getId() + ", siteMemberships=" + siteMemberships + + ", getId()=" + getId() + ", getFirstName()=" + + getFirstName() + ", getCompany()=" + getCompany() + + ", getLastName()=" + getLastName() + "]"; + } + } + + public static class SiteInformation implements Comparable + { + private String shortName; + private String title; + private String sitePreset; + private String description; + private SiteVisibility siteVisibility; + + public SiteInformation(String shortName, String title, String description, SiteVisibility siteVisibility) + { + super(); + if(shortName == null) + { + throw new IllegalArgumentException(); + } + this.shortName = shortName; + this.title = title; + this.description = description; + this.siteVisibility = siteVisibility; + } + + public String getShortName() + { + return shortName; + } + + public String getTitle() + { + return title; + } + + public String getSitePreset() + { + return sitePreset; + } + + public String getDescription() + { + return description; + } + + public SiteVisibility getSiteVisibility() + { + return siteVisibility; + } + + public boolean equals(Object other) + { + if(this == other) + { + return true; + } + + if(!(other instanceof SiteInformation)) + { + return false; + } + + SiteInformation site = (SiteInformation)other; + return shortName == site.getShortName(); + } + + @Override + public int compareTo(SiteInformation site) + { + return shortName.compareTo(site.getShortName()); + } + + public int hashCode() + { + return getShortName().hashCode(); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/RestApiHttpClient.java b/source/test-java/org/alfresco/rest/api/tests/RestApiHttpClient.java index 24f6307765..f2427ced7b 100644 --- a/source/test-java/org/alfresco/rest/api/tests/RestApiHttpClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/RestApiHttpClient.java @@ -1,400 +1,400 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.MessageFormat; -import java.util.Map; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.web.scripts.TenantWebScriptServlet; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.framework.Api; -import org.alfresco.rest.framework.Api.SCOPE; -import org.alfresco.rest.framework.core.ResourceInspector; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.service.cmr.repository.NodeRef; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.UsernamePasswordCredentials; -import org.apache.commons.httpclient.auth.AuthScope; -import org.apache.commons.httpclient.methods.DeleteMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.PutMethod; -import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.apache.commons.httpclient.params.HttpClientParams; -import org.apache.commons.httpclient.params.HttpConnectionManagerParams; -import org.apache.commons.httpclient.params.HttpConnectionParams; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; - -/** - * A http client for talking to the rest apis. - * - * The caller can pass in a rest api implementation class to the http method (get, post, put, delete supported) - * and the url will be generated. - * - * @author steveglover - * - */ -public class RestApiHttpClient -{ -/* private static final Log logger = LogFactory.getLog(RestApiHttpClient.class); - - private static final String INDEX_URL = "http://{0}:{1}{2}/a"; - private static final String BASE_URL = "http://{0}:{1}{2}/a/{3}/{4}/alfresco/versions/1/"; - - private String host = "localhost"; - private int port = 8081; - private HttpClient httpClient; - - private int maxTotalConnections = 255; - private int maxHostConnections = 255; - - private String contextPath; - - private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); - - public RestApiHttpClient() - { - } - - public RestApiHttpClient(String host, int port, String contextPath) - { - super(); - this.host = host; - this.port = port; - this.contextPath = contextPath; - constructHttpClient(); - } - - public void setHost(String host) - { - this.host = host; - } - - public void setPort(int port) - { - this.port = port; - } - - public void setContextPath(String contextPath) - { - this.contextPath = contextPath; - } - - public void init() - { - constructHttpClient(); - } - - private void log(String msg) - { - if(logger.isDebugEnabled()) - { - logger.debug(msg); - } - } - - protected void constructHttpClient() - { - MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); - this.httpClient = new HttpClient(connectionManager); - HttpClientParams params = httpClient.getParams(); - params.setBooleanParameter(HttpConnectionParams.TCP_NODELAY, true); - params.setBooleanParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, false); - HttpConnectionManagerParams connectionManagerParams = httpClient.getHttpConnectionManager().getParams(); - connectionManagerParams.setMaxTotalConnections(maxTotalConnections); - connectionManagerParams.setDefaultMaxConnectionsPerHost(maxHostConnections); - - httpClient.getHostConfiguration().setHost(host, port); - httpClient.getParams().setAuthenticationPreemptive(true); - } - - protected AnnotationMetadata getAnnotationMetadata(String classname) throws IOException - { - MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(classname); - AnnotationMetadata annotationMetaData = metadataReader.getAnnotationMetadata(); - return annotationMetaData; - } - - public JSONObject submitRequest(HttpMethod req, String user, String password, int expectedStatus) throws HttpException, IOException - { - String contentAsString = null; - - try - { - httpClient.getState().setCredentials( - new AuthScope(host, port, null), - new UsernamePasswordCredentials(user, password) - ); - - httpClient.getParams().setAuthenticationPreemptive(true); - - String requestBody = null; - if(req instanceof PostMethod) - { - PostMethod post = (PostMethod)req; - RequestEntity entity = post.getRequestEntity(); - if(entity != null) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - entity.writeRequest(bos); - requestBody = new String(bos.toByteArray(), "UTF-8"); - } - } - else if(req instanceof PutMethod) - { - PutMethod put = (PutMethod)req; - RequestEntity entity = put.getRequestEntity(); - if(entity != null) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - entity.writeRequest(bos); - requestBody = new String(bos.toByteArray(), "UTF-8"); - } - } - - long start = System.currentTimeMillis(); - - int ret = httpClient.executeMethod(req); - - long end = System.currentTimeMillis(); - - contentAsString = req.getResponseBodyAsString(); - - log(req.getName() + " request " + req.getURI().toString()); - log(requestBody != null ? " \nbody = " + requestBody + "\n" : ""); - log("user " + user); - log(" returned " + ret + " and took " + (end - start) + "ms"); - log("Response content " + contentAsString); - - assertEquals(expectedStatus, ret); - } - finally - { - if(req != null) - { - req.releaseConnection(); - } - } - - JSONObject jsonRsp = (contentAsString != null ? (JSONObject)JSONValue.parse(contentAsString) : null); - return jsonRsp; - } - - public JSONObject get(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, Map params, final int expectedStatus) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); - } - - public JSONObject post(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, final String body, final int expectedStatus) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if(body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); - } - - public JSONObject delete(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, Map params, final int expectedStatus) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, params); - String url = endpoint.getUrl(); - - DeleteMethod req = new DeleteMethod(url); - return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); - } - - public JSONObject put(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, final String body, final int expectedStatus) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, null); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url); - if(body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); - } - - - * Encapsulates information relating to a rest api end point, generating and encoding urls - * based on the rest api implementation class. - - private class RestApiEndpoint - { - private Object collectionEntityId; - private Object relationEntityId; - private String tenantDomain; - private Class resourceClass; - private SCOPE scope; - private Map params; - - private String entityCollectionName; - private String relationshipCollectionName; - - RestApiEndpoint(Class resourceClass, String tenantDomain, Object collectionEntityId, Object relationEntityId, Map params) throws IOException - { - this.tenantDomain = tenantDomain; - this.resourceClass = resourceClass; - this.collectionEntityId = collectionEntityId; - this.relationEntityId = relationEntityId; - this.params = params; - - if(resourceClass != null) - { - Api api = ResourceInspector.inspectApi(resourceClass); - this.scope = api.getScope(); - - extractRelationCollectionInfo(); - extractEntityCollectionInfo(); - } - } - - private String encodeToString(Object o) throws UnsupportedEncodingException - { - String ret = null; - - if(o instanceof NodeRef) - { - NodeRef nodeRef = (NodeRef)o; - ret = (o != null ? nodeRef.getId() : null); - } - else - { - ret = (o != null ? o.toString() : null); - } - - return ret; - } - - private void extractRelationCollectionInfo() throws IOException - { - AnnotationMetadata annotationMetaData = getAnnotationMetadata(resourceClass.getCanonicalName()); - if(annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) - { - if(annotationMetaData.getAnnotationTypes().contains(RelationshipResource.class.getCanonicalName())) - { - Map attrs = annotationMetaData.getAnnotationAttributes(RelationshipResource.class.getName()); - this.relationshipCollectionName = (String)attrs.get("name"); - Class entityResource = (Class)attrs.get("entityResource"); - - extractEntityCollectionInfo(entityResource.getCanonicalName()); - } - } - else - { - throw new AlfrescoRuntimeException(""); - } - } - - private void extractEntityCollectionInfo() throws IOException - { - extractEntityCollectionInfo(resourceClass.getCanonicalName()); - } - - private void extractEntityCollectionInfo(String className) throws IOException - { - AnnotationMetadata annotationMetaData = getAnnotationMetadata(className); - if(annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) - { - if(annotationMetaData.getAnnotationTypes().contains(EntityResource.class.getCanonicalName())) - { - Map attrs = annotationMetaData.getAnnotationAttributes(EntityResource.class.getName()); - this.entityCollectionName = (String)attrs.get("name"); - } - } - else - { - throw new AlfrescoRuntimeException(""); - } - } - - public String getUrl() throws UnsupportedEncodingException - { - StringBuilder sb = new StringBuilder(); - - if(resourceClass != null) - { - sb.append(MessageFormat.format(BASE_URL, new Object[] {host, String.valueOf(port), contextPath, - tenantDomain == null ? TenantWebScriptServlet.DEFAULT_TENANT : tenantDomain, scope.toString()})); - - String collectionEntityIdString = encodeToString(collectionEntityId); - String relationEntityIdString = encodeToString(relationEntityId); - - if(entityCollectionName != null) - { - sb.append(entityCollectionName); - sb.append("/"); - if(collectionEntityIdString != null) - { - sb.append(collectionEntityIdString); - sb.append("/"); - } - } - - if(relationshipCollectionName != null) - { - sb.append(relationshipCollectionName); - sb.append("/"); - if(relationEntityIdString != null) - { - sb.append(relationEntityIdString); - sb.append("/"); - } - } - } - else - { - sb.append(MessageFormat.format(INDEX_URL, new Object[] {host, String.valueOf(port), contextPath})); - } - - if(params != null && params.size() > 0) - { - sb.append("?"); - - for(String paramName : params.keySet()) - { - sb.append(URLEncoder.encode(paramName, "UTF-8")); - sb.append("="); - sb.append(URLEncoder.encode(params.get(paramName), "UTF-8")); - sb.append("&"); - } - - sb.deleteCharAt(sb.length() - 1); - } - - String url = sb.toString(); - return url; - } - }*/ -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.MessageFormat; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.web.scripts.TenantWebScriptServlet; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.Api.SCOPE; +import org.alfresco.rest.framework.core.ResourceInspector; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.service.cmr.repository.NodeRef; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; + +/** + * A http client for talking to the rest apis. + * + * The caller can pass in a rest api implementation class to the http method (get, post, put, delete supported) + * and the url will be generated. + * + * @author steveglover + * + */ +public class RestApiHttpClient +{ +/* private static final Log logger = LogFactory.getLog(RestApiHttpClient.class); + + private static final String INDEX_URL = "http://{0}:{1}{2}/a"; + private static final String BASE_URL = "http://{0}:{1}{2}/a/{3}/{4}/alfresco/versions/1/"; + + private String host = "localhost"; + private int port = 8081; + private HttpClient httpClient; + + private int maxTotalConnections = 255; + private int maxHostConnections = 255; + + private String contextPath; + + private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); + + public RestApiHttpClient() + { + } + + public RestApiHttpClient(String host, int port, String contextPath) + { + super(); + this.host = host; + this.port = port; + this.contextPath = contextPath; + constructHttpClient(); + } + + public void setHost(String host) + { + this.host = host; + } + + public void setPort(int port) + { + this.port = port; + } + + public void setContextPath(String contextPath) + { + this.contextPath = contextPath; + } + + public void init() + { + constructHttpClient(); + } + + private void log(String msg) + { + if(logger.isDebugEnabled()) + { + logger.debug(msg); + } + } + + protected void constructHttpClient() + { + MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); + this.httpClient = new HttpClient(connectionManager); + HttpClientParams params = httpClient.getParams(); + params.setBooleanParameter(HttpConnectionParams.TCP_NODELAY, true); + params.setBooleanParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, false); + HttpConnectionManagerParams connectionManagerParams = httpClient.getHttpConnectionManager().getParams(); + connectionManagerParams.setMaxTotalConnections(maxTotalConnections); + connectionManagerParams.setDefaultMaxConnectionsPerHost(maxHostConnections); + + httpClient.getHostConfiguration().setHost(host, port); + httpClient.getParams().setAuthenticationPreemptive(true); + } + + protected AnnotationMetadata getAnnotationMetadata(String classname) throws IOException + { + MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(classname); + AnnotationMetadata annotationMetaData = metadataReader.getAnnotationMetadata(); + return annotationMetaData; + } + + public JSONObject submitRequest(HttpMethod req, String user, String password, int expectedStatus) throws HttpException, IOException + { + String contentAsString = null; + + try + { + httpClient.getState().setCredentials( + new AuthScope(host, port, null), + new UsernamePasswordCredentials(user, password) + ); + + httpClient.getParams().setAuthenticationPreemptive(true); + + String requestBody = null; + if(req instanceof PostMethod) + { + PostMethod post = (PostMethod)req; + RequestEntity entity = post.getRequestEntity(); + if(entity != null) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + entity.writeRequest(bos); + requestBody = new String(bos.toByteArray(), "UTF-8"); + } + } + else if(req instanceof PutMethod) + { + PutMethod put = (PutMethod)req; + RequestEntity entity = put.getRequestEntity(); + if(entity != null) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + entity.writeRequest(bos); + requestBody = new String(bos.toByteArray(), "UTF-8"); + } + } + + long start = System.currentTimeMillis(); + + int ret = httpClient.executeMethod(req); + + long end = System.currentTimeMillis(); + + contentAsString = req.getResponseBodyAsString(); + + log(req.getName() + " request " + req.getURI().toString()); + log(requestBody != null ? " \nbody = " + requestBody + "\n" : ""); + log("user " + user); + log(" returned " + ret + " and took " + (end - start) + "ms"); + log("Response content " + contentAsString); + + assertEquals(expectedStatus, ret); + } + finally + { + if(req != null) + { + req.releaseConnection(); + } + } + + JSONObject jsonRsp = (contentAsString != null ? (JSONObject)JSONValue.parse(contentAsString) : null); + return jsonRsp; + } + + public JSONObject get(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, Map params, final int expectedStatus) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); + } + + public JSONObject post(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, final String body, final int expectedStatus) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if(body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); + } + + public JSONObject delete(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, Map params, final int expectedStatus) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, params); + String url = endpoint.getUrl(); + + DeleteMethod req = new DeleteMethod(url); + return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); + } + + public JSONObject put(final Class c, final String tenantDomain, final TestPerson runAsUser, final Object entityId, final Object relationshipEntityId, final String body, final int expectedStatus) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, tenantDomain, entityId, relationshipEntityId, null); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if(body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, runAsUser.getUsername(), runAsUser.getPassword(), expectedStatus); + } + + + * Encapsulates information relating to a rest api end point, generating and encoding urls + * based on the rest api implementation class. + + private class RestApiEndpoint + { + private Object collectionEntityId; + private Object relationEntityId; + private String tenantDomain; + private Class resourceClass; + private SCOPE scope; + private Map params; + + private String entityCollectionName; + private String relationshipCollectionName; + + RestApiEndpoint(Class resourceClass, String tenantDomain, Object collectionEntityId, Object relationEntityId, Map params) throws IOException + { + this.tenantDomain = tenantDomain; + this.resourceClass = resourceClass; + this.collectionEntityId = collectionEntityId; + this.relationEntityId = relationEntityId; + this.params = params; + + if(resourceClass != null) + { + Api api = ResourceInspector.inspectApi(resourceClass); + this.scope = api.getScope(); + + extractRelationCollectionInfo(); + extractEntityCollectionInfo(); + } + } + + private String encodeToString(Object o) throws UnsupportedEncodingException + { + String ret = null; + + if(o instanceof NodeRef) + { + NodeRef nodeRef = (NodeRef)o; + ret = (o != null ? nodeRef.getId() : null); + } + else + { + ret = (o != null ? o.toString() : null); + } + + return ret; + } + + private void extractRelationCollectionInfo() throws IOException + { + AnnotationMetadata annotationMetaData = getAnnotationMetadata(resourceClass.getCanonicalName()); + if(annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) + { + if(annotationMetaData.getAnnotationTypes().contains(RelationshipResource.class.getCanonicalName())) + { + Map attrs = annotationMetaData.getAnnotationAttributes(RelationshipResource.class.getName()); + this.relationshipCollectionName = (String)attrs.get("name"); + Class entityResource = (Class)attrs.get("entityResource"); + + extractEntityCollectionInfo(entityResource.getCanonicalName()); + } + } + else + { + throw new AlfrescoRuntimeException(""); + } + } + + private void extractEntityCollectionInfo() throws IOException + { + extractEntityCollectionInfo(resourceClass.getCanonicalName()); + } + + private void extractEntityCollectionInfo(String className) throws IOException + { + AnnotationMetadata annotationMetaData = getAnnotationMetadata(className); + if(annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) + { + if(annotationMetaData.getAnnotationTypes().contains(EntityResource.class.getCanonicalName())) + { + Map attrs = annotationMetaData.getAnnotationAttributes(EntityResource.class.getName()); + this.entityCollectionName = (String)attrs.get("name"); + } + } + else + { + throw new AlfrescoRuntimeException(""); + } + } + + public String getUrl() throws UnsupportedEncodingException + { + StringBuilder sb = new StringBuilder(); + + if(resourceClass != null) + { + sb.append(MessageFormat.format(BASE_URL, new Object[] {host, String.valueOf(port), contextPath, + tenantDomain == null ? TenantWebScriptServlet.DEFAULT_TENANT : tenantDomain, scope.toString()})); + + String collectionEntityIdString = encodeToString(collectionEntityId); + String relationEntityIdString = encodeToString(relationEntityId); + + if(entityCollectionName != null) + { + sb.append(entityCollectionName); + sb.append("/"); + if(collectionEntityIdString != null) + { + sb.append(collectionEntityIdString); + sb.append("/"); + } + } + + if(relationshipCollectionName != null) + { + sb.append(relationshipCollectionName); + sb.append("/"); + if(relationEntityIdString != null) + { + sb.append(relationEntityIdString); + sb.append("/"); + } + } + } + else + { + sb.append(MessageFormat.format(INDEX_URL, new Object[] {host, String.valueOf(port), contextPath})); + } + + if(params != null && params.size() > 0) + { + sb.append("?"); + + for(String paramName : params.keySet()) + { + sb.append(URLEncoder.encode(paramName, "UTF-8")); + sb.append("="); + sb.append(URLEncoder.encode(params.get(paramName), "UTF-8")); + sb.append("&"); + } + + sb.deleteCharAt(sb.length() - 1); + } + + String url = sb.toString(); + return url; + } + }*/ +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestActivities.java b/source/test-java/org/alfresco/rest/api/tests/TestActivities.java index 3a36c54724..65690a202c 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestActivities.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestActivities.java @@ -1,854 +1,854 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.Activities.ActivityWho; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Activity; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.json.simple.JSONObject; -import org.junit.Before; -import org.junit.Test; - -public class TestActivities extends EnterpriseTestApi -{ - private SiteService siteService; - - private TestNetwork network1; - private TestNetwork network2; - private TestNetwork defaultNetwork; - - private TestPerson person1; // network1 - private TestPerson person2; // network1 - private TestPerson person3; // network2 - private TestPerson person4; // defaultNetwork - private TestPerson person5; // defaultNetwork - - private TestSite testSite; // network1 - private TestSite testSite1; // network1 - private TestSite testSite2; // network2 - private TestSite testSite3; // defaultNetwork - - @Before - public void setup() throws Exception - { - this.network1 = repoService.createNetworkWithAlias("activitiesNetwork1", true); - this.network2 = repoService.createNetworkWithAlias("activitiesNetwork2", true); - this.defaultNetwork = repoService.createNetwork(TenantService.DEFAULT_DOMAIN, true); - siteService = (SiteService) applicationContext.getBean("SiteService"); - - try - { - AuthenticationUtil.pushAuthentication(); - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - network1.create(); - network2.create(); - defaultNetwork.create(); - } - finally - { - AuthenticationUtil.popAuthentication(); - } - - // Create some users and sites - final List people = new ArrayList(5); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - - return null; - } - }, network2.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = defaultNetwork.createUser(); - people.add(person); - person = defaultNetwork.createUser(); - people.add(person); - - return null; - } - }, defaultNetwork.getId()); - - this.person1 = people.get(0); - this.person2 = people.get(1); - this.person3 = people.get(2); - this.person4 = people.get(3); - this.person5 = people.get(4); - - this.testSite = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - site.inviteToSite(person2.getId(), SiteRole.SiteCollaborator); - - return site; - } - }, person1.getId(), network1.getId()); - } - }, false, true); - - this.testSite1 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network1.createSite(siteInfo); - } - }, person1.getId(), network1.getId()); - } - }, false, true); - - // create some activities against those sites - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @SuppressWarnings("unchecked") - @Override - public Void doWork() throws Exception - { - // ensure at least 3 activities - JSONObject activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite1.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite1.getSiteId(), activityData); - - return null; - } - }, person1.getId(), network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @SuppressWarnings("unchecked") - @Override - public Void doWork() throws Exception - { - // ensure at least 3 activities - JSONObject activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - return null; - } - }, person2.getId(), network1.getId()); - - // user generates activities in 2 networks - this.testSite2 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network2.createSite(siteInfo); - } - }, person3.getId(), network2.getId()); - } - }, false, true); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @SuppressWarnings("unchecked") - @Override - public Void doWork() throws Exception - { - // ensure at least 3 activities - JSONObject activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); - - return null; - } - }, person3.getId(), network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @SuppressWarnings("unchecked") - @Override - public Void doWork() throws Exception - { - // ensure at least 3 activities - JSONObject activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); - - activityData = new JSONObject(); - activityData.put("title", GUID.generate()); - activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); - repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); - - return null; - } - }, person3.getId(), network2.getId()); - - this.testSite3 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return defaultNetwork.createSite(siteInfo); - } - }, person4.getId(), defaultNetwork.getId()); - } - }, false, true); - - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @SuppressWarnings("unchecked") - @Override - public Void doWork() throws Exception - { - siteService.setMembership(testSite3.getSiteId(), person5.getId(), SiteModel.SITE_CONSUMER); - - return null; - } - }, person4.getId(), defaultNetwork.getId()); - - repoService.generateFeed(); - } - - @Test - public void testPersonActivities() throws Exception - { - People peopleProxy = publicApiClient.people(); - - //Test with default tenant domain. see ALF-20448 - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person5.getId(), null, false, true); - return activities; - } - }, person5.getId(), defaultNetwork.getId()); - - for(Activity activity: expectedActivities) - { - if(activity.getSiteId() == null) - { - fail("SiteId should present in user-joined activity."); - } - } - - { - int skipCount = 0; - int maxItems = expectedActivities.size(); - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("who", String.valueOf(ActivityWho.me)); - publicApiClient.setRequestContext(new RequestContext(defaultNetwork.getId(), person5.getId())); - ListResponse response = peopleProxy.getActivities(person5.getId(), params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - - } - - // Test Case cloud-2204 - // Test case cloud-1500 - // Test Case cloud-2216 - // paging - - // Test Case cloud-1500 - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("who", String.valueOf(ActivityWho.me)); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = peopleProxy.getActivities(person1.getId(), params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - - { - int skipCount = 2; - int maxItems = expectedActivities.size() - 2; - assertTrue(maxItems > 0); - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("who", String.valueOf(ActivityWho.me)); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = peopleProxy.getActivities(person1.getId(), params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - - // "-me-" user - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("who", String.valueOf(ActivityWho.me)); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = peopleProxy.getActivities(org.alfresco.rest.api.People.DEFAULT_USER, params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - } - - // unknown user - 404 - try - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - peopleProxy.getActivities(GUID.generate(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown site - 404 - try - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - Map params = createParams(paging, null); - params.put("siteId", GUID.generate()); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.getActivities(GUID.generate(), params); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // user from another network - 404 - try - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - peopleProxy.getActivities(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // another user from the same network - 403 - try - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - peopleProxy.getActivities(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - try - { - List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, true); - return activities; - } - }, person1.getId(), network1.getId()); - assertTrue(activities.size() > 0); - Activity activity = activities.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.remove("people", person1.getId(), "activities", String.valueOf(activity.getId()), "Unable to DELETE a person activity"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1500 - // other user activities - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List expectedActivities = repoService.getActivities(person1.getId(), null, true, false); - return expectedActivities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("who", String.valueOf(ActivityWho.others)); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = peopleProxy.getActivities(person1.getId(), params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - - // all activities with siteId exclusion - { - List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List expectedActivities = repoService.getActivities(person1.getId(), testSite.getSiteId(), false, false); - return expectedActivities; - } - }, person1.getId(), network1.getId()); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); - - Map params = createParams(paging, null); - params.put("siteId", testSite.getSiteId()); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = peopleProxy.getActivities(person1.getId(), params); - checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); - } - - // all activities with siteId exclusion, unknown site id - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - - Map params = createParams(paging, null); - params.put("siteId", GUID.generate()); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.getActivities(person1.getId(), params); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown person id - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - - Map params = createParams(paging, null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.getActivities(GUID.generate(), params); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid who parameter - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - - Map params = createParams(paging, null); - params.put("who", GUID.generate()); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.getActivities(person1.getId(), params); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1970 - // Not allowed methods -// try -// { -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); -// peopleProxy.create("people", person1.getId(), "activities", null, null, "Unable to POST to person activities"); -// fail(""); -// } -// catch(PublicApiException e) -// { -// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); -// } -// -// try -// { -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); -// peopleProxy.update("people", person1.getId(), "activities", null, null, "Unable to PUT person activities"); -// fail(""); -// } -// catch(PublicApiException e) -// { -// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); -// } -// -// try -// { -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); -// peopleProxy.remove("people", person1.getId(), "activities", null, "Unable to DELETE person activities"); -// fail(""); -// } -// catch(PublicApiException e) -// { -// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); -// } -// -// try -// { -// List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() -// { -// @Override -// public List doWork() throws Exception -// { -// List activities = repoService.getActivities(person1.getId(), null, false, true); -// return activities; -// } -// }, person1.getId(), network1.getId()); -// assertTrue(activities.size() > 0); -// Activity activity = activities.get(0); -// -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); -// peopleProxy.create("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to POST to a person activity"); -// fail(""); -// } -// catch(PublicApiException e) -// { -// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); -// } -// -// try -// { -// List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() -// { -// @Override -// public List doWork() throws Exception -// { -// List activities = repoService.getActivities(person1.getId(), null, false, true); -// return activities; -// } -// }, person1.getId(), network1.getId()); -// assertTrue(activities.size() > 0); -// Activity activity = activities.get(0); -// -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); -// peopleProxy.update("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to PUT a person activity"); -// fail(""); -// } -// catch(PublicApiException e) -// { -// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); -// } - - // Test Case cloud-1970 - // not allowed methods - { - List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List activities = repoService.getActivities(person1.getId(), null, false, false); - return activities; - } - }, person1.getId(), network1.getId()); - assertTrue(activities.size() > 0); - Activity activity = activities.get(0); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.create("people", person1.getId(), "activities", null, null, "Unable to POST to activities"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.create("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to POST to an activity"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.update("people", person1.getId(), "activities", null, null, "Unable to PUT activities"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.update("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to PUT an activity"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.remove("people", person1.getId(), "activities", null, "Unable to DELETE activities"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.remove("people", person1.getId(), "activities", String.valueOf(activity.getId()), "Unable to DELETE an activity"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - } - - /* - * Test that empty roles are not returned - */ - @Test - public void testPUBLICAPI23() throws Exception - { - // Add and then remove personId as a member of the public site - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - testSite.updateMember(person2.getId(), SiteRole.SiteConsumer); - testSite.removeMember(person2.getId()); - - return null; - } - }, person1.getId(), network1.getId()); - - // make sure activities have been generated - repoService.generateFeed(); - - // check that (empty) role is not in the response - - People peopleProxy = publicApiClient.people(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - - int skipCount = 0; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems); - ListResponse activities = peopleProxy.getActivities(person2.getId(), createParams(paging, null)); - for(Activity activity : activities.getList()) - { - String activityType = activity.getActivityType(); - if(activityType.equals("org.alfresco.site.user-left")) - { - String role = (String)activity.getSummary().get("role"); - String feedPersonId = activity.getFeedPersonId(); - if(feedPersonId.equals(person2.getId())) - { - assertTrue(role == null); - break; - } - } - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.Activities.ActivityWho; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Activity; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; + +public class TestActivities extends EnterpriseTestApi +{ + private SiteService siteService; + + private TestNetwork network1; + private TestNetwork network2; + private TestNetwork defaultNetwork; + + private TestPerson person1; // network1 + private TestPerson person2; // network1 + private TestPerson person3; // network2 + private TestPerson person4; // defaultNetwork + private TestPerson person5; // defaultNetwork + + private TestSite testSite; // network1 + private TestSite testSite1; // network1 + private TestSite testSite2; // network2 + private TestSite testSite3; // defaultNetwork + + @Before + public void setup() throws Exception + { + this.network1 = repoService.createNetworkWithAlias("activitiesNetwork1", true); + this.network2 = repoService.createNetworkWithAlias("activitiesNetwork2", true); + this.defaultNetwork = repoService.createNetwork(TenantService.DEFAULT_DOMAIN, true); + siteService = (SiteService) applicationContext.getBean("SiteService"); + + try + { + AuthenticationUtil.pushAuthentication(); + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + network1.create(); + network2.create(); + defaultNetwork.create(); + } + finally + { + AuthenticationUtil.popAuthentication(); + } + + // Create some users and sites + final List people = new ArrayList(5); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + + return null; + } + }, network2.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = defaultNetwork.createUser(); + people.add(person); + person = defaultNetwork.createUser(); + people.add(person); + + return null; + } + }, defaultNetwork.getId()); + + this.person1 = people.get(0); + this.person2 = people.get(1); + this.person3 = people.get(2); + this.person4 = people.get(3); + this.person5 = people.get(4); + + this.testSite = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + site.inviteToSite(person2.getId(), SiteRole.SiteCollaborator); + + return site; + } + }, person1.getId(), network1.getId()); + } + }, false, true); + + this.testSite1 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network1.createSite(siteInfo); + } + }, person1.getId(), network1.getId()); + } + }, false, true); + + // create some activities against those sites + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @SuppressWarnings("unchecked") + @Override + public Void doWork() throws Exception + { + // ensure at least 3 activities + JSONObject activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite1.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite1.getSiteId(), activityData); + + return null; + } + }, person1.getId(), network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @SuppressWarnings("unchecked") + @Override + public Void doWork() throws Exception + { + // ensure at least 3 activities + JSONObject activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + return null; + } + }, person2.getId(), network1.getId()); + + // user generates activities in 2 networks + this.testSite2 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network2.createSite(siteInfo); + } + }, person3.getId(), network2.getId()); + } + }, false, true); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @SuppressWarnings("unchecked") + @Override + public Void doWork() throws Exception + { + // ensure at least 3 activities + JSONObject activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite.getSiteId(), activityData); + + return null; + } + }, person3.getId(), network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @SuppressWarnings("unchecked") + @Override + public Void doWork() throws Exception + { + // ensure at least 3 activities + JSONObject activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); + + activityData = new JSONObject(); + activityData.put("title", GUID.generate()); + activityData.put("nodeRef", testSite2.getContainerNodeRef("documentLibrary").toString()); + repoService.postActivity("org.alfresco.documentlibrary.file-added", testSite2.getSiteId(), activityData); + + return null; + } + }, person3.getId(), network2.getId()); + + this.testSite3 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return defaultNetwork.createSite(siteInfo); + } + }, person4.getId(), defaultNetwork.getId()); + } + }, false, true); + + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @SuppressWarnings("unchecked") + @Override + public Void doWork() throws Exception + { + siteService.setMembership(testSite3.getSiteId(), person5.getId(), SiteModel.SITE_CONSUMER); + + return null; + } + }, person4.getId(), defaultNetwork.getId()); + + repoService.generateFeed(); + } + + @Test + public void testPersonActivities() throws Exception + { + People peopleProxy = publicApiClient.people(); + + //Test with default tenant domain. see ALF-20448 + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person5.getId(), null, false, true); + return activities; + } + }, person5.getId(), defaultNetwork.getId()); + + for(Activity activity: expectedActivities) + { + if(activity.getSiteId() == null) + { + fail("SiteId should present in user-joined activity."); + } + } + + { + int skipCount = 0; + int maxItems = expectedActivities.size(); + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("who", String.valueOf(ActivityWho.me)); + publicApiClient.setRequestContext(new RequestContext(defaultNetwork.getId(), person5.getId())); + ListResponse response = peopleProxy.getActivities(person5.getId(), params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + + } + + // Test Case cloud-2204 + // Test case cloud-1500 + // Test Case cloud-2216 + // paging + + // Test Case cloud-1500 + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("who", String.valueOf(ActivityWho.me)); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = peopleProxy.getActivities(person1.getId(), params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + + { + int skipCount = 2; + int maxItems = expectedActivities.size() - 2; + assertTrue(maxItems > 0); + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("who", String.valueOf(ActivityWho.me)); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = peopleProxy.getActivities(person1.getId(), params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + + // "-me-" user + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("who", String.valueOf(ActivityWho.me)); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = peopleProxy.getActivities(org.alfresco.rest.api.People.DEFAULT_USER, params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + } + + // unknown user - 404 + try + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + peopleProxy.getActivities(GUID.generate(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown site - 404 + try + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + Map params = createParams(paging, null); + params.put("siteId", GUID.generate()); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.getActivities(GUID.generate(), params); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // user from another network - 404 + try + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + peopleProxy.getActivities(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // another user from the same network - 403 + try + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + peopleProxy.getActivities(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + try + { + List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, true); + return activities; + } + }, person1.getId(), network1.getId()); + assertTrue(activities.size() > 0); + Activity activity = activities.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.remove("people", person1.getId(), "activities", String.valueOf(activity.getId()), "Unable to DELETE a person activity"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1500 + // other user activities + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List expectedActivities = repoService.getActivities(person1.getId(), null, true, false); + return expectedActivities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("who", String.valueOf(ActivityWho.others)); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = peopleProxy.getActivities(person1.getId(), params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + + // all activities with siteId exclusion + { + List expectedActivities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List expectedActivities = repoService.getActivities(person1.getId(), testSite.getSiteId(), false, false); + return expectedActivities; + } + }, person1.getId(), network1.getId()); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedActivities.size(), null); + + Map params = createParams(paging, null); + params.put("siteId", testSite.getSiteId()); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = peopleProxy.getActivities(person1.getId(), params); + checkList(expectedActivities.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), response); + } + + // all activities with siteId exclusion, unknown site id + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + + Map params = createParams(paging, null); + params.put("siteId", GUID.generate()); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.getActivities(person1.getId(), params); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown person id + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + + Map params = createParams(paging, null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.getActivities(GUID.generate(), params); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid who parameter + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + + Map params = createParams(paging, null); + params.put("who", GUID.generate()); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.getActivities(person1.getId(), params); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1970 + // Not allowed methods +// try +// { +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); +// peopleProxy.create("people", person1.getId(), "activities", null, null, "Unable to POST to person activities"); +// fail(""); +// } +// catch(PublicApiException e) +// { +// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); +// } +// +// try +// { +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); +// peopleProxy.update("people", person1.getId(), "activities", null, null, "Unable to PUT person activities"); +// fail(""); +// } +// catch(PublicApiException e) +// { +// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); +// } +// +// try +// { +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); +// peopleProxy.remove("people", person1.getId(), "activities", null, "Unable to DELETE person activities"); +// fail(""); +// } +// catch(PublicApiException e) +// { +// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); +// } +// +// try +// { +// List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() +// { +// @Override +// public List doWork() throws Exception +// { +// List activities = repoService.getActivities(person1.getId(), null, false, true); +// return activities; +// } +// }, person1.getId(), network1.getId()); +// assertTrue(activities.size() > 0); +// Activity activity = activities.get(0); +// +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); +// peopleProxy.create("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to POST to a person activity"); +// fail(""); +// } +// catch(PublicApiException e) +// { +// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); +// } +// +// try +// { +// List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() +// { +// @Override +// public List doWork() throws Exception +// { +// List activities = repoService.getActivities(person1.getId(), null, false, true); +// return activities; +// } +// }, person1.getId(), network1.getId()); +// assertTrue(activities.size() > 0); +// Activity activity = activities.get(0); +// +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); +// peopleProxy.update("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to PUT a person activity"); +// fail(""); +// } +// catch(PublicApiException e) +// { +// assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); +// } + + // Test Case cloud-1970 + // not allowed methods + { + List activities = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List activities = repoService.getActivities(person1.getId(), null, false, false); + return activities; + } + }, person1.getId(), network1.getId()); + assertTrue(activities.size() > 0); + Activity activity = activities.get(0); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.create("people", person1.getId(), "activities", null, null, "Unable to POST to activities"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.create("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to POST to an activity"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.update("people", person1.getId(), "activities", null, null, "Unable to PUT activities"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.update("people", person1.getId(), "activities", String.valueOf(activity.getId()), null, "Unable to PUT an activity"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.remove("people", person1.getId(), "activities", null, "Unable to DELETE activities"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.remove("people", person1.getId(), "activities", String.valueOf(activity.getId()), "Unable to DELETE an activity"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + } + + /* + * Test that empty roles are not returned + */ + @Test + public void testPUBLICAPI23() throws Exception + { + // Add and then remove personId as a member of the public site + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + testSite.updateMember(person2.getId(), SiteRole.SiteConsumer); + testSite.removeMember(person2.getId()); + + return null; + } + }, person1.getId(), network1.getId()); + + // make sure activities have been generated + repoService.generateFeed(); + + // check that (empty) role is not in the response + + People peopleProxy = publicApiClient.people(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + + int skipCount = 0; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems); + ListResponse activities = peopleProxy.getActivities(person2.getId(), createParams(paging, null)); + for(Activity activity : activities.getList()) + { + String activityType = activity.getActivityType(); + if(activityType.equals("org.alfresco.site.user-left")) + { + String role = (String)activity.getSummary().get("role"); + String feedPersonId = activity.getFeedPersonId(); + if(feedPersonId.equals(person2.getId())) + { + assertTrue(role == null); + break; + } + } + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestCMIS.java b/source/test-java/org/alfresco/rest/api/tests/TestCMIS.java index 1f5457dec0..6907e1826b 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestCMIS.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestCMIS.java @@ -1,2446 +1,2446 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.Serializable; -import java.io.StringWriter; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.alfresco.cmis.client.AlfrescoDocument; -import org.alfresco.cmis.client.AlfrescoFolder; -import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl; -import org.alfresco.cmis.client.type.AlfrescoType; -import org.alfresco.model.ContentModel; -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService; -import org.alfresco.opencmis.dictionary.QNameFilter; -import org.alfresco.opencmis.dictionary.QNameFilterImpl; -import org.alfresco.opencmis.mapping.NodeRefProperty; -import org.alfresco.repo.action.ActionModel; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.content.filestore.FileContentWriter; -import org.alfresco.repo.dictionary.DictionaryBootstrap; -import org.alfresco.repo.dictionary.DictionaryDAO; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.version.VersionableAspectTest; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.HttpResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.CmisSession; -import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.CMISNode; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.FolderNode; -import org.alfresco.rest.api.tests.client.data.MemberOfSite; -import org.alfresco.rest.api.tests.client.data.NodeRating; -import org.alfresco.rest.api.tests.client.data.NodeRating.Aggregate; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockType; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.GUID; -import org.alfresco.util.TempFileProvider; -import org.apache.chemistry.opencmis.client.api.CmisObject; -import org.apache.chemistry.opencmis.client.api.Document; -import org.apache.chemistry.opencmis.client.api.FileableCmisObject; -import org.apache.chemistry.opencmis.client.api.Folder; -import org.apache.chemistry.opencmis.client.api.ItemIterable; -import org.apache.chemistry.opencmis.client.api.ObjectId; -import org.apache.chemistry.opencmis.client.api.ObjectType; -import org.apache.chemistry.opencmis.client.api.OperationContext; -import org.apache.chemistry.opencmis.client.api.Property; -import org.apache.chemistry.opencmis.client.api.Relationship; -import org.apache.chemistry.opencmis.client.api.Repository; -import org.apache.chemistry.opencmis.client.api.SecondaryType; -import org.apache.chemistry.opencmis.client.api.Session; -import org.apache.chemistry.opencmis.client.api.SessionFactory; -import org.apache.chemistry.opencmis.client.api.Tree; -import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; -import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; -import org.apache.chemistry.opencmis.commons.PropertyIds; -import org.apache.chemistry.opencmis.commons.SessionParameter; -import org.apache.chemistry.opencmis.commons.data.ContentStream; -import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; -import org.apache.chemistry.opencmis.commons.enums.VersioningState; -import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; -import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; -import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException; -import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.io.IOUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.context.ApplicationContext; -import org.springframework.extensions.surf.util.URLEncoder; - -public class TestCMIS extends EnterpriseTestApi -{ - private static final String CMIS_VERSION_10 = "1.0"; - - private static final String CMIS_VERSION_11 = "1.1"; - - private static final String TYPE_CMIS_DOCUMENT = "cmis:document"; - - - private static final String DOCUMENT_LIBRARY_CONTAINER_NAME = "documentLibrary"; - - private static final String TEST_SITE_NAME_PATTERN = "testSite-%d"; - - private static final String TEST_USER_NAME_PATTERN = "testUser-%d"; - - private static final String TEST_DOCUMENT_NAME_PATTERN = "testDocument-%s.txt"; - - private static final String DOCUMENT_LIBRARY_PATH_PATTERN = "/Sites/%s/" + DOCUMENT_LIBRARY_CONTAINER_NAME; - - private static final String TEST_PASSWORD = "password"; - - - private DictionaryDAO dictionaryDAO; - private LockService lockService; - private TenantService tenantService; - private CMISStrictDictionaryService cmisDictionary; - private QNameFilter cmisTypeExclusions; - private NodeService nodeService; - private Properties globalProperties; - - @Before - public void before() throws Exception - { - ApplicationContext ctx = getTestFixture().getApplicationContext(); - this.dictionaryDAO = (DictionaryDAO)ctx.getBean("dictionaryDAO"); - this.lockService = (LockService) ctx.getBean("lockService"); - this.tenantService = (TenantService)ctx.getBean("tenantService"); - this.cmisDictionary = (CMISStrictDictionaryService)ctx.getBean("OpenCMISDictionaryService"); - this.cmisTypeExclusions = (QNameFilter)ctx.getBean("cmisTypeExclusions"); - this.nodeService = (NodeService) ctx.getBean("NodeService"); - - this.globalProperties = (Properties) ctx.getBean("global-properties"); - this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "true"); - } - - @After - public void after() - { - this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "false"); - } - - private void checkSecondaryTypes(Document doc, Set expectedSecondaryTypes, Set expectedMissingSecondaryTypes) - { - final List secondaryTypesList = doc.getSecondaryTypes(); - assertNotNull(secondaryTypesList); - List secondaryTypes = new AbstractList() - { - @Override - public String get(int index) - { - SecondaryType type = secondaryTypesList.get(index); - return type.getId(); - } - - @Override - public int size() - { - return secondaryTypesList.size(); - } - }; - if(expectedSecondaryTypes != null) - { - assertTrue("Missing secondary types: " + secondaryTypes, secondaryTypes.containsAll(expectedSecondaryTypes)); - } - if(expectedMissingSecondaryTypes != null) - { - assertTrue("Expected missing secondary types but at least one is still present: " + secondaryTypes, !secondaryTypes.containsAll(expectedMissingSecondaryTypes)); - } - } - - private String getBareObjectId(String objectId) - { - int idx = objectId.indexOf(";"); - String bareObjectId = null; - if(idx != -1) - { - bareObjectId = objectId.substring(0, idx); - } - else - { - bareObjectId = objectId; - } - - return bareObjectId; - } - - /** - * Tests OpenCMIS api. - */ - @SuppressWarnings("unchecked") - @Test - public void testCMIS() throws Exception - { - // Test Case cloud-2353 - // Test Case cloud-2354 - // Test Case cloud-2356 - // Test Case cloud-2378 - // Test Case cloud-2357 - // Test Case cloud-2358 - // Test Case cloud-2360 - - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - Iterator personIt = network1.getPersonIds().iterator(); - final String personId = personIt.next(); - assertNotNull(personId); - Person person = repoService.getPerson(personId); - assertNotNull(person); - - // Create a site - final TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = network1.createSite(siteInfo); - return site; - } - }, personId, network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - Nodes nodesProxy = publicApiClient.nodes(); - Comments commentsProxy = publicApiClient.comments(); - - String expectedContent = "Ipsum and so on"; - Document doc = null; - Folder documentLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary"); - FolderNode expectedDocumentLibrary = (FolderNode)CMISNode.createNode(documentLibrary); - Document testDoc = null; - Folder testFolder = null; - FolderNode testFolderNode = null; - - // create some sub-folders and documents - { - for(int i = 0; i < 3; i++) - { - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); - properties.put(PropertyIds.NAME, "folder-" + i); - } - - Folder f = documentLibrary.createFolder(properties); - FolderNode fn = (FolderNode)CMISNode.createNode(f); - if(testFolder == null) - { - testFolder = f; - testFolderNode = fn; - } - expectedDocumentLibrary.addFolder(fn); - - for(int k = 0; k < 3; k++) - { - properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); - properties.put(PropertyIds.NAME, "folder-" + k); - } - - Folder f1 = f.createFolder(properties); - FolderNode childFolder = (FolderNode)CMISNode.createNode(f1); - fn.addFolder(childFolder); - } - - for(int j = 0; j < 3; j++) - { - properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, "doc-" + j); - } - - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(expectedContent); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - Document d = f.createDocument(properties, fileContent, VersioningState.MAJOR); - if(testDoc == null) - { - testDoc = d; - } - - CMISNode childDocument = CMISNode.createNode(d); - fn.addNode(childDocument); - } - } - - for(int i = 0; i < 10; i++) - { - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, "doc-" + i); - } - - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(expectedContent); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - documentLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - } - } - - // try to add and remove ratings, comments, tags to folders created by CMIS - { - Aggregate aggregate = new Aggregate(1, null); - NodeRating expectedNodeRating = new NodeRating("likes", true, aggregate); - Comment expectedComment = new Comment("commenty", "commenty", false, null, person, person); - Tag expectedTag = new Tag("taggy"); - - NodeRating rating = nodesProxy.createNodeRating(testFolder.getId(), expectedNodeRating); - expectedNodeRating.expected(rating); - assertNotNull(rating.getId()); - - Tag tag = nodesProxy.createNodeTag(testFolder.getId(), expectedTag); - expectedTag.expected(tag); - assertNotNull(tag.getId()); - - Comment comment = commentsProxy.createNodeComment(testFolder.getId(), expectedComment); - expectedComment.expected(comment); - assertNotNull(comment.getId()); - } - - // try to add and remove ratings, comments, tags to documents created by CMIS - { - Aggregate aggregate = new Aggregate(1, null); - NodeRating expectedNodeRating = new NodeRating("likes", true, aggregate); - Comment expectedComment = new Comment("commenty", "commenty", false, null, person, person); - Tag expectedTag = new Tag("taggy"); - - NodeRating rating = nodesProxy.createNodeRating(testDoc.getId(), expectedNodeRating); - expectedNodeRating.expected(rating); - assertNotNull(rating.getId()); - - Tag tag = nodesProxy.createNodeTag(testDoc.getId(), expectedTag); - expectedTag.expected(tag); - assertNotNull(tag.getId()); - - Comment comment = commentsProxy.createNodeComment(testDoc.getId(), expectedComment); - expectedComment.expected(comment); - assertNotNull(comment.getId()); - } - - // descendants - { - List> descendants = documentLibrary.getDescendants(4); - expectedDocumentLibrary.checkDescendants(descendants); - } - - // upload/setContent - { - Map fileProps = new HashMap(); - { - fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(expectedContent); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - doc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); - - String nodeId = stripCMISSuffix(doc.getId()); - final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); - ContentReader reader = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public ContentReader doWork() throws Exception - { - ContentReader reader = repoService.getContent(nodeRef, ContentModel.PROP_CONTENT); - return reader; - } - }, personId, network1.getId()); - - String actualContent = reader.getContentString(); - assertEquals(expectedContent, actualContent); - } - - // get content - { - ContentStream stream = doc.getContentStream(); - StringWriter writer = new StringWriter(); - IOUtils.copy(stream.getStream(), writer, "UTF-8"); - String actualContent = writer.toString(); - assertEquals(expectedContent, actualContent); - } - - // get children - { - Folder folder = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary/" + testFolder.getName()); - - ItemIterable children = folder.getChildren(); - testFolderNode.checkChildren(children); - } - - // query - { - Folder folder = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary/" + testFolder.getName()); - String folderId = folder.getId(); - - Set expectedFolderNames = new HashSet(); - for(CMISNode n : testFolderNode.getFolderNodes().values()) - { - expectedFolderNames.add((String)n.getProperty("cmis:name")); - } - int expectedNumFolders = expectedFolderNames.size(); - int numMatchingFoldersFound = 0; - List results = cmisSession.query("SELECT * FROM cmis:folder WHERE IN_TREE('" + folderId + "')", false, 0, Integer.MAX_VALUE); - for(CMISNode node : results) - { - String name = (String)node.getProperties().get("cmis:name"); - if(expectedFolderNames.contains(name)) - { - numMatchingFoldersFound++; - } - } - assertEquals(expectedNumFolders, numMatchingFoldersFound); - - Set expectedDocNames = new HashSet(); - for(CMISNode n : testFolderNode.getDocumentNodes().values()) - { - expectedDocNames.add((String)n.getProperty("cmis:name")); - } - int expectedNumDocs = expectedDocNames.size(); - int numMatchingDocsFound = 0; - results = cmisSession.query("SELECT * FROM cmis:document where IN_TREE('" + folderId + "')", false, 0, Integer.MAX_VALUE); - for(CMISNode node : results) - { - String name = (String)node.getProperties().get("cmis:name"); - if(expectedDocNames.contains(name)) - { - numMatchingDocsFound++; - } - } - assertEquals(expectedNumDocs, numMatchingDocsFound); - } - - // versioning - { - String nodeId = stripCMISSuffix(doc.getId()); - final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); - - // checkout - ObjectId pwcId = doc.checkOut(); - Document pwc = (Document)cmisSession.getObject(pwcId.getId()); - Boolean isCheckedOut = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Boolean doWork() throws Exception - { - Boolean isCheckedOut = repoService.isCheckedOut(nodeRef); - return isCheckedOut; - } - }, personId, network1.getId()); - assertTrue(isCheckedOut); - - // checkin with new content - expectedContent = "Big bad wolf"; - - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(expectedContent); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - ObjectId checkinId = pwc.checkIn(true, Collections.EMPTY_MAP, fileContent, "checkin 1"); - doc = (Document)cmisSession.getObject(checkinId.getId()); - isCheckedOut = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Boolean doWork() throws Exception - { - Boolean isCheckedOut = repoService.isCheckedOut(nodeRef); - return isCheckedOut; - } - }, personId, network1.getId()); - assertFalse(isCheckedOut); - - // check that the content has been updated - ContentStream stream = doc.getContentStream(); - StringWriter writer = new StringWriter(); - IOUtils.copy(stream.getStream(), writer, "UTF-8"); - String actualContent = writer.toString(); - assertEquals(expectedContent, actualContent); - - List allVersions = doc.getAllVersions(); - assertEquals(2, allVersions.size()); - assertEquals("2.0", allVersions.get(0).getVersionLabel()); - assertEquals(CMIS_VERSION_10, allVersions.get(1).getVersionLabel()); - } - - { - // https://issues.alfresco.com/jira/browse/PUBLICAPI-95 - // Test that documents are created with autoVersion=true - - Map fileProps = new HashMap(); - { - fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - { - // a versioned document - - Document autoVersionedDoc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); - String objectId = autoVersionedDoc.getId(); - String bareObjectId = getBareObjectId(objectId); - final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, bareObjectId); - Boolean autoVersion = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Boolean doWork() throws Exception - { - Boolean autoVersion = (Boolean)repoService.getProperty(nodeRef, ContentModel.PROP_AUTO_VERSION); - return autoVersion; - } - }, personId, network1.getId()); - assertEquals(Boolean.TRUE, autoVersion); - } - - // https://issues.alfresco.com/jira/browse/PUBLICAPI-92 - // Test that a get on an objectId without a version suffix returns the current version of the document - { - // do a few checkout, checkin cycles to create some versions - fileProps = new HashMap(); - { - fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - - Document autoVersionedDoc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); - String objectId = autoVersionedDoc.getId(); - String bareObjectId = getBareObjectId(objectId); - - for(int i = 0; i < 3; i++) - { - Document doc1 = (Document)cmisSession.getObject(bareObjectId); - - ObjectId pwcId = doc1.checkOut(); - Document pwc = (Document)cmisSession.getObject(pwcId.getId()); - - ContentStreamImpl contentStream = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - expectedContent = GUID.generate(); - writer.putContent(expectedContent); - ContentReader reader = writer.getReader(); - contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - contentStream.setStream(reader.getContentInputStream()); - } - pwc.checkIn(true, Collections.EMPTY_MAP, contentStream, "checkin " + i); - } - - // get the object, supplying an objectId without a version suffix - Document doc1 = (Document)cmisSession.getObject(bareObjectId); - String versionLabel = doc1.getVersionLabel(); - ContentStream cs = doc1.getContentStream(); - String content = IOUtils.toString(cs.getStream()); - - assertEquals("4.0", versionLabel); - assertEquals(expectedContent, content); - } - } - } - - /** - * Tests CMIS and non-CMIS public api interactions - */ - @SuppressWarnings("deprecation") - @Test - public void testScenario1() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - Iterator personIt = network1.getPersonIds().iterator(); - final String person = personIt.next(); - assertNotNull(person); - - Sites sitesProxy = publicApiClient.sites(); - Comments commentsProxy = publicApiClient.comments(); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - - ListResponse sites = sitesProxy.getPersonSites(person, null); - assertTrue(sites.getList().size() > 0); - MemberOfSite siteMember = sites.getList().get(0); - String siteId = siteMember.getSite().getSiteId(); - - Folder documentLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteId + "/documentLibrary"); - - System.out.println("documentLibrary id = " + documentLibrary.getId()); - - Map fileProps = new HashMap(); - { - fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - Document doc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); - - System.out.println("Document id = " + doc.getId()); - - Comment c = commentsProxy.createNodeComment(doc.getId(), new Comment("comment title 1", "comment 1")); - - System.out.println("Comment = " + c); - - // Now lock the document - String nodeRefStr = (String) doc.getPropertyValue("alfcmis:nodeRef"); - final NodeRef nodeRef = new NodeRef(nodeRefStr); - final TenantRunAsWork runAsWork = new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - lockService.lock(nodeRef, LockType.WRITE_LOCK); - return null; - } - }; - RetryingTransactionCallback txnWork = new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - TenantUtil.runAsUserTenant(runAsWork, "bob", network1.getId()); - return null; - } - }; - transactionHelper.doInTransaction(txnWork); - - // Now attempt to update the document's metadata - try - { - doc.delete(); - } - catch (CmisUpdateConflictException e) - { - // Expected: ACE-762 BM-0012: NodeLockedException not handled by CMIS - } - } - - //@Test - public void testInvalidMethods() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - Iterator personIt = network1.getPersonIds().iterator(); - final String person = personIt.next(); - assertNotNull(person); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - - publicApiClient.post(Binding.atom, CMIS_VERSION_10, null, null); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - - publicApiClient.head(Binding.atom, CMIS_VERSION_10, null, null); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - - publicApiClient.options(Binding.atom, CMIS_VERSION_10, null, null); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - - publicApiClient.trace(Binding.atom, CMIS_VERSION_10, null, null); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); - - publicApiClient.patch(Binding.atom, CMIS_VERSION_10, null, null); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - - @Test - public void testPublicApi110() throws Exception - { - Iterator networksIt = getTestFixture().networksIterator(); - final TestNetwork network1 = networksIt.next(); - Iterator personIt = network1.getPersonIds().iterator(); - final String person1Id = personIt.next(); - final String person2Id = personIt.next(); - - final List nodes = new ArrayList(5); - - // Create some favourite targets, sites, files and folders - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName1 = "site" + GUID.generate(); - SiteInformation siteInfo1 = new SiteInformation(siteName1, siteName1, siteName1, SiteVisibility.PUBLIC); - TestSite site1 = network1.createSite(siteInfo1); - - String siteName2 = "site" + GUID.generate(); - SiteInformation siteInfo2 = new SiteInformation(siteName2, siteName2, siteName2, SiteVisibility.PRIVATE); - TestSite site2 = network1.createSite(siteInfo2); - - NodeRef nodeRef1 = repoService.createDocument(site1.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); - nodes.add(nodeRef1); - NodeRef nodeRef2 = repoService.createDocument(site1.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); - nodes.add(nodeRef2); - NodeRef nodeRef3 = repoService.createDocument(site2.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); - nodes.add(nodeRef3); - repoService.createAssociation(nodeRef2, nodeRef1, ContentModel.ASSOC_ORIGINAL); - repoService.createAssociation(nodeRef3, nodeRef1, ContentModel.ASSOC_ORIGINAL); - - site1.inviteToSite(person2Id, SiteRole.SiteCollaborator); - - return null; - } - }, person1Id, network1.getId()); - - { - OperationContext cmisOperationCtxOverride = new OperationContextImpl(); - cmisOperationCtxOverride.setIncludeRelationships(IncludeRelationships.BOTH); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2Id, cmisOperationCtxOverride)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - - CmisObject o1 = cmisSession.getObject(nodes.get(0).getId()); - List relationships = o1.getRelationships(); - assertEquals(1, relationships.size()); - Relationship r = relationships.get(0); - CmisObject source = r.getSource(); - CmisObject target = r.getTarget(); - String sourceVersionSeriesId = (String)source.getProperty(PropertyIds.VERSION_SERIES_ID).getFirstValue(); - String targetVersionSeriesId = (String)target.getProperty(PropertyIds.VERSION_SERIES_ID).getFirstValue(); - assertEquals(nodes.get(1).getId(), sourceVersionSeriesId); - assertEquals(nodes.get(0).getId(), targetVersionSeriesId); - } - } - - @Test - public void testObjectIds() throws Exception - { - String username = "enterpriseuser" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person = repoService.createUser(personInfo, username, null); - String personId = person.getId(); - - final List folders = new ArrayList(); - final List documents = new ArrayList(); - - AuthenticationUtil.runAs(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - folders.add(folderNodeRef); - - name = GUID.generate(); - NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); - documents.add(docNodeRef); - - return null; - } - }, personId); - - NodeRef folderNodeRef = folders.get(0); - NodeRef docNodeRef = documents.get(0); - - publicApiClient.setRequestContext(new RequestContext(personId)); - - // use cmisatom endpoint - List repositories = publicApiClient.getCMISRepositories(); - CmisSession cmisSession = publicApiClient.getCMISSession(repositories.get(0)); - - // test CMIS accepts NodeRefs and guids as input - // if input is NodeRef, return NodeRef. If input is guid, return guid. - { - String nodeRefStr = docNodeRef.toString(); - CmisObject o = cmisSession.getObject(nodeRefStr); - assertEquals(docNodeRef.toString(), stripCMISSuffix(o.getId())); - - nodeRefStr = folderNodeRef.toString(); - o = cmisSession.getObject(nodeRefStr); - assertEquals(folderNodeRef.toString(), stripCMISSuffix(o.getId())); - - String objectId = docNodeRef.getId(); - o = cmisSession.getObject(objectId); - assertEquals(objectId, stripCMISSuffix(o.getId())); - - objectId = folderNodeRef.getId(); - o = cmisSession.getObject(objectId); - assertEquals(objectId, stripCMISSuffix(o.getId())); - } - - // query - { - // searching by NodeRef, expect result objectIds to be Noderefs - Set expectedObjectIds = new HashSet(); - expectedObjectIds.add(docNodeRef.toString()); - int numMatchingDocs = 0; - - // NodeRef input - List results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.toString() + "')", false, 0, Integer.MAX_VALUE); - assertEquals(expectedObjectIds.size(), results.size()); - for(CMISNode node : results) - { - String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); - if(expectedObjectIds.contains(objectId)) - { - numMatchingDocs++; - } - } - assertEquals(expectedObjectIds.size(), numMatchingDocs); - - // searching by guid, expect result objectIds to be NodeRefs - numMatchingDocs = 0; - - // node guid input - results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.getId() + "')", false, 0, Integer.MAX_VALUE); - assertEquals(expectedObjectIds.size(), results.size()); - for(CMISNode node : results) - { - String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); - System.out.println("objectId = " + objectId); - if(expectedObjectIds.contains(objectId)) - { - numMatchingDocs++; - } - } - assertEquals(expectedObjectIds.size(), numMatchingDocs); - } - - // public api - - Iterator networksIt = getTestFixture().networksIterator(); - final TestNetwork network1 = networksIt.next(); - Iterator personIt = network1.getPersonIds().iterator(); - final String person1Id = personIt.next(); - - final List folders1 = new ArrayList(); - final List documents1 = new ArrayList(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - folders1.add(folderNodeRef); - - name = GUID.generate(); - NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); - documents1.add(docNodeRef); - - return null; - } - }, person1Id, network1.getId()); - - folderNodeRef = folders1.get(0); - docNodeRef = documents1.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - - // test CMIS accepts NodeRefs and guids as input - // objectIds returned from public api CMIS are always the guid - { - String nodeRefStr = docNodeRef.toString(); - CmisObject o = cmisSession.getObject(nodeRefStr); - String objectId = docNodeRef.getId(); - assertEquals(objectId, stripCMISSuffix(o.getId())); - - nodeRefStr = folderNodeRef.toString(); - o = cmisSession.getObject(nodeRefStr); - objectId = folderNodeRef.getId(); - assertEquals(objectId, stripCMISSuffix(o.getId())); - - o = cmisSession.getObject(objectId); - assertEquals(objectId, stripCMISSuffix(o.getId())); - - objectId = folderNodeRef.getId(); - o = cmisSession.getObject(objectId); - assertEquals(objectId, stripCMISSuffix(o.getId())); - } - - // query - { - // searching by NodeRef, expect result objectIds to be objectId - Set expectedObjectIds = new HashSet(); - expectedObjectIds.add(docNodeRef.getId()); - int numMatchingDocs = 0; - - // NodeRef input - List results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.toString() + "')", false, 0, Integer.MAX_VALUE); - assertEquals(expectedObjectIds.size(), results.size()); - for(CMISNode node : results) - { - String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); - if(expectedObjectIds.contains(objectId)) - { - numMatchingDocs++; - } - } - assertEquals(expectedObjectIds.size(), numMatchingDocs); - - // searching by guid, expect result objectIds to be objectId - numMatchingDocs = 0; - - // node guid input - results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.getId() + "')", false, 0, Integer.MAX_VALUE); - assertEquals(expectedObjectIds.size(), results.size()); - for(CMISNode node : results) - { - String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); - System.out.println("objectId = " + objectId); - if(expectedObjectIds.contains(objectId)) - { - numMatchingDocs++; - } - } - assertEquals(expectedObjectIds.size(), numMatchingDocs); - } - } - - @Test - public void testAspects() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final List folders = new ArrayList(); - final List documents = new ArrayList(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - folders.add(folderNodeRef); - - for(int i = 0; i < 3; i++) - { - name = GUID.generate(); - NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); - assertFalse(repoService.getAspects(docNodeRef).contains(ContentModel.ASPECT_TITLED)); - documents.add(docNodeRef); - } - - return null; - } - }, person1Id, network1.getId()); - - final NodeRef doc1NodeRef = documents.get(0); - final NodeRef doc2NodeRef = documents.get(1); - final NodeRef doc3NodeRef = documents.get(2); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - CmisSession atomCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - CmisSession browserCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.browser, CMIS_VERSION_11); - - // Test that adding aspects works for both 1.0 and 1.1 - - // 1.0 - { - AlfrescoDocument doc = (AlfrescoDocument)atomCmisSession10.getObject(doc1NodeRef.getId()); - - doc = (AlfrescoDocument)doc.addAspect("P:cm:titled"); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc1NodeRef); - assertTrue("Missing aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - - return null; - } - }, person1Id, network1.getId()); - - doc.removeAspect("P:cm:titled"); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc1NodeRef); - assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - - return null; - } - }, person1Id, network1.getId()); - } - - // 1.1 atom (secondary types) - { - final Document doc = (Document)atomCmisSession11.getObject(doc2NodeRef.getId()); - - final List secondaryTypesList = doc.getSecondaryTypes(); - final List secondaryTypes = new ArrayList(); - if (secondaryTypesList != null) - { - for(SecondaryType secondaryType : secondaryTypesList) - { - secondaryTypes.add(secondaryType.getId()); - } - } - - secondaryTypes.add("P:sys:temporary"); - secondaryTypes.add("P:cm:titled"); - Map properties = new HashMap(); - { - // create a document with 2 secondary types - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc1 = (Document)doc.updateProperties(properties); - checkSecondaryTypes(doc1, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled"})), null); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc2NodeRef); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - - return null; - } - }, person1Id, network1.getId()); - - secondaryTypes.add("P:cm:author"); - properties = new HashMap(); - { - // create a document with 2 secondary types - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc2 = (Document)doc1.updateProperties(properties); - checkSecondaryTypes(doc2, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled", "P:cm:author"})), null); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc2NodeRef); - String title = (String)repoService.getProperty(doc2NodeRef, ContentModel.PROP_TITLE); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - assertEquals(null, title); - - return null; - } - }, person1Id, network1.getId()); - - // remove a secondary type - secondaryTypes.remove("P:cm:titled"); - properties = new HashMap(); - { - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc3 = (Document)doc2.updateProperties(properties); - checkSecondaryTypes(doc3, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:author"})), - new HashSet(Arrays.asList(new String[] {"P:cm:titled"}))); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc2NodeRef); - String title = (String)repoService.getProperty(doc2NodeRef, ContentModel.PROP_TITLE); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - assertEquals(null, title); - - return null; - } - }, person1Id, network1.getId()); - } - - // 1.1 browser (secondary types) - { - Document doc = (Document)browserCmisSession11.getObject(doc3NodeRef.getId()); - final List secondaryTypesList = doc.getSecondaryTypes(); - final List secondaryTypes = new ArrayList(); - if (secondaryTypesList != null) - { - for (SecondaryType secondaryType : secondaryTypesList) - { - secondaryTypes.add(secondaryType.getId()); - } - } - - secondaryTypes.add("P:sys:temporary"); - secondaryTypes.add("P:cm:titled"); - Map properties = new HashMap(); - { - // create a document with 2 secondary types - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc1 = (Document)doc.updateProperties(properties); - checkSecondaryTypes(doc1, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled"})), null); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc3NodeRef); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - return null; - } - }, person1Id, network1.getId()); - - secondaryTypes.add("P:cm:author"); - properties = new HashMap(); - { - // create a document with 2 secondary types - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc2 = (Document)doc1.updateProperties(properties); - checkSecondaryTypes(doc2, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled", "P:cm:author"})), null); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc3NodeRef); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); - - return null; - } - }, person1Id, network1.getId()); - - secondaryTypes.remove("P:cm:titled"); - properties = new HashMap(); - { - // create a document with 2 secondary types - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - } - Document doc3 = (Document)doc2.updateProperties(properties); - checkSecondaryTypes(doc3, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:author"})), - new HashSet(Arrays.asList(new String[] {"P:cm:titled"}))); - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Set aspects = repoService.getAspects(doc3NodeRef); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); - assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); - assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); - - return null; - } - }, person1Id, network1.getId()); - } - } - - /** - * ALF-18968 - * - * @see QNameFilterImpl#listOfHardCodedExcludedTypes() - */ - @Test - public void testTypeFiltering() throws Exception - { - // Force an exclusion in order to test the exclusion inheritance - cmisTypeExclusions.setExcluded(ActionModel.TYPE_ACTION_BASE, true); - // Quick check - assertTrue(cmisTypeExclusions.isExcluded(ActionModel.TYPE_ACTION_BASE)); - - // Test that a type defined with this excluded parent type does not break the CMIS dictionary - DictionaryBootstrap bootstrap = new DictionaryBootstrap(); - List bootstrapModels = new ArrayList(); - bootstrapModels.add("publicapi/test-model.xml"); - bootstrap.setModels(bootstrapModels); - bootstrap.setDictionaryDAO(dictionaryDAO); - bootstrap.setTenantService(tenantService); - bootstrap.bootstrap(); - cmisDictionary.afterDictionaryInit(); - - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - // test that this type is excluded; the 'action' model (act prefix) is in the list of hardcoded exclusions - QName type = QName.createQName("{http://www.alfresco.org/test/testCMIS}type1"); - assertTrue(cmisTypeExclusions.isExcluded(type)); - - // and that we can't get to it through CMIS - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - try - { - cmisSession.getTypeDefinition("D:testCMIS:type1"); - fail("Type should not be available"); - } - catch(CmisObjectNotFoundException e) - { - // ok - } - } - - /** - * MNT-12680 - * The creation date of version should be the same as creation date of the original node - * @throws Exception - */ - @Test - public void testCreationDate() throws Exception - { - // create a site - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - final TestSite site = network1.createSite(siteInfo); - final NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "testdoc.txt", "Test Doc1 Title", "Test Doc1 Description", - "Test Content"); - return resNode; - } - }, person1Id, network1.getId()); - - // create a document - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - AlfrescoFolder docLibrary = (AlfrescoFolder) cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("some content"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - Document autoVersionedDoc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - String objectId = autoVersionedDoc.getId(); - String bareObjectId = getBareObjectId(objectId); - // create versions - for (int i = 0; i < 3; i++) - { - Document doc1 = (Document) cmisSession.getObject(bareObjectId); - - ObjectId pwcId = doc1.checkOut(); - Document pwc = (Document) cmisSession.getObject(pwcId.getId()); - - ContentStreamImpl contentStream = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(GUID.generate()); - ContentReader reader = writer.getReader(); - contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - contentStream.setStream(reader.getContentInputStream()); - } - pwc.checkIn(true, Collections.EMPTY_MAP, contentStream, "checkin " + i); - } - - GregorianCalendar cDateFirst = cmisSession.getAllVersions(bareObjectId).get(0).getCreationDate(); - GregorianCalendar cDateSecond = cmisSession.getAllVersions(bareObjectId).get(2).getCreationDate(); - - if (cDateFirst.before(cDateSecond) || cDateFirst.after(cDateSecond)) - { - fail("The creation date of version should be the same as creation date of the original node"); - } - } - - /** - * Test that updating properties does not automatically create a new version. - * Test that updating content creates a new version automatically. - * - */ - @Test - public void testVersioning() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - String versionLabel = doc.getVersionLabel(); - - // ...and check that updating its properties does not create a new version - properties = new HashMap(); - { - properties.put(PropertyIds.DESCRIPTION, GUID.generate()); - } - AlfrescoDocument doc1 = (AlfrescoDocument)doc.updateProperties(properties); - doc1 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); - String versionLabel1 = doc1.getVersionLabel(); - - assertTrue(Float.parseFloat(versionLabel) < Float.parseFloat(versionLabel1)); - - // ...and check that updating its content creates a new version - fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - doc1.setContentStream(fileContent, true); - AlfrescoDocument doc2 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); - @SuppressWarnings("unused") - String versionLabel2 = doc2.getVersionLabel(); - - assertTrue("Set content stream should create a new version automatically", Float.parseFloat(versionLabel1) < Float.parseFloat(versionLabel2)); - } - - /** - * Test that updating properties does automatically create a new version if - * autoVersion, initialVersion and autoVersionOnUpdateProps are TRUE - */ - @Test - public void testVersioningUsingUpdateProperties() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, "1.0", AlfrescoObjectFactoryImpl.class.getName()); - AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document"); - properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - String versionLabel = doc.getVersionLabel(); - - String nodeRefStr = doc.getPropertyValue(NodeRefProperty.NodeRefPropertyId).toString(); - final NodeRef nodeRef = new NodeRef(nodeRefStr); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - // ensure autoversioning is enabled - assertTrue(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)); - - Map versionProperties = new HashMap(); - versionProperties.put(ContentModel.PROP_AUTO_VERSION, true); - versionProperties.put(ContentModel.PROP_INITIAL_VERSION, true); - versionProperties.put(ContentModel.PROP_AUTO_VERSION_PROPS, true); - - nodeService.addProperties(nodeRef, versionProperties); - - return null; - } - }, person1Id, network1.getId()); - - // ...and check that updating its properties creates a new minor version... - properties = new HashMap(); - { - properties.put(PropertyIds.DESCRIPTION, GUID.generate()); - } - AlfrescoDocument doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false).updateProperties(properties); - doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false); - String versionLabel1 = doc1.getVersionLabel(); - - assertTrue(Double.parseDouble(versionLabel) < Double.parseDouble(versionLabel1)); - - // ...and check that updating its content creates a new version - fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - doc1.setContentStream(fileContent, true); - - AlfrescoDocument doc2 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); - String versionLabel2 = doc2.getVersionLabel(); - - assertTrue("Set content stream should create a new version automatically", Double.parseDouble(versionLabel1) < Double.parseDouble(versionLabel2)); - assertTrue("It should be latest version : " + versionLabel2, doc2.isLatestVersion()); - - doc2.deleteContentStream(); - AlfrescoDocument doc3 = (AlfrescoDocument)doc2.getObjectOfLatestVersion(false); - String versionLabel3 = doc3.getVersionLabel(); - - assertTrue("Delete content stream should create a new version automatically", Double.parseDouble(versionLabel1) < Double.parseDouble(versionLabel3)); - assertTrue("It should be latest version : " + versionLabel3, doc3.isLatestVersion()); - } - - - /** - * 1) Creating a file with incorrect char in description property - * 2) Get xml with incorrect char in description - * 3) Check xml - * @throws Exception - */ - @Test - public void testGetXmlWithIncorrectDesctiption() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - NodeRef fileNode = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - final TestSite site = network1.createSite(siteInfo); - - NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "testdoc \u0010.txt", "Test Doc1 Title \u0010", "d\u0010", "Test Content"); - return resNode; - } - }, person1Id, network1.getId()); - - String cmisId = fileNode.getId(); - HashMap reqParams = new HashMap(); - reqParams.put("id", cmisId+";1.0"); - reqParams.put("filter", "*"); - reqParams.put("includeAllowableActions", "true"); - reqParams.put("includeACL", "true"); - reqParams.put("includePolicyIds", "true"); - reqParams.put("includeRelationships", "both"); - reqParams.put("renditionFilter", "*"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - HttpResponse resp = publicApiClient.get(Binding.atom, CMIS_VERSION_11, "id", reqParams); - String xml = resp.getResponse(); - // Response hasn't full info at error - writer just stops at incorrect character. - // Therefore we can check end tag of root element - assertTrue("No end tag was found", xml.endsWith("")); - } - - /** - * 1) Creating a file with currency symbols in the name, title and description (MNT-15044) - * 2) Get the document with correct chars in the properties. - * @throws Exception - */ - @Test - public void testGetXmlWithCorrectCurrencySymbols() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - NodeRef fileNode = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - final TestSite site = network1.createSite(siteInfo); - - NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), - "Euro \u20AC Pound \u00A3 Franc \u20A3.txt", - "Euro \u20AC Pound \u00A3 Franc \u20A3 File", - "\u20A3 \u00A3 \u20A3", - "\u20A3 \u00A3 \u20A3"); - return resNode; - } - }, person1Id, network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - - String objectId = fileNode.getId(); - Document doc = (Document)atomCmisSession10.getObject(objectId); - - String name = (String)doc.getProperty(PropertyIds.NAME).getFirstValue(); - String title = (String)doc.getProperty("cm:title").getFirstValue(); - String description = (String)doc.getProperty("cm:description").getFirstValue(); - - assertEquals("Euro \u20AC Pound \u00A3 Franc \u20A3.txt", name); - assertEquals("Euro \u20AC Pound \u00A3 Franc \u20A3 File", title); - assertEquals("\u20A3 \u00A3 \u20A3", description); - } - - /* - * Test that creating a document with a number of initial aspects does not create lots of initial versions - */ - @Test - public void testALF19320() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - Map properties = new HashMap(); - { - // create a document with 2 aspects - properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document,P:cm:titled,P:cm:author"); - properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - String versionLabel = doc.getVersionLabel(); - assertEquals(CMIS_VERSION_10, versionLabel); - - AlfrescoDocument doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false); - String versionLabel1 = doc1.getVersionLabel(); - assertEquals(CMIS_VERSION_10, versionLabel1); - } - - /* MNT-10175 test */ - @Test - public void testAppendContentVersioning() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - // Use CMIS 1.1 to test content appending - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - String name = GUID.generate() + ".txt"; - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, name); - } - // Create content to append - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - String versionLabel1 = doc.getObjectOfLatestVersion(false).getVersionLabel(); - - // append a few times - for(int i = 0; i < 5; i++) - { - doc.appendContentStream(fileContent, false); - } - - String versionLabel2 = doc.getObjectOfLatestVersion(false).getVersionLabel(); - - // Version label should not be incremented by appending with isLustChunk = false - assertEquals(versionLabel1, versionLabel2); - - doc.appendContentStream(fileContent, true); - - String versionLabel3 = doc.getObjectOfLatestVersion(false).getVersionLabel(); - Integer majorVer1 = Integer.valueOf(versionLabel2.substring(0, 1)); - Integer majorVer2 = Integer.valueOf(versionLabel3.substring(0, 1)); - - Integer minorVer1 = Integer.valueOf(versionLabel2.substring(2, 3)); - Integer minorVer2 = Integer.valueOf(versionLabel3.substring(2, 3)); - - // Only one MINOR version should be created - assertEquals(majorVer1, majorVer2); - assertEquals(Integer.valueOf(minorVer1 + 1), minorVer2); - } - - @Test - public void testAppendContentStream() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - String name = "mydoc-" + GUID.generate() + ".txt"; - Map properties = new HashMap(); - { - // create a document with 2 aspects - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, name); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - - // append a few times - for(int i = 0; i < 5; i++) - { - fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - doc.appendContentStream(fileContent, false); - } - fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - doc.appendContentStream(fileContent, true); - - // check the appends - String path = "/Sites/" + siteName + "/documentLibrary/" + name; - Document doc1 = (Document)cmisSession.getObjectByPath(path); - ContentStream contentStream = doc1.getContentStream(); - InputStream in = contentStream.getStream(); - StringWriter writer = new StringWriter(); - IOUtils.copy(in, writer, "UTF-8"); - String content = writer.toString(); - assertEquals("Ipsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so on", content); - } - - @Test - public void testSecondaryTypes() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - String name = "mydoc-" + GUID.generate() + ".txt"; - final List secondaryTypes = new ArrayList(); - secondaryTypes.add("P:cm:summarizable"); - Map properties = new HashMap(); - { - // create a document with 2 aspects - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); - properties.put("cm:summary", "My summary"); - properties.put(PropertyIds.NAME, name); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - - { - // check that the secondary types and properties are present - { - checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); - String summary = (String)doc.getProperty("cm:summary").getFirstValue(); - assertEquals("My summary", summary); - } - - { - doc = (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + name); - checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); - String summary = (String)doc.getProperty("cm:summary").getFirstValue(); - assertEquals("My summary", summary); - } - } - - // update property and check - { - properties = new HashMap(); - { - properties.put("cm:summary", "My updated summary"); - } - doc.updateProperties(properties); - - { - doc = (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + name); - checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); - String summary = (String)doc.getProperty("cm:summary").getFirstValue(); - assertEquals("My updated summary", summary); - } - - { - checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); - String summary = (String)doc.getProperty("cm:summary").getFirstValue(); - assertEquals("My updated summary", summary); - } - } - } - - /* MNT-10161 related test - mapping of cmis:description for CMIS 1.1 */ - @Test - public void testMNT_10161() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - final String nodeDescription = "Test description"; - - final String nodeName = GUID.generate(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), nodeName); - /* create node with property description */ - return repoService.createDocument(folderNodeRef, nodeName, "title", nodeDescription, "content"); - } - }, person1Id, network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Document doc = - (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + nodeName + "/" + nodeName); - - /* ensure we got the node */ - assertNotNull(doc); - - /* get mapped cmis:description */ - Property descrProperty = doc.getProperty(PropertyIds.DESCRIPTION); - - /* ensure that cmis:description is set properly */ - assertTrue(nodeDescription.equals(descrProperty.getValue())); - } - - /* MNT-10687 related test - appendContent to PWC CMIS 1.1 */ - @Test - public void testMNT_10687() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - String name = "mydoc-" + GUID.generate() + ".txt"; - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, name); - } - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - /* Create document */ - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - - /* Checkout document */ - ObjectId pwcId = doc.checkOut(); - Document pwc = (Document)cmisSession.getObject(pwcId.getId()); - - /* append content to PWC */ - fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent(" and so on"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - pwc.appendContentStream(fileContent, true); - - pwc.checkIn(false, null, null, "Check In"); - - ContentStream contentStream = doc.getObjectOfLatestVersion(false).getContentStream(); - InputStream in = contentStream.getStream(); - StringWriter writer = new StringWriter(); - IOUtils.copy(in, writer, "UTF-8"); - String content = writer.toString(); - assertEquals("Ipsum and so on", content); - } - - @Test - public void testMNT_13057() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - String guid = GUID.generate(); - String name = guid + "_KRUIS_LOGO_100%_PMS.txt"; - String urlFileName = guid + "_KRUIS_LOGO_100%25_PMS.txt"; - - final String siteName = "site" + System.currentTimeMillis(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, person1Id, network1.getId()); - - // Create a document... - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); - - Map properties = new HashMap(); - { - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, name); - } - - ContentStreamImpl fileContent = new ContentStreamImpl(); - { - ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); - writer.putContent("Ipsum"); - ContentReader reader = writer.getReader(); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(reader.getContentInputStream()); - } - - /* Create document */ - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - - String id = doc.getId(); - assertNotNull(id); - Map params = new HashMap(); - params.put("id", URLEncoder.encode(id)); - - urlFileName += "?id=" + URLEncoder.encode(id); - - HttpResponse response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/atom/content/" + urlFileName, null); - assertEquals(200, response.getStatusCode()); - } - - @Test - public void testMNT10430() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, - null, null, null, null, null); - TestPerson person1 = network1.createUser(personInfo); - String person1Id = person1.getId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.browser, CMIS_VERSION_11, - "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); - - ObjectType objectType = cmisSession.getTypeDefinition("D:testcmis:maDoc"); - - // try and get the mandatory aspects - List mandatoryAspects = ((AlfrescoType)objectType).getMandatoryAspects(); - System.out.println("Mandatory Aspects"); - for(String mandatoryAspect : mandatoryAspects) - { - System.out.println(mandatoryAspect); - } - assertTrue("The aspects should have P:cm:generalclassifiable", mandatoryAspects.contains("P:cm:generalclassifiable")); - } - - @Test - public void testMnt11631() throws Exception - { - final TestNetwork network = getTestFixture().getRandomNetwork(); - - String username = String.format(TEST_USER_NAME_PATTERN, System.currentTimeMillis()); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person = network.createUser(personInfo); - String personId = person.getId(); - - final String siteName = String.format(TEST_SITE_NAME_PATTERN, System.currentTimeMillis()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - - String name = GUID.generate(); - NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); - return folderNodeRef; - } - }, personId, network.getId()); - - publicApiClient.setRequestContext(new RequestContext(network.getId(), personId)); - CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - Folder docLibrary = (Folder) cmisSession.getObjectByPath(String.format(DOCUMENT_LIBRARY_PATH_PATTERN, siteName)); - String name = String.format(TEST_DOCUMENT_NAME_PATTERN, GUID.generate()); - - Map properties = new HashMap(); - properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); - properties.put(PropertyIds.NAME, name); - - ContentStreamImpl fileContent = new ContentStreamImpl(); - ByteArrayInputStream stream = new ByteArrayInputStream(GUID.generate().getBytes()); - fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); - fileContent.setStream(stream); - - Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); - - ObjectId pwcId = doc.checkOut(); - Document pwc = (Document) cmisSession.getObject(pwcId.getId()); - - assertIsPwcProperty(pwc, false); - - cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10); - CmisObject pwc10 = cmisSession.getObject(pwc.getId()); - assertIsPwcProperty(pwc10, true); - } - - private void assertIsPwcProperty(CmisObject pwc, boolean nullExpected) - { - boolean isPwcFound = false; - Boolean isPwcValueTrue = null; - for (Property property : pwc.getProperties()) - { - if ((null != property) && PropertyIds.IS_PRIVATE_WORKING_COPY.equals(property.getId())) - { - isPwcFound = true; - isPwcValueTrue = property.getValue(); - break; - } - } - - if (nullExpected) - { - assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property is not null!"), !isPwcFound || (null == isPwcValueTrue)); - return; - } - - assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property has not been found!"), isPwcFound); - assertNotNull(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property value must not be null!"), isPwcValueTrue); - assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property value must be equal to 'true'!"), isPwcValueTrue); - } - - @Test - public void testCanConnectCMISUsingDefaultTenant() throws Exception - { - testCanConnectCMISUsingDefaultTenantImpl(Binding.atom, CMIS_VERSION_11); - testCanConnectCMISUsingDefaultTenantImpl(Binding.atom, CMIS_VERSION_10); - testCanConnectCMISUsingDefaultTenantImpl(Binding.browser, CMIS_VERSION_11); - } - - private void testCanConnectCMISUsingDefaultTenantImpl(Binding binding, String cmisVersion) - { - String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, cmisVersion, null); - - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, "admin"); - parameters.put(SessionParameter.PASSWORD, "admin"); - - parameters.put(SessionParameter.ATOMPUB_URL, url); - parameters.put(SessionParameter.BROWSER_URL, url); - parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); - - SessionFactory factory = SessionFactoryImpl.newInstance(); - // perform request : http://host:port/alfresco/api/-default-/public/cmis/versions/${cmisVersion}/${binding} - List repositories = factory.getRepositories(parameters); - - assertTrue(repositories.size() > 0); - - parameters.put(SessionParameter.REPOSITORY_ID, TenantUtil.DEFAULT_TENANT); - Session session = factory.createSession(parameters); - // perform request : http://host:port/alfresco/api/-default-/public/cmis/versions/${cmisVersion}/${binding}/type?id=cmis:document - ObjectType objectType = session.getTypeDefinition("cmis:document"); - - assertNotNull(objectType); - } - - @Test - public void testACE3433() throws Exception - { - final TestNetwork network = getTestFixture().getRandomNetwork(); - - NodeRef rootNodeRef = TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - NodeRef rootNodeRef = repoService.getNodeService().getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); - List childAssocs = repoService.getNodeService().getChildAssocsByPropertyValue(rootNodeRef, - ContentModel.PROP_TITLE, "Company Home"); - assertEquals(1, childAssocs.size()); - NodeRef companyHomeNodeRef = childAssocs.get(0).getChildRef(); - return companyHomeNodeRef; - } - - }, network.getId()); - assertNotNull(rootNodeRef); - - // atom - { - Binding binding = Binding.atom; - String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, "1.1", null); - - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, "admin@" + network.getId()); - parameters.put(SessionParameter.PASSWORD, "admin"); - parameters.put(SessionParameter.ATOMPUB_URL, url); - parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); - - SessionFactory factory = SessionFactoryImpl.newInstance(); - Repository repository = factory.getRepositories(parameters).get(0); - String rootFolderId = repository.getRootFolderId(); - - assertEquals(rootNodeRef.getId(), rootFolderId); - } - - { - Binding binding = Binding.browser; - String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, "1.1", null); - - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, "admin@" + network.getId()); - parameters.put(SessionParameter.PASSWORD, "admin"); - parameters.put(SessionParameter.BROWSER_URL, url); - parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); - - SessionFactory factory = SessionFactoryImpl.newInstance(); - Repository repository = factory.getRepositories(parameters).get(0); - String rootFolderId = repository.getRootFolderId(); - - assertEquals(rootNodeRef.getId(), rootFolderId); - } - } - - @Test - public void testMNT12956QueryingCMIS11UsesDictionary11() throws Exception - { - final TestNetwork network1 = getTestFixture().getRandomNetwork(); - - String username = "user" + System.currentTimeMillis(); - PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); - TestPerson person = network1.createUser(personInfo); - String personId = person.getId(); - - final List documents = new ArrayList(); - final String filename = GUID.generate(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - TestSite site = repoService.createSite(null, siteInfo); - NodeRef docNodeRef = repoService.createDocument(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), filename, "test content"); - documents.add(docNodeRef); - - return null; - } - }, personId, network1.getId()); - - NodeRef docNodeRef = documents.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); - CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); - CmisSession atomCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); - - // query - { - // searching by NodeRef, expect result objectIds to be objectId - Set expectedObjectIds = new HashSet(); - expectedObjectIds.add(docNodeRef.getId()); - int numMatchingDocs = 0; - - // NodeRef input - List results = atomCmisSession11.query("SELECT cmis:objectId,cmis:name,cmis:secondaryObjectTypeIds FROM cmis:document WHERE cmis:name LIKE '" + filename + "'", false, 0, Integer.MAX_VALUE); - assertEquals(expectedObjectIds.size(), results.size()); - for(CMISNode node : results) - { - String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); - if(expectedObjectIds.contains(objectId)) - { - numMatchingDocs++; - } - } - assertEquals(expectedObjectIds.size(), numMatchingDocs); - - try - { - results = atomCmisSession10.query("SELECT cmis:objectId,cmis:name,cmis:secondaryObjectTypeIds FROM cmis:document WHERE cmis:name LIKE '" + filename + "'", false, 0, Integer.MAX_VALUE); - fail("OpenCMIS 1.0 knows nothing about cmis:secondaryObjectTypeIds"); - } - catch (CmisInvalidArgumentException expectedException) - { - // ok - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Serializable; +import java.io.StringWriter; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.alfresco.cmis.client.AlfrescoDocument; +import org.alfresco.cmis.client.AlfrescoFolder; +import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl; +import org.alfresco.cmis.client.type.AlfrescoType; +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService; +import org.alfresco.opencmis.dictionary.QNameFilter; +import org.alfresco.opencmis.dictionary.QNameFilterImpl; +import org.alfresco.opencmis.mapping.NodeRefProperty; +import org.alfresco.repo.action.ActionModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.filestore.FileContentWriter; +import org.alfresco.repo.dictionary.DictionaryBootstrap; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.version.VersionableAspectTest; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.HttpResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.CmisSession; +import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.CMISNode; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.FolderNode; +import org.alfresco.rest.api.tests.client.data.MemberOfSite; +import org.alfresco.rest.api.tests.client.data.NodeRating; +import org.alfresco.rest.api.tests.client.data.NodeRating.Aggregate; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockType; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; +import org.alfresco.util.TempFileProvider; +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.chemistry.opencmis.client.api.Document; +import org.apache.chemistry.opencmis.client.api.FileableCmisObject; +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.chemistry.opencmis.client.api.ItemIterable; +import org.apache.chemistry.opencmis.client.api.ObjectId; +import org.apache.chemistry.opencmis.client.api.ObjectType; +import org.apache.chemistry.opencmis.client.api.OperationContext; +import org.apache.chemistry.opencmis.client.api.Property; +import org.apache.chemistry.opencmis.client.api.Relationship; +import org.apache.chemistry.opencmis.client.api.Repository; +import org.apache.chemistry.opencmis.client.api.SecondaryType; +import org.apache.chemistry.opencmis.client.api.Session; +import org.apache.chemistry.opencmis.client.api.SessionFactory; +import org.apache.chemistry.opencmis.client.api.Tree; +import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; +import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.SessionParameter; +import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; +import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.io.IOUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.surf.util.URLEncoder; + +public class TestCMIS extends EnterpriseTestApi +{ + private static final String CMIS_VERSION_10 = "1.0"; + + private static final String CMIS_VERSION_11 = "1.1"; + + private static final String TYPE_CMIS_DOCUMENT = "cmis:document"; + + + private static final String DOCUMENT_LIBRARY_CONTAINER_NAME = "documentLibrary"; + + private static final String TEST_SITE_NAME_PATTERN = "testSite-%d"; + + private static final String TEST_USER_NAME_PATTERN = "testUser-%d"; + + private static final String TEST_DOCUMENT_NAME_PATTERN = "testDocument-%s.txt"; + + private static final String DOCUMENT_LIBRARY_PATH_PATTERN = "/Sites/%s/" + DOCUMENT_LIBRARY_CONTAINER_NAME; + + private static final String TEST_PASSWORD = "password"; + + + private DictionaryDAO dictionaryDAO; + private LockService lockService; + private TenantService tenantService; + private CMISStrictDictionaryService cmisDictionary; + private QNameFilter cmisTypeExclusions; + private NodeService nodeService; + private Properties globalProperties; + + @Before + public void before() throws Exception + { + ApplicationContext ctx = getTestFixture().getApplicationContext(); + this.dictionaryDAO = (DictionaryDAO)ctx.getBean("dictionaryDAO"); + this.lockService = (LockService) ctx.getBean("lockService"); + this.tenantService = (TenantService)ctx.getBean("tenantService"); + this.cmisDictionary = (CMISStrictDictionaryService)ctx.getBean("OpenCMISDictionaryService"); + this.cmisTypeExclusions = (QNameFilter)ctx.getBean("cmisTypeExclusions"); + this.nodeService = (NodeService) ctx.getBean("NodeService"); + + this.globalProperties = (Properties) ctx.getBean("global-properties"); + this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "true"); + } + + @After + public void after() + { + this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "false"); + } + + private void checkSecondaryTypes(Document doc, Set expectedSecondaryTypes, Set expectedMissingSecondaryTypes) + { + final List secondaryTypesList = doc.getSecondaryTypes(); + assertNotNull(secondaryTypesList); + List secondaryTypes = new AbstractList() + { + @Override + public String get(int index) + { + SecondaryType type = secondaryTypesList.get(index); + return type.getId(); + } + + @Override + public int size() + { + return secondaryTypesList.size(); + } + }; + if(expectedSecondaryTypes != null) + { + assertTrue("Missing secondary types: " + secondaryTypes, secondaryTypes.containsAll(expectedSecondaryTypes)); + } + if(expectedMissingSecondaryTypes != null) + { + assertTrue("Expected missing secondary types but at least one is still present: " + secondaryTypes, !secondaryTypes.containsAll(expectedMissingSecondaryTypes)); + } + } + + private String getBareObjectId(String objectId) + { + int idx = objectId.indexOf(";"); + String bareObjectId = null; + if(idx != -1) + { + bareObjectId = objectId.substring(0, idx); + } + else + { + bareObjectId = objectId; + } + + return bareObjectId; + } + + /** + * Tests OpenCMIS api. + */ + @SuppressWarnings("unchecked") + @Test + public void testCMIS() throws Exception + { + // Test Case cloud-2353 + // Test Case cloud-2354 + // Test Case cloud-2356 + // Test Case cloud-2378 + // Test Case cloud-2357 + // Test Case cloud-2358 + // Test Case cloud-2360 + + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + Iterator personIt = network1.getPersonIds().iterator(); + final String personId = personIt.next(); + assertNotNull(personId); + Person person = repoService.getPerson(personId); + assertNotNull(person); + + // Create a site + final TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = network1.createSite(siteInfo); + return site; + } + }, personId, network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + Nodes nodesProxy = publicApiClient.nodes(); + Comments commentsProxy = publicApiClient.comments(); + + String expectedContent = "Ipsum and so on"; + Document doc = null; + Folder documentLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary"); + FolderNode expectedDocumentLibrary = (FolderNode)CMISNode.createNode(documentLibrary); + Document testDoc = null; + Folder testFolder = null; + FolderNode testFolderNode = null; + + // create some sub-folders and documents + { + for(int i = 0; i < 3; i++) + { + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); + properties.put(PropertyIds.NAME, "folder-" + i); + } + + Folder f = documentLibrary.createFolder(properties); + FolderNode fn = (FolderNode)CMISNode.createNode(f); + if(testFolder == null) + { + testFolder = f; + testFolderNode = fn; + } + expectedDocumentLibrary.addFolder(fn); + + for(int k = 0; k < 3; k++) + { + properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); + properties.put(PropertyIds.NAME, "folder-" + k); + } + + Folder f1 = f.createFolder(properties); + FolderNode childFolder = (FolderNode)CMISNode.createNode(f1); + fn.addFolder(childFolder); + } + + for(int j = 0; j < 3; j++) + { + properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, "doc-" + j); + } + + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(expectedContent); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + Document d = f.createDocument(properties, fileContent, VersioningState.MAJOR); + if(testDoc == null) + { + testDoc = d; + } + + CMISNode childDocument = CMISNode.createNode(d); + fn.addNode(childDocument); + } + } + + for(int i = 0; i < 10; i++) + { + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, "doc-" + i); + } + + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(expectedContent); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + documentLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + } + } + + // try to add and remove ratings, comments, tags to folders created by CMIS + { + Aggregate aggregate = new Aggregate(1, null); + NodeRating expectedNodeRating = new NodeRating("likes", true, aggregate); + Comment expectedComment = new Comment("commenty", "commenty", false, null, person, person); + Tag expectedTag = new Tag("taggy"); + + NodeRating rating = nodesProxy.createNodeRating(testFolder.getId(), expectedNodeRating); + expectedNodeRating.expected(rating); + assertNotNull(rating.getId()); + + Tag tag = nodesProxy.createNodeTag(testFolder.getId(), expectedTag); + expectedTag.expected(tag); + assertNotNull(tag.getId()); + + Comment comment = commentsProxy.createNodeComment(testFolder.getId(), expectedComment); + expectedComment.expected(comment); + assertNotNull(comment.getId()); + } + + // try to add and remove ratings, comments, tags to documents created by CMIS + { + Aggregate aggregate = new Aggregate(1, null); + NodeRating expectedNodeRating = new NodeRating("likes", true, aggregate); + Comment expectedComment = new Comment("commenty", "commenty", false, null, person, person); + Tag expectedTag = new Tag("taggy"); + + NodeRating rating = nodesProxy.createNodeRating(testDoc.getId(), expectedNodeRating); + expectedNodeRating.expected(rating); + assertNotNull(rating.getId()); + + Tag tag = nodesProxy.createNodeTag(testDoc.getId(), expectedTag); + expectedTag.expected(tag); + assertNotNull(tag.getId()); + + Comment comment = commentsProxy.createNodeComment(testDoc.getId(), expectedComment); + expectedComment.expected(comment); + assertNotNull(comment.getId()); + } + + // descendants + { + List> descendants = documentLibrary.getDescendants(4); + expectedDocumentLibrary.checkDescendants(descendants); + } + + // upload/setContent + { + Map fileProps = new HashMap(); + { + fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(expectedContent); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + doc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); + + String nodeId = stripCMISSuffix(doc.getId()); + final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); + ContentReader reader = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public ContentReader doWork() throws Exception + { + ContentReader reader = repoService.getContent(nodeRef, ContentModel.PROP_CONTENT); + return reader; + } + }, personId, network1.getId()); + + String actualContent = reader.getContentString(); + assertEquals(expectedContent, actualContent); + } + + // get content + { + ContentStream stream = doc.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(stream.getStream(), writer, "UTF-8"); + String actualContent = writer.toString(); + assertEquals(expectedContent, actualContent); + } + + // get children + { + Folder folder = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary/" + testFolder.getName()); + + ItemIterable children = folder.getChildren(); + testFolderNode.checkChildren(children); + } + + // query + { + Folder folder = (Folder)cmisSession.getObjectByPath("/Sites/" + site.getSiteId() + "/documentLibrary/" + testFolder.getName()); + String folderId = folder.getId(); + + Set expectedFolderNames = new HashSet(); + for(CMISNode n : testFolderNode.getFolderNodes().values()) + { + expectedFolderNames.add((String)n.getProperty("cmis:name")); + } + int expectedNumFolders = expectedFolderNames.size(); + int numMatchingFoldersFound = 0; + List results = cmisSession.query("SELECT * FROM cmis:folder WHERE IN_TREE('" + folderId + "')", false, 0, Integer.MAX_VALUE); + for(CMISNode node : results) + { + String name = (String)node.getProperties().get("cmis:name"); + if(expectedFolderNames.contains(name)) + { + numMatchingFoldersFound++; + } + } + assertEquals(expectedNumFolders, numMatchingFoldersFound); + + Set expectedDocNames = new HashSet(); + for(CMISNode n : testFolderNode.getDocumentNodes().values()) + { + expectedDocNames.add((String)n.getProperty("cmis:name")); + } + int expectedNumDocs = expectedDocNames.size(); + int numMatchingDocsFound = 0; + results = cmisSession.query("SELECT * FROM cmis:document where IN_TREE('" + folderId + "')", false, 0, Integer.MAX_VALUE); + for(CMISNode node : results) + { + String name = (String)node.getProperties().get("cmis:name"); + if(expectedDocNames.contains(name)) + { + numMatchingDocsFound++; + } + } + assertEquals(expectedNumDocs, numMatchingDocsFound); + } + + // versioning + { + String nodeId = stripCMISSuffix(doc.getId()); + final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId); + + // checkout + ObjectId pwcId = doc.checkOut(); + Document pwc = (Document)cmisSession.getObject(pwcId.getId()); + Boolean isCheckedOut = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + Boolean isCheckedOut = repoService.isCheckedOut(nodeRef); + return isCheckedOut; + } + }, personId, network1.getId()); + assertTrue(isCheckedOut); + + // checkin with new content + expectedContent = "Big bad wolf"; + + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(expectedContent); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + ObjectId checkinId = pwc.checkIn(true, Collections.EMPTY_MAP, fileContent, "checkin 1"); + doc = (Document)cmisSession.getObject(checkinId.getId()); + isCheckedOut = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + Boolean isCheckedOut = repoService.isCheckedOut(nodeRef); + return isCheckedOut; + } + }, personId, network1.getId()); + assertFalse(isCheckedOut); + + // check that the content has been updated + ContentStream stream = doc.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(stream.getStream(), writer, "UTF-8"); + String actualContent = writer.toString(); + assertEquals(expectedContent, actualContent); + + List allVersions = doc.getAllVersions(); + assertEquals(2, allVersions.size()); + assertEquals("2.0", allVersions.get(0).getVersionLabel()); + assertEquals(CMIS_VERSION_10, allVersions.get(1).getVersionLabel()); + } + + { + // https://issues.alfresco.com/jira/browse/PUBLICAPI-95 + // Test that documents are created with autoVersion=true + + Map fileProps = new HashMap(); + { + fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + { + // a versioned document + + Document autoVersionedDoc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); + String objectId = autoVersionedDoc.getId(); + String bareObjectId = getBareObjectId(objectId); + final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, bareObjectId); + Boolean autoVersion = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + Boolean autoVersion = (Boolean)repoService.getProperty(nodeRef, ContentModel.PROP_AUTO_VERSION); + return autoVersion; + } + }, personId, network1.getId()); + assertEquals(Boolean.TRUE, autoVersion); + } + + // https://issues.alfresco.com/jira/browse/PUBLICAPI-92 + // Test that a get on an objectId without a version suffix returns the current version of the document + { + // do a few checkout, checkin cycles to create some versions + fileProps = new HashMap(); + { + fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + + Document autoVersionedDoc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); + String objectId = autoVersionedDoc.getId(); + String bareObjectId = getBareObjectId(objectId); + + for(int i = 0; i < 3; i++) + { + Document doc1 = (Document)cmisSession.getObject(bareObjectId); + + ObjectId pwcId = doc1.checkOut(); + Document pwc = (Document)cmisSession.getObject(pwcId.getId()); + + ContentStreamImpl contentStream = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + expectedContent = GUID.generate(); + writer.putContent(expectedContent); + ContentReader reader = writer.getReader(); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(reader.getContentInputStream()); + } + pwc.checkIn(true, Collections.EMPTY_MAP, contentStream, "checkin " + i); + } + + // get the object, supplying an objectId without a version suffix + Document doc1 = (Document)cmisSession.getObject(bareObjectId); + String versionLabel = doc1.getVersionLabel(); + ContentStream cs = doc1.getContentStream(); + String content = IOUtils.toString(cs.getStream()); + + assertEquals("4.0", versionLabel); + assertEquals(expectedContent, content); + } + } + } + + /** + * Tests CMIS and non-CMIS public api interactions + */ + @SuppressWarnings("deprecation") + @Test + public void testScenario1() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + Iterator personIt = network1.getPersonIds().iterator(); + final String person = personIt.next(); + assertNotNull(person); + + Sites sitesProxy = publicApiClient.sites(); + Comments commentsProxy = publicApiClient.comments(); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + + ListResponse sites = sitesProxy.getPersonSites(person, null); + assertTrue(sites.getList().size() > 0); + MemberOfSite siteMember = sites.getList().get(0); + String siteId = siteMember.getSite().getSiteId(); + + Folder documentLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteId + "/documentLibrary"); + + System.out.println("documentLibrary id = " + documentLibrary.getId()); + + Map fileProps = new HashMap(); + { + fileProps.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + fileProps.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + Document doc = documentLibrary.createDocument(fileProps, fileContent, VersioningState.MAJOR); + + System.out.println("Document id = " + doc.getId()); + + Comment c = commentsProxy.createNodeComment(doc.getId(), new Comment("comment title 1", "comment 1")); + + System.out.println("Comment = " + c); + + // Now lock the document + String nodeRefStr = (String) doc.getPropertyValue("alfcmis:nodeRef"); + final NodeRef nodeRef = new NodeRef(nodeRefStr); + final TenantRunAsWork runAsWork = new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + lockService.lock(nodeRef, LockType.WRITE_LOCK); + return null; + } + }; + RetryingTransactionCallback txnWork = new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + TenantUtil.runAsUserTenant(runAsWork, "bob", network1.getId()); + return null; + } + }; + transactionHelper.doInTransaction(txnWork); + + // Now attempt to update the document's metadata + try + { + doc.delete(); + } + catch (CmisUpdateConflictException e) + { + // Expected: ACE-762 BM-0012: NodeLockedException not handled by CMIS + } + } + + //@Test + public void testInvalidMethods() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + Iterator personIt = network1.getPersonIds().iterator(); + final String person = personIt.next(); + assertNotNull(person); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + + publicApiClient.post(Binding.atom, CMIS_VERSION_10, null, null); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + + publicApiClient.head(Binding.atom, CMIS_VERSION_10, null, null); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + + publicApiClient.options(Binding.atom, CMIS_VERSION_10, null, null); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + + publicApiClient.trace(Binding.atom, CMIS_VERSION_10, null, null); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person)); + + publicApiClient.patch(Binding.atom, CMIS_VERSION_10, null, null); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + + @Test + public void testPublicApi110() throws Exception + { + Iterator networksIt = getTestFixture().networksIterator(); + final TestNetwork network1 = networksIt.next(); + Iterator personIt = network1.getPersonIds().iterator(); + final String person1Id = personIt.next(); + final String person2Id = personIt.next(); + + final List nodes = new ArrayList(5); + + // Create some favourite targets, sites, files and folders + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName1 = "site" + GUID.generate(); + SiteInformation siteInfo1 = new SiteInformation(siteName1, siteName1, siteName1, SiteVisibility.PUBLIC); + TestSite site1 = network1.createSite(siteInfo1); + + String siteName2 = "site" + GUID.generate(); + SiteInformation siteInfo2 = new SiteInformation(siteName2, siteName2, siteName2, SiteVisibility.PRIVATE); + TestSite site2 = network1.createSite(siteInfo2); + + NodeRef nodeRef1 = repoService.createDocument(site1.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); + nodes.add(nodeRef1); + NodeRef nodeRef2 = repoService.createDocument(site1.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); + nodes.add(nodeRef2); + NodeRef nodeRef3 = repoService.createDocument(site2.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); + nodes.add(nodeRef3); + repoService.createAssociation(nodeRef2, nodeRef1, ContentModel.ASSOC_ORIGINAL); + repoService.createAssociation(nodeRef3, nodeRef1, ContentModel.ASSOC_ORIGINAL); + + site1.inviteToSite(person2Id, SiteRole.SiteCollaborator); + + return null; + } + }, person1Id, network1.getId()); + + { + OperationContext cmisOperationCtxOverride = new OperationContextImpl(); + cmisOperationCtxOverride.setIncludeRelationships(IncludeRelationships.BOTH); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2Id, cmisOperationCtxOverride)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + + CmisObject o1 = cmisSession.getObject(nodes.get(0).getId()); + List relationships = o1.getRelationships(); + assertEquals(1, relationships.size()); + Relationship r = relationships.get(0); + CmisObject source = r.getSource(); + CmisObject target = r.getTarget(); + String sourceVersionSeriesId = (String)source.getProperty(PropertyIds.VERSION_SERIES_ID).getFirstValue(); + String targetVersionSeriesId = (String)target.getProperty(PropertyIds.VERSION_SERIES_ID).getFirstValue(); + assertEquals(nodes.get(1).getId(), sourceVersionSeriesId); + assertEquals(nodes.get(0).getId(), targetVersionSeriesId); + } + } + + @Test + public void testObjectIds() throws Exception + { + String username = "enterpriseuser" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person = repoService.createUser(personInfo, username, null); + String personId = person.getId(); + + final List folders = new ArrayList(); + final List documents = new ArrayList(); + + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + folders.add(folderNodeRef); + + name = GUID.generate(); + NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); + documents.add(docNodeRef); + + return null; + } + }, personId); + + NodeRef folderNodeRef = folders.get(0); + NodeRef docNodeRef = documents.get(0); + + publicApiClient.setRequestContext(new RequestContext(personId)); + + // use cmisatom endpoint + List repositories = publicApiClient.getCMISRepositories(); + CmisSession cmisSession = publicApiClient.getCMISSession(repositories.get(0)); + + // test CMIS accepts NodeRefs and guids as input + // if input is NodeRef, return NodeRef. If input is guid, return guid. + { + String nodeRefStr = docNodeRef.toString(); + CmisObject o = cmisSession.getObject(nodeRefStr); + assertEquals(docNodeRef.toString(), stripCMISSuffix(o.getId())); + + nodeRefStr = folderNodeRef.toString(); + o = cmisSession.getObject(nodeRefStr); + assertEquals(folderNodeRef.toString(), stripCMISSuffix(o.getId())); + + String objectId = docNodeRef.getId(); + o = cmisSession.getObject(objectId); + assertEquals(objectId, stripCMISSuffix(o.getId())); + + objectId = folderNodeRef.getId(); + o = cmisSession.getObject(objectId); + assertEquals(objectId, stripCMISSuffix(o.getId())); + } + + // query + { + // searching by NodeRef, expect result objectIds to be Noderefs + Set expectedObjectIds = new HashSet(); + expectedObjectIds.add(docNodeRef.toString()); + int numMatchingDocs = 0; + + // NodeRef input + List results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.toString() + "')", false, 0, Integer.MAX_VALUE); + assertEquals(expectedObjectIds.size(), results.size()); + for(CMISNode node : results) + { + String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); + if(expectedObjectIds.contains(objectId)) + { + numMatchingDocs++; + } + } + assertEquals(expectedObjectIds.size(), numMatchingDocs); + + // searching by guid, expect result objectIds to be NodeRefs + numMatchingDocs = 0; + + // node guid input + results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.getId() + "')", false, 0, Integer.MAX_VALUE); + assertEquals(expectedObjectIds.size(), results.size()); + for(CMISNode node : results) + { + String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); + System.out.println("objectId = " + objectId); + if(expectedObjectIds.contains(objectId)) + { + numMatchingDocs++; + } + } + assertEquals(expectedObjectIds.size(), numMatchingDocs); + } + + // public api + + Iterator networksIt = getTestFixture().networksIterator(); + final TestNetwork network1 = networksIt.next(); + Iterator personIt = network1.getPersonIds().iterator(); + final String person1Id = personIt.next(); + + final List folders1 = new ArrayList(); + final List documents1 = new ArrayList(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + folders1.add(folderNodeRef); + + name = GUID.generate(); + NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); + documents1.add(docNodeRef); + + return null; + } + }, person1Id, network1.getId()); + + folderNodeRef = folders1.get(0); + docNodeRef = documents1.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + + // test CMIS accepts NodeRefs and guids as input + // objectIds returned from public api CMIS are always the guid + { + String nodeRefStr = docNodeRef.toString(); + CmisObject o = cmisSession.getObject(nodeRefStr); + String objectId = docNodeRef.getId(); + assertEquals(objectId, stripCMISSuffix(o.getId())); + + nodeRefStr = folderNodeRef.toString(); + o = cmisSession.getObject(nodeRefStr); + objectId = folderNodeRef.getId(); + assertEquals(objectId, stripCMISSuffix(o.getId())); + + o = cmisSession.getObject(objectId); + assertEquals(objectId, stripCMISSuffix(o.getId())); + + objectId = folderNodeRef.getId(); + o = cmisSession.getObject(objectId); + assertEquals(objectId, stripCMISSuffix(o.getId())); + } + + // query + { + // searching by NodeRef, expect result objectIds to be objectId + Set expectedObjectIds = new HashSet(); + expectedObjectIds.add(docNodeRef.getId()); + int numMatchingDocs = 0; + + // NodeRef input + List results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.toString() + "')", false, 0, Integer.MAX_VALUE); + assertEquals(expectedObjectIds.size(), results.size()); + for(CMISNode node : results) + { + String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); + if(expectedObjectIds.contains(objectId)) + { + numMatchingDocs++; + } + } + assertEquals(expectedObjectIds.size(), numMatchingDocs); + + // searching by guid, expect result objectIds to be objectId + numMatchingDocs = 0; + + // node guid input + results = cmisSession.query("SELECT * FROM cmis:document WHERE IN_TREE('" + folderNodeRef.getId() + "')", false, 0, Integer.MAX_VALUE); + assertEquals(expectedObjectIds.size(), results.size()); + for(CMISNode node : results) + { + String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); + System.out.println("objectId = " + objectId); + if(expectedObjectIds.contains(objectId)) + { + numMatchingDocs++; + } + } + assertEquals(expectedObjectIds.size(), numMatchingDocs); + } + } + + @Test + public void testAspects() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final List folders = new ArrayList(); + final List documents = new ArrayList(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + folders.add(folderNodeRef); + + for(int i = 0; i < 3; i++) + { + name = GUID.generate(); + NodeRef docNodeRef = repoService.createDocument(folderNodeRef, name, "test content"); + assertFalse(repoService.getAspects(docNodeRef).contains(ContentModel.ASPECT_TITLED)); + documents.add(docNodeRef); + } + + return null; + } + }, person1Id, network1.getId()); + + final NodeRef doc1NodeRef = documents.get(0); + final NodeRef doc2NodeRef = documents.get(1); + final NodeRef doc3NodeRef = documents.get(2); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + CmisSession atomCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + CmisSession browserCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.browser, CMIS_VERSION_11); + + // Test that adding aspects works for both 1.0 and 1.1 + + // 1.0 + { + AlfrescoDocument doc = (AlfrescoDocument)atomCmisSession10.getObject(doc1NodeRef.getId()); + + doc = (AlfrescoDocument)doc.addAspect("P:cm:titled"); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc1NodeRef); + assertTrue("Missing aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + + return null; + } + }, person1Id, network1.getId()); + + doc.removeAspect("P:cm:titled"); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc1NodeRef); + assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + + return null; + } + }, person1Id, network1.getId()); + } + + // 1.1 atom (secondary types) + { + final Document doc = (Document)atomCmisSession11.getObject(doc2NodeRef.getId()); + + final List secondaryTypesList = doc.getSecondaryTypes(); + final List secondaryTypes = new ArrayList(); + if (secondaryTypesList != null) + { + for(SecondaryType secondaryType : secondaryTypesList) + { + secondaryTypes.add(secondaryType.getId()); + } + } + + secondaryTypes.add("P:sys:temporary"); + secondaryTypes.add("P:cm:titled"); + Map properties = new HashMap(); + { + // create a document with 2 secondary types + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc1 = (Document)doc.updateProperties(properties); + checkSecondaryTypes(doc1, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled"})), null); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc2NodeRef); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + + return null; + } + }, person1Id, network1.getId()); + + secondaryTypes.add("P:cm:author"); + properties = new HashMap(); + { + // create a document with 2 secondary types + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc2 = (Document)doc1.updateProperties(properties); + checkSecondaryTypes(doc2, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled", "P:cm:author"})), null); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc2NodeRef); + String title = (String)repoService.getProperty(doc2NodeRef, ContentModel.PROP_TITLE); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + assertEquals(null, title); + + return null; + } + }, person1Id, network1.getId()); + + // remove a secondary type + secondaryTypes.remove("P:cm:titled"); + properties = new HashMap(); + { + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc3 = (Document)doc2.updateProperties(properties); + checkSecondaryTypes(doc3, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:author"})), + new HashSet(Arrays.asList(new String[] {"P:cm:titled"}))); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc2NodeRef); + String title = (String)repoService.getProperty(doc2NodeRef, ContentModel.PROP_TITLE); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + assertEquals(null, title); + + return null; + } + }, person1Id, network1.getId()); + } + + // 1.1 browser (secondary types) + { + Document doc = (Document)browserCmisSession11.getObject(doc3NodeRef.getId()); + final List secondaryTypesList = doc.getSecondaryTypes(); + final List secondaryTypes = new ArrayList(); + if (secondaryTypesList != null) + { + for (SecondaryType secondaryType : secondaryTypesList) + { + secondaryTypes.add(secondaryType.getId()); + } + } + + secondaryTypes.add("P:sys:temporary"); + secondaryTypes.add("P:cm:titled"); + Map properties = new HashMap(); + { + // create a document with 2 secondary types + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc1 = (Document)doc.updateProperties(properties); + checkSecondaryTypes(doc1, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled"})), null); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc3NodeRef); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + return null; + } + }, person1Id, network1.getId()); + + secondaryTypes.add("P:cm:author"); + properties = new HashMap(); + { + // create a document with 2 secondary types + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc2 = (Document)doc1.updateProperties(properties); + checkSecondaryTypes(doc2, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:titled", "P:cm:author"})), null); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc3NodeRef); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); + + return null; + } + }, person1Id, network1.getId()); + + secondaryTypes.remove("P:cm:titled"); + properties = new HashMap(); + { + // create a document with 2 secondary types + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + } + Document doc3 = (Document)doc2.updateProperties(properties); + checkSecondaryTypes(doc3, new HashSet(Arrays.asList(new String[] {"P:sys:temporary", "P:cm:author"})), + new HashSet(Arrays.asList(new String[] {"P:cm:titled"}))); + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Set aspects = repoService.getAspects(doc3NodeRef); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_AUTHOR)); + assertTrue("Missing aspects in current set " + aspects, aspects.contains(ContentModel.ASPECT_TEMPORARY)); + assertFalse("Unexpected aspect in current set " + aspects, aspects.contains(ContentModel.ASPECT_TITLED)); + + return null; + } + }, person1Id, network1.getId()); + } + } + + /** + * ALF-18968 + * + * @see QNameFilterImpl#listOfHardCodedExcludedTypes() + */ + @Test + public void testTypeFiltering() throws Exception + { + // Force an exclusion in order to test the exclusion inheritance + cmisTypeExclusions.setExcluded(ActionModel.TYPE_ACTION_BASE, true); + // Quick check + assertTrue(cmisTypeExclusions.isExcluded(ActionModel.TYPE_ACTION_BASE)); + + // Test that a type defined with this excluded parent type does not break the CMIS dictionary + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + bootstrapModels.add("publicapi/test-model.xml"); + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + cmisDictionary.afterDictionaryInit(); + + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + // test that this type is excluded; the 'action' model (act prefix) is in the list of hardcoded exclusions + QName type = QName.createQName("{http://www.alfresco.org/test/testCMIS}type1"); + assertTrue(cmisTypeExclusions.isExcluded(type)); + + // and that we can't get to it through CMIS + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + try + { + cmisSession.getTypeDefinition("D:testCMIS:type1"); + fail("Type should not be available"); + } + catch(CmisObjectNotFoundException e) + { + // ok + } + } + + /** + * MNT-12680 + * The creation date of version should be the same as creation date of the original node + * @throws Exception + */ + @Test + public void testCreationDate() throws Exception + { + // create a site + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + final TestSite site = network1.createSite(siteInfo); + final NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "testdoc.txt", "Test Doc1 Title", "Test Doc1 Description", + "Test Content"); + return resNode; + } + }, person1Id, network1.getId()); + + // create a document + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + AlfrescoFolder docLibrary = (AlfrescoFolder) cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("some content"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + Document autoVersionedDoc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + String objectId = autoVersionedDoc.getId(); + String bareObjectId = getBareObjectId(objectId); + // create versions + for (int i = 0; i < 3; i++) + { + Document doc1 = (Document) cmisSession.getObject(bareObjectId); + + ObjectId pwcId = doc1.checkOut(); + Document pwc = (Document) cmisSession.getObject(pwcId.getId()); + + ContentStreamImpl contentStream = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(GUID.generate()); + ContentReader reader = writer.getReader(); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(reader.getContentInputStream()); + } + pwc.checkIn(true, Collections.EMPTY_MAP, contentStream, "checkin " + i); + } + + GregorianCalendar cDateFirst = cmisSession.getAllVersions(bareObjectId).get(0).getCreationDate(); + GregorianCalendar cDateSecond = cmisSession.getAllVersions(bareObjectId).get(2).getCreationDate(); + + if (cDateFirst.before(cDateSecond) || cDateFirst.after(cDateSecond)) + { + fail("The creation date of version should be the same as creation date of the original node"); + } + } + + /** + * Test that updating properties does not automatically create a new version. + * Test that updating content creates a new version automatically. + * + */ + @Test + public void testVersioning() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + String versionLabel = doc.getVersionLabel(); + + // ...and check that updating its properties does not create a new version + properties = new HashMap(); + { + properties.put(PropertyIds.DESCRIPTION, GUID.generate()); + } + AlfrescoDocument doc1 = (AlfrescoDocument)doc.updateProperties(properties); + doc1 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); + String versionLabel1 = doc1.getVersionLabel(); + + assertTrue(Float.parseFloat(versionLabel) < Float.parseFloat(versionLabel1)); + + // ...and check that updating its content creates a new version + fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + doc1.setContentStream(fileContent, true); + AlfrescoDocument doc2 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); + @SuppressWarnings("unused") + String versionLabel2 = doc2.getVersionLabel(); + + assertTrue("Set content stream should create a new version automatically", Float.parseFloat(versionLabel1) < Float.parseFloat(versionLabel2)); + } + + /** + * Test that updating properties does automatically create a new version if + * autoVersion, initialVersion and autoVersionOnUpdateProps are TRUE + */ + @Test + public void testVersioningUsingUpdateProperties() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, "1.0", AlfrescoObjectFactoryImpl.class.getName()); + AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document"); + properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + String versionLabel = doc.getVersionLabel(); + + String nodeRefStr = doc.getPropertyValue(NodeRefProperty.NodeRefPropertyId).toString(); + final NodeRef nodeRef = new NodeRef(nodeRefStr); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + // ensure autoversioning is enabled + assertTrue(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)); + + Map versionProperties = new HashMap(); + versionProperties.put(ContentModel.PROP_AUTO_VERSION, true); + versionProperties.put(ContentModel.PROP_INITIAL_VERSION, true); + versionProperties.put(ContentModel.PROP_AUTO_VERSION_PROPS, true); + + nodeService.addProperties(nodeRef, versionProperties); + + return null; + } + }, person1Id, network1.getId()); + + // ...and check that updating its properties creates a new minor version... + properties = new HashMap(); + { + properties.put(PropertyIds.DESCRIPTION, GUID.generate()); + } + AlfrescoDocument doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false).updateProperties(properties); + doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false); + String versionLabel1 = doc1.getVersionLabel(); + + assertTrue(Double.parseDouble(versionLabel) < Double.parseDouble(versionLabel1)); + + // ...and check that updating its content creates a new version + fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + doc1.setContentStream(fileContent, true); + + AlfrescoDocument doc2 = (AlfrescoDocument)doc1.getObjectOfLatestVersion(false); + String versionLabel2 = doc2.getVersionLabel(); + + assertTrue("Set content stream should create a new version automatically", Double.parseDouble(versionLabel1) < Double.parseDouble(versionLabel2)); + assertTrue("It should be latest version : " + versionLabel2, doc2.isLatestVersion()); + + doc2.deleteContentStream(); + AlfrescoDocument doc3 = (AlfrescoDocument)doc2.getObjectOfLatestVersion(false); + String versionLabel3 = doc3.getVersionLabel(); + + assertTrue("Delete content stream should create a new version automatically", Double.parseDouble(versionLabel1) < Double.parseDouble(versionLabel3)); + assertTrue("It should be latest version : " + versionLabel3, doc3.isLatestVersion()); + } + + + /** + * 1) Creating a file with incorrect char in description property + * 2) Get xml with incorrect char in description + * 3) Check xml + * @throws Exception + */ + @Test + public void testGetXmlWithIncorrectDesctiption() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + NodeRef fileNode = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + final TestSite site = network1.createSite(siteInfo); + + NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "testdoc \u0010.txt", "Test Doc1 Title \u0010", "d\u0010", "Test Content"); + return resNode; + } + }, person1Id, network1.getId()); + + String cmisId = fileNode.getId(); + HashMap reqParams = new HashMap(); + reqParams.put("id", cmisId+";1.0"); + reqParams.put("filter", "*"); + reqParams.put("includeAllowableActions", "true"); + reqParams.put("includeACL", "true"); + reqParams.put("includePolicyIds", "true"); + reqParams.put("includeRelationships", "both"); + reqParams.put("renditionFilter", "*"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + HttpResponse resp = publicApiClient.get(Binding.atom, CMIS_VERSION_11, "id", reqParams); + String xml = resp.getResponse(); + // Response hasn't full info at error - writer just stops at incorrect character. + // Therefore we can check end tag of root element + assertTrue("No end tag was found", xml.endsWith("")); + } + + /** + * 1) Creating a file with currency symbols in the name, title and description (MNT-15044) + * 2) Get the document with correct chars in the properties. + * @throws Exception + */ + @Test + public void testGetXmlWithCorrectCurrencySymbols() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + NodeRef fileNode = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + final TestSite site = network1.createSite(siteInfo); + + NodeRef resNode = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), + "Euro \u20AC Pound \u00A3 Franc \u20A3.txt", + "Euro \u20AC Pound \u00A3 Franc \u20A3 File", + "\u20A3 \u00A3 \u20A3", + "\u20A3 \u00A3 \u20A3"); + return resNode; + } + }, person1Id, network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + + String objectId = fileNode.getId(); + Document doc = (Document)atomCmisSession10.getObject(objectId); + + String name = (String)doc.getProperty(PropertyIds.NAME).getFirstValue(); + String title = (String)doc.getProperty("cm:title").getFirstValue(); + String description = (String)doc.getProperty("cm:description").getFirstValue(); + + assertEquals("Euro \u20AC Pound \u00A3 Franc \u20A3.txt", name); + assertEquals("Euro \u20AC Pound \u00A3 Franc \u20A3 File", title); + assertEquals("\u20A3 \u00A3 \u20A3", description); + } + + /* + * Test that creating a document with a number of initial aspects does not create lots of initial versions + */ + @Test + public void testALF19320() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + AlfrescoFolder docLibrary = (AlfrescoFolder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + Map properties = new HashMap(); + { + // create a document with 2 aspects + properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document,P:cm:titled,P:cm:author"); + properties.put(PropertyIds.NAME, "mydoc-" + GUID.generate() + ".txt"); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + AlfrescoDocument doc = (AlfrescoDocument)docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + String versionLabel = doc.getVersionLabel(); + assertEquals(CMIS_VERSION_10, versionLabel); + + AlfrescoDocument doc1 = (AlfrescoDocument)doc.getObjectOfLatestVersion(false); + String versionLabel1 = doc1.getVersionLabel(); + assertEquals(CMIS_VERSION_10, versionLabel1); + } + + /* MNT-10175 test */ + @Test + public void testAppendContentVersioning() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + // Use CMIS 1.1 to test content appending + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + String name = GUID.generate() + ".txt"; + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, name); + } + // Create content to append + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + String versionLabel1 = doc.getObjectOfLatestVersion(false).getVersionLabel(); + + // append a few times + for(int i = 0; i < 5; i++) + { + doc.appendContentStream(fileContent, false); + } + + String versionLabel2 = doc.getObjectOfLatestVersion(false).getVersionLabel(); + + // Version label should not be incremented by appending with isLustChunk = false + assertEquals(versionLabel1, versionLabel2); + + doc.appendContentStream(fileContent, true); + + String versionLabel3 = doc.getObjectOfLatestVersion(false).getVersionLabel(); + Integer majorVer1 = Integer.valueOf(versionLabel2.substring(0, 1)); + Integer majorVer2 = Integer.valueOf(versionLabel3.substring(0, 1)); + + Integer minorVer1 = Integer.valueOf(versionLabel2.substring(2, 3)); + Integer minorVer2 = Integer.valueOf(versionLabel3.substring(2, 3)); + + // Only one MINOR version should be created + assertEquals(majorVer1, majorVer2); + assertEquals(Integer.valueOf(minorVer1 + 1), minorVer2); + } + + @Test + public void testAppendContentStream() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + String name = "mydoc-" + GUID.generate() + ".txt"; + Map properties = new HashMap(); + { + // create a document with 2 aspects + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, name); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + + // append a few times + for(int i = 0; i < 5; i++) + { + fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + doc.appendContentStream(fileContent, false); + } + fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + doc.appendContentStream(fileContent, true); + + // check the appends + String path = "/Sites/" + siteName + "/documentLibrary/" + name; + Document doc1 = (Document)cmisSession.getObjectByPath(path); + ContentStream contentStream = doc1.getContentStream(); + InputStream in = contentStream.getStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(in, writer, "UTF-8"); + String content = writer.toString(); + assertEquals("Ipsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so onIpsum and so on", content); + } + + @Test + public void testSecondaryTypes() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + String name = "mydoc-" + GUID.generate() + ".txt"; + final List secondaryTypes = new ArrayList(); + secondaryTypes.add("P:cm:summarizable"); + Map properties = new HashMap(); + { + // create a document with 2 aspects + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes); + properties.put("cm:summary", "My summary"); + properties.put(PropertyIds.NAME, name); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + + { + // check that the secondary types and properties are present + { + checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); + String summary = (String)doc.getProperty("cm:summary").getFirstValue(); + assertEquals("My summary", summary); + } + + { + doc = (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + name); + checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); + String summary = (String)doc.getProperty("cm:summary").getFirstValue(); + assertEquals("My summary", summary); + } + } + + // update property and check + { + properties = new HashMap(); + { + properties.put("cm:summary", "My updated summary"); + } + doc.updateProperties(properties); + + { + doc = (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + name); + checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); + String summary = (String)doc.getProperty("cm:summary").getFirstValue(); + assertEquals("My updated summary", summary); + } + + { + checkSecondaryTypes(doc, Collections.singleton("P:cm:summarizable"), null); + String summary = (String)doc.getProperty("cm:summary").getFirstValue(); + assertEquals("My updated summary", summary); + } + } + } + + /* MNT-10161 related test - mapping of cmis:description for CMIS 1.1 */ + @Test + public void testMNT_10161() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + final String nodeDescription = "Test description"; + + final String nodeName = GUID.generate(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), nodeName); + /* create node with property description */ + return repoService.createDocument(folderNodeRef, nodeName, "title", nodeDescription, "content"); + } + }, person1Id, network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Document doc = + (Document)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary/" + nodeName + "/" + nodeName); + + /* ensure we got the node */ + assertNotNull(doc); + + /* get mapped cmis:description */ + Property descrProperty = doc.getProperty(PropertyIds.DESCRIPTION); + + /* ensure that cmis:description is set properly */ + assertTrue(nodeDescription.equals(descrProperty.getValue())); + } + + /* MNT-10687 related test - appendContent to PWC CMIS 1.1 */ + @Test + public void testMNT_10687() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + String name = "mydoc-" + GUID.generate() + ".txt"; + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, name); + } + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + /* Create document */ + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + + /* Checkout document */ + ObjectId pwcId = doc.checkOut(); + Document pwc = (Document)cmisSession.getObject(pwcId.getId()); + + /* append content to PWC */ + fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent(" and so on"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + pwc.appendContentStream(fileContent, true); + + pwc.checkIn(false, null, null, "Check In"); + + ContentStream contentStream = doc.getObjectOfLatestVersion(false).getContentStream(); + InputStream in = contentStream.getStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(in, writer, "UTF-8"); + String content = writer.toString(); + assertEquals("Ipsum and so on", content); + } + + @Test + public void testMNT_13057() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + String guid = GUID.generate(); + String name = guid + "_KRUIS_LOGO_100%_PMS.txt"; + String urlFileName = guid + "_KRUIS_LOGO_100%25_PMS.txt"; + + final String siteName = "site" + System.currentTimeMillis(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, person1Id, network1.getId()); + + // Create a document... + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder)cmisSession.getObjectByPath("/Sites/" + siteName + "/documentLibrary"); + + Map properties = new HashMap(); + { + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, name); + } + + ContentStreamImpl fileContent = new ContentStreamImpl(); + { + ContentWriter writer = new FileContentWriter(TempFileProvider.createTempFile(GUID.generate(), ".txt")); + writer.putContent("Ipsum"); + ContentReader reader = writer.getReader(); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(reader.getContentInputStream()); + } + + /* Create document */ + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + + String id = doc.getId(); + assertNotNull(id); + Map params = new HashMap(); + params.put("id", URLEncoder.encode(id)); + + urlFileName += "?id=" + URLEncoder.encode(id); + + HttpResponse response = publicApiClient.get(network1.getId() + "/public/cmis/versions/1.1/atom/content/" + urlFileName, null); + assertEquals(200, response.getStatusCode()); + } + + @Test + public void testMNT10430() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, + null, null, null, null, null); + TestPerson person1 = network1.createUser(personInfo); + String person1Id = person1.getId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.browser, CMIS_VERSION_11, + "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); + + ObjectType objectType = cmisSession.getTypeDefinition("D:testcmis:maDoc"); + + // try and get the mandatory aspects + List mandatoryAspects = ((AlfrescoType)objectType).getMandatoryAspects(); + System.out.println("Mandatory Aspects"); + for(String mandatoryAspect : mandatoryAspects) + { + System.out.println(mandatoryAspect); + } + assertTrue("The aspects should have P:cm:generalclassifiable", mandatoryAspects.contains("P:cm:generalclassifiable")); + } + + @Test + public void testMnt11631() throws Exception + { + final TestNetwork network = getTestFixture().getRandomNetwork(); + + String username = String.format(TEST_USER_NAME_PATTERN, System.currentTimeMillis()); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person = network.createUser(personInfo); + String personId = person.getId(); + + final String siteName = String.format(TEST_SITE_NAME_PATTERN, System.currentTimeMillis()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + + String name = GUID.generate(); + NodeRef folderNodeRef = repoService.createFolder(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), name); + return folderNodeRef; + } + }, personId, network.getId()); + + publicApiClient.setRequestContext(new RequestContext(network.getId(), personId)); + CmisSession cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + Folder docLibrary = (Folder) cmisSession.getObjectByPath(String.format(DOCUMENT_LIBRARY_PATH_PATTERN, siteName)); + String name = String.format(TEST_DOCUMENT_NAME_PATTERN, GUID.generate()); + + Map properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, TYPE_CMIS_DOCUMENT); + properties.put(PropertyIds.NAME, name); + + ContentStreamImpl fileContent = new ContentStreamImpl(); + ByteArrayInputStream stream = new ByteArrayInputStream(GUID.generate().getBytes()); + fileContent.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + fileContent.setStream(stream); + + Document doc = docLibrary.createDocument(properties, fileContent, VersioningState.MAJOR); + + ObjectId pwcId = doc.checkOut(); + Document pwc = (Document) cmisSession.getObject(pwcId.getId()); + + assertIsPwcProperty(pwc, false); + + cmisSession = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10); + CmisObject pwc10 = cmisSession.getObject(pwc.getId()); + assertIsPwcProperty(pwc10, true); + } + + private void assertIsPwcProperty(CmisObject pwc, boolean nullExpected) + { + boolean isPwcFound = false; + Boolean isPwcValueTrue = null; + for (Property property : pwc.getProperties()) + { + if ((null != property) && PropertyIds.IS_PRIVATE_WORKING_COPY.equals(property.getId())) + { + isPwcFound = true; + isPwcValueTrue = property.getValue(); + break; + } + } + + if (nullExpected) + { + assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property is not null!"), !isPwcFound || (null == isPwcValueTrue)); + return; + } + + assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property has not been found!"), isPwcFound); + assertNotNull(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property value must not be null!"), isPwcValueTrue); + assertTrue(("'" + PropertyIds.IS_PRIVATE_WORKING_COPY + "' property value must be equal to 'true'!"), isPwcValueTrue); + } + + @Test + public void testCanConnectCMISUsingDefaultTenant() throws Exception + { + testCanConnectCMISUsingDefaultTenantImpl(Binding.atom, CMIS_VERSION_11); + testCanConnectCMISUsingDefaultTenantImpl(Binding.atom, CMIS_VERSION_10); + testCanConnectCMISUsingDefaultTenantImpl(Binding.browser, CMIS_VERSION_11); + } + + private void testCanConnectCMISUsingDefaultTenantImpl(Binding binding, String cmisVersion) + { + String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, cmisVersion, null); + + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, "admin"); + parameters.put(SessionParameter.PASSWORD, "admin"); + + parameters.put(SessionParameter.ATOMPUB_URL, url); + parameters.put(SessionParameter.BROWSER_URL, url); + parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); + + SessionFactory factory = SessionFactoryImpl.newInstance(); + // perform request : http://host:port/alfresco/api/-default-/public/cmis/versions/${cmisVersion}/${binding} + List repositories = factory.getRepositories(parameters); + + assertTrue(repositories.size() > 0); + + parameters.put(SessionParameter.REPOSITORY_ID, TenantUtil.DEFAULT_TENANT); + Session session = factory.createSession(parameters); + // perform request : http://host:port/alfresco/api/-default-/public/cmis/versions/${cmisVersion}/${binding}/type?id=cmis:document + ObjectType objectType = session.getTypeDefinition("cmis:document"); + + assertNotNull(objectType); + } + + @Test + public void testACE3433() throws Exception + { + final TestNetwork network = getTestFixture().getRandomNetwork(); + + NodeRef rootNodeRef = TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + NodeRef rootNodeRef = repoService.getNodeService().getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + List childAssocs = repoService.getNodeService().getChildAssocsByPropertyValue(rootNodeRef, + ContentModel.PROP_TITLE, "Company Home"); + assertEquals(1, childAssocs.size()); + NodeRef companyHomeNodeRef = childAssocs.get(0).getChildRef(); + return companyHomeNodeRef; + } + + }, network.getId()); + assertNotNull(rootNodeRef); + + // atom + { + Binding binding = Binding.atom; + String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, "1.1", null); + + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, "admin@" + network.getId()); + parameters.put(SessionParameter.PASSWORD, "admin"); + parameters.put(SessionParameter.ATOMPUB_URL, url); + parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); + + SessionFactory factory = SessionFactoryImpl.newInstance(); + Repository repository = factory.getRepositories(parameters).get(0); + String rootFolderId = repository.getRootFolderId(); + + assertEquals(rootNodeRef.getId(), rootFolderId); + } + + { + Binding binding = Binding.browser; + String url = httpClient.getPublicApiCmisUrl(TenantUtil.DEFAULT_TENANT, binding, "1.1", null); + + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, "admin@" + network.getId()); + parameters.put(SessionParameter.PASSWORD, "admin"); + parameters.put(SessionParameter.BROWSER_URL, url); + parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); + + SessionFactory factory = SessionFactoryImpl.newInstance(); + Repository repository = factory.getRepositories(parameters).get(0); + String rootFolderId = repository.getRootFolderId(); + + assertEquals(rootNodeRef.getId(), rootFolderId); + } + } + + @Test + public void testMNT12956QueryingCMIS11UsesDictionary11() throws Exception + { + final TestNetwork network1 = getTestFixture().getRandomNetwork(); + + String username = "user" + System.currentTimeMillis(); + PersonInfo personInfo = new PersonInfo(username, username, username, TEST_PASSWORD, null, null, null, null, null, null, null); + TestPerson person = network1.createUser(personInfo); + String personId = person.getId(); + + final List documents = new ArrayList(); + final String filename = GUID.generate(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + TestSite site = repoService.createSite(null, siteInfo); + NodeRef docNodeRef = repoService.createDocument(site.getContainerNodeRef(DOCUMENT_LIBRARY_CONTAINER_NAME), filename, "test content"); + documents.add(docNodeRef); + + return null; + } + }, personId, network1.getId()); + + NodeRef docNodeRef = documents.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); + CmisSession atomCmisSession10 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_10, AlfrescoObjectFactoryImpl.class.getName()); + CmisSession atomCmisSession11 = publicApiClient.createPublicApiCMISSession(Binding.atom, CMIS_VERSION_11); + + // query + { + // searching by NodeRef, expect result objectIds to be objectId + Set expectedObjectIds = new HashSet(); + expectedObjectIds.add(docNodeRef.getId()); + int numMatchingDocs = 0; + + // NodeRef input + List results = atomCmisSession11.query("SELECT cmis:objectId,cmis:name,cmis:secondaryObjectTypeIds FROM cmis:document WHERE cmis:name LIKE '" + filename + "'", false, 0, Integer.MAX_VALUE); + assertEquals(expectedObjectIds.size(), results.size()); + for(CMISNode node : results) + { + String objectId = stripCMISSuffix((String)node.getProperties().get(PropertyIds.OBJECT_ID)); + if(expectedObjectIds.contains(objectId)) + { + numMatchingDocs++; + } + } + assertEquals(expectedObjectIds.size(), numMatchingDocs); + + try + { + results = atomCmisSession10.query("SELECT cmis:objectId,cmis:name,cmis:secondaryObjectTypeIds FROM cmis:document WHERE cmis:name LIKE '" + filename + "'", false, 0, Integer.MAX_VALUE); + fail("OpenCMIS 1.0 knows nothing about cmis:secondaryObjectTypeIds"); + } + catch (CmisInvalidArgumentException expectedException) + { + // ok + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestCMISAPI.java b/source/test-java/org/alfresco/rest/api/tests/TestCMISAPI.java index b6afae3ac9..e21deda113 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestCMISAPI.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestCMISAPI.java @@ -1,27 +1,27 @@ -package org.alfresco.rest.api.tests; - -import org.junit.AfterClass; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -/** - * Public CMIS API tests. - * - * @author steveglover - * - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestEnterpriseAtomPubTCK.class, - TestPublicApiAtomPub10TCK.class, - TestPublicApiAtomPub11TCK.class, - TestPublicApiBrowser11TCK.class -}) -public class TestCMISAPI -{ - @AfterClass - public static void after() throws Exception - { -// EnterprisePublicApiTestFixture.cleanup(); - } -} +package org.alfresco.rest.api.tests; + +import org.junit.AfterClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Public CMIS API tests. + * + * @author steveglover + * + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestEnterpriseAtomPubTCK.class, + TestPublicApiAtomPub10TCK.class, + TestPublicApiAtomPub11TCK.class, + TestPublicApiBrowser11TCK.class +}) +public class TestCMISAPI +{ + @AfterClass + public static void after() throws Exception + { +// EnterprisePublicApiTestFixture.cleanup(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestEnterpriseAtomPubTCK.java b/source/test-java/org/alfresco/rest/api/tests/TestEnterpriseAtomPubTCK.java index c509ea900f..18be216c44 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestEnterpriseAtomPubTCK.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestEnterpriseAtomPubTCK.java @@ -1,194 +1,194 @@ -package org.alfresco.rest.api.tests; - -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.opencmis.OpenCMISClientContext; -import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; -import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; -import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; -import org.alfresco.repo.dictionary.DictionaryDAO; -import org.alfresco.repo.dictionary.M2Aspect; -import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.M2Property; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.web.util.JettyComponent; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; -import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; -import org.apache.chemistry.opencmis.tck.impl.TestParameters; -import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; -import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; -import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; -import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; -import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; -import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; -import org.apache.chemistry.opencmis.tck.tests.types.TypesTestGroup; -import org.apache.chemistry.opencmis.tck.tests.versioning.CheckedOutTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersionDeleteTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningSmokeTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningStateCreateTest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.Test; - -/** - * OpenCMIS TCK unit tests. - * - * @author steveglover - * - */ -public class TestEnterpriseAtomPubTCK extends AbstractEnterpriseOpenCMIS10TCKTest -{ - private static final String CMIS_URL = "http://{0}:{1}/{2}/cmisatom"; - protected static final Log logger = LogFactory.getLog(TestEnterpriseAtomPubTCK.class); - - private static NodeRef getCompanyHome(NodeService nodeService, SearchService searchService, NamespaceService namespaceService) - { - NodeRef storeRootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); - List results = searchService.selectNodes( - storeRootNodeRef, - "/app:company_home", - null, - namespaceService, - false, - SearchService.LANGUAGE_XPATH); - if (results.size() == 0) - { - throw new AlfrescoRuntimeException("Didn't find Company Home"); - } - NodeRef companyHomeNodeRef = results.get(0); - return companyHomeNodeRef; - } - - @Before - public void setup() throws Exception - { - JettyComponent jetty = getTestFixture().getJettyComponent(); - - final SearchService searchService = (SearchService)jetty.getApplicationContext().getBean("searchService");; - final NodeService nodeService = (NodeService)jetty.getApplicationContext().getBean("nodeService"); - final FileFolderService fileFolderService = (FileFolderService)jetty.getApplicationContext().getBean("fileFolderService"); - final NamespaceService namespaceService = (NamespaceService)jetty.getApplicationContext().getBean("namespaceService"); - final TransactionService transactionService = (TransactionService)jetty.getApplicationContext().getBean("transactionService"); - final String name = "abc" + System.currentTimeMillis(); - - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - NodeRef companyHome = getCompanyHome(nodeService, searchService, namespaceService); - fileFolderService.create(companyHome, name, ContentModel.TYPE_FOLDER).getNodeRef(); - - return null; - } - }, false, true); - - int port = jetty.getPort(); - Map cmisParameters = new HashMap(); - cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); - cmisParameters.put(TestParameters.DEFAULT_TEST_FOLDER_PARENT, "/" + name); - clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, - MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco"), "admin", "admin", cmisParameters, jetty.getApplicationContext()); - - overrideVersionableAspectProperties(jetty.getApplicationContext()); - } - -// Commented out: See https://issues.alfresco.com/jira/browse/MNT-11123?focusedCommentId=339130&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-339130 -// @Test -// public void testCMISTCKBasics() throws Exception -// { -// BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); -// JUnitHelper.run(basicsTestGroup); -// } - - @Test - public void testCMISTCKCRUD() throws Exception - { - CRUDTestGroup crudTestGroup = new CRUDTestGroup(); - JUnitHelper.run(crudTestGroup); - } - - @Test - public void testCMISTCKVersioning() throws Exception - { - OverrideVersioningTestGroup versioningTestGroup = new OverrideVersioningTestGroup(); - JUnitHelper.run(versioningTestGroup); - } - - @Test - public void testCMISTCKFiling() throws Exception - { - FilingTestGroup filingTestGroup = new FilingTestGroup(); - JUnitHelper.run(filingTestGroup); - } - - @Test - public void testCMISTCKControl() throws Exception - { - ControlTestGroup controlTestGroup = new ControlTestGroup(); - JUnitHelper.run(controlTestGroup); - } - - @Test - public void testCMISTCKQuery() throws Exception - { - OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); - JUnitHelper.run(queryTestGroup); - } - - private class OverrideVersioningTestGroup extends AbstractSessionTestGroup - { - @Override - public void init(Map parameters) throws Exception - { - super.init(parameters); - - setName("Versioning Test Group"); - setDescription("Versioning tests."); - - addTest(new VersioningSmokeTest()); - addTest(new VersionDeleteTest()); - addTest(new VersioningStateCreateTest()); - // relies on Solr being available - addTest(new CheckedOutTest()); - } - } - - private class OverrideQueryTestGroup extends AbstractSessionTestGroup - { - @Override - public void init(Map parameters) throws Exception - { - super.init(parameters); - - setName("Query Test Group"); - setDescription("Query and content changes tests."); - - addTest(new QuerySmokeTest()); - // The test fails on Lucene see MNT-11223 - // addTest(new QueryRootFolderTest()); - addTest(new QueryForObjectCustom()); - addTest(new QueryLikeTestCustom()); - addTest(new QueryInFolderTestCustom()); - addTest(new ContentChangesSmokeTest()); - } - } -} +package org.alfresco.rest.api.tests; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.OpenCMISClientContext; +import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; +import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; +import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.M2Aspect; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.repo.dictionary.M2Property; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.web.util.JettyComponent; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; +import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; +import org.apache.chemistry.opencmis.tck.impl.TestParameters; +import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; +import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; +import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; +import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; +import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; +import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; +import org.apache.chemistry.opencmis.tck.tests.types.TypesTestGroup; +import org.apache.chemistry.opencmis.tck.tests.versioning.CheckedOutTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersionDeleteTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningSmokeTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningStateCreateTest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; + +/** + * OpenCMIS TCK unit tests. + * + * @author steveglover + * + */ +public class TestEnterpriseAtomPubTCK extends AbstractEnterpriseOpenCMIS10TCKTest +{ + private static final String CMIS_URL = "http://{0}:{1}/{2}/cmisatom"; + protected static final Log logger = LogFactory.getLog(TestEnterpriseAtomPubTCK.class); + + private static NodeRef getCompanyHome(NodeService nodeService, SearchService searchService, NamespaceService namespaceService) + { + NodeRef storeRootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + List results = searchService.selectNodes( + storeRootNodeRef, + "/app:company_home", + null, + namespaceService, + false, + SearchService.LANGUAGE_XPATH); + if (results.size() == 0) + { + throw new AlfrescoRuntimeException("Didn't find Company Home"); + } + NodeRef companyHomeNodeRef = results.get(0); + return companyHomeNodeRef; + } + + @Before + public void setup() throws Exception + { + JettyComponent jetty = getTestFixture().getJettyComponent(); + + final SearchService searchService = (SearchService)jetty.getApplicationContext().getBean("searchService");; + final NodeService nodeService = (NodeService)jetty.getApplicationContext().getBean("nodeService"); + final FileFolderService fileFolderService = (FileFolderService)jetty.getApplicationContext().getBean("fileFolderService"); + final NamespaceService namespaceService = (NamespaceService)jetty.getApplicationContext().getBean("namespaceService"); + final TransactionService transactionService = (TransactionService)jetty.getApplicationContext().getBean("transactionService"); + final String name = "abc" + System.currentTimeMillis(); + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + NodeRef companyHome = getCompanyHome(nodeService, searchService, namespaceService); + fileFolderService.create(companyHome, name, ContentModel.TYPE_FOLDER).getNodeRef(); + + return null; + } + }, false, true); + + int port = jetty.getPort(); + Map cmisParameters = new HashMap(); + cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); + cmisParameters.put(TestParameters.DEFAULT_TEST_FOLDER_PARENT, "/" + name); + clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, + MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco"), "admin", "admin", cmisParameters, jetty.getApplicationContext()); + + overrideVersionableAspectProperties(jetty.getApplicationContext()); + } + +// Commented out: See https://issues.alfresco.com/jira/browse/MNT-11123?focusedCommentId=339130&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-339130 +// @Test +// public void testCMISTCKBasics() throws Exception +// { +// BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); +// JUnitHelper.run(basicsTestGroup); +// } + + @Test + public void testCMISTCKCRUD() throws Exception + { + CRUDTestGroup crudTestGroup = new CRUDTestGroup(); + JUnitHelper.run(crudTestGroup); + } + + @Test + public void testCMISTCKVersioning() throws Exception + { + OverrideVersioningTestGroup versioningTestGroup = new OverrideVersioningTestGroup(); + JUnitHelper.run(versioningTestGroup); + } + + @Test + public void testCMISTCKFiling() throws Exception + { + FilingTestGroup filingTestGroup = new FilingTestGroup(); + JUnitHelper.run(filingTestGroup); + } + + @Test + public void testCMISTCKControl() throws Exception + { + ControlTestGroup controlTestGroup = new ControlTestGroup(); + JUnitHelper.run(controlTestGroup); + } + + @Test + public void testCMISTCKQuery() throws Exception + { + OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); + JUnitHelper.run(queryTestGroup); + } + + private class OverrideVersioningTestGroup extends AbstractSessionTestGroup + { + @Override + public void init(Map parameters) throws Exception + { + super.init(parameters); + + setName("Versioning Test Group"); + setDescription("Versioning tests."); + + addTest(new VersioningSmokeTest()); + addTest(new VersionDeleteTest()); + addTest(new VersioningStateCreateTest()); + // relies on Solr being available + addTest(new CheckedOutTest()); + } + } + + private class OverrideQueryTestGroup extends AbstractSessionTestGroup + { + @Override + public void init(Map parameters) throws Exception + { + super.init(parameters); + + setName("Query Test Group"); + setDescription("Query and content changes tests."); + + addTest(new QuerySmokeTest()); + // The test fails on Lucene see MNT-11223 + // addTest(new QueryRootFolderTest()); + addTest(new QueryForObjectCustom()); + addTest(new QueryLikeTestCustom()); + addTest(new QueryInFolderTestCustom()); + addTest(new ContentChangesSmokeTest()); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestFavouriteSites.java b/source/test-java/org/alfresco/rest/api/tests/TestFavouriteSites.java index 499931c43f..275c99b102 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestFavouriteSites.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestFavouriteSites.java @@ -1,521 +1,521 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.FavouriteSite; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Test; - -public class TestFavouriteSites extends EnterpriseTestApi -{ - @Test - public void testFavouriteSites() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - assertTrue(networksIt.hasNext()); - final TestNetwork network1 = networksIt.next(); - assertTrue(networksIt.hasNext()); - final TestNetwork network2 = networksIt.next(); - - // Create some users and sites - final List people = new ArrayList(); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - person = network2.createUser(); - people.add(person); - - return null; - } - }, network2.getId()); - - final TestPerson person1 = people.get(0); - final TestPerson person2 = people.get(1); - final TestPerson person3 = people.get(2); - final TestPerson person4 = people.get(3); - final TestPerson person5 = people.get(3); - - TestSite testSite = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network1.createSite(siteInfo); - } - }, person1.getId(), network1.getId()); - } - }, false, true); - - TestSite testSite1 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network1.createSite(siteInfo); - } - }, person1.getId(), network1.getId()); - } - }, false, true); - - TestSite testSite3 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network1.createSite(siteInfo); - } - }, person1.getId(), network1.getId()); - } - }, false, true); - - TestSite testSite4 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public TestSite execute() throws Throwable - { - return TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); - return network1.createSite(siteInfo); - } - }, person5.getId(), network2.getId()); - } - }, false, true); - - Sites sitesProxy = publicApiClient.sites(); - - // invalid methods - try - { - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.create("people", person1.getId(), "favorite-sites", testSite.getSiteId(), fs.toJSON().toString(), "Unable to POST to a favorite-site"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.update("people", person1.getId(), "favorite-sites", null, fs.toJSON().toString(), "Unable to PUT favorite-sites"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.update("people", person1.getId(), "favorite-sites", testSite.getSiteId(), fs.toJSON().toString(), "Unable to PUT a favorite-site"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.remove("people", person1.getId(), "favorite-sites", null, "Unable to DELETE favorite-sites"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // Create favourite site - - // unknown user - 404 - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - sitesProxy.createFavouriteSite("invalid.user", fs); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // user from another network - 401 (not able to auth against tenant) - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - sitesProxy.createFavouriteSite(person1.getId(), fs); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // another user from the same network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - sitesProxy.createFavouriteSite(person2.getId(), fs); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // a member of this site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - FavouriteSite resp = sitesProxy.createFavouriteSite(person1.getId(), fs); - fs.expected(resp); - } - - // add same favourite site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.createFavouriteSite(person1.getId(), new FavouriteSite(testSite.getSiteId())); - fail(); - } - catch(PublicApiException e) - { - assertEquals(409, e.getHttpResponse().getStatusCode()); - } - - // "-me" user - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); - FavouriteSite resp = sitesProxy.createFavouriteSite(org.alfresco.rest.api.People.DEFAULT_USER, fs); - fs.expected(resp); - - final List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - return repoService.getFavouriteSites(person2); - } - }, person2.getId(), network1.getId()); - - // check it's there - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.getFavouriteSites(person2.getId(), createParams(paging, null)); - } - - // not a member of this site - { - FavouriteSite fs = new FavouriteSite(testSite1.getSiteId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite ret = sitesProxy.createFavouriteSite(person1.getId(), fs); - fs.expected(ret); - } - - // GET favourite sites - { - final List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - return repoService.getFavouriteSites(person1); - } - }, person1.getId(), network1.getId()); - - // Test Case cloud-1490 - // unknown user - try - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.getFavouriteSites(GUID.generate(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // authentication: unknown user - try - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), GUID.generate(), "password")); - sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // another user from the same network - 403 - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // another user from another network - 401 - try - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); - sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // successful GET - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); - } - - // skipCount is greater than the number of favourite sites - { - int skipCount = expectedFavouriteSites.size() + 100; - Paging paging = getPaging(skipCount, null, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - List expected = Collections.emptyList(); - ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - checkList(expected, paging.getExpectedPaging(), response); - } - - // "-me-" user - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = sitesProxy.getFavouriteSites(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); - checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); - } - } - - // user is a member of the site which he has favourited - { - publicApiClient.setRequestContext(new RequestContext(network2.getId(), person5.getId())); - - List expectedFavouriteSites = new ArrayList(1); - FavouriteSite fs = new FavouriteSite(testSite4.getSiteId()); - expectedFavouriteSites.add(fs); - - FavouriteSite ret = sitesProxy.createFavouriteSite(person5.getId(), fs); - fs.expected(ret); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - ListResponse response = sitesProxy.getFavouriteSites(person5.getId(), createParams(paging, null)); - checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); - } - - // remove - { - // create some favourite sites - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - FavouriteSite fs = new FavouriteSite(testSite); - sitesProxy.createFavouriteSite(person3.getId(), fs); - fs = new FavouriteSite(testSite1); - sitesProxy.createFavouriteSite(person3.getId(), fs); - } - - // known user - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite); - sitesProxy.removeFavouriteSite(person1.getId(), fs); - - List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - return repoService.getFavouriteSites(person1); - } - }, person1.getId(), network1.getId()); - - // check removed - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); - assertFalse(response.getList().contains(fs)); - } - - // unknown user - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite); - sitesProxy.removeFavouriteSite(GUID.generate(), fs); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(GUID.generate()); - sitesProxy.removeFavouriteSite(person1.getId(), fs); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // try to remove a favourite site that is not a favourite site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - FavouriteSite fs = new FavouriteSite(testSite3); - sitesProxy.removeFavouriteSite(person1.getId(), fs); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // "-me-" user - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - FavouriteSite fs = new FavouriteSite(testSite1); - sitesProxy.removeFavouriteSite(org.alfresco.rest.api.People.DEFAULT_USER, fs); - - List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - return repoService.getFavouriteSites(person3); - } - }, person3.getId(), network1.getId()); - - // check removed - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - ListResponse response = sitesProxy.getFavouriteSites(person3.getId(), createParams(paging, null)); - assertFalse(response.getList().contains(fs)); - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.FavouriteSite; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Test; + +public class TestFavouriteSites extends EnterpriseTestApi +{ + @Test + public void testFavouriteSites() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + assertTrue(networksIt.hasNext()); + final TestNetwork network1 = networksIt.next(); + assertTrue(networksIt.hasNext()); + final TestNetwork network2 = networksIt.next(); + + // Create some users and sites + final List people = new ArrayList(); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + person = network2.createUser(); + people.add(person); + + return null; + } + }, network2.getId()); + + final TestPerson person1 = people.get(0); + final TestPerson person2 = people.get(1); + final TestPerson person3 = people.get(2); + final TestPerson person4 = people.get(3); + final TestPerson person5 = people.get(3); + + TestSite testSite = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network1.createSite(siteInfo); + } + }, person1.getId(), network1.getId()); + } + }, false, true); + + TestSite testSite1 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network1.createSite(siteInfo); + } + }, person1.getId(), network1.getId()); + } + }, false, true); + + TestSite testSite3 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network1.createSite(siteInfo); + } + }, person1.getId(), network1.getId()); + } + }, false, true); + + TestSite testSite4 = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public TestSite execute() throws Throwable + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(GUID.generate(), "", "", SiteVisibility.PUBLIC); + return network1.createSite(siteInfo); + } + }, person5.getId(), network2.getId()); + } + }, false, true); + + Sites sitesProxy = publicApiClient.sites(); + + // invalid methods + try + { + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.create("people", person1.getId(), "favorite-sites", testSite.getSiteId(), fs.toJSON().toString(), "Unable to POST to a favorite-site"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.update("people", person1.getId(), "favorite-sites", null, fs.toJSON().toString(), "Unable to PUT favorite-sites"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.update("people", person1.getId(), "favorite-sites", testSite.getSiteId(), fs.toJSON().toString(), "Unable to PUT a favorite-site"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.remove("people", person1.getId(), "favorite-sites", null, "Unable to DELETE favorite-sites"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // Create favourite site + + // unknown user - 404 + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + sitesProxy.createFavouriteSite("invalid.user", fs); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // user from another network - 401 (not able to auth against tenant) + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + sitesProxy.createFavouriteSite(person1.getId(), fs); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // another user from the same network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + sitesProxy.createFavouriteSite(person2.getId(), fs); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // a member of this site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + FavouriteSite resp = sitesProxy.createFavouriteSite(person1.getId(), fs); + fs.expected(resp); + } + + // add same favourite site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.createFavouriteSite(person1.getId(), new FavouriteSite(testSite.getSiteId())); + fail(); + } + catch(PublicApiException e) + { + assertEquals(409, e.getHttpResponse().getStatusCode()); + } + + // "-me" user + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + FavouriteSite fs = new FavouriteSite(testSite.getSiteId()); + FavouriteSite resp = sitesProxy.createFavouriteSite(org.alfresco.rest.api.People.DEFAULT_USER, fs); + fs.expected(resp); + + final List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + return repoService.getFavouriteSites(person2); + } + }, person2.getId(), network1.getId()); + + // check it's there + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.getFavouriteSites(person2.getId(), createParams(paging, null)); + } + + // not a member of this site + { + FavouriteSite fs = new FavouriteSite(testSite1.getSiteId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite ret = sitesProxy.createFavouriteSite(person1.getId(), fs); + fs.expected(ret); + } + + // GET favourite sites + { + final List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + return repoService.getFavouriteSites(person1); + } + }, person1.getId(), network1.getId()); + + // Test Case cloud-1490 + // unknown user + try + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.getFavouriteSites(GUID.generate(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // authentication: unknown user + try + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), GUID.generate(), "password")); + sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // another user from the same network - 403 + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // another user from another network - 401 + try + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); + sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // successful GET + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); + } + + // skipCount is greater than the number of favourite sites + { + int skipCount = expectedFavouriteSites.size() + 100; + Paging paging = getPaging(skipCount, null, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + List expected = Collections.emptyList(); + ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + checkList(expected, paging.getExpectedPaging(), response); + } + + // "-me-" user + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = sitesProxy.getFavouriteSites(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); + checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); + } + } + + // user is a member of the site which he has favourited + { + publicApiClient.setRequestContext(new RequestContext(network2.getId(), person5.getId())); + + List expectedFavouriteSites = new ArrayList(1); + FavouriteSite fs = new FavouriteSite(testSite4.getSiteId()); + expectedFavouriteSites.add(fs); + + FavouriteSite ret = sitesProxy.createFavouriteSite(person5.getId(), fs); + fs.expected(ret); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + ListResponse response = sitesProxy.getFavouriteSites(person5.getId(), createParams(paging, null)); + checkList(expectedFavouriteSites, paging.getExpectedPaging(), response); + } + + // remove + { + // create some favourite sites + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + FavouriteSite fs = new FavouriteSite(testSite); + sitesProxy.createFavouriteSite(person3.getId(), fs); + fs = new FavouriteSite(testSite1); + sitesProxy.createFavouriteSite(person3.getId(), fs); + } + + // known user + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite); + sitesProxy.removeFavouriteSite(person1.getId(), fs); + + List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + return repoService.getFavouriteSites(person1); + } + }, person1.getId(), network1.getId()); + + // check removed + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse response = sitesProxy.getFavouriteSites(person1.getId(), createParams(paging, null)); + assertFalse(response.getList().contains(fs)); + } + + // unknown user + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite); + sitesProxy.removeFavouriteSite(GUID.generate(), fs); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(GUID.generate()); + sitesProxy.removeFavouriteSite(person1.getId(), fs); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // try to remove a favourite site that is not a favourite site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + FavouriteSite fs = new FavouriteSite(testSite3); + sitesProxy.removeFavouriteSite(person1.getId(), fs); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // "-me-" user + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + FavouriteSite fs = new FavouriteSite(testSite1); + sitesProxy.removeFavouriteSite(org.alfresco.rest.api.People.DEFAULT_USER, fs); + + List expectedFavouriteSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + return repoService.getFavouriteSites(person3); + } + }, person3.getId(), network1.getId()); + + // check removed + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavouriteSites.size(), expectedFavouriteSites.size()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + ListResponse response = sitesProxy.getFavouriteSites(person3.getId(), createParams(paging, null)); + assertFalse(response.getList().contains(fs)); + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestFavourites.java b/source/test-java/org/alfresco/rest/api/tests/TestFavourites.java index 7193eb8df3..8b238d773e 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestFavourites.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestFavourites.java @@ -1,1686 +1,1686 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.Favourites; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.SiteMembershipRequests; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.Favourite; -import org.alfresco.rest.api.tests.client.data.FavouriteDocument; -import org.alfresco.rest.api.tests.client.data.FavouriteFolder; -import org.alfresco.rest.api.tests.client.data.FavouritesTarget; -import org.alfresco.rest.api.tests.client.data.FileFavouriteTarget; -import org.alfresco.rest.api.tests.client.data.FolderFavouriteTarget; -import org.alfresco.rest.api.tests.client.data.InvalidFavouriteTarget; -import org.alfresco.rest.api.tests.client.data.JSONAble; -import org.alfresco.rest.api.tests.client.data.Site; -import org.alfresco.rest.api.tests.client.data.SiteFavouriteTarget; -import org.alfresco.rest.api.tests.client.data.SiteImpl; -import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.favourites.FavouritesService; -import org.alfresco.service.cmr.favourites.FavouritesService.Type; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.alfresco.util.Pair; -import org.apache.commons.httpclient.HttpStatus; -import org.json.simple.JSONObject; -import org.junit.Before; -import org.junit.Test; - -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; - -/** - * - * @author steveglover - * @since publicapi1.0 - */ -public class TestFavourites extends EnterpriseTestApi -{ - private static enum TARGET_TYPE - { - file, folder, site; - }; - - private TestNetwork network1; - private TestPerson person10; - private String person10Id; - private TestPerson person11; - private String person11Id; - private TestPerson person12; - private String person12Id; - private TestPerson person14; - private String person14Id; - - private TestNetwork network2; - private TestPerson person21; - private String person21Id; - - private List personSites = new ArrayList(); - private List person1PublicSites = new ArrayList(); - private List person1PrivateSites = new ArrayList(); - - private List personDocs = new ArrayList(); - private List personFolders = new ArrayList(); - private List person1PublicDocs = new ArrayList(); - private List person1PublicFolders = new ArrayList(); - private List person1PrivateDocs = new ArrayList(); - private List person1PrivateFolders = new ArrayList(); - - private Favourites favouritesProxy; - private SiteMembershipRequests siteMembershipRequestsProxy; - - private void sort(List favourites, final List> sortProps) - { - Comparator comparator = new Comparator() - { - @Override - public int compare(Favourite o1, Favourite o2) - { - int ret = 0; - for(Pair sort : sortProps) - { - FavouritesService.SortFields field = sort.getFirst(); - Boolean ascending = sort.getSecond(); - if(field.equals(FavouritesService.SortFields.username)) - { - if(ascending) - { - if(o1.getUsername() != null && o2.getUsername() != null) - { - ret = collator.compare(o1.getUsername(), o2.getUsername()); - } - } - else - { - if(o1.getUsername() != null && o2.getUsername() != null) - { - ret = o2.getUsername().compareTo(o1.getUsername()); - } - } - - if(ret != 0) - { - break; - } - } - else if(field.equals(FavouritesService.SortFields.type)) - { - if(ascending) - { - ret = o1.getType().compareTo(o2.getType()); - } - else - { - ret = o2.getType().compareTo(o1.getType()); - } - - if(ret != 0) - { - break; - } - } - else if(field.equals(FavouritesService.SortFields.createdAt)) - { - if(ascending) - { - ret = o1.getCreatedAt().compareTo(o2.getCreatedAt()); - } - else - { - ret = o2.getCreatedAt().compareTo(o1.getCreatedAt()); - } - - if(ret != 0) - { - break; - } - } - } - - return ret; - } - }; - Collections.sort(favourites, comparator); - } - - /** - * Returns a new list. - * - * @param favourites List - * @param types Set - * @return ArrayList - */ - private ArrayList filter(List favourites, final Set types) - { - Predicate predicate = new Predicate() - { - @Override - public boolean apply(Favourite other) - { - Type type = null; - if(other.getTarget() instanceof FileFavouriteTarget) - { - type = Type.FILE; - } - else if(other.getTarget() instanceof FolderFavouriteTarget) - { - type = Type.FOLDER; - } - else if(other.getTarget() instanceof SiteFavouriteTarget) - { - type = Type.SITE; - } - - boolean ret = (type != null && types.contains(type)); - return ret; - } - }; - ArrayList ret = Lists.newArrayList(Collections2.filter(favourites, predicate)); - return ret; - } - - @Before - public void setup() throws Exception - { - final Iterator networksIt = getTestFixture().networksIterator(); - - // Workaround for domain name mismatch in lucene indexing that occurs when this test runs. - repoService.disableInTxnIndexing(); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public Void execute() throws Throwable - { - try - { - AuthenticationUtil.pushAuthentication(); - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - // create some users - TestFavourites.this.network1 = networksIt.next(); - - String name = GUID.generate(); - PersonInfo personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); - TestFavourites.this.person10 = network1.createUser(personInfo); - assertNotNull(TestFavourites.this.person10); - TestFavourites.this.person10Id = TestFavourites.this.person10.getId(); - name = GUID.generate(); - personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); - TestFavourites.this.person11 = network1.createUser(personInfo); - assertNotNull(TestFavourites.this.person11); - TestFavourites.this.person11Id = TestFavourites.this.person11.getId(); - name = GUID.generate(); - personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); - TestFavourites.this.person12 = network1.createUser(personInfo); - assertNotNull(TestFavourites.this.person12); - TestFavourites.this.person12Id = TestFavourites.this.person12.getId(); - name = GUID.generate(); - personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); - TestFavourites.this.person14 = network1.createUser(personInfo); - assertNotNull(TestFavourites.this.person14); - TestFavourites.this.person14Id = TestFavourites.this.person14.getId(); - - TestFavourites.this.network2 = networksIt.next(); - name = GUID.generate(); - personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); - TestFavourites.this.person21 = network2.createUser(personInfo); - assertNotNull(TestFavourites.this.person21); - TestFavourites.this.person21Id = TestFavourites.this.person21.getId(); - - return null; - } - finally - { - AuthenticationUtil.popAuthentication(); - } - } - }, false, true); - - // Create some favourite targets, sites, files and folders - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + GUID.generate(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - person1PublicSites.add(site); - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); - person1PublicDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1", "Test Folder1 Title", "Test Folder1 Description"); - person1PublicFolders.add(nodeRef); - nodeRef = repoService.createDocument(nodeRef, "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); - person1PublicDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2", "Test Folder2 Title", "Test Folder2 Description"); - person1PublicFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Doc3 Title", "Test Doc3 Description", "Test Content"); - person1PublicDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3", "Test Folder3 Title", "Test Folder3 Description"); - person1PublicFolders.add(nodeRef); - - siteName = "site" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - site = network1.createSite(siteInfo); - person1PublicSites.add(site); - - siteName = "site" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - site = network1.createSite(siteInfo); - person1PrivateSites.add(site); - - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); - person1PrivateDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1", "Test Folder1 Title", "Test Folder1 Description"); - person1PrivateFolders.add(nodeRef); - nodeRef = repoService.createDocument(nodeRef, "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); - person1PrivateDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2", "Test Folder2 Title", "Test Folder2 Description"); - person1PrivateFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Doc3 Title", "Test Doc3 Description", "Test Content"); - person1PrivateDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3", "Test Folder3 Title", "Test Folder3 Description"); - person1PrivateFolders.add(nodeRef); - - return null; - } - }, person11Id, network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - person1PublicSites.add(site); - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); - personFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); - personFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); - personFolders.add(nodeRef); - - return null; - } - }, person10Id, network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + GUID.generate(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - personSites.add(site); - - site.inviteToSite(person11Id, SiteRole.SiteCollaborator); - - siteName = "site" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - site = network1.createSite(siteInfo); - personSites.add(site); - - return null; - } - }, person10Id, network1.getId()); - - this.favouritesProxy = publicApiClient.favourites(); - this.siteMembershipRequestsProxy = publicApiClient.siteMembershipRequests(); - } - - private void updateFavourite(String networkId, String runAsUserId, String personId, TARGET_TYPE type) throws Exception - { - { - int size = 0; - - try - { - // get a favourite id - ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); - List favourites = resp.getList(); - size = favourites.size(); - assertTrue(size > 0); - Favourite favourite = favourites.get(0); - - favouritesProxy.update("people", personId, "favorites", favourite.getTargetGuid(), favourite.toJSON().toString(), "Unable to update favourite"); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // check nothing has changed - ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); - List favourites = resp.getList(); - assertEquals(size, favourites.size()); - } - } - - private Favourite deleteFavourite(String networkId, String runAsUserId, String personId, TARGET_TYPE type) throws Exception - { - Exception e = null; - - publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); - - // get a favourite id - ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); - List favourites = resp.getList(); - int size = favourites.size(); - assertTrue(size > 0); - Favourite favourite = favourites.get(0); - - try - { - // catch 404's - favouritesProxy.removeFavourite(personId, favourite.getTargetGuid()); - } - catch(PublicApiException exc) - { - e = exc; - } - - // check favourite has been removed - resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); - favourites = resp.getList(); - boolean stillExists = false; - for(Favourite f : favourites) - { - if(f.getTargetGuid().equals(favourite.getTargetGuid())) - { - stillExists = true; - break; - } - } - assertFalse(stillExists); - - if(e != null) - { - throw e; - } - - return favourite; - } - - private ListResponse getFavourites(String networkId, String runAsUserId, String personId, int skipCount, int maxItems, Integer total, - Integer expectedTotal, TARGET_TYPE type) throws PublicApiException, ParseException - { - publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); - - Paging paging = null; - if(total == null && expectedTotal == null) - { - paging = getPaging(skipCount, maxItems); - } - else - { - paging = getPaging(skipCount, maxItems, total, expectedTotal); - } - Map params = null; - if(type != null) - { - params = Collections.singletonMap("where", "(EXISTS(target/" + type + "))"); - } - ListResponse resp = favouritesProxy.getFavourites(personId, createParams(paging, params)); - return resp; - } - - private Favourite makeFolderFavourite(String targetGuid) throws ParseException - { - FavouriteFolder folder = new FavouriteFolder(targetGuid); - FolderFavouriteTarget target = new FolderFavouriteTarget(folder); - Date creationData = new Date(); - Favourite favourite = new Favourite(creationData, null, target); - return favourite; - } - - private Favourite makeFileFavourite(String targetGuid) throws ParseException - { - FavouriteDocument document = new FavouriteDocument(targetGuid); - FileFavouriteTarget target = new FileFavouriteTarget(document); - Date creationData = new Date(); - Favourite favourite = new Favourite(creationData, null, target); - return favourite; - } - - private Favourite makeSiteFavourite(Site site) throws ParseException - { - SiteFavouriteTarget target = new SiteFavouriteTarget(site); - Date creationDate = new Date(); - Favourite favourite = new Favourite(creationDate, null, target); - return favourite; - } - - @Test - public void testInvalidRequests() throws Exception - { - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite favourite = makeSiteFavourite(person1PublicSites.get(0)); - Favourite ret = favouritesProxy.createFavourite(person11Id, favourite); - favourite.expected(ret); - fail(); - } - catch(PublicApiException e) - { - // Note: un-authorized comes back as 404 - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // cloud-2468 - // invalid type - // NOTE: The test below has swapped to attempt to favorite a comment rather than a - // a wiki page as the WikiService has moved to the Share Services AMP in 5.1 - - try - { - log("cloud-2468"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - final NodeRef document = personDocs.get(0); - final NodeRef comment = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - NodeRef comment = repoService.createComment(document, new Comment("Title", "Content")); - return comment; - } - }, person10Id, network1.getId()); - - final String guid = comment.getId(); - JSONAble commentJSON = new JSONAble() - { - @SuppressWarnings("unchecked") - @Override - public JSONObject toJSON() - { - JSONObject json = new JSONObject(); - json.put("guid", guid); - return json; - } - }; - - FavouritesTarget target = new InvalidFavouriteTarget("comment", commentJSON, guid); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - try - { - log("cloud-2468"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Site site = person1PublicSites.get(0); - FavouritesTarget target = new InvalidFavouriteTarget(GUID.generate(), site, site.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // type = file, target is a site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - String siteGuid = person1PublicSites.get(0).getGuid(); - FavouriteDocument document = new FavouriteDocument(siteGuid); - Favourite favourite = makeFileFavourite(document.getGuid()); - Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); - favourite.expected(ret); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // type = folder, target is a site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - String siteGuid = person1PublicSites.get(0).getGuid(); - FavouriteFolder folder = new FavouriteFolder(siteGuid); - Favourite favourite = makeFolderFavourite(folder.getGuid()); - Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); - favourite.expected(ret); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // type = folder, target is a file - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouriteFolder folder = new FavouriteFolder(person1PublicDocs.get(0).getId()); - Favourite favourite = makeFolderFavourite(folder.getGuid()); - Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); - favourite.expected(ret); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // type = file, target is a folder - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouriteDocument document = new FavouriteDocument(person1PublicFolders.get(0).getId()); - Favourite favourite = makeFileFavourite(document.getGuid()); - Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); - favourite.expected(ret); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // make sure that a user can't favourite on behalf of another user - // 2471 - { - log("cloud-2471"); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouriteDocument document = new FavouriteDocument(person1PublicDocs.get(0).getId()); - Favourite favourite = makeFileFavourite(document.getGuid()); - favouritesProxy.createFavourite(person11Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - // Note: un-authorized comes back as 404 - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // person1 should have no favourites - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - ListResponse response = favouritesProxy.getFavourites(person11Id, createParams(null, null)); - assertEquals(0, response.getList().size()); - } - - // invalid/non-existent user - // 2469 - try - { - log("cloud-2469"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite favourite = makeSiteFavourite(personSites.get(0)); - Favourite ret = favouritesProxy.createFavourite(GUID.generate(), favourite); - favourite.expected(ret); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // make sure that a user can't see other user's favourites. - // 2465 - try - { - log("cloud-2465"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - favouritesProxy.getFavourites(person11Id, null); - fail(); - } - catch(PublicApiException e) - { - // Note: un-authorized comes back as 404 - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // 2464, unknown user - try - { - log("cloud-2464"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - favouritesProxy.getFavourites(GUID.generate(), null); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // non-existent entity for a given type - // 2480 - { - log("cloud-2480"); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - SiteImpl site = new SiteImpl(); - site.setGuid(GUID.generate()); - Favourite favourite = makeSiteFavourite((Site)site); - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); - assertEquals(0, response.getList().size()); - } - - { - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouriteDocument document = new FavouriteDocument(GUID.generate()); - Favourite favourite = makeFileFavourite(document.getGuid()); - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); - assertEquals(0, response.getList().size()); - } - - { - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouriteFolder folder = new FavouriteFolder(GUID.generate()); - Favourite favourite = makeFolderFavourite(folder.getGuid()); - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); - assertEquals(0, response.getList().size()); - } - - // 2470 - // incorrect type for a given favourite target - { - log("cloud-2470"); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Site site = person1PublicSites.get(0); - FavouritesTarget target = new InvalidFavouriteTarget("folder", site, site.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Site site = person1PublicSites.get(0); - FavouritesTarget target = new InvalidFavouriteTarget("file", site, site.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - FavouriteDocument document = new FavouriteDocument(person1PublicDocs.get(0).getId()); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouritesTarget target = new InvalidFavouriteTarget("site", document, document.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouritesTarget target = new InvalidFavouriteTarget("folder", document, document.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - FavouriteFolder folder = new FavouriteFolder(person1PublicFolders.get(0).getId()); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouritesTarget target = new InvalidFavouriteTarget("site", folder, folder.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - FavouritesTarget target = new InvalidFavouriteTarget("file", folder, folder.getGuid()); - Favourite favourite = new Favourite(target); - - favouritesProxy.createFavourite(person10Id, favourite); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - // none of these POSTs should have resulted in favourites being created... - ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); - assertEquals(0, response.getList().size()); - } - - // invalid methods - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - try - { - Favourite favourite = new Favourite(null); - favouritesProxy.update("people", "-me-", "favorites", null, favourite.toJSON().toString(), "Unable to PUT favourites"); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - } - - @Test - public void testValidRequests() throws Exception - { - List expectedFavourites = new ArrayList(); - - { - // add some favourites - // 2467 - - log("cloud-2467"); - - Favourite siteFavourite1 = makeSiteFavourite(person1PublicSites.get(0)); - - FavouriteDocument document = repoService.getDocument(network1.getId(), person1PublicDocs.get(0)); - Favourite fileFavourite1 = makeFileFavourite(document.getGuid()); - - FavouriteFolder folder = repoService.getFolder(network1.getId(), person1PublicFolders.get(0)); - Favourite folderFavourite1 = makeFolderFavourite(folder.getGuid()); - - Favourite siteFavourite2 = makeSiteFavourite(person1PublicSites.get(1)); - - document = repoService.getDocument(network1.getId(), person1PublicDocs.get(1)); - Favourite fileFavourite2 = makeFileFavourite(document.getGuid()); - - folder = repoService.getFolder(network1.getId(), person1PublicFolders.get(1)); - Favourite folderFavourite2 = makeFolderFavourite(folder.getGuid()); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite1); - expectedFavourites.add(ret); - siteFavourite1.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite1); - expectedFavourites.add(ret); - fileFavourite1.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite1); - expectedFavourites.add(ret); - folderFavourite1.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite2); - expectedFavourites.add(ret); - siteFavourite2.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite2); - expectedFavourites.add(ret); - fileFavourite2.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite2); - expectedFavourites.add(ret); - folderFavourite2.expected(ret); - } - - // already a favourite - 201 - { - log("cloud-2472"); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite1); - siteFavourite1.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite1); - folderFavourite1.expected(ret); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite1); - fileFavourite1.expected(ret); - } - } - - { - // cloud-2498 - // cloud-2499 - // create and list favourites across networks - - List person21ExpectedFavourites = new ArrayList(); - - log("cloud-2498"); - log("cloud-2499"); - - { - // favourite a site in another network - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); - - Favourite favourite = makeSiteFavourite(person1PrivateSites.get(0)); - try - { - favouritesProxy.createFavourite("-me-", favourite); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - int skipCount = 0; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); - try - { - favouritesProxy.getFavourites("-me-", createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - // favourite a document in another network - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); - - FavouriteDocument document1 = new FavouriteDocument(person1PrivateDocs.get(0).getId()); - Favourite favourite = makeFileFavourite(document1.getGuid()); - try - { - favouritesProxy.createFavourite("-me-", favourite); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - sort(person21ExpectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); - try - { - favouritesProxy.getFavourites("-me-", createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - // favourite a folder in another network - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); - - FavouriteFolder folder1 = new FavouriteFolder(person1PrivateFolders.get(0).getId()); - Favourite favourite = makeFolderFavourite(folder1.getGuid()); - try - { - favouritesProxy.createFavourite("-me-", favourite); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - sort(person21ExpectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); - try - { - favouritesProxy.getFavourites("-me-", createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - } - } - - // GET favourites - // test paging and sorting - { - // cloud-2458 - // cloud-2462 - // cloud-2461 - { - log("cloud-2458"); - log("cloud-2461"); - log("cloud-2462"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - List expected = new ArrayList(expectedFavourites); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, null)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - List expected = new ArrayList(expectedFavourites); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 2; - int maxItems = 4; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, null)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // 2466 - // GET favourites for "-me-" - { - log("cloud-2466"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - List expected = new ArrayList(expectedFavourites); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites("-me-", createParams(paging, null)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - // 2459 - { - log("cloud-2459"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, 0, 0); - ListResponse resp = favouritesProxy.getFavourites(person11Id, createParams(paging, null)); - List empty = Collections.emptyList(); - checkList(empty, paging.getExpectedPaging(), resp); - } - - // cloud-2460: filtering by target type - { - log("cloud-2460"); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.FILE)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/file))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.FOLDER)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/folder))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/file - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.FILE)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/file))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/folder - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.FOLDER)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/folder))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.SITE)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/site))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/folder OR target/file. - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.FOLDER, Type.FILE)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/file) OR EXISTS(target/folder))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/site OR target/file. - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.SITE, Type.FILE)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/file) OR EXISTS(target/site))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // target/site OR target/folder. - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Set types = new HashSet(Arrays.asList(Type.SITE, Type.FOLDER)); - List expected = filter(expectedFavourites, types); - sort(expected, FavouritesService.DEFAULT_SORT_PROPS); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); - Map params = Collections.singletonMap("where", "(EXISTS(target/site) OR EXISTS(target/folder))"); - ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); - checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - // GET a favourite - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - favouritesProxy.getFavourite(person10Id, GUID.generate()); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite favourite = expectedFavourites.get(0); - - favouritesProxy.getFavourite(GUID.generate(), favourite.getTargetGuid()); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - Favourite favourite = expectedFavourites.get(0); - - Favourite resp = favouritesProxy.getFavourite(person10Id, favourite.getTargetGuid()); - favourite.expected(resp); - } - - // cloud-2479, PUT case - { - log("cloud-2479.1"); - updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.site); - - log("cloud-2479.2"); - updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.file); - - log("cloud-2479.3"); - updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.folder); - } - - try - { - // cloud-2474 - // non-existent personId - log("cloud-2474"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - favouritesProxy.removeFavourite(GUID.generate(), GUID.generate()); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // cloud-2475 - // try delete a non-existent favourite for a node that exists - { - log("cloud-2475"); - - NodeRef doc = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public NodeRef doWork() throws Exception - { - NodeRef containerNodeRef = person1PublicSites.get(0).getContainerNodeRef("documentLibrary"); - NodeRef doc = repoService.createDocument(containerNodeRef, GUID.generate(), ""); - return doc; - } - }, person11Id, network1.getId()); - - String favouriteId = doc.getId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - - ListResponse before = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); - List beforeList = before.getList(); - assertTrue(beforeList.size() > 0); - - try - { - favouritesProxy.removeFavourite(person10Id, favouriteId); - fail("Should be a 404"); - } - catch(PublicApiException e) - { - // expected - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // check no favourites have been removed - ListResponse after = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); - assertEquals(beforeList.size(), after.getList().size()); - } - - // cloud-2473, DELETE case - { - log("cloud-2473.1"); - deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.site); - - log("cloud-2473.2"); - deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.file); - - log("cloud-2473.3"); - Favourite favourite = deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.folder); - - // try to delete non-existent favourite - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); - favouritesProxy.removeFavourite(person10Id, favourite.getTargetGuid()); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // cloud-2476 - // try delete another user's favourite - { - log("cloud-2476"); - - // make sure there are favourites to delete -// publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); -// SiteFavouriteTarget target = new SiteFavouriteTarget(person1Sites.get(0)); -// Favourite favourite = new Favourite(target); -// favouritesProxy.createFavourite(personId, favourite); - - ListResponse before = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); - assertTrue(before.getList().size() > 0); - Favourite favourite = before.getList().get(0); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - favouritesProxy.removeFavourite(person10Id, favourite.getTargetGuid()); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - ListResponse after = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); - assertEquals(before.getList().size(), after.getList().size()); - } - } - - @Test - public void testPUBLICAPI141() throws Exception - { - final TestSite publicSite = person1PublicSites.get(0); // person1's public site - final TestSite publicSite1 = person1PublicSites.get(1); // person1's public site - final TestSite privateSite = person1PrivateSites.get(0); // person1's private site - final NodeRef folderNodeRef = person1PublicFolders.get(0); // person1's folder - final NodeRef nodeRef = person1PublicDocs.get(1); // a file in the folder - final List expectedFavourites = new ArrayList(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); - - // invite to another user's public site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(publicSite.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person12Id, siteMembershipRequest); - - // favourite other users site, folder and file - Favourite folderFavourite = makeFolderFavourite(folderNodeRef.getId()); - favouritesProxy.createFavourite(person12Id, folderFavourite); - - Favourite fileFavourite = makeFileFavourite(nodeRef.getId()); - favouritesProxy.createFavourite(person12Id, fileFavourite); - - final Favourite siteFavourite = makeSiteFavourite(publicSite); - favouritesProxy.createFavourite(person12Id, siteFavourite); - expectedFavourites.add(siteFavourite); - - final Favourite siteFavourite1 = makeSiteFavourite(publicSite1); - favouritesProxy.createFavourite(person12Id, siteFavourite1); - expectedFavourites.add(siteFavourite1); - - sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); - - // move the folder and file to person1's private site - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - NodeRef documentLibraryNodeRef = privateSite.getContainerNodeRef("documentLibrary"); - repoService.moveNode(folderNodeRef, documentLibraryNodeRef); - - return null; - } - }, person11Id, network1.getId()); - - try - { - favouritesProxy.getFavourite(person12Id, folderFavourite.getTargetGuid()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - favouritesProxy.getFavourite(person12Id, fileFavourite.getTargetGuid()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites(person12Id, createParams(paging, null)); - checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // make the public sites private - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - publicSite.setSiteVisibility(SiteVisibility.PRIVATE); - publicSite1.setSiteVisibility(SiteVisibility.PRIVATE); - - return null; - } - }, person11Id, network1.getId()); - expectedFavourites.remove(siteFavourite1); - - // Given that person2Id is still a member of 'publicSite', they should still have access and therefore - // it should show up in their favourites. But person2Id is not a member of 'publicSite1', they should - // not have access and therefore it should not show up in their favourites. - { - Favourite actual = favouritesProxy.getFavourite(person12Id, siteFavourite.getTargetGuid()); - siteFavourite.expected(actual); - - try - { - favouritesProxy.getFavourite(person12Id, siteFavourite1.getTargetGuid()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites(person12Id, createParams(paging, null)); - checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - } - - @Test - public void testPUBLICAPI156() throws Exception - { - final TestSite publicSite = person1PublicSites.get(0); // person1's public site - final TestSite publicSite1 = person1PublicSites.get(1); // person1's public site - final NodeRef folderNodeRef = person1PublicFolders.get(0); // person1's folder - final NodeRef nodeRef = person1PublicDocs.get(1); // a file in the folder - final List expectedFavourites = new ArrayList(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - // invite to another user's public site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(publicSite.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - - // favourite other users site, folder and file - Favourite folderFavourite = makeFolderFavourite(folderNodeRef.getId()); - favouritesProxy.createFavourite(person14Id, folderFavourite); - expectedFavourites.add(folderFavourite); - - Favourite fileFavourite = makeFileFavourite(nodeRef.getId()); - favouritesProxy.createFavourite(person14Id, fileFavourite); - expectedFavourites.add(fileFavourite); - - final Favourite siteFavourite = makeSiteFavourite(publicSite); - favouritesProxy.createFavourite(person14Id, siteFavourite); - expectedFavourites.add(siteFavourite); - - final Favourite siteFavourite1 = makeSiteFavourite(publicSite1); - favouritesProxy.createFavourite(person14Id, siteFavourite1); - expectedFavourites.add(siteFavourite1); - - sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); - - // remove the folder and file - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.deleteNode(nodeRef); - repoService.deleteNode(folderNodeRef); - - return null; - } - }, person11Id, network1.getId()); - - expectedFavourites.remove(folderFavourite); - expectedFavourites.remove(fileFavourite); - sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); - - // GETs should not return the favourites nor error - { - try - { - favouritesProxy.getFavourite(person14Id, folderFavourite.getTargetGuid()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - favouritesProxy.getFavourite(person14Id, fileFavourite.getTargetGuid()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); - ListResponse resp = favouritesProxy.getFavourites(person14Id, createParams(paging, null)); - checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - } +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.Favourites; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.SiteMembershipRequests; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.Favourite; +import org.alfresco.rest.api.tests.client.data.FavouriteDocument; +import org.alfresco.rest.api.tests.client.data.FavouriteFolder; +import org.alfresco.rest.api.tests.client.data.FavouritesTarget; +import org.alfresco.rest.api.tests.client.data.FileFavouriteTarget; +import org.alfresco.rest.api.tests.client.data.FolderFavouriteTarget; +import org.alfresco.rest.api.tests.client.data.InvalidFavouriteTarget; +import org.alfresco.rest.api.tests.client.data.JSONAble; +import org.alfresco.rest.api.tests.client.data.Site; +import org.alfresco.rest.api.tests.client.data.SiteFavouriteTarget; +import org.alfresco.rest.api.tests.client.data.SiteImpl; +import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.favourites.FavouritesService; +import org.alfresco.service.cmr.favourites.FavouritesService.Type; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.alfresco.util.Pair; +import org.apache.commons.httpclient.HttpStatus; +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; + +/** + * + * @author steveglover + * @since publicapi1.0 + */ +public class TestFavourites extends EnterpriseTestApi +{ + private static enum TARGET_TYPE + { + file, folder, site; + }; + + private TestNetwork network1; + private TestPerson person10; + private String person10Id; + private TestPerson person11; + private String person11Id; + private TestPerson person12; + private String person12Id; + private TestPerson person14; + private String person14Id; + + private TestNetwork network2; + private TestPerson person21; + private String person21Id; + + private List personSites = new ArrayList(); + private List person1PublicSites = new ArrayList(); + private List person1PrivateSites = new ArrayList(); + + private List personDocs = new ArrayList(); + private List personFolders = new ArrayList(); + private List person1PublicDocs = new ArrayList(); + private List person1PublicFolders = new ArrayList(); + private List person1PrivateDocs = new ArrayList(); + private List person1PrivateFolders = new ArrayList(); + + private Favourites favouritesProxy; + private SiteMembershipRequests siteMembershipRequestsProxy; + + private void sort(List favourites, final List> sortProps) + { + Comparator comparator = new Comparator() + { + @Override + public int compare(Favourite o1, Favourite o2) + { + int ret = 0; + for(Pair sort : sortProps) + { + FavouritesService.SortFields field = sort.getFirst(); + Boolean ascending = sort.getSecond(); + if(field.equals(FavouritesService.SortFields.username)) + { + if(ascending) + { + if(o1.getUsername() != null && o2.getUsername() != null) + { + ret = collator.compare(o1.getUsername(), o2.getUsername()); + } + } + else + { + if(o1.getUsername() != null && o2.getUsername() != null) + { + ret = o2.getUsername().compareTo(o1.getUsername()); + } + } + + if(ret != 0) + { + break; + } + } + else if(field.equals(FavouritesService.SortFields.type)) + { + if(ascending) + { + ret = o1.getType().compareTo(o2.getType()); + } + else + { + ret = o2.getType().compareTo(o1.getType()); + } + + if(ret != 0) + { + break; + } + } + else if(field.equals(FavouritesService.SortFields.createdAt)) + { + if(ascending) + { + ret = o1.getCreatedAt().compareTo(o2.getCreatedAt()); + } + else + { + ret = o2.getCreatedAt().compareTo(o1.getCreatedAt()); + } + + if(ret != 0) + { + break; + } + } + } + + return ret; + } + }; + Collections.sort(favourites, comparator); + } + + /** + * Returns a new list. + * + * @param favourites List + * @param types Set + * @return ArrayList + */ + private ArrayList filter(List favourites, final Set types) + { + Predicate predicate = new Predicate() + { + @Override + public boolean apply(Favourite other) + { + Type type = null; + if(other.getTarget() instanceof FileFavouriteTarget) + { + type = Type.FILE; + } + else if(other.getTarget() instanceof FolderFavouriteTarget) + { + type = Type.FOLDER; + } + else if(other.getTarget() instanceof SiteFavouriteTarget) + { + type = Type.SITE; + } + + boolean ret = (type != null && types.contains(type)); + return ret; + } + }; + ArrayList ret = Lists.newArrayList(Collections2.filter(favourites, predicate)); + return ret; + } + + @Before + public void setup() throws Exception + { + final Iterator networksIt = getTestFixture().networksIterator(); + + // Workaround for domain name mismatch in lucene indexing that occurs when this test runs. + repoService.disableInTxnIndexing(); + + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public Void execute() throws Throwable + { + try + { + AuthenticationUtil.pushAuthentication(); + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + // create some users + TestFavourites.this.network1 = networksIt.next(); + + String name = GUID.generate(); + PersonInfo personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); + TestFavourites.this.person10 = network1.createUser(personInfo); + assertNotNull(TestFavourites.this.person10); + TestFavourites.this.person10Id = TestFavourites.this.person10.getId(); + name = GUID.generate(); + personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); + TestFavourites.this.person11 = network1.createUser(personInfo); + assertNotNull(TestFavourites.this.person11); + TestFavourites.this.person11Id = TestFavourites.this.person11.getId(); + name = GUID.generate(); + personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); + TestFavourites.this.person12 = network1.createUser(personInfo); + assertNotNull(TestFavourites.this.person12); + TestFavourites.this.person12Id = TestFavourites.this.person12.getId(); + name = GUID.generate(); + personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); + TestFavourites.this.person14 = network1.createUser(personInfo); + assertNotNull(TestFavourites.this.person14); + TestFavourites.this.person14Id = TestFavourites.this.person14.getId(); + + TestFavourites.this.network2 = networksIt.next(); + name = GUID.generate(); + personInfo = new PersonInfo(name, name, name, "password", null, null, null, null, null, null, null); + TestFavourites.this.person21 = network2.createUser(personInfo); + assertNotNull(TestFavourites.this.person21); + TestFavourites.this.person21Id = TestFavourites.this.person21.getId(); + + return null; + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + }, false, true); + + // Create some favourite targets, sites, files and folders + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + GUID.generate(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + person1PublicSites.add(site); + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); + person1PublicDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1", "Test Folder1 Title", "Test Folder1 Description"); + person1PublicFolders.add(nodeRef); + nodeRef = repoService.createDocument(nodeRef, "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); + person1PublicDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2", "Test Folder2 Title", "Test Folder2 Description"); + person1PublicFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Doc3 Title", "Test Doc3 Description", "Test Content"); + person1PublicDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3", "Test Folder3 Title", "Test Folder3 Description"); + person1PublicFolders.add(nodeRef); + + siteName = "site" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + site = network1.createSite(siteInfo); + person1PublicSites.add(site); + + siteName = "site" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + site = network1.createSite(siteInfo); + person1PrivateSites.add(site); + + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Doc1 Title", "Test Doc1 Description", "Test Content"); + person1PrivateDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1", "Test Folder1 Title", "Test Folder1 Description"); + person1PrivateFolders.add(nodeRef); + nodeRef = repoService.createDocument(nodeRef, "Test Doc2", "Test Doc2 Title", "Test Doc2 Description", "Test Content"); + person1PrivateDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2", "Test Folder2 Title", "Test Folder2 Description"); + person1PrivateFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Doc3 Title", "Test Doc3 Description", "Test Content"); + person1PrivateDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3", "Test Folder3 Title", "Test Folder3 Description"); + person1PrivateFolders.add(nodeRef); + + return null; + } + }, person11Id, network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + person1PublicSites.add(site); + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); + personFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); + personFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); + personFolders.add(nodeRef); + + return null; + } + }, person10Id, network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + GUID.generate(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + personSites.add(site); + + site.inviteToSite(person11Id, SiteRole.SiteCollaborator); + + siteName = "site" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + site = network1.createSite(siteInfo); + personSites.add(site); + + return null; + } + }, person10Id, network1.getId()); + + this.favouritesProxy = publicApiClient.favourites(); + this.siteMembershipRequestsProxy = publicApiClient.siteMembershipRequests(); + } + + private void updateFavourite(String networkId, String runAsUserId, String personId, TARGET_TYPE type) throws Exception + { + { + int size = 0; + + try + { + // get a favourite id + ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); + List favourites = resp.getList(); + size = favourites.size(); + assertTrue(size > 0); + Favourite favourite = favourites.get(0); + + favouritesProxy.update("people", personId, "favorites", favourite.getTargetGuid(), favourite.toJSON().toString(), "Unable to update favourite"); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // check nothing has changed + ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); + List favourites = resp.getList(); + assertEquals(size, favourites.size()); + } + } + + private Favourite deleteFavourite(String networkId, String runAsUserId, String personId, TARGET_TYPE type) throws Exception + { + Exception e = null; + + publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); + + // get a favourite id + ListResponse resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); + List favourites = resp.getList(); + int size = favourites.size(); + assertTrue(size > 0); + Favourite favourite = favourites.get(0); + + try + { + // catch 404's + favouritesProxy.removeFavourite(personId, favourite.getTargetGuid()); + } + catch(PublicApiException exc) + { + e = exc; + } + + // check favourite has been removed + resp = getFavourites(networkId, runAsUserId, personId, 0, Integer.MAX_VALUE, null, null, type); + favourites = resp.getList(); + boolean stillExists = false; + for(Favourite f : favourites) + { + if(f.getTargetGuid().equals(favourite.getTargetGuid())) + { + stillExists = true; + break; + } + } + assertFalse(stillExists); + + if(e != null) + { + throw e; + } + + return favourite; + } + + private ListResponse getFavourites(String networkId, String runAsUserId, String personId, int skipCount, int maxItems, Integer total, + Integer expectedTotal, TARGET_TYPE type) throws PublicApiException, ParseException + { + publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); + + Paging paging = null; + if(total == null && expectedTotal == null) + { + paging = getPaging(skipCount, maxItems); + } + else + { + paging = getPaging(skipCount, maxItems, total, expectedTotal); + } + Map params = null; + if(type != null) + { + params = Collections.singletonMap("where", "(EXISTS(target/" + type + "))"); + } + ListResponse resp = favouritesProxy.getFavourites(personId, createParams(paging, params)); + return resp; + } + + private Favourite makeFolderFavourite(String targetGuid) throws ParseException + { + FavouriteFolder folder = new FavouriteFolder(targetGuid); + FolderFavouriteTarget target = new FolderFavouriteTarget(folder); + Date creationData = new Date(); + Favourite favourite = new Favourite(creationData, null, target); + return favourite; + } + + private Favourite makeFileFavourite(String targetGuid) throws ParseException + { + FavouriteDocument document = new FavouriteDocument(targetGuid); + FileFavouriteTarget target = new FileFavouriteTarget(document); + Date creationData = new Date(); + Favourite favourite = new Favourite(creationData, null, target); + return favourite; + } + + private Favourite makeSiteFavourite(Site site) throws ParseException + { + SiteFavouriteTarget target = new SiteFavouriteTarget(site); + Date creationDate = new Date(); + Favourite favourite = new Favourite(creationDate, null, target); + return favourite; + } + + @Test + public void testInvalidRequests() throws Exception + { + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite favourite = makeSiteFavourite(person1PublicSites.get(0)); + Favourite ret = favouritesProxy.createFavourite(person11Id, favourite); + favourite.expected(ret); + fail(); + } + catch(PublicApiException e) + { + // Note: un-authorized comes back as 404 + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // cloud-2468 + // invalid type + // NOTE: The test below has swapped to attempt to favorite a comment rather than a + // a wiki page as the WikiService has moved to the Share Services AMP in 5.1 + + try + { + log("cloud-2468"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + final NodeRef document = personDocs.get(0); + final NodeRef comment = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + NodeRef comment = repoService.createComment(document, new Comment("Title", "Content")); + return comment; + } + }, person10Id, network1.getId()); + + final String guid = comment.getId(); + JSONAble commentJSON = new JSONAble() + { + @SuppressWarnings("unchecked") + @Override + public JSONObject toJSON() + { + JSONObject json = new JSONObject(); + json.put("guid", guid); + return json; + } + }; + + FavouritesTarget target = new InvalidFavouriteTarget("comment", commentJSON, guid); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + try + { + log("cloud-2468"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Site site = person1PublicSites.get(0); + FavouritesTarget target = new InvalidFavouriteTarget(GUID.generate(), site, site.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // type = file, target is a site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + String siteGuid = person1PublicSites.get(0).getGuid(); + FavouriteDocument document = new FavouriteDocument(siteGuid); + Favourite favourite = makeFileFavourite(document.getGuid()); + Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); + favourite.expected(ret); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // type = folder, target is a site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + String siteGuid = person1PublicSites.get(0).getGuid(); + FavouriteFolder folder = new FavouriteFolder(siteGuid); + Favourite favourite = makeFolderFavourite(folder.getGuid()); + Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); + favourite.expected(ret); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // type = folder, target is a file + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouriteFolder folder = new FavouriteFolder(person1PublicDocs.get(0).getId()); + Favourite favourite = makeFolderFavourite(folder.getGuid()); + Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); + favourite.expected(ret); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // type = file, target is a folder + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouriteDocument document = new FavouriteDocument(person1PublicFolders.get(0).getId()); + Favourite favourite = makeFileFavourite(document.getGuid()); + Favourite ret = favouritesProxy.createFavourite(person10Id, favourite); + favourite.expected(ret); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // make sure that a user can't favourite on behalf of another user + // 2471 + { + log("cloud-2471"); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouriteDocument document = new FavouriteDocument(person1PublicDocs.get(0).getId()); + Favourite favourite = makeFileFavourite(document.getGuid()); + favouritesProxy.createFavourite(person11Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + // Note: un-authorized comes back as 404 + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // person1 should have no favourites + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + ListResponse response = favouritesProxy.getFavourites(person11Id, createParams(null, null)); + assertEquals(0, response.getList().size()); + } + + // invalid/non-existent user + // 2469 + try + { + log("cloud-2469"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite favourite = makeSiteFavourite(personSites.get(0)); + Favourite ret = favouritesProxy.createFavourite(GUID.generate(), favourite); + favourite.expected(ret); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // make sure that a user can't see other user's favourites. + // 2465 + try + { + log("cloud-2465"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + favouritesProxy.getFavourites(person11Id, null); + fail(); + } + catch(PublicApiException e) + { + // Note: un-authorized comes back as 404 + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // 2464, unknown user + try + { + log("cloud-2464"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + favouritesProxy.getFavourites(GUID.generate(), null); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // non-existent entity for a given type + // 2480 + { + log("cloud-2480"); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + SiteImpl site = new SiteImpl(); + site.setGuid(GUID.generate()); + Favourite favourite = makeSiteFavourite((Site)site); + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); + assertEquals(0, response.getList().size()); + } + + { + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouriteDocument document = new FavouriteDocument(GUID.generate()); + Favourite favourite = makeFileFavourite(document.getGuid()); + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); + assertEquals(0, response.getList().size()); + } + + { + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouriteFolder folder = new FavouriteFolder(GUID.generate()); + Favourite favourite = makeFolderFavourite(folder.getGuid()); + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); + assertEquals(0, response.getList().size()); + } + + // 2470 + // incorrect type for a given favourite target + { + log("cloud-2470"); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Site site = person1PublicSites.get(0); + FavouritesTarget target = new InvalidFavouriteTarget("folder", site, site.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Site site = person1PublicSites.get(0); + FavouritesTarget target = new InvalidFavouriteTarget("file", site, site.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + FavouriteDocument document = new FavouriteDocument(person1PublicDocs.get(0).getId()); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouritesTarget target = new InvalidFavouriteTarget("site", document, document.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouritesTarget target = new InvalidFavouriteTarget("folder", document, document.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + FavouriteFolder folder = new FavouriteFolder(person1PublicFolders.get(0).getId()); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouritesTarget target = new InvalidFavouriteTarget("site", folder, folder.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + FavouritesTarget target = new InvalidFavouriteTarget("file", folder, folder.getGuid()); + Favourite favourite = new Favourite(target); + + favouritesProxy.createFavourite(person10Id, favourite); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + // none of these POSTs should have resulted in favourites being created... + ListResponse response = favouritesProxy.getFavourites(person10Id, createParams(null, null)); + assertEquals(0, response.getList().size()); + } + + // invalid methods + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + try + { + Favourite favourite = new Favourite(null); + favouritesProxy.update("people", "-me-", "favorites", null, favourite.toJSON().toString(), "Unable to PUT favourites"); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + } + + @Test + public void testValidRequests() throws Exception + { + List expectedFavourites = new ArrayList(); + + { + // add some favourites + // 2467 + + log("cloud-2467"); + + Favourite siteFavourite1 = makeSiteFavourite(person1PublicSites.get(0)); + + FavouriteDocument document = repoService.getDocument(network1.getId(), person1PublicDocs.get(0)); + Favourite fileFavourite1 = makeFileFavourite(document.getGuid()); + + FavouriteFolder folder = repoService.getFolder(network1.getId(), person1PublicFolders.get(0)); + Favourite folderFavourite1 = makeFolderFavourite(folder.getGuid()); + + Favourite siteFavourite2 = makeSiteFavourite(person1PublicSites.get(1)); + + document = repoService.getDocument(network1.getId(), person1PublicDocs.get(1)); + Favourite fileFavourite2 = makeFileFavourite(document.getGuid()); + + folder = repoService.getFolder(network1.getId(), person1PublicFolders.get(1)); + Favourite folderFavourite2 = makeFolderFavourite(folder.getGuid()); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite1); + expectedFavourites.add(ret); + siteFavourite1.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite1); + expectedFavourites.add(ret); + fileFavourite1.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite1); + expectedFavourites.add(ret); + folderFavourite1.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite2); + expectedFavourites.add(ret); + siteFavourite2.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite2); + expectedFavourites.add(ret); + fileFavourite2.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite2); + expectedFavourites.add(ret); + folderFavourite2.expected(ret); + } + + // already a favourite - 201 + { + log("cloud-2472"); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, siteFavourite1); + siteFavourite1.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, folderFavourite1); + folderFavourite1.expected(ret); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite ret = favouritesProxy.createFavourite(person10Id, fileFavourite1); + fileFavourite1.expected(ret); + } + } + + { + // cloud-2498 + // cloud-2499 + // create and list favourites across networks + + List person21ExpectedFavourites = new ArrayList(); + + log("cloud-2498"); + log("cloud-2499"); + + { + // favourite a site in another network + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); + + Favourite favourite = makeSiteFavourite(person1PrivateSites.get(0)); + try + { + favouritesProxy.createFavourite("-me-", favourite); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + int skipCount = 0; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); + try + { + favouritesProxy.getFavourites("-me-", createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + // favourite a document in another network + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); + + FavouriteDocument document1 = new FavouriteDocument(person1PrivateDocs.get(0).getId()); + Favourite favourite = makeFileFavourite(document1.getGuid()); + try + { + favouritesProxy.createFavourite("-me-", favourite); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + sort(person21ExpectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); + try + { + favouritesProxy.getFavourites("-me-", createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + // favourite a folder in another network + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21Id)); + + FavouriteFolder folder1 = new FavouriteFolder(person1PrivateFolders.get(0).getId()); + Favourite favourite = makeFolderFavourite(folder1.getGuid()); + try + { + favouritesProxy.createFavourite("-me-", favourite); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + sort(person21ExpectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, person21ExpectedFavourites.size(), person21ExpectedFavourites.size()); + try + { + favouritesProxy.getFavourites("-me-", createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + } + } + + // GET favourites + // test paging and sorting + { + // cloud-2458 + // cloud-2462 + // cloud-2461 + { + log("cloud-2458"); + log("cloud-2461"); + log("cloud-2462"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + List expected = new ArrayList(expectedFavourites); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, null)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + List expected = new ArrayList(expectedFavourites); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 2; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, null)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // 2466 + // GET favourites for "-me-" + { + log("cloud-2466"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + List expected = new ArrayList(expectedFavourites); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites("-me-", createParams(paging, null)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + // 2459 + { + log("cloud-2459"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, 0, 0); + ListResponse resp = favouritesProxy.getFavourites(person11Id, createParams(paging, null)); + List empty = Collections.emptyList(); + checkList(empty, paging.getExpectedPaging(), resp); + } + + // cloud-2460: filtering by target type + { + log("cloud-2460"); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.FILE)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/file))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.FOLDER)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/folder))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/file + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.FILE)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/file))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/folder + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.FOLDER)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/folder))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.SITE)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/site))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/folder OR target/file. + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.FOLDER, Type.FILE)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/file) OR EXISTS(target/folder))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/site OR target/file. + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.SITE, Type.FILE)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/file) OR EXISTS(target/site))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // target/site OR target/folder. + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Set types = new HashSet(Arrays.asList(Type.SITE, Type.FOLDER)); + List expected = filter(expectedFavourites, types); + sort(expected, FavouritesService.DEFAULT_SORT_PROPS); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expected.size(), expected.size()); + Map params = Collections.singletonMap("where", "(EXISTS(target/site) OR EXISTS(target/folder))"); + ListResponse resp = favouritesProxy.getFavourites(person10Id, createParams(paging, params)); + checkList(expected.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + // GET a favourite + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + favouritesProxy.getFavourite(person10Id, GUID.generate()); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite favourite = expectedFavourites.get(0); + + favouritesProxy.getFavourite(GUID.generate(), favourite.getTargetGuid()); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + Favourite favourite = expectedFavourites.get(0); + + Favourite resp = favouritesProxy.getFavourite(person10Id, favourite.getTargetGuid()); + favourite.expected(resp); + } + + // cloud-2479, PUT case + { + log("cloud-2479.1"); + updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.site); + + log("cloud-2479.2"); + updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.file); + + log("cloud-2479.3"); + updateFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.folder); + } + + try + { + // cloud-2474 + // non-existent personId + log("cloud-2474"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + favouritesProxy.removeFavourite(GUID.generate(), GUID.generate()); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // cloud-2475 + // try delete a non-existent favourite for a node that exists + { + log("cloud-2475"); + + NodeRef doc = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + NodeRef containerNodeRef = person1PublicSites.get(0).getContainerNodeRef("documentLibrary"); + NodeRef doc = repoService.createDocument(containerNodeRef, GUID.generate(), ""); + return doc; + } + }, person11Id, network1.getId()); + + String favouriteId = doc.getId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + + ListResponse before = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); + List beforeList = before.getList(); + assertTrue(beforeList.size() > 0); + + try + { + favouritesProxy.removeFavourite(person10Id, favouriteId); + fail("Should be a 404"); + } + catch(PublicApiException e) + { + // expected + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // check no favourites have been removed + ListResponse after = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); + assertEquals(beforeList.size(), after.getList().size()); + } + + // cloud-2473, DELETE case + { + log("cloud-2473.1"); + deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.site); + + log("cloud-2473.2"); + deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.file); + + log("cloud-2473.3"); + Favourite favourite = deleteFavourite(network1.getId(), person10Id, person10Id, TARGET_TYPE.folder); + + // try to delete non-existent favourite + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person10Id)); + favouritesProxy.removeFavourite(person10Id, favourite.getTargetGuid()); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // cloud-2476 + // try delete another user's favourite + { + log("cloud-2476"); + + // make sure there are favourites to delete +// publicApiClient.setRequestContext(new RequestContext(network1.getId(), personId)); +// SiteFavouriteTarget target = new SiteFavouriteTarget(person1Sites.get(0)); +// Favourite favourite = new Favourite(target); +// favouritesProxy.createFavourite(personId, favourite); + + ListResponse before = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); + assertTrue(before.getList().size() > 0); + Favourite favourite = before.getList().get(0); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + favouritesProxy.removeFavourite(person10Id, favourite.getTargetGuid()); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + ListResponse after = getFavourites(network1.getId(), person10Id, person10Id, 0, Integer.MAX_VALUE, null, null, null); + assertEquals(before.getList().size(), after.getList().size()); + } + } + + @Test + public void testPUBLICAPI141() throws Exception + { + final TestSite publicSite = person1PublicSites.get(0); // person1's public site + final TestSite publicSite1 = person1PublicSites.get(1); // person1's public site + final TestSite privateSite = person1PrivateSites.get(0); // person1's private site + final NodeRef folderNodeRef = person1PublicFolders.get(0); // person1's folder + final NodeRef nodeRef = person1PublicDocs.get(1); // a file in the folder + final List expectedFavourites = new ArrayList(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); + + // invite to another user's public site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(publicSite.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person12Id, siteMembershipRequest); + + // favourite other users site, folder and file + Favourite folderFavourite = makeFolderFavourite(folderNodeRef.getId()); + favouritesProxy.createFavourite(person12Id, folderFavourite); + + Favourite fileFavourite = makeFileFavourite(nodeRef.getId()); + favouritesProxy.createFavourite(person12Id, fileFavourite); + + final Favourite siteFavourite = makeSiteFavourite(publicSite); + favouritesProxy.createFavourite(person12Id, siteFavourite); + expectedFavourites.add(siteFavourite); + + final Favourite siteFavourite1 = makeSiteFavourite(publicSite1); + favouritesProxy.createFavourite(person12Id, siteFavourite1); + expectedFavourites.add(siteFavourite1); + + sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); + + // move the folder and file to person1's private site + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + NodeRef documentLibraryNodeRef = privateSite.getContainerNodeRef("documentLibrary"); + repoService.moveNode(folderNodeRef, documentLibraryNodeRef); + + return null; + } + }, person11Id, network1.getId()); + + try + { + favouritesProxy.getFavourite(person12Id, folderFavourite.getTargetGuid()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + favouritesProxy.getFavourite(person12Id, fileFavourite.getTargetGuid()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites(person12Id, createParams(paging, null)); + checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // make the public sites private + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + publicSite.setSiteVisibility(SiteVisibility.PRIVATE); + publicSite1.setSiteVisibility(SiteVisibility.PRIVATE); + + return null; + } + }, person11Id, network1.getId()); + expectedFavourites.remove(siteFavourite1); + + // Given that person2Id is still a member of 'publicSite', they should still have access and therefore + // it should show up in their favourites. But person2Id is not a member of 'publicSite1', they should + // not have access and therefore it should not show up in their favourites. + { + Favourite actual = favouritesProxy.getFavourite(person12Id, siteFavourite.getTargetGuid()); + siteFavourite.expected(actual); + + try + { + favouritesProxy.getFavourite(person12Id, siteFavourite1.getTargetGuid()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites(person12Id, createParams(paging, null)); + checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + } + + @Test + public void testPUBLICAPI156() throws Exception + { + final TestSite publicSite = person1PublicSites.get(0); // person1's public site + final TestSite publicSite1 = person1PublicSites.get(1); // person1's public site + final NodeRef folderNodeRef = person1PublicFolders.get(0); // person1's folder + final NodeRef nodeRef = person1PublicDocs.get(1); // a file in the folder + final List expectedFavourites = new ArrayList(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + // invite to another user's public site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(publicSite.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + + // favourite other users site, folder and file + Favourite folderFavourite = makeFolderFavourite(folderNodeRef.getId()); + favouritesProxy.createFavourite(person14Id, folderFavourite); + expectedFavourites.add(folderFavourite); + + Favourite fileFavourite = makeFileFavourite(nodeRef.getId()); + favouritesProxy.createFavourite(person14Id, fileFavourite); + expectedFavourites.add(fileFavourite); + + final Favourite siteFavourite = makeSiteFavourite(publicSite); + favouritesProxy.createFavourite(person14Id, siteFavourite); + expectedFavourites.add(siteFavourite); + + final Favourite siteFavourite1 = makeSiteFavourite(publicSite1); + favouritesProxy.createFavourite(person14Id, siteFavourite1); + expectedFavourites.add(siteFavourite1); + + sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); + + // remove the folder and file + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.deleteNode(nodeRef); + repoService.deleteNode(folderNodeRef); + + return null; + } + }, person11Id, network1.getId()); + + expectedFavourites.remove(folderFavourite); + expectedFavourites.remove(fileFavourite); + sort(expectedFavourites, FavouritesService.DEFAULT_SORT_PROPS); + + // GETs should not return the favourites nor error + { + try + { + favouritesProxy.getFavourite(person14Id, folderFavourite.getTargetGuid()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + favouritesProxy.getFavourite(person14Id, fileFavourite.getTargetGuid()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedFavourites.size(), expectedFavourites.size()); + ListResponse resp = favouritesProxy.getFavourites(person14Id, createParams(paging, null)); + checkList(sublist(expectedFavourites, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/TestFixture.java b/source/test-java/org/alfresco/rest/api/tests/TestFixture.java index 63cb02796d..c8e1009d7d 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestFixture.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestFixture.java @@ -1,22 +1,22 @@ -package org.alfresco.rest.api.tests; - -import java.util.Iterator; - -import org.alfresco.repo.web.util.JettyComponent; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.springframework.context.ApplicationContext; - -public interface TestFixture -{ - public final static int PORT = 8081; - public final static String CONTEXT_PATH = "/alfresco"; - public final static String PUBLIC_API_SERVLET_NAME = "api"; - - ApplicationContext getApplicationContext(); - RepoService getRepoService(); - Iterator getNetworksIt(); - TestNetwork getRandomNetwork(); - Iterator networksIterator(); - JettyComponent getJettyComponent(); - TestNetwork getNetwork(String name); -} +package org.alfresco.rest.api.tests; + +import java.util.Iterator; + +import org.alfresco.repo.web.util.JettyComponent; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.springframework.context.ApplicationContext; + +public interface TestFixture +{ + public final static int PORT = 8081; + public final static String CONTEXT_PATH = "/alfresco"; + public final static String PUBLIC_API_SERVLET_NAME = "api"; + + ApplicationContext getApplicationContext(); + RepoService getRepoService(); + Iterator getNetworksIt(); + TestNetwork getRandomNetwork(); + Iterator networksIterator(); + JettyComponent getJettyComponent(); + TestNetwork getNetwork(String name); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestNetworks.java b/source/test-java/org/alfresco/rest/api/tests/TestNetworks.java index 02d1df9e18..45f5c35b90 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestNetworks.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestNetworks.java @@ -1,441 +1,441 @@ -package org.alfresco.rest.api.tests; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.client.HttpResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.PersonNetwork; -import org.alfresco.rest.api.tests.util.RestApiUtil; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; -import static org.junit.Assert.assertNotNull; - -public class TestNetworks extends EnterpriseTestApi -{ - private List people = new ArrayList(3); - private List networks = new ArrayList(); - - private TestNetwork network1; - private TestNetwork network2; - private TestNetwork network3; - - private TestPerson person11; - private TestPerson person12; - private TestPerson person21; - private TestPerson person31; - - @Before - public void setup() - { - // create some networks - for(int i = 0; i < 2; i++) - { - final TestNetwork network = repoService.createNetworkWithAlias("network" + i, true); - network.create(); - networks.add(network); - } - - final TestNetwork network = repoService.createNetworkWithAlias("cmisnew.test", true); - network.create(); - networks.add(network); - - // do we have all the networks created? - assertEquals(3, networks.size()); - - this.network1 = networks.get(0); - this.network2 = networks.get(1); - this.network3 = networks.get(2); - - // create a couple of users in one of the networks - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - return null; - } - }, network1.getId()); - - // create a user in another network - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - return null; - } - }, network2.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network3.createUser(); - people.add(person); - return null; - } - }, network3.getId()); - - Iterator peopleIt = people.iterator(); - this.person11 = peopleIt.next(); - this.person12 = peopleIt.next(); - this.person21 = peopleIt.next(); - this.person31 = peopleIt.next(); - } - - @Test - public void testPersonNetworks() throws Exception - { - People peopleProxy = publicApiClient.people(); - - { - /** - * Test http://:/alfresco/a i.e. tenant servlet root - should return user's networks - * - */ - - final TestNetwork testAccount = getTestFixture().getRandomNetwork(); - Iterator personIt = testAccount.getPeople().iterator(); - final TestPerson person = personIt.next(); - - RequestContext rc = new RequestContext(null, person.getId()); - publicApiClient.setRequestContext(rc); - - HttpResponse response = publicApiClient.delete(null, null, null, null, null); - //url /null/alfresco/versions/1 does not map to a Web Script - assertEquals(404, response.getStatusCode()); - PublicApiClient.ExpectedErrorResponse errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); - assertNotNull(errorResponse); - assertNotNull(errorResponse.getErrorKey()); - assertNotNull(errorResponse.getBriefSummary()); - - - response = publicApiClient.put(null, null, null, null, null, null, null); - assertEquals(404, response.getStatusCode()); - errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); - assertNotNull(errorResponse); - assertNotNull(errorResponse.getErrorKey()); - assertNotNull(errorResponse.getBriefSummary()); - - - response = publicApiClient.post(null, null, null, null, null, null); - assertEquals(404, response.getStatusCode()); - errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); - assertNotNull(errorResponse); - assertNotNull(errorResponse.getErrorKey()); - assertNotNull(errorResponse.getBriefSummary()); - - List expectedNetworkMembers = person.getNetworkMemberships(); - - int expectedTotal = expectedNetworkMembers.size(); - - { - // GET / - users networks - Paging paging = getPaging(0, Integer.MAX_VALUE, expectedTotal, expectedTotal); - publicApiClient.setRequestContext(new RequestContext("-default-", person.getId())); - response = publicApiClient.index(createParams(paging, null)); - ListResponse resp = PersonNetwork.parseNetworkMembers(response.getJsonResponse()); - assertEquals(200, response.getStatusCode()); - - checkList(new ArrayList(expectedNetworkMembers), paging.getExpectedPaging(), resp); - } - } - - // user from another network - { - publicApiClient.setRequestContext(new RequestContext("-default-", person21.getId())); - - List networksMemberships = Collections.emptyList(); - - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); - peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // user from the same network - try - { - List networksMemberships = person12.getNetworkMemberships(); - - publicApiClient.setRequestContext(new RequestContext("-default-", person12.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); - peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - List networksMemberships = person11.getNetworkMemberships(); - - // Test Case cloud-2203 - // Test Case cloud-1498 - // test paging - { - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); - ListResponse resp = peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); - checkList(networksMemberships.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // "-me-" user - { - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); - ListResponse resp = peopleProxy.getNetworkMemberships(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); - checkList(networksMemberships.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // unknown person id - try - { - List networkMemberships = person11.getNetworkMemberships(); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging expectedPaging = getPaging(skipCount, maxItems, networkMemberships.size(), networkMemberships.size()); - peopleProxy.getNetworkMemberships("invalidUser", createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid caller authentication - try - { - List networkMemberships = person11.getNetworkMemberships(); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId(), GUID.generate())); - - int skipCount = 0; - int maxItems = 2; - Paging expectedPaging = getPaging(skipCount, maxItems, networkMemberships.size(), networkMemberships.size()); - peopleProxy.getNetworkMemberships(person11.getId(), createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1499 - // unknown person id - try - { - List networkMemberships = person11.getNetworkMemberships(); - - assertTrue(networkMemberships.size() > 0); - PersonNetwork network = networkMemberships.get(0); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.getNetworkMembership("invalidUser", network.getId()); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid caller authentication - try - { - List networkMemberships = person11.getNetworkMemberships(); - - assertTrue(networkMemberships.size() > 0); - PersonNetwork network = networkMemberships.get(0); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId(), GUID.generate())); - peopleProxy.getNetworkMembership(person11.getId(), network.getId()); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // incorrect network id - try - { - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.getNetworkMembership(person11.getId(), GUID.generate()); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // 1969 - // not allowed methods - // POST, POST networkId, PUT, PUT networkId, DELETE, DELETE networkId - try - { - PersonNetwork pn = new PersonNetwork(GUID.generate()); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.create("people", person11.getId(), "networks", null, pn.toJSON().toString(), "Unable to POST to person networks"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - PersonNetwork pn = networksMemberships.get(0); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.create("people", person11.getId(), "networks", pn.getId(), pn.toJSON().toString(), "Unable to POST to a person network"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - PersonNetwork pn = new PersonNetwork(GUID.generate()); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.update("people", person11.getId(), "networks", null, pn.toJSON().toString(), "Unable to PUT person networks"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - PersonNetwork pn = networksMemberships.get(0); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.update("people", person11.getId(), "networks", pn.getId(), pn.toJSON().toString(), "Unable to PUT a person network"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.remove("people", person11.getId(), "networks", null, "Unable to DELETE person networks"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - PersonNetwork pn = networksMemberships.get(0); - - publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); - peopleProxy.remove("people", person11.getId(), "networks", pn.getId(), "Unable to DELETE a person network"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // user not a member of the network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging expectedPaging = getPaging(skipCount, maxItems); - peopleProxy.getNetworkMemberships(person11.getId(), createParams(expectedPaging, null)); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - /* - * CLOUD-1856: test that a network id of the form "cmis*" works - */ - @Test - public void testCLOUD1856() throws Exception - { - People peopleProxy = publicApiClient.people(); - - publicApiClient.setRequestContext(new RequestContext(network3.getId(), person31.getId())); - Person ret = peopleProxy.getPerson(person31.getId()); - person31.expected(ret); - } - - // ALF-20216, ALF-20217, ALF-20098 - // http://localhost:8080/alfresco/api/-default- - @Test - public void testALF20098() throws Exception - { - final TestNetwork testAccount = getTestFixture().getRandomNetwork(); - Iterator personIt = testAccount.getPeople().iterator(); - final TestPerson person = personIt.next(); - - RequestContext rc = new RequestContext("-default-", person.getId()); - publicApiClient.setRequestContext(rc); - - HttpResponse response = publicApiClient.get("-default-", null); - assertEquals(200, response.getStatusCode()); - } - -} +package org.alfresco.rest.api.tests; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.client.HttpResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.PersonNetwork; +import org.alfresco.rest.api.tests.util.RestApiUtil; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; + +public class TestNetworks extends EnterpriseTestApi +{ + private List people = new ArrayList(3); + private List networks = new ArrayList(); + + private TestNetwork network1; + private TestNetwork network2; + private TestNetwork network3; + + private TestPerson person11; + private TestPerson person12; + private TestPerson person21; + private TestPerson person31; + + @Before + public void setup() + { + // create some networks + for(int i = 0; i < 2; i++) + { + final TestNetwork network = repoService.createNetworkWithAlias("network" + i, true); + network.create(); + networks.add(network); + } + + final TestNetwork network = repoService.createNetworkWithAlias("cmisnew.test", true); + network.create(); + networks.add(network); + + // do we have all the networks created? + assertEquals(3, networks.size()); + + this.network1 = networks.get(0); + this.network2 = networks.get(1); + this.network3 = networks.get(2); + + // create a couple of users in one of the networks + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + return null; + } + }, network1.getId()); + + // create a user in another network + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + return null; + } + }, network2.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network3.createUser(); + people.add(person); + return null; + } + }, network3.getId()); + + Iterator peopleIt = people.iterator(); + this.person11 = peopleIt.next(); + this.person12 = peopleIt.next(); + this.person21 = peopleIt.next(); + this.person31 = peopleIt.next(); + } + + @Test + public void testPersonNetworks() throws Exception + { + People peopleProxy = publicApiClient.people(); + + { + /** + * Test http://:/alfresco/a i.e. tenant servlet root - should return user's networks + * + */ + + final TestNetwork testAccount = getTestFixture().getRandomNetwork(); + Iterator personIt = testAccount.getPeople().iterator(); + final TestPerson person = personIt.next(); + + RequestContext rc = new RequestContext(null, person.getId()); + publicApiClient.setRequestContext(rc); + + HttpResponse response = publicApiClient.delete(null, null, null, null, null); + //url /null/alfresco/versions/1 does not map to a Web Script + assertEquals(404, response.getStatusCode()); + PublicApiClient.ExpectedErrorResponse errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); + assertNotNull(errorResponse); + assertNotNull(errorResponse.getErrorKey()); + assertNotNull(errorResponse.getBriefSummary()); + + + response = publicApiClient.put(null, null, null, null, null, null, null); + assertEquals(404, response.getStatusCode()); + errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); + assertNotNull(errorResponse); + assertNotNull(errorResponse.getErrorKey()); + assertNotNull(errorResponse.getBriefSummary()); + + + response = publicApiClient.post(null, null, null, null, null, null); + assertEquals(404, response.getStatusCode()); + errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse()); + assertNotNull(errorResponse); + assertNotNull(errorResponse.getErrorKey()); + assertNotNull(errorResponse.getBriefSummary()); + + List expectedNetworkMembers = person.getNetworkMemberships(); + + int expectedTotal = expectedNetworkMembers.size(); + + { + // GET / - users networks + Paging paging = getPaging(0, Integer.MAX_VALUE, expectedTotal, expectedTotal); + publicApiClient.setRequestContext(new RequestContext("-default-", person.getId())); + response = publicApiClient.index(createParams(paging, null)); + ListResponse resp = PersonNetwork.parseNetworkMembers(response.getJsonResponse()); + assertEquals(200, response.getStatusCode()); + + checkList(new ArrayList(expectedNetworkMembers), paging.getExpectedPaging(), resp); + } + } + + // user from another network + { + publicApiClient.setRequestContext(new RequestContext("-default-", person21.getId())); + + List networksMemberships = Collections.emptyList(); + + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); + peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // user from the same network + try + { + List networksMemberships = person12.getNetworkMemberships(); + + publicApiClient.setRequestContext(new RequestContext("-default-", person12.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); + peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + List networksMemberships = person11.getNetworkMemberships(); + + // Test Case cloud-2203 + // Test Case cloud-1498 + // test paging + { + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); + ListResponse resp = peopleProxy.getNetworkMemberships(person11.getId(), createParams(paging, null)); + checkList(networksMemberships.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // "-me-" user + { + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, networksMemberships.size(), networksMemberships.size()); + ListResponse resp = peopleProxy.getNetworkMemberships(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); + checkList(networksMemberships.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // unknown person id + try + { + List networkMemberships = person11.getNetworkMemberships(); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging expectedPaging = getPaging(skipCount, maxItems, networkMemberships.size(), networkMemberships.size()); + peopleProxy.getNetworkMemberships("invalidUser", createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid caller authentication + try + { + List networkMemberships = person11.getNetworkMemberships(); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId(), GUID.generate())); + + int skipCount = 0; + int maxItems = 2; + Paging expectedPaging = getPaging(skipCount, maxItems, networkMemberships.size(), networkMemberships.size()); + peopleProxy.getNetworkMemberships(person11.getId(), createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1499 + // unknown person id + try + { + List networkMemberships = person11.getNetworkMemberships(); + + assertTrue(networkMemberships.size() > 0); + PersonNetwork network = networkMemberships.get(0); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.getNetworkMembership("invalidUser", network.getId()); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid caller authentication + try + { + List networkMemberships = person11.getNetworkMemberships(); + + assertTrue(networkMemberships.size() > 0); + PersonNetwork network = networkMemberships.get(0); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId(), GUID.generate())); + peopleProxy.getNetworkMembership(person11.getId(), network.getId()); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // incorrect network id + try + { + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.getNetworkMembership(person11.getId(), GUID.generate()); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // 1969 + // not allowed methods + // POST, POST networkId, PUT, PUT networkId, DELETE, DELETE networkId + try + { + PersonNetwork pn = new PersonNetwork(GUID.generate()); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.create("people", person11.getId(), "networks", null, pn.toJSON().toString(), "Unable to POST to person networks"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + PersonNetwork pn = networksMemberships.get(0); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.create("people", person11.getId(), "networks", pn.getId(), pn.toJSON().toString(), "Unable to POST to a person network"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + PersonNetwork pn = new PersonNetwork(GUID.generate()); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.update("people", person11.getId(), "networks", null, pn.toJSON().toString(), "Unable to PUT person networks"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + PersonNetwork pn = networksMemberships.get(0); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.update("people", person11.getId(), "networks", pn.getId(), pn.toJSON().toString(), "Unable to PUT a person network"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.remove("people", person11.getId(), "networks", null, "Unable to DELETE person networks"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + PersonNetwork pn = networksMemberships.get(0); + + publicApiClient.setRequestContext(new RequestContext("-default-", person11.getId())); + peopleProxy.remove("people", person11.getId(), "networks", pn.getId(), "Unable to DELETE a person network"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // user not a member of the network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging expectedPaging = getPaging(skipCount, maxItems); + peopleProxy.getNetworkMemberships(person11.getId(), createParams(expectedPaging, null)); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + /* + * CLOUD-1856: test that a network id of the form "cmis*" works + */ + @Test + public void testCLOUD1856() throws Exception + { + People peopleProxy = publicApiClient.people(); + + publicApiClient.setRequestContext(new RequestContext(network3.getId(), person31.getId())); + Person ret = peopleProxy.getPerson(person31.getId()); + person31.expected(ret); + } + + // ALF-20216, ALF-20217, ALF-20098 + // http://localhost:8080/alfresco/api/-default- + @Test + public void testALF20098() throws Exception + { + final TestNetwork testAccount = getTestFixture().getRandomNetwork(); + Iterator personIt = testAccount.getPeople().iterator(); + final TestPerson person = personIt.next(); + + RequestContext rc = new RequestContext("-default-", person.getId()); + publicApiClient.setRequestContext(rc); + + HttpResponse response = publicApiClient.get("-default-", null); + assertEquals(200, response.getStatusCode()); + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestNodeComments.java b/source/test-java/org/alfresco/rest/api/tests/TestNodeComments.java index 1d7cb27c7c..b5e6a6d1fb 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestNodeComments.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestNodeComments.java @@ -1,802 +1,802 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.activities.ActivityType; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Activity; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -public class TestNodeComments extends EnterpriseTestApi -{ - private TestNetwork network1; - private TestNetwork network2; - - private List people = new ArrayList(); - private List sites = new ArrayList(); - - private TestPerson person11; - private TestPerson person12; - private TestPerson person21; - private TestPerson person22; - - private NodeRef nodeRef1; - private NodeRef folderNodeRef1; - private NodeRef nodeRef2; - private NodeRef nodeRef3; - private NodeRef nodeRef4; - private NodeRef cmObjectNodeRef; - private NodeRef customTypeObject; - - @Before - public void setup() throws Exception - { - Iterator accountsIt = getTestFixture().getNetworksIt(); - this.network1 = accountsIt.next(); - this.network2 = accountsIt.next(); - - // Create users in different networks and a site - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - person = network2.createUser(); - people.add(person); - - return null; - } - }, network2.getId()); - - this.person11 = people.get(0); - this.person12 = people.get(1); - this.person21 = people.get(2); - this.person22 = people.get(3); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - sites.add(site); - - return null; - } - }, person11.getId(), network1.getId()); - - final TestSite site1 = sites.get(0); - - final List nodes = new ArrayList(); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - NodeRef nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc", "Test Content"); - nodes.add(nodeRef); - nodeRef = repoService.createFolder(site1.getContainerNodeRef("documentLibrary"), "Test Folder"); - nodes.add(nodeRef); - nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content 1"); - nodes.add(nodeRef); - nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 2", "Test Content 2"); - nodes.add(nodeRef); - nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 3", "Test Content 3"); - nodes.add(nodeRef); - nodeRef = repoService.createCmObject(site1.getContainerNodeRef("documentLibrary"), "CM Object"); - nodes.add(nodeRef); - nodeRef = repoService.createObjectOfCustomType(site1.getContainerNodeRef("documentLibrary"), "Custom type object", "{custom.model}sop"); - nodes.add(nodeRef); - - return null; - } - }, person11.getId(), network1.getId()); - - this.nodeRef1 = nodes.get(0); - this.folderNodeRef1 = nodes.get(1); - this.nodeRef2 = nodes.get(2); - this.nodeRef3 = nodes.get(3); - this.nodeRef4 = nodes.get(4); - this.cmObjectNodeRef = nodes.get(5); - this.customTypeObject = nodes.get(6); - } - - @Test - // TODO test embedded entity createdBy full visibility e.g. view comment by another user who's full details the caller can't see - // TODO test update comment and modifiedBy in result is a person object - public void testNodeComments() throws Exception - { - Comments commentsProxy = publicApiClient.comments(); - Nodes nodesProxy = publicApiClient.nodes(); - People peopleProxy = publicApiClient.people(); - - // Test Case cloud-1518 - // Create comments - - // invalid node id - try - { - Comment comment = new Comment("Test Comment 4", "Test Comment 4"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.createNodeComment(GUID.generate(), comment); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // person from the same network - no permission - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - Comment comment = new Comment("Test Comment 4", "Test Comment 4"); - commentsProxy.createNodeComment(nodeRef1.getId(), comment); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-2196 - // multi-byte characters, create and update comments - { - Comment[] multiByteComments = new Comment[] - { - new Comment("ڠڡڢ", "ڠڡڢ"), - new Comment("\u67e5\u770b\u5168\u90e8", "\u67e5\u770b\u5168\u90e8") - }; - - Map createdComments = new HashMap(); - for(Comment comment : multiByteComments) - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment ret = commentsProxy.createNodeComment(nodeRef2.getId(), comment); - createdComments.put(ret.getId(), ret); - } - - // test that it is possible to add comment to custom type node - commentsProxy.createNodeComment(customTypeObject.getId(), new Comment("Custom type node comment", "The Comment")); - - try - { - // test that it is not possible to add comment to cm:object node - commentsProxy.createNodeComment(cmObjectNodeRef.getId(), new Comment("CM Object node comment", "The Comment")); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // get comments of the non-folder/non-document nodeRef - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - commentsProxy.getNodeComments(cmObjectNodeRef.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - ListResponse resp = commentsProxy.getNodeComments(nodeRef2.getId(), createParams(paging, null)); - List retComments = resp.getList(); - assertEquals(2, retComments.size()); - for(Comment comment : retComments) - { - String commentId = comment.getId(); - Comment expectedComment = createdComments.get(commentId); - expectedComment.expected(comment); - } - - Comment[] multiByteCommentUpdates = new Comment[] - { - new Comment("ӉӋӐӞ", "ӉӋӐӞ"), - new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03") - }; - - Map updatedComments = new HashMap(); - for(Comment comment : multiByteCommentUpdates) - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment ret = commentsProxy.createNodeComment(nodeRef2.getId(), comment); - updatedComments.put(ret.getId(), ret); - } - - skipCount = 0; - maxItems = 2; - paging = getPaging(skipCount, maxItems); - resp = commentsProxy.getNodeComments(nodeRef2.getId(), createParams(paging, null)); - retComments = resp.getList(); - assertEquals(2, retComments.size()); - for(Comment comment : retComments) - { - String commentId = comment.getId(); - Comment expectedComment = updatedComments.get(commentId); - expectedComment.expected(comment); - } - } - - { - // special characters - Comment comment = new Comment("", "?*^&*(,"); - List expectedComments = new ArrayList(1); - expectedComments.add(comment); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.createNodeComment(nodeRef3.getId(), comment); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef3.getId(), createParams(paging, null)); - checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - try - { - Comment comment = new Comment("", ""); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.createNodeComment(nodeRef2.getId(), comment); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - DateFormat format = PublicApiDateFormat.getDateFormat(); - final List expectedComments = new ArrayList(10); - final List comments = new ArrayList(10); - comments.add(new Comment("Test Comment 4", "Test Comment 4")); - comments.add(new Comment("Test Comment 1", "Test Comment 1")); - comments.add(new Comment("Test Comment 3", "Test Comment 3")); - comments.add(new Comment("Test Comment 2", "Test Comment 2")); - - { - Date time = new Date(); - for(Comment comment : comments) - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment resp = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - // check response - assertEquals(comment.getContent(), resp.getContent()); - assertTrue(format.parse(resp.getCreatedAt()).after(time)); - person11.expected(resp.getCreatedBy()); - assertNotNull(resp.getId()); - - expectedComments.add(resp); - } - - // check activities have been raised - repoService.generateFeed(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Paging paging = getPaging(0, Integer.MAX_VALUE); - ListResponse activities = peopleProxy.getActivities(person11.getId(), createParams(paging, null)); - - boolean found = false; - for(Activity activity : activities.getList()) - { - String activityType = activity.getActivityType(); - if(activityType.equals(ActivityType.COMMENT_CREATED)) - { - Map summary = activity.getSummary(); - assertNotNull(summary); - String objectId = (String)summary.get("objectId"); - assertNotNull(objectId); - if(nodeRef1.getId().equals(objectId)) - { - found = true; - break; - } - } - } - - assertTrue(found); - } - } - - // try to add a comment to a comment - try - { - Comment comment = comments.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - expectedComments.add(newComment); - - commentsProxy.createNodeComment(newComment.getId(), comment); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // try to add a comment to a tag - try - { - Comment comment = comments.get(0); - Tag tag = new Tag("taggification"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Tag addedTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); - commentsProxy.createNodeComment(addedTag.getId(), comment); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // add a comment to a folder - { - Date time = new Date(); - - Comment comment = comments.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment resp = commentsProxy.createNodeComment(folderNodeRef1.getId(), comment); - - // check response - assertEquals(comment.getContent(), resp.getContent()); - assertTrue(format.parse(resp.getCreatedAt()).after(time)); - person11.expected(resp.getCreatedBy()); - assertNotNull(resp.getId()); - } - - Collections.sort(expectedComments); - - // Test Case cloud-2205 - // Test Case cloud-2217 - // Test Case cloud-1517 - // pagination - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 2; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // invalid node id - 404 - try - { - int skipCount = 0; - int maxItems = 2; - Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - commentsProxy.getNodeComments("invalid", createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - commentsProxy.getNodeComments(nodeRef1.getId() + ";pwc", createParams(paging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // suffix the node id with a version number - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId() + ";3.0", createParams(paging, null)); - checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // view comments of a document created by another person in the same network, who is not a member of the site - // in which the comment resides - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // document owned by another person in another network, the user is not a member of that network - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1971 - // invalid methods - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); - List nodeComments = resp.getList(); - assertTrue(nodeComments.size() > 0); - Comment comment = nodeComments.get(0); - - try - { - commentsProxy.create("nodes", nodeRef1.getId(), "comments", comment.getId(), null, "Unable to POST to a node comment"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - commentsProxy.update("nodes", nodeRef1.getId(), "comments", null, null, "Unable to PUT node comments"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - commentsProxy.getSingle("nodes", nodeRef1.getId(), "comments", comment.getId(), "Unable to GET a node comment"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - commentsProxy.remove("nodes", nodeRef1.getId(), "comments", null, "Unable to DELETE node comments"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - - // Test Case cloud-2184 - // update comments - { - Comment[] testComments = new Comment[] - { - new Comment("ӉӋӐӞ", "ӉӋӐӞ"), - new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03") - }; - - List mlComments = new ArrayList(); - mlComments.add(new Comment("ӉӋӐӞ", "ӉӋӐӞ")); - mlComments.add(new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03")); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - // create some comments - Map createdComments = new HashMap(); - for(Comment comment : testComments) - { - - Comment ret = commentsProxy.createNodeComment(nodeRef4.getId(), comment); - createdComments.put(ret.getId(), ret); - } - - // update them with multi-byte content - int i = 0; - List updatedComments = new ArrayList(); - for(Comment comment : createdComments.values()) - { - Comment updateComment = mlComments.get(i); - Comment ret = commentsProxy.updateNodeComment(nodeRef4.getId(), comment.getId(), updateComment); - updatedComments.add(ret); - i++; - } - Collections.sort(updatedComments); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, mlComments.size(), mlComments.size()); - ListResponse resp = commentsProxy.getNodeComments(nodeRef4.getId(), createParams(paging, null)); - checkList(updatedComments, paging.getExpectedPaging(), resp); - } - - // invalid node id - try - { - Comment comment = expectedComments.get(1); - Comment update = new Comment("Test Comment 4", "Test Comment 4"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.updateNodeComment(GUID.generate(), comment.getId(), update); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid comment id - try - { - Comment update = new Comment("Test Comment 4", "Test Comment 4"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.updateNodeComment(nodeRef1.getId(), GUID.generate(), update); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // person from the same network, not comment creator - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - Comment comment = expectedComments.get(1); - Comment update = new Comment("Test Comment 4", "Test Comment 4"); - commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // person from a different network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person22.getId())); - Comment comment = expectedComments.get(1); - Comment update = new Comment("Test Comment 4", "Test Comment 4"); - commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // successful update - { - Date time = new Date(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Comment comment = expectedComments.get(1); - Comment update = new Comment("Updated comment", "Updated comment"); - Comment resp = commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); - - Thread.sleep(100); // simulate a user edit to a comment - - Comment expected = new Comment(comment); - expected.setTitle("Updated comment"); - expected.setEdited(true); - expected.setContent("Updated comment"); - expected.setModifiedBy(repoService.getPerson(person11.getId())); - expected.setModifiedAt(PublicApiDateFormat.getDateFormat().format(time)); - expected.expected(resp); - } - - // delete comments - - // invalid node ref - try - { - Comment comment = expectedComments.get(1); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.removeNodeComment(GUID.generate(), comment.getId()); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid comment id - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.removeNodeComment(nodeRef1.getId(), GUID.generate()); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // successful delete - { - Comment toDelete = expectedComments.get(1); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - commentsProxy.removeNodeComment(nodeRef1.getId(), toDelete.getId()); - - // check it's been removed - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); - List actualComments = resp.getList(); - assertFalse(actualComments.contains(toDelete)); - } - - // PUT: test update with null/empty comment - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Comment comment = new Comment(); - comment.setContent("my comment"); - Comment createdComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - - { - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.lockNode(nodeRef1); - return null; - } - }, person11.getId(), network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Comment updatedComment = new Comment(); - updatedComment.setContent(null); - commentsProxy.updateNodeComment(nodeRef1.getId(), createdComment.getId(), updatedComment); - } - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // locked node comments - try - { - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.lockNode(nodeRef1); - return null; - } - }, person11.getId(), network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - // test GET for a locked node - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); - commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); - - // test POST for a locked node - - Comment comment = new Comment(); - comment.setContent("my comment"); - Comment createdComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - - // test PUT for a locked node - { - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.lockNode(nodeRef1); - return null; - } - }, person11.getId(), network1.getId()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Comment updatedComment = new Comment(); - updatedComment.setContent("my comment"); - commentsProxy.updateNodeComment(nodeRef1.getId(), createdComment.getId(), updatedComment); - } - } - finally - { - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.unlockNode(nodeRef1); - return null; - } - }, person11.getId(), network1.getId()); - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.activities.ActivityType; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Activity; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +public class TestNodeComments extends EnterpriseTestApi +{ + private TestNetwork network1; + private TestNetwork network2; + + private List people = new ArrayList(); + private List sites = new ArrayList(); + + private TestPerson person11; + private TestPerson person12; + private TestPerson person21; + private TestPerson person22; + + private NodeRef nodeRef1; + private NodeRef folderNodeRef1; + private NodeRef nodeRef2; + private NodeRef nodeRef3; + private NodeRef nodeRef4; + private NodeRef cmObjectNodeRef; + private NodeRef customTypeObject; + + @Before + public void setup() throws Exception + { + Iterator accountsIt = getTestFixture().getNetworksIt(); + this.network1 = accountsIt.next(); + this.network2 = accountsIt.next(); + + // Create users in different networks and a site + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + person = network2.createUser(); + people.add(person); + + return null; + } + }, network2.getId()); + + this.person11 = people.get(0); + this.person12 = people.get(1); + this.person21 = people.get(2); + this.person22 = people.get(3); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + sites.add(site); + + return null; + } + }, person11.getId(), network1.getId()); + + final TestSite site1 = sites.get(0); + + final List nodes = new ArrayList(); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + NodeRef nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc", "Test Content"); + nodes.add(nodeRef); + nodeRef = repoService.createFolder(site1.getContainerNodeRef("documentLibrary"), "Test Folder"); + nodes.add(nodeRef); + nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content 1"); + nodes.add(nodeRef); + nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 2", "Test Content 2"); + nodes.add(nodeRef); + nodeRef = repoService.createDocument(site1.getContainerNodeRef("documentLibrary"), "Test Doc 3", "Test Content 3"); + nodes.add(nodeRef); + nodeRef = repoService.createCmObject(site1.getContainerNodeRef("documentLibrary"), "CM Object"); + nodes.add(nodeRef); + nodeRef = repoService.createObjectOfCustomType(site1.getContainerNodeRef("documentLibrary"), "Custom type object", "{custom.model}sop"); + nodes.add(nodeRef); + + return null; + } + }, person11.getId(), network1.getId()); + + this.nodeRef1 = nodes.get(0); + this.folderNodeRef1 = nodes.get(1); + this.nodeRef2 = nodes.get(2); + this.nodeRef3 = nodes.get(3); + this.nodeRef4 = nodes.get(4); + this.cmObjectNodeRef = nodes.get(5); + this.customTypeObject = nodes.get(6); + } + + @Test + // TODO test embedded entity createdBy full visibility e.g. view comment by another user who's full details the caller can't see + // TODO test update comment and modifiedBy in result is a person object + public void testNodeComments() throws Exception + { + Comments commentsProxy = publicApiClient.comments(); + Nodes nodesProxy = publicApiClient.nodes(); + People peopleProxy = publicApiClient.people(); + + // Test Case cloud-1518 + // Create comments + + // invalid node id + try + { + Comment comment = new Comment("Test Comment 4", "Test Comment 4"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.createNodeComment(GUID.generate(), comment); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // person from the same network - no permission + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + Comment comment = new Comment("Test Comment 4", "Test Comment 4"); + commentsProxy.createNodeComment(nodeRef1.getId(), comment); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-2196 + // multi-byte characters, create and update comments + { + Comment[] multiByteComments = new Comment[] + { + new Comment("ڠڡڢ", "ڠڡڢ"), + new Comment("\u67e5\u770b\u5168\u90e8", "\u67e5\u770b\u5168\u90e8") + }; + + Map createdComments = new HashMap(); + for(Comment comment : multiByteComments) + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment ret = commentsProxy.createNodeComment(nodeRef2.getId(), comment); + createdComments.put(ret.getId(), ret); + } + + // test that it is possible to add comment to custom type node + commentsProxy.createNodeComment(customTypeObject.getId(), new Comment("Custom type node comment", "The Comment")); + + try + { + // test that it is not possible to add comment to cm:object node + commentsProxy.createNodeComment(cmObjectNodeRef.getId(), new Comment("CM Object node comment", "The Comment")); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // get comments of the non-folder/non-document nodeRef + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + commentsProxy.getNodeComments(cmObjectNodeRef.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + ListResponse resp = commentsProxy.getNodeComments(nodeRef2.getId(), createParams(paging, null)); + List retComments = resp.getList(); + assertEquals(2, retComments.size()); + for(Comment comment : retComments) + { + String commentId = comment.getId(); + Comment expectedComment = createdComments.get(commentId); + expectedComment.expected(comment); + } + + Comment[] multiByteCommentUpdates = new Comment[] + { + new Comment("ӉӋӐӞ", "ӉӋӐӞ"), + new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03") + }; + + Map updatedComments = new HashMap(); + for(Comment comment : multiByteCommentUpdates) + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment ret = commentsProxy.createNodeComment(nodeRef2.getId(), comment); + updatedComments.put(ret.getId(), ret); + } + + skipCount = 0; + maxItems = 2; + paging = getPaging(skipCount, maxItems); + resp = commentsProxy.getNodeComments(nodeRef2.getId(), createParams(paging, null)); + retComments = resp.getList(); + assertEquals(2, retComments.size()); + for(Comment comment : retComments) + { + String commentId = comment.getId(); + Comment expectedComment = updatedComments.get(commentId); + expectedComment.expected(comment); + } + } + + { + // special characters + Comment comment = new Comment("", "?*^&*(,"); + List expectedComments = new ArrayList(1); + expectedComments.add(comment); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.createNodeComment(nodeRef3.getId(), comment); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef3.getId(), createParams(paging, null)); + checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + try + { + Comment comment = new Comment("", ""); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.createNodeComment(nodeRef2.getId(), comment); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + DateFormat format = PublicApiDateFormat.getDateFormat(); + final List expectedComments = new ArrayList(10); + final List comments = new ArrayList(10); + comments.add(new Comment("Test Comment 4", "Test Comment 4")); + comments.add(new Comment("Test Comment 1", "Test Comment 1")); + comments.add(new Comment("Test Comment 3", "Test Comment 3")); + comments.add(new Comment("Test Comment 2", "Test Comment 2")); + + { + Date time = new Date(); + for(Comment comment : comments) + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment resp = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + // check response + assertEquals(comment.getContent(), resp.getContent()); + assertTrue(format.parse(resp.getCreatedAt()).after(time)); + person11.expected(resp.getCreatedBy()); + assertNotNull(resp.getId()); + + expectedComments.add(resp); + } + + // check activities have been raised + repoService.generateFeed(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Paging paging = getPaging(0, Integer.MAX_VALUE); + ListResponse activities = peopleProxy.getActivities(person11.getId(), createParams(paging, null)); + + boolean found = false; + for(Activity activity : activities.getList()) + { + String activityType = activity.getActivityType(); + if(activityType.equals(ActivityType.COMMENT_CREATED)) + { + Map summary = activity.getSummary(); + assertNotNull(summary); + String objectId = (String)summary.get("objectId"); + assertNotNull(objectId); + if(nodeRef1.getId().equals(objectId)) + { + found = true; + break; + } + } + } + + assertTrue(found); + } + } + + // try to add a comment to a comment + try + { + Comment comment = comments.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + expectedComments.add(newComment); + + commentsProxy.createNodeComment(newComment.getId(), comment); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // try to add a comment to a tag + try + { + Comment comment = comments.get(0); + Tag tag = new Tag("taggification"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Tag addedTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); + commentsProxy.createNodeComment(addedTag.getId(), comment); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // add a comment to a folder + { + Date time = new Date(); + + Comment comment = comments.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment resp = commentsProxy.createNodeComment(folderNodeRef1.getId(), comment); + + // check response + assertEquals(comment.getContent(), resp.getContent()); + assertTrue(format.parse(resp.getCreatedAt()).after(time)); + person11.expected(resp.getCreatedBy()); + assertNotNull(resp.getId()); + } + + Collections.sort(expectedComments); + + // Test Case cloud-2205 + // Test Case cloud-2217 + // Test Case cloud-1517 + // pagination + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 2; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // invalid node id - 404 + try + { + int skipCount = 0; + int maxItems = 2; + Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + commentsProxy.getNodeComments("invalid", createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + commentsProxy.getNodeComments(nodeRef1.getId() + ";pwc", createParams(paging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // suffix the node id with a version number + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId() + ";3.0", createParams(paging, null)); + checkList(expectedComments.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // view comments of a document created by another person in the same network, who is not a member of the site + // in which the comment resides + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // document owned by another person in another network, the user is not a member of that network + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1971 + // invalid methods + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); + List nodeComments = resp.getList(); + assertTrue(nodeComments.size() > 0); + Comment comment = nodeComments.get(0); + + try + { + commentsProxy.create("nodes", nodeRef1.getId(), "comments", comment.getId(), null, "Unable to POST to a node comment"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + commentsProxy.update("nodes", nodeRef1.getId(), "comments", null, null, "Unable to PUT node comments"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + commentsProxy.getSingle("nodes", nodeRef1.getId(), "comments", comment.getId(), "Unable to GET a node comment"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + commentsProxy.remove("nodes", nodeRef1.getId(), "comments", null, "Unable to DELETE node comments"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + + // Test Case cloud-2184 + // update comments + { + Comment[] testComments = new Comment[] + { + new Comment("ӉӋӐӞ", "ӉӋӐӞ"), + new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03") + }; + + List mlComments = new ArrayList(); + mlComments.add(new Comment("ӉӋӐӞ", "ӉӋӐӞ")); + mlComments.add(new Comment("\u4e00\u4e01\u4e02\u4e03", "\u4e00\u4e01\u4e02\u4e03")); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + // create some comments + Map createdComments = new HashMap(); + for(Comment comment : testComments) + { + + Comment ret = commentsProxy.createNodeComment(nodeRef4.getId(), comment); + createdComments.put(ret.getId(), ret); + } + + // update them with multi-byte content + int i = 0; + List updatedComments = new ArrayList(); + for(Comment comment : createdComments.values()) + { + Comment updateComment = mlComments.get(i); + Comment ret = commentsProxy.updateNodeComment(nodeRef4.getId(), comment.getId(), updateComment); + updatedComments.add(ret); + i++; + } + Collections.sort(updatedComments); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, mlComments.size(), mlComments.size()); + ListResponse resp = commentsProxy.getNodeComments(nodeRef4.getId(), createParams(paging, null)); + checkList(updatedComments, paging.getExpectedPaging(), resp); + } + + // invalid node id + try + { + Comment comment = expectedComments.get(1); + Comment update = new Comment("Test Comment 4", "Test Comment 4"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.updateNodeComment(GUID.generate(), comment.getId(), update); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid comment id + try + { + Comment update = new Comment("Test Comment 4", "Test Comment 4"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.updateNodeComment(nodeRef1.getId(), GUID.generate(), update); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // person from the same network, not comment creator + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + Comment comment = expectedComments.get(1); + Comment update = new Comment("Test Comment 4", "Test Comment 4"); + commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // person from a different network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person22.getId())); + Comment comment = expectedComments.get(1); + Comment update = new Comment("Test Comment 4", "Test Comment 4"); + commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // successful update + { + Date time = new Date(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Comment comment = expectedComments.get(1); + Comment update = new Comment("Updated comment", "Updated comment"); + Comment resp = commentsProxy.updateNodeComment(nodeRef1.getId(), comment.getId(), update); + + Thread.sleep(100); // simulate a user edit to a comment + + Comment expected = new Comment(comment); + expected.setTitle("Updated comment"); + expected.setEdited(true); + expected.setContent("Updated comment"); + expected.setModifiedBy(repoService.getPerson(person11.getId())); + expected.setModifiedAt(PublicApiDateFormat.getDateFormat().format(time)); + expected.expected(resp); + } + + // delete comments + + // invalid node ref + try + { + Comment comment = expectedComments.get(1); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.removeNodeComment(GUID.generate(), comment.getId()); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid comment id + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.removeNodeComment(nodeRef1.getId(), GUID.generate()); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // successful delete + { + Comment toDelete = expectedComments.get(1); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + commentsProxy.removeNodeComment(nodeRef1.getId(), toDelete.getId()); + + // check it's been removed + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging expectedPaging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + ListResponse resp = commentsProxy.getNodeComments(nodeRef1.getId(), createParams(expectedPaging, null)); + List actualComments = resp.getList(); + assertFalse(actualComments.contains(toDelete)); + } + + // PUT: test update with null/empty comment + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Comment comment = new Comment(); + comment.setContent("my comment"); + Comment createdComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.lockNode(nodeRef1); + return null; + } + }, person11.getId(), network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Comment updatedComment = new Comment(); + updatedComment.setContent(null); + commentsProxy.updateNodeComment(nodeRef1.getId(), createdComment.getId(), updatedComment); + } + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // locked node comments + try + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.lockNode(nodeRef1); + return null; + } + }, person11.getId(), network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + // test GET for a locked node + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedComments.size(), expectedComments.size()); + commentsProxy.getNodeComments(nodeRef1.getId(), createParams(paging, null)); + + // test POST for a locked node + + Comment comment = new Comment(); + comment.setContent("my comment"); + Comment createdComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + + // test PUT for a locked node + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.lockNode(nodeRef1); + return null; + } + }, person11.getId(), network1.getId()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Comment updatedComment = new Comment(); + updatedComment.setContent("my comment"); + commentsProxy.updateNodeComment(nodeRef1.getId(), createdComment.getId(), updatedComment); + } + } + finally + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.unlockNode(nodeRef1); + return null; + } + }, person11.getId(), network1.getId()); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestNodeRatings.java b/source/test-java/org/alfresco/rest/api/tests/TestNodeRatings.java index 3c2cf68e54..109891f502 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestNodeRatings.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestNodeRatings.java @@ -1,500 +1,500 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.activities.ActivityType; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Activity; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.NodeRating; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Test; - -public class TestNodeRatings extends EnterpriseTestApi -{ - @Test - public void testNodeRatings() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - assertTrue(networksIt.hasNext()); - final TestNetwork network1 = networksIt.next(); - assertTrue(networksIt.hasNext()); - final TestNetwork network2 = networksIt.next(); - - final List people = new ArrayList(3); - - // create users - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - return null; - } - }, network2.getId()); - - final TestPerson person11 = people.get(0); - final TestPerson person12 = people.get(1); - final TestPerson person21 = people.get(2); - - final List nodes = new ArrayList(); - final List sites = new ArrayList(); - - // Create site - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - sites.add(site); - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content"); - nodes.add(nodeRef); - - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 2", "Test Content"); - nodes.add(nodeRef); - - return null; - } - }, person11.getId(), network1.getId()); - - final NodeRef nodeRef1 = nodes.get(0); - - Comments commentsProxy = publicApiClient.comments(); - People peopleProxy = publicApiClient.people(); - Nodes nodesProxy = publicApiClient.nodes(); - DateFormat format = PublicApiDateFormat.getDateFormat(); - - // Test Case cloud-1976 - // Create node ratings - // try to add a rating to a comment - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Comment comment = new Comment("Test Comment", "Test Comment"); - Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - NodeRating rating = new NodeRating("likes", true); - nodesProxy.createNodeRating(newComment.getId(), rating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // invalid node id - try - { - NodeRating rating = new NodeRating("likes", true); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.createNodeRating(GUID.generate(), rating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // try to add a rating to a tag - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Tag tag = new Tag("testTag"); - Tag newTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); - NodeRating rating = new NodeRating("likes", true); - nodesProxy.createNodeRating(newTag.getId(), rating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // invalid rating scheme - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("missingRatingScheme", Double.valueOf(1.0f))); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // invalid rating - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("likes", Double.valueOf(2.0f))); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // invalid rating - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("fiveStar", true)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // invalid rating - can't rate own content for fiveStar - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("fiveStar", 5)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // valid ratings - { - NodeRating rating = new NodeRating("likes", true); - - Date time = new Date(); - - // rate by multiple users in more than 1 network - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - NodeRating ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); - assertEquals(rating.getMyRating(), ret.getMyRating()); - assertTrue(format.parse(ret.getRatedAt()).after(time)); - assertEquals(rating.getId(), ret.getId()); - assertEquals(new NodeRating.Aggregate(1, null), ret.getAggregate()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); - assertEquals(rating.getMyRating(), ret.getMyRating()); - assertTrue(format.parse(ret.getRatedAt()).after(time)); - assertEquals(rating.getId(), ret.getId()); - assertEquals(new NodeRating.Aggregate(2, null), ret.getAggregate()); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); - assertEquals(rating.getMyRating(), ret.getMyRating()); - assertTrue(format.parse(ret.getRatedAt()).after(time)); - assertEquals(rating.getId(), ret.getId()); - assertEquals(new NodeRating.Aggregate(2, null), ret.getAggregate()); - - // different network - unauthorized - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - nodesProxy.createNodeRating(nodeRef1.getId(), rating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-2209 - // Test Case cloud-2220 - // Test Case cloud-1520 - // check that the node ratings are there, test paging - - { - // person11 - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - List expectedRatings = repoService.getNodeRatings(person11.getId(), network1.getId(), nodeRef1); - - { - int skipCount = 0; - int maxItems = 1; - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 1; - int maxItems = Integer.MAX_VALUE; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 1; - int maxItems = expectedRatings.size(); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - - // person12 - List expectedRatings = repoService.getNodeRatings(person12.getId(), network1.getId(), nodeRef1); - - { - int skipCount = 0; - int maxItems = 1; - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 1; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - { - // person21 - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - - List expectedRatings = Collections.emptyList(); - - try - { - int skipCount = 0; - int maxItems = 1; - - Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); - nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - // invalid node id - try - { - int skipCount = 1; - int maxItems = Integer.MAX_VALUE; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Paging paging = getPaging(skipCount, maxItems); - nodesProxy.getNodeRatings(GUID.generate(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // check activities have been raised for the created ratings - repoService.generateFeed(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - Paging paging = getPaging(0, Integer.MAX_VALUE); - ListResponse activities = peopleProxy.getActivities(person11.getId(), createParams(paging, null)); - - boolean found = false; - for(Activity activity : activities.getList()) - { - String activityType = activity.getActivityType(); - if(activityType.equals(ActivityType.FILE_LIKED)) - { - Map summary = activity.getSummary(); - assertNotNull(summary); - String objectId = (String)summary.get("objectId"); - assertNotNull(objectId); - if(nodeRef1.getId().equals(objectId)) - { - found = true; - break; - } - } - } - - assertTrue(found); - } - } - - { - // remove node rating - - NodeRating rating = new NodeRating("likes", null); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - nodesProxy.removeNodeRating(nodeRef1.getId(), rating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - nodesProxy.removeNodeRating(nodeRef1.getId(), rating); - } - - // check list - { - List ratings = repoService.getNodeRatings(person11.getId(), network1.getId(), nodeRef1); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - Paging paging = getPaging(skipCount, maxItems, ratings.size(), ratings.size()); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); - checkList(ratings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - // get a node rating - // 1977 - { - NodeRating rating = new NodeRating("likes", true); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - NodeRating expected = nodesProxy.createNodeRating(nodeRef1.getId(), rating); - NodeRating actual = nodesProxy.getNodeRating(nodeRef1.getId(), "likes"); - expected.expected(actual); - } - - { - // update node rating - NodeRating rating = new NodeRating("fiveStar", 2); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - - // create initial rating - NodeRating createdRating = nodesProxy.createNodeRating(nodeRef1.getId(), rating); - NodeRating updateRating = new NodeRating(createdRating.getId(), 5); - - // update - not supported - try - { - nodesProxy.updateNodeRating(nodeRef1.getId(), updateRating); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - - // Test Case cloud-1977 - // invalid methods - { - // get an arbitrary rating - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(getPaging(0, Integer.MAX_VALUE), null)); - List nodeRatings = resp.getList(); - assertTrue(nodeRatings.size() > 0); - - try - { - NodeRating rating = new NodeRating("likes", true); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.create("nodes", nodeRef1.getId(), "ratings", "likes", rating.toJSON().toString(), "Unable to POST to a node rating"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.update("nodes", nodeRef1.getId(), "ratings", null, null, "Unable to PUT node ratings"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.remove("nodes", nodeRef1.getId(), "ratings", null, "Unable to DELETE node ratings"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - NodeRating rating = nodeRatings.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - nodesProxy.update("nodes", nodeRef1.getId(), "ratings", rating.getId(), null, "Unable to PUT a node rating"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.activities.ActivityType; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Activity; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.NodeRating; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Test; + +public class TestNodeRatings extends EnterpriseTestApi +{ + @Test + public void testNodeRatings() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + assertTrue(networksIt.hasNext()); + final TestNetwork network1 = networksIt.next(); + assertTrue(networksIt.hasNext()); + final TestNetwork network2 = networksIt.next(); + + final List people = new ArrayList(3); + + // create users + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + return null; + } + }, network2.getId()); + + final TestPerson person11 = people.get(0); + final TestPerson person12 = people.get(1); + final TestPerson person21 = people.get(2); + + final List nodes = new ArrayList(); + final List sites = new ArrayList(); + + // Create site + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + sites.add(site); + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content"); + nodes.add(nodeRef); + + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 2", "Test Content"); + nodes.add(nodeRef); + + return null; + } + }, person11.getId(), network1.getId()); + + final NodeRef nodeRef1 = nodes.get(0); + + Comments commentsProxy = publicApiClient.comments(); + People peopleProxy = publicApiClient.people(); + Nodes nodesProxy = publicApiClient.nodes(); + DateFormat format = PublicApiDateFormat.getDateFormat(); + + // Test Case cloud-1976 + // Create node ratings + // try to add a rating to a comment + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Comment comment = new Comment("Test Comment", "Test Comment"); + Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + NodeRating rating = new NodeRating("likes", true); + nodesProxy.createNodeRating(newComment.getId(), rating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // invalid node id + try + { + NodeRating rating = new NodeRating("likes", true); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.createNodeRating(GUID.generate(), rating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // try to add a rating to a tag + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Tag tag = new Tag("testTag"); + Tag newTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); + NodeRating rating = new NodeRating("likes", true); + nodesProxy.createNodeRating(newTag.getId(), rating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // invalid rating scheme + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("missingRatingScheme", Double.valueOf(1.0f))); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // invalid rating + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("likes", Double.valueOf(2.0f))); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // invalid rating + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("fiveStar", true)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // invalid rating - can't rate own content for fiveStar + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.createNodeRating(nodeRef1.getId(), new NodeRating("fiveStar", 5)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // valid ratings + { + NodeRating rating = new NodeRating("likes", true); + + Date time = new Date(); + + // rate by multiple users in more than 1 network + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + NodeRating ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); + assertEquals(rating.getMyRating(), ret.getMyRating()); + assertTrue(format.parse(ret.getRatedAt()).after(time)); + assertEquals(rating.getId(), ret.getId()); + assertEquals(new NodeRating.Aggregate(1, null), ret.getAggregate()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); + assertEquals(rating.getMyRating(), ret.getMyRating()); + assertTrue(format.parse(ret.getRatedAt()).after(time)); + assertEquals(rating.getId(), ret.getId()); + assertEquals(new NodeRating.Aggregate(2, null), ret.getAggregate()); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + ret = nodesProxy.createNodeRating(nodeRef1.getId(), rating); + assertEquals(rating.getMyRating(), ret.getMyRating()); + assertTrue(format.parse(ret.getRatedAt()).after(time)); + assertEquals(rating.getId(), ret.getId()); + assertEquals(new NodeRating.Aggregate(2, null), ret.getAggregate()); + + // different network - unauthorized + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + nodesProxy.createNodeRating(nodeRef1.getId(), rating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-2209 + // Test Case cloud-2220 + // Test Case cloud-1520 + // check that the node ratings are there, test paging + + { + // person11 + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + List expectedRatings = repoService.getNodeRatings(person11.getId(), network1.getId(), nodeRef1); + + { + int skipCount = 0; + int maxItems = 1; + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 1; + int maxItems = Integer.MAX_VALUE; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 1; + int maxItems = expectedRatings.size(); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + + // person12 + List expectedRatings = repoService.getNodeRatings(person12.getId(), network1.getId(), nodeRef1); + + { + int skipCount = 0; + int maxItems = 1; + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 1; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedRatings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + { + // person21 + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + + List expectedRatings = Collections.emptyList(); + + try + { + int skipCount = 0; + int maxItems = 1; + + Paging paging = getPaging(skipCount, maxItems, expectedRatings.size(), expectedRatings.size()); + nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + // invalid node id + try + { + int skipCount = 1; + int maxItems = Integer.MAX_VALUE; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Paging paging = getPaging(skipCount, maxItems); + nodesProxy.getNodeRatings(GUID.generate(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // check activities have been raised for the created ratings + repoService.generateFeed(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + Paging paging = getPaging(0, Integer.MAX_VALUE); + ListResponse activities = peopleProxy.getActivities(person11.getId(), createParams(paging, null)); + + boolean found = false; + for(Activity activity : activities.getList()) + { + String activityType = activity.getActivityType(); + if(activityType.equals(ActivityType.FILE_LIKED)) + { + Map summary = activity.getSummary(); + assertNotNull(summary); + String objectId = (String)summary.get("objectId"); + assertNotNull(objectId); + if(nodeRef1.getId().equals(objectId)) + { + found = true; + break; + } + } + } + + assertTrue(found); + } + } + + { + // remove node rating + + NodeRating rating = new NodeRating("likes", null); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + nodesProxy.removeNodeRating(nodeRef1.getId(), rating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + nodesProxy.removeNodeRating(nodeRef1.getId(), rating); + } + + // check list + { + List ratings = repoService.getNodeRatings(person11.getId(), network1.getId(), nodeRef1); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + Paging paging = getPaging(skipCount, maxItems, ratings.size(), ratings.size()); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(paging, null)); + checkList(ratings.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + // get a node rating + // 1977 + { + NodeRating rating = new NodeRating("likes", true); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + NodeRating expected = nodesProxy.createNodeRating(nodeRef1.getId(), rating); + NodeRating actual = nodesProxy.getNodeRating(nodeRef1.getId(), "likes"); + expected.expected(actual); + } + + { + // update node rating + NodeRating rating = new NodeRating("fiveStar", 2); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + + // create initial rating + NodeRating createdRating = nodesProxy.createNodeRating(nodeRef1.getId(), rating); + NodeRating updateRating = new NodeRating(createdRating.getId(), 5); + + // update - not supported + try + { + nodesProxy.updateNodeRating(nodeRef1.getId(), updateRating); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + + // Test Case cloud-1977 + // invalid methods + { + // get an arbitrary rating + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + ListResponse resp = nodesProxy.getNodeRatings(nodeRef1.getId(), createParams(getPaging(0, Integer.MAX_VALUE), null)); + List nodeRatings = resp.getList(); + assertTrue(nodeRatings.size() > 0); + + try + { + NodeRating rating = new NodeRating("likes", true); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.create("nodes", nodeRef1.getId(), "ratings", "likes", rating.toJSON().toString(), "Unable to POST to a node rating"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.update("nodes", nodeRef1.getId(), "ratings", null, null, "Unable to PUT node ratings"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.remove("nodes", nodeRef1.getId(), "ratings", null, "Unable to DELETE node ratings"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + NodeRating rating = nodeRatings.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + nodesProxy.update("nodes", nodeRef1.getId(), "ratings", rating.getId(), null, "Unable to PUT a node rating"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPeople.java b/source/test-java/org/alfresco/rest/api/tests/TestPeople.java index 3d13609a6d..296bbc3aa4 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPeople.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPeople.java @@ -1,89 +1,89 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.util.Iterator; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Test; - -public class TestPeople extends EnterpriseTestApi -{ - @Test - public void testPeople() throws Exception - { - Iterator accountsIt = getTestFixture().getNetworksIt(); - final TestNetwork account1 = accountsIt.next(); - Iterator personIt1 = account1.getPersonIds().iterator(); - final String person1 = personIt1.next(); - final String person2 = personIt1.next(); - - final TestNetwork account2 = accountsIt.next(); - Iterator personIt2 = account2.getPersonIds().iterator(); - final String person3 = personIt2.next(); - - People peopleProxy = publicApiClient.people(); - - // Test Case cloud-2192 - // should be able to see oneself - { - publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); - Person resp = peopleProxy.getPerson(person1); - Person person1Entity = repoService.getPerson(person1); - check(person1Entity, resp); - } - - // should be able to see another user in the same domain, and be able to see full profile - { - publicApiClient.setRequestContext(new RequestContext(account1.getId(), person2)); - Person resp = peopleProxy.getPerson(person1); - Person person1Entity = repoService.getPerson(person1); - check(person1Entity, resp); - } - - // "-me-" user - { - publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); - Person resp = peopleProxy.getPerson(org.alfresco.rest.api.People.DEFAULT_USER); - Person person1Entity = repoService.getPerson(person1); - check(person1Entity, resp); - } - - // shouldn't be able to see another user in another domain - publicApiClient.setRequestContext(new RequestContext(account1.getId(), person3)); - try - { - peopleProxy.getPerson(person1); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - RepoService.TestPerson testP = account1.createUser(); - String personId = testP.getId(); - String desc = "Nice person"; - account1.addUserDescription(personId, desc); - publicApiClient.setRequestContext(new RequestContext(account1.getId(), personId)); - Person resp = publicApiClient.people().getPerson(personId); - assertEquals(resp.getId(), personId); - assertEquals(resp.getDescription(), desc); - } - -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.util.Iterator; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Test; + +public class TestPeople extends EnterpriseTestApi +{ + @Test + public void testPeople() throws Exception + { + Iterator accountsIt = getTestFixture().getNetworksIt(); + final TestNetwork account1 = accountsIt.next(); + Iterator personIt1 = account1.getPersonIds().iterator(); + final String person1 = personIt1.next(); + final String person2 = personIt1.next(); + + final TestNetwork account2 = accountsIt.next(); + Iterator personIt2 = account2.getPersonIds().iterator(); + final String person3 = personIt2.next(); + + People peopleProxy = publicApiClient.people(); + + // Test Case cloud-2192 + // should be able to see oneself + { + publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); + Person resp = peopleProxy.getPerson(person1); + Person person1Entity = repoService.getPerson(person1); + check(person1Entity, resp); + } + + // should be able to see another user in the same domain, and be able to see full profile + { + publicApiClient.setRequestContext(new RequestContext(account1.getId(), person2)); + Person resp = peopleProxy.getPerson(person1); + Person person1Entity = repoService.getPerson(person1); + check(person1Entity, resp); + } + + // "-me-" user + { + publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); + Person resp = peopleProxy.getPerson(org.alfresco.rest.api.People.DEFAULT_USER); + Person person1Entity = repoService.getPerson(person1); + check(person1Entity, resp); + } + + // shouldn't be able to see another user in another domain + publicApiClient.setRequestContext(new RequestContext(account1.getId(), person3)); + try + { + peopleProxy.getPerson(person1); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + RepoService.TestPerson testP = account1.createUser(); + String personId = testP.getId(); + String desc = "Nice person"; + account1.addUserDescription(personId, desc); + publicApiClient.setRequestContext(new RequestContext(account1.getId(), personId)); + Person resp = publicApiClient.people().getPerson(personId); + assertEquals(resp.getId(), personId); + assertEquals(resp.getDescription(), desc); + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPersonSites.java b/source/test-java/org/alfresco/rest/api/tests/TestPersonSites.java index e6a3d68501..9eb18911e0 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPersonSites.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPersonSites.java @@ -1,736 +1,736 @@ - -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.MemberOfSite; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -public class TestPersonSites extends EnterpriseTestApi -{ - private TestNetwork network1; - private TestNetwork network2; - - private TestPerson person11; - private TestPerson person12; - private TestPerson person21; - - private List sites = new ArrayList<>(10); - - /* Sites and users used to test the site sorting */ - private TestPerson person31; - private TestPerson person32; - private TestSite site1; - private TestSite site2; - private TestSite site3; - private String site1_name = "a_" + GUID.generate(); - private String site1_title = "c_" + GUID.generate(); - private SiteRole site1_role = SiteRole.SiteContributor; - private String site2_name = "b_" + GUID.generate(); - private String site2_title = "a_" + GUID.generate(); - private SiteRole site2_role = SiteRole.SiteManager; - private String site3_name = "c_" + GUID.generate(); - private String site3_title = "b_" + GUID.generate(); - private SiteRole site3_role = SiteRole.SiteConsumer; - - - public void initializeSites() throws Exception - { - /* - * Create data for testing the site sorting. We create the sites as - * person31 and assign roles to person32. The list requests will be - * performed as person32. - */ - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - person31 = network1.createUser(); - person32 = network1.createUser(); - return null; - } - }, network1.getId()); - - this.site1 = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(site1_name, site1_title, site1_title, SiteVisibility.PRIVATE); - TestSite site = network1.createSite(siteInfo); - site.inviteToSite(person32.getId(), site1_role); - return site; - } - }, person31.getId(), network1.getId()); - - this.site2 = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(site2_name, site2_title, site2_title, SiteVisibility.PRIVATE); - TestSite site = network1.createSite(siteInfo); - site.inviteToSite(person32.getId(), site2_role); - return site; - } - }, person31.getId(), network1.getId()); - - this.site3 = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(site3_name, site3_title, site3_title, SiteVisibility.PRIVATE); - TestSite site = network1.createSite(siteInfo); - site.inviteToSite(person32.getId(), site3_role); - return site; - } - }, person31.getId(), network1.getId()); - } - - @Before - public void setup() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - - assertTrue(networksIt.hasNext()); - this.network1 = networksIt.next(); - - assertTrue(networksIt.hasNext()); - this.network2 = networksIt.next(); - - // create a user - - final List people = new ArrayList(1); - - // Create some users - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - - return null; - } - }, network2.getId()); - - this.person11 = people.get(0); - this.person12 = people.get(1); - this.person21 = people.get(2); - - // ...and some sites - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PUBLIC); - site.inviteToSite(person11.getId(), SiteRole.SiteContributor); - sites.add(site); - - site = network1.createSite(SiteVisibility.MODERATED); - site.inviteToSite(person11.getId(), SiteRole.SiteContributor); - sites.add(site); - - site = network1.createSite(SiteVisibility.PRIVATE); - site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); - sites.add(site); - - site = network1.createSite(SiteVisibility.PUBLIC); - site.inviteToSite(person11.getId(), SiteRole.SiteManager); - sites.add(site); - - site = network1.createSite(SiteVisibility.PRIVATE); - site.inviteToSite(person11.getId(), SiteRole.SiteCollaborator); - sites.add(site); - - //Special site for person removal - site = network1.createSite(SiteVisibility.PRIVATE); - site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); - sites.add(site); - return null; - } - }, person12.getId(), network1.getId()); - } - - @Test - public void testPersonSites() throws Exception - { - Set personSites = new TreeSet(); - - //Get last site for use with personRemoveSite - TestSite personRemoveSite = sites.get(sites.size() - 1); - sites.remove(sites.size() - 1); - - personSites.addAll(network1.getSiteMemberships(person11.getId())); - - // Create some sites - personSites.addAll(TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List expectedSites = new ArrayList(); - - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); - - site = network1.createSite(SiteVisibility.PUBLIC); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); - - site = network1.createSite(SiteVisibility.MODERATED); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); - - return expectedSites; - } - }, person11.getId(), network1.getId())); - - personSites.addAll(TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List expectedSites = new ArrayList(); - - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); - - site = network1.createSite(SiteVisibility.PUBLIC); - site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); - - site = network1.createSite(SiteVisibility.MODERATED); - site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); - expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); - - return expectedSites; - } - }, person12.getId(), network1.getId())); - - final List expectedSites = new ArrayList(personSites); - Sites sitesProxy = publicApiClient.sites(); - - // Test Case cloud-1487 - - // unknown user - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - sitesProxy.getPersonSites(GUID.generate(), null); - fail(""); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-2200 - // Test Case cloud-2213 - // user should be able to list their sites - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - ListResponse resp = sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); - checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 2; - int maxItems = 8; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - ListResponse resp = sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); - checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // "-me-" user - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - ListResponse resp = sitesProxy.getPersonSites(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); - checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // a user in another tenant should not be able to list a user's sites - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); - fail(""); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // Test case cloud-1488 - { - MemberOfSite memberOfSite = expectedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - MemberOfSite ret = sitesProxy.getPersonSite(person11.getId(), memberOfSite.getSiteId()); - memberOfSite.expected(ret); - } - - try - { - MemberOfSite memberOfSite = expectedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.getPersonSite(GUID.generate(), memberOfSite.getSiteId()); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.getPersonSite(person11.getId(), GUID.generate()); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1487 - // unknown person id - try - { - MemberOfSite memberOfSite = expectedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.getPersonSite(GUID.generate(), memberOfSite.getSiteId()); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.getPersonSite(person11.getId(), GUID.generate()); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - { - //Tests removing a person from the site - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.remove("people", person11.getId(), "sites", personRemoveSite.getSiteId(), "Unable to DELETE a person site"); - - try - { - sitesProxy.getPersonSite(person11.getId(), personRemoveSite.getSiteId()); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // TODO - // person from external network listing user sites - - // Test Case cloud-1966 - // Not allowed methods - try - { - MemberOfSite memberOfSite = expectedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.create("people", person11.getId(), "sites", memberOfSite.getSiteId(), null, "Unable to POST to a person site"); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.create("people", person11.getId(), "sites", null, null, "Unable to POST to person sites"); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - MemberOfSite memberOfSite = expectedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.update("people", person11.getId(), "sites", memberOfSite.getSiteId(), null, "Unable to PUT a person site"); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.update("people", person11.getId(), "sites", null, null, "Unable to PUT person sites"); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - sitesProxy.remove("people", person11.getId(), "sites", null, "Unable to DELETE person sites"); - fail(); - } - catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - - /** - * Retrieves the site memberships associated to a user - * - * @param sortColumn - * @param asc - * @return - * @throws Exception - */ - private ListResponse getSiteMembershipsForPerson32(final Paging paging, String sortColumn, boolean asc) throws Exception - { - final Sites sitesProxy = publicApiClient.sites(); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person32.getId())); - - // sort params - final Map params = new HashMap(); - if (sortColumn != null) - { - params.put("orderBy", sortColumn + " " + (asc ? "ASC" : "DESC")); - } - - // get memberships - ListResponse resp = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public ListResponse doWork() throws Exception - { - ListResponse resp = sitesProxy.getPersonSites(person32.getId(), createParams(paging, params)); - - return resp; - } - }, person32.getId(), network1.getId()); - - return resp; - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Title ASC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingByTitleAsc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteTitle", true); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site3, site3_role)); - expectedList.add(new MemberOfSite(site1, site1_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Title DESC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingByTitleDesc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteTitle", false); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site3, site3_role)); - expectedList.add(new MemberOfSite(site2, site2_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Role ASC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingByRoleAsc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "Role", true); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site1, site1_role)); - expectedList.add(new MemberOfSite(site2, site2_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Role DESC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingByRoleDesc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "Role", false); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site1, site1_role)); - expectedList.add(new MemberOfSite(site3, site3_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Site Name ASC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingBySiteNameAsc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteShortName", true); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site2, site2_role)); - expectedList.add(new MemberOfSite(site3, site3_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * to a user order = Site Name DESC skip = 1, count = 2 - * - * @throws Exception - */ - public void testSortingAndPagingBySiteNameDesc() throws Exception - { - // paging - int skipCount = 1; - int maxItems = 2; - int totalResults = 3; - Paging paging = getPaging(skipCount, maxItems, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteShortName", false); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site2, site2_role)); - expectedList.add(new MemberOfSite(site1, site1_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - } - - /** - * Tests the capability to sort and paginate the site memberships associated - * default sorting, all results - * - * @throws Exception - */ - public void testSortingAndPagingDefault() throws Exception - { - // paging - int totalResults = 3; - Paging paging = getPaging(null, null, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(null, null, false); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site2, site2_role)); - expectedList.add(new MemberOfSite(site3, site3_role)); - expectedList.add(new MemberOfSite(site1, site1_role)); - - checkList(expectedList, paging.getExpectedPaging(), resp); - - } - - @Test - public void testSortingAndPaging() throws Exception - { - initializeSites(); - - testSortingAndPagingByTitleAsc(); - testSortingAndPagingByTitleDesc(); - testSortingAndPagingByRoleAsc(); - testSortingAndPagingByRoleDesc(); - testSortingAndPagingBySiteNameAsc(); - testSortingAndPagingBySiteNameDesc(); - testSortingAndPagingDefault(); - } - - // ACE-4823 - @Test - public void testSitesWithSameTitles() throws Exception - { - // Creates 3 sites - initializeSites(); - - final String site4_name = "d_" + GUID.generate(); - final String site4_title = site3_title; // Same title as site3 - final SiteRole site4_role = SiteRole.SiteCollaborator; - - TestSite site4 = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - SiteInformation siteInfo = new SiteInformation(site4_name, site4_title, site4_title, SiteVisibility.PRIVATE); - TestSite site = network1.createSite(siteInfo); - site.inviteToSite(person32.getId(), site4_role); - return site; - } - }, person31.getId(), network1.getId()); - assertNotNull(site4); - - // paging - int totalResults = 4; - Paging paging = getPaging(null, null, totalResults, null); - - // get memberships - ListResponse resp = getSiteMembershipsForPerson32(null, null, false); - - // check results - List expectedList = new LinkedList<>(); - expectedList.add(new MemberOfSite(site2, site2_role)); - expectedList.add(new MemberOfSite(site3, site3_role)); - expectedList.add(new MemberOfSite(site4, site4_role)); - expectedList.add(new MemberOfSite(site1, site1_role)); - - try - { - checkList(expectedList, paging.getExpectedPaging(), resp); - } - catch (AssertionError error) - { - // Site3 and Site4 have a same title, and as we are sorting on titles (default sorting), - // we can't guarantee the order in which the sites will - // return, hence swap the sites and compare again. - Collections.swap(expectedList, 1, 2); - checkList(expectedList, paging.getExpectedPaging(), resp); - } - } -} + +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.MemberOfSite; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +public class TestPersonSites extends EnterpriseTestApi +{ + private TestNetwork network1; + private TestNetwork network2; + + private TestPerson person11; + private TestPerson person12; + private TestPerson person21; + + private List sites = new ArrayList<>(10); + + /* Sites and users used to test the site sorting */ + private TestPerson person31; + private TestPerson person32; + private TestSite site1; + private TestSite site2; + private TestSite site3; + private String site1_name = "a_" + GUID.generate(); + private String site1_title = "c_" + GUID.generate(); + private SiteRole site1_role = SiteRole.SiteContributor; + private String site2_name = "b_" + GUID.generate(); + private String site2_title = "a_" + GUID.generate(); + private SiteRole site2_role = SiteRole.SiteManager; + private String site3_name = "c_" + GUID.generate(); + private String site3_title = "b_" + GUID.generate(); + private SiteRole site3_role = SiteRole.SiteConsumer; + + + public void initializeSites() throws Exception + { + /* + * Create data for testing the site sorting. We create the sites as + * person31 and assign roles to person32. The list requests will be + * performed as person32. + */ + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + person31 = network1.createUser(); + person32 = network1.createUser(); + return null; + } + }, network1.getId()); + + this.site1 = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(site1_name, site1_title, site1_title, SiteVisibility.PRIVATE); + TestSite site = network1.createSite(siteInfo); + site.inviteToSite(person32.getId(), site1_role); + return site; + } + }, person31.getId(), network1.getId()); + + this.site2 = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(site2_name, site2_title, site2_title, SiteVisibility.PRIVATE); + TestSite site = network1.createSite(siteInfo); + site.inviteToSite(person32.getId(), site2_role); + return site; + } + }, person31.getId(), network1.getId()); + + this.site3 = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(site3_name, site3_title, site3_title, SiteVisibility.PRIVATE); + TestSite site = network1.createSite(siteInfo); + site.inviteToSite(person32.getId(), site3_role); + return site; + } + }, person31.getId(), network1.getId()); + } + + @Before + public void setup() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + + assertTrue(networksIt.hasNext()); + this.network1 = networksIt.next(); + + assertTrue(networksIt.hasNext()); + this.network2 = networksIt.next(); + + // create a user + + final List people = new ArrayList(1); + + // Create some users + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + + return null; + } + }, network2.getId()); + + this.person11 = people.get(0); + this.person12 = people.get(1); + this.person21 = people.get(2); + + // ...and some sites + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PUBLIC); + site.inviteToSite(person11.getId(), SiteRole.SiteContributor); + sites.add(site); + + site = network1.createSite(SiteVisibility.MODERATED); + site.inviteToSite(person11.getId(), SiteRole.SiteContributor); + sites.add(site); + + site = network1.createSite(SiteVisibility.PRIVATE); + site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); + sites.add(site); + + site = network1.createSite(SiteVisibility.PUBLIC); + site.inviteToSite(person11.getId(), SiteRole.SiteManager); + sites.add(site); + + site = network1.createSite(SiteVisibility.PRIVATE); + site.inviteToSite(person11.getId(), SiteRole.SiteCollaborator); + sites.add(site); + + //Special site for person removal + site = network1.createSite(SiteVisibility.PRIVATE); + site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); + sites.add(site); + return null; + } + }, person12.getId(), network1.getId()); + } + + @Test + public void testPersonSites() throws Exception + { + Set personSites = new TreeSet(); + + //Get last site for use with personRemoveSite + TestSite personRemoveSite = sites.get(sites.size() - 1); + sites.remove(sites.size() - 1); + + personSites.addAll(network1.getSiteMemberships(person11.getId())); + + // Create some sites + personSites.addAll(TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List expectedSites = new ArrayList(); + + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); + + site = network1.createSite(SiteVisibility.PUBLIC); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); + + site = network1.createSite(SiteVisibility.MODERATED); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteManager)); + + return expectedSites; + } + }, person11.getId(), network1.getId())); + + personSites.addAll(TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List expectedSites = new ArrayList(); + + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); + + site = network1.createSite(SiteVisibility.PUBLIC); + site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); + + site = network1.createSite(SiteVisibility.MODERATED); + site.inviteToSite(person11.getId(), SiteRole.SiteConsumer); + expectedSites.add(new MemberOfSite(site, SiteRole.SiteConsumer)); + + return expectedSites; + } + }, person12.getId(), network1.getId())); + + final List expectedSites = new ArrayList(personSites); + Sites sitesProxy = publicApiClient.sites(); + + // Test Case cloud-1487 + + // unknown user + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + sitesProxy.getPersonSites(GUID.generate(), null); + fail(""); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-2200 + // Test Case cloud-2213 + // user should be able to list their sites + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + ListResponse resp = sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); + checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 2; + int maxItems = 8; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + ListResponse resp = sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); + checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // "-me-" user + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + ListResponse resp = sitesProxy.getPersonSites(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); + checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // a user in another tenant should not be able to list a user's sites + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + sitesProxy.getPersonSites(person11.getId(), createParams(paging, null)); + fail(""); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // Test case cloud-1488 + { + MemberOfSite memberOfSite = expectedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + MemberOfSite ret = sitesProxy.getPersonSite(person11.getId(), memberOfSite.getSiteId()); + memberOfSite.expected(ret); + } + + try + { + MemberOfSite memberOfSite = expectedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.getPersonSite(GUID.generate(), memberOfSite.getSiteId()); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.getPersonSite(person11.getId(), GUID.generate()); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1487 + // unknown person id + try + { + MemberOfSite memberOfSite = expectedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.getPersonSite(GUID.generate(), memberOfSite.getSiteId()); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.getPersonSite(person11.getId(), GUID.generate()); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + { + //Tests removing a person from the site + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.remove("people", person11.getId(), "sites", personRemoveSite.getSiteId(), "Unable to DELETE a person site"); + + try + { + sitesProxy.getPersonSite(person11.getId(), personRemoveSite.getSiteId()); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // TODO + // person from external network listing user sites + + // Test Case cloud-1966 + // Not allowed methods + try + { + MemberOfSite memberOfSite = expectedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.create("people", person11.getId(), "sites", memberOfSite.getSiteId(), null, "Unable to POST to a person site"); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.create("people", person11.getId(), "sites", null, null, "Unable to POST to person sites"); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + MemberOfSite memberOfSite = expectedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.update("people", person11.getId(), "sites", memberOfSite.getSiteId(), null, "Unable to PUT a person site"); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.update("people", person11.getId(), "sites", null, null, "Unable to PUT person sites"); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + sitesProxy.remove("people", person11.getId(), "sites", null, "Unable to DELETE person sites"); + fail(); + } + catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + + /** + * Retrieves the site memberships associated to a user + * + * @param sortColumn + * @param asc + * @return + * @throws Exception + */ + private ListResponse getSiteMembershipsForPerson32(final Paging paging, String sortColumn, boolean asc) throws Exception + { + final Sites sitesProxy = publicApiClient.sites(); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person32.getId())); + + // sort params + final Map params = new HashMap(); + if (sortColumn != null) + { + params.put("orderBy", sortColumn + " " + (asc ? "ASC" : "DESC")); + } + + // get memberships + ListResponse resp = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public ListResponse doWork() throws Exception + { + ListResponse resp = sitesProxy.getPersonSites(person32.getId(), createParams(paging, params)); + + return resp; + } + }, person32.getId(), network1.getId()); + + return resp; + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Title ASC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingByTitleAsc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteTitle", true); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site3, site3_role)); + expectedList.add(new MemberOfSite(site1, site1_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Title DESC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingByTitleDesc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteTitle", false); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site3, site3_role)); + expectedList.add(new MemberOfSite(site2, site2_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Role ASC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingByRoleAsc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "Role", true); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site1, site1_role)); + expectedList.add(new MemberOfSite(site2, site2_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Role DESC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingByRoleDesc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "Role", false); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site1, site1_role)); + expectedList.add(new MemberOfSite(site3, site3_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Site Name ASC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingBySiteNameAsc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteShortName", true); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site2, site2_role)); + expectedList.add(new MemberOfSite(site3, site3_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * to a user order = Site Name DESC skip = 1, count = 2 + * + * @throws Exception + */ + public void testSortingAndPagingBySiteNameDesc() throws Exception + { + // paging + int skipCount = 1; + int maxItems = 2; + int totalResults = 3; + Paging paging = getPaging(skipCount, maxItems, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(paging, "SiteShortName", false); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site2, site2_role)); + expectedList.add(new MemberOfSite(site1, site1_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + } + + /** + * Tests the capability to sort and paginate the site memberships associated + * default sorting, all results + * + * @throws Exception + */ + public void testSortingAndPagingDefault() throws Exception + { + // paging + int totalResults = 3; + Paging paging = getPaging(null, null, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(null, null, false); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site2, site2_role)); + expectedList.add(new MemberOfSite(site3, site3_role)); + expectedList.add(new MemberOfSite(site1, site1_role)); + + checkList(expectedList, paging.getExpectedPaging(), resp); + + } + + @Test + public void testSortingAndPaging() throws Exception + { + initializeSites(); + + testSortingAndPagingByTitleAsc(); + testSortingAndPagingByTitleDesc(); + testSortingAndPagingByRoleAsc(); + testSortingAndPagingByRoleDesc(); + testSortingAndPagingBySiteNameAsc(); + testSortingAndPagingBySiteNameDesc(); + testSortingAndPagingDefault(); + } + + // ACE-4823 + @Test + public void testSitesWithSameTitles() throws Exception + { + // Creates 3 sites + initializeSites(); + + final String site4_name = "d_" + GUID.generate(); + final String site4_title = site3_title; // Same title as site3 + final SiteRole site4_role = SiteRole.SiteCollaborator; + + TestSite site4 = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + SiteInformation siteInfo = new SiteInformation(site4_name, site4_title, site4_title, SiteVisibility.PRIVATE); + TestSite site = network1.createSite(siteInfo); + site.inviteToSite(person32.getId(), site4_role); + return site; + } + }, person31.getId(), network1.getId()); + assertNotNull(site4); + + // paging + int totalResults = 4; + Paging paging = getPaging(null, null, totalResults, null); + + // get memberships + ListResponse resp = getSiteMembershipsForPerson32(null, null, false); + + // check results + List expectedList = new LinkedList<>(); + expectedList.add(new MemberOfSite(site2, site2_role)); + expectedList.add(new MemberOfSite(site3, site3_role)); + expectedList.add(new MemberOfSite(site4, site4_role)); + expectedList.add(new MemberOfSite(site1, site1_role)); + + try + { + checkList(expectedList, paging.getExpectedPaging(), resp); + } + catch (AssertionError error) + { + // Site3 and Site4 have a same title, and as we are sorting on titles (default sorting), + // we can't guarantee the order in which the sites will + // return, hence swap the sites and compare again. + Collections.swap(expectedList, 1, 2); + checkList(expectedList, paging.getExpectedPaging(), resp); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPublicApi128.java b/source/test-java/org/alfresco/rest/api/tests/TestPublicApi128.java index 02fe1da347..de84eef7eb 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPublicApi128.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPublicApi128.java @@ -1,160 +1,160 @@ -package org.alfresco.rest.api.tests; - -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.junit.Before; -import org.junit.Test; - -/** - * Case sensitivity public api tests. - * - * @author steveglover - * - */ -public class TestPublicApi128 extends EnterpriseTestApi -{ - private long time; - - private static final String userId = "bOb.Jones"; - private static final String networkPrefix = "MiXeDCasE"; - private static final String networkDomain = "coM"; - - private String networkId; - private TestNetwork mixedCaseNetwork; - @SuppressWarnings("unused") - private TestPerson person1; - - private String getNetworkId(String networkIdPrefix, String networkIdDomain) - { - return networkIdPrefix + time + "." + networkIdDomain; - } - - private String getUserName(String username, String networkIdPrefix, String networkIdDomain) - { - return username + "@" + getNetworkId(networkIdPrefix, networkIdDomain); - } - - @Before - public void setup() - { - // mixed case network - this.time = System.currentTimeMillis(); - this.networkId = getNetworkId(networkPrefix, networkDomain); - - transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - @SuppressWarnings("synthetic-access") - public Void execute() throws Throwable - { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - TestPublicApi128.this.mixedCaseNetwork = repoService.createNetwork(TestPublicApi128.this.networkId, true); - TestPublicApi128.this.mixedCaseNetwork.create(); - - // mixed case user - PersonInfo personInfo = new PersonInfo("Bob", "Jones", TestPublicApi128.userId, "password", null, null, null, null, null, null, null); - TestPublicApi128.this.person1 = mixedCaseNetwork.createUser(personInfo); - - return null; - } - }, false, true); - } - - @Test - public void testPublicApi128() throws Exception - { - People peopleProxy = publicApiClient.people(); - - // try to get person activities given a mixture of cases for networkId and user id - { - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); - - int skipCount = 0; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities("-me-", createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "COM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities("-me-", createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "COM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities("-me-", createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "COM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities("-me-", createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.JONES", networkPrefix, networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "CoM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.JONES", "MIXEDCASE", networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "coM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.JONES", "MIXEDCASE", "CoM"), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "COM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("Bob.JONES", "MIXEDCASE", networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("Bob.JONES", networkPrefix, networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "COm"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.JONES", "MixEDCASE", networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "COM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.joNES", "MIXEDcasE", networkDomain), createParams(paging, null)); - - publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "coM"))); - - skipCount = 0; - maxItems = 10; - paging = getPaging(skipCount, maxItems); - peopleProxy.getActivities(getUserName("BOB.joNES", networkPrefix, "cOM"), createParams(paging, null)); - } - } -} +package org.alfresco.rest.api.tests; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.junit.Before; +import org.junit.Test; + +/** + * Case sensitivity public api tests. + * + * @author steveglover + * + */ +public class TestPublicApi128 extends EnterpriseTestApi +{ + private long time; + + private static final String userId = "bOb.Jones"; + private static final String networkPrefix = "MiXeDCasE"; + private static final String networkDomain = "coM"; + + private String networkId; + private TestNetwork mixedCaseNetwork; + @SuppressWarnings("unused") + private TestPerson person1; + + private String getNetworkId(String networkIdPrefix, String networkIdDomain) + { + return networkIdPrefix + time + "." + networkIdDomain; + } + + private String getUserName(String username, String networkIdPrefix, String networkIdDomain) + { + return username + "@" + getNetworkId(networkIdPrefix, networkIdDomain); + } + + @Before + public void setup() + { + // mixed case network + this.time = System.currentTimeMillis(); + this.networkId = getNetworkId(networkPrefix, networkDomain); + + transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @SuppressWarnings("synthetic-access") + public Void execute() throws Throwable + { + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + TestPublicApi128.this.mixedCaseNetwork = repoService.createNetwork(TestPublicApi128.this.networkId, true); + TestPublicApi128.this.mixedCaseNetwork.create(); + + // mixed case user + PersonInfo personInfo = new PersonInfo("Bob", "Jones", TestPublicApi128.userId, "password", null, null, null, null, null, null, null); + TestPublicApi128.this.person1 = mixedCaseNetwork.createUser(personInfo); + + return null; + } + }, false, true); + } + + @Test + public void testPublicApi128() throws Exception + { + People peopleProxy = publicApiClient.people(); + + // try to get person activities given a mixture of cases for networkId and user id + { + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); + + int skipCount = 0; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities("-me-", createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "COM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities("-me-", createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "COM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities("-me-", createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "COM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities("-me-", createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.JONES", networkPrefix, networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "CoM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.JONES", "MIXEDCASE", networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "coM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.JONES", "MIXEDCASE", "CoM"), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "COM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("Bob.JONES", "MIXEDCASE", networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", networkPrefix, networkDomain))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("Bob.JONES", networkPrefix, networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId, getUserName("BOB.JONES", "MIXEDCASE", "COm"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.JONES", "MixEDCASE", networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("BOB.JONES", "MIXEDCASE", "COM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.joNES", "MIXEDcasE", networkDomain), createParams(paging, null)); + + publicApiClient.setRequestContext(new RequestContext(networkId.toUpperCase(), getUserName("Bob.JONES", "MIXEDCASE", "coM"))); + + skipCount = 0; + maxItems = 10; + paging = getPaging(skipCount, maxItems); + peopleProxy.getActivities(getUserName("BOB.joNES", networkPrefix, "cOM"), createParams(paging, null)); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub10TCK.java b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub10TCK.java index ce6448067b..03c66b7e2b 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub10TCK.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub10TCK.java @@ -1,139 +1,139 @@ -package org.alfresco.rest.api.tests; - -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.opencmis.OpenCMISClientContext; -import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; -import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; -import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; -import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; -import org.apache.chemistry.opencmis.tck.impl.TestParameters; -import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; -import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; -import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; -import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; -import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; -import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; -import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningTestGroup; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; - -/** - * OpenCMIS TCK unit tests. - * - * @author steveglover - * - */ -public class TestPublicApiAtomPub10TCK extends AbstractEnterpriseOpenCMIS10TCKTest -{ - private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.0/atom"; - protected static final Log logger = LogFactory.getLog(TestPublicApiAtomPub10TCK.class); - - @Before - public void before() throws Exception - { - int port = getTestFixture().getJettyComponent().getPort(); - TestNetwork network = getTestFixture().getRandomNetwork(); - Map cmisParameters = new HashMap(); - cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); - clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, - MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), - "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); - overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); - } - - @AfterClass - public static void shutdown() throws Exception - { - } - - @Test - public void testCMISTCKBasics() throws Exception - { - BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); - JUnitHelper.run(basicsTestGroup); - } - - @Test - public void testCMISTCKCRUD() throws Exception - { - CRUDTestGroup crudTestGroup = new CRUDTestGroup(); - JUnitHelper.run(crudTestGroup); - } - - @Test - public void testCMISTCKVersioning() throws Exception - { - VersioningTestGroup versioningTestGroup = new VersioningTestGroup(); - JUnitHelper.run(versioningTestGroup); - } - - @Test - public void testCMISTCKFiling() throws Exception - { - FilingTestGroup filingTestGroup = new FilingTestGroup(); - JUnitHelper.run(filingTestGroup); - } - - @Test - public void testCMISTCKControl() throws Exception - { - ControlTestGroup controlTestGroup = new ControlTestGroup(); - JUnitHelper.run(controlTestGroup); - } - - @Test - public void testCMISTCKQuery() throws Exception - { - OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); - JUnitHelper.run(queryTestGroup); - } - -// private class OverrideVersioningTestGroup extends AbstractSessionTestGroup -// { -// @Override -// public void init(Map parameters) throws Exception -// { -// super.init(parameters); -// -// setName("Versioning Test Group"); -// setDescription("Versioning tests."); -// -// addTest(new VersioningSmokeTest()); -// addTest(new VersionDeleteTest()); -// addTest(new VersioningStateCreateTest()); -// // relies on Solr being available -// addTest(new CheckedOutTest()); -// } -// } - - private class OverrideQueryTestGroup extends AbstractSessionTestGroup - { - @Override - public void init(Map parameters) throws Exception - { - super.init(parameters); - - setName("Query Test Group"); - setDescription("Query and content changes tests."); - - // this is failing because of an MT issue (the thread is a specific tenant but the DB metadata query is searching - // against the workspace://SpacesStore) - addTest(new QuerySmokeTest()); - // The test fails on Lucene see MNT-11223 -// addTest(new QueryRootFolderTest()); - addTest(new QueryForObjectCustom()); - addTest(new QueryLikeTestCustom()); - addTest(new QueryInFolderTestCustom()); - addTest(new ContentChangesSmokeTest()); - } - } +package org.alfresco.rest.api.tests; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.opencmis.OpenCMISClientContext; +import org.alfresco.opencmis.tck.tests.query.QueryForObjectCustom; +import org.alfresco.opencmis.tck.tests.query.QueryInFolderTestCustom; +import org.alfresco.opencmis.tck.tests.query.QueryLikeTestCustom; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTestGroup; +import org.apache.chemistry.opencmis.tck.impl.JUnitHelper; +import org.apache.chemistry.opencmis.tck.impl.TestParameters; +import org.apache.chemistry.opencmis.tck.tests.basics.BasicsTestGroup; +import org.apache.chemistry.opencmis.tck.tests.control.ControlTestGroup; +import org.apache.chemistry.opencmis.tck.tests.crud.CRUDTestGroup; +import org.apache.chemistry.opencmis.tck.tests.filing.FilingTestGroup; +import org.apache.chemistry.opencmis.tck.tests.query.ContentChangesSmokeTest; +import org.apache.chemistry.opencmis.tck.tests.query.QuerySmokeTest; +import org.apache.chemistry.opencmis.tck.tests.versioning.VersioningTestGroup; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +/** + * OpenCMIS TCK unit tests. + * + * @author steveglover + * + */ +public class TestPublicApiAtomPub10TCK extends AbstractEnterpriseOpenCMIS10TCKTest +{ + private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.0/atom"; + protected static final Log logger = LogFactory.getLog(TestPublicApiAtomPub10TCK.class); + + @Before + public void before() throws Exception + { + int port = getTestFixture().getJettyComponent().getPort(); + TestNetwork network = getTestFixture().getRandomNetwork(); + Map cmisParameters = new HashMap(); + cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); + clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, + MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), + "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); + overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); + } + + @AfterClass + public static void shutdown() throws Exception + { + } + + @Test + public void testCMISTCKBasics() throws Exception + { + BasicsTestGroup basicsTestGroup = new BasicsTestGroup(); + JUnitHelper.run(basicsTestGroup); + } + + @Test + public void testCMISTCKCRUD() throws Exception + { + CRUDTestGroup crudTestGroup = new CRUDTestGroup(); + JUnitHelper.run(crudTestGroup); + } + + @Test + public void testCMISTCKVersioning() throws Exception + { + VersioningTestGroup versioningTestGroup = new VersioningTestGroup(); + JUnitHelper.run(versioningTestGroup); + } + + @Test + public void testCMISTCKFiling() throws Exception + { + FilingTestGroup filingTestGroup = new FilingTestGroup(); + JUnitHelper.run(filingTestGroup); + } + + @Test + public void testCMISTCKControl() throws Exception + { + ControlTestGroup controlTestGroup = new ControlTestGroup(); + JUnitHelper.run(controlTestGroup); + } + + @Test + public void testCMISTCKQuery() throws Exception + { + OverrideQueryTestGroup queryTestGroup = new OverrideQueryTestGroup(); + JUnitHelper.run(queryTestGroup); + } + +// private class OverrideVersioningTestGroup extends AbstractSessionTestGroup +// { +// @Override +// public void init(Map parameters) throws Exception +// { +// super.init(parameters); +// +// setName("Versioning Test Group"); +// setDescription("Versioning tests."); +// +// addTest(new VersioningSmokeTest()); +// addTest(new VersionDeleteTest()); +// addTest(new VersioningStateCreateTest()); +// // relies on Solr being available +// addTest(new CheckedOutTest()); +// } +// } + + private class OverrideQueryTestGroup extends AbstractSessionTestGroup + { + @Override + public void init(Map parameters) throws Exception + { + super.init(parameters); + + setName("Query Test Group"); + setDescription("Query and content changes tests."); + + // this is failing because of an MT issue (the thread is a specific tenant but the DB metadata query is searching + // against the workspace://SpacesStore) + addTest(new QuerySmokeTest()); + // The test fails on Lucene see MNT-11223 +// addTest(new QueryRootFolderTest()); + addTest(new QueryForObjectCustom()); + addTest(new QueryLikeTestCustom()); + addTest(new QueryInFolderTestCustom()); + addTest(new ContentChangesSmokeTest()); + } + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub11TCK.java b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub11TCK.java index 64088a4016..d3798b0088 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub11TCK.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiAtomPub11TCK.java @@ -1,46 +1,46 @@ -package org.alfresco.rest.api.tests; - -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.opencmis.OpenCMISClientContext; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.tck.impl.TestParameters; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.AfterClass; -import org.junit.Before; - -/** - * OpenCMIS TCK unit tests. - * - * @author steveglover - * - */ -public class TestPublicApiAtomPub11TCK extends AbstractEnterpriseOpenCMIS11TCKTest -{ - private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.1/atom"; - protected static final Log logger = LogFactory.getLog(TestPublicApiAtomPub11TCK.class); - - @Before - public void before() throws Exception - { - int port = getTestFixture().getJettyComponent().getPort(); - TestNetwork network = getTestFixture().getRandomNetwork(); - Map cmisParameters = new HashMap(); - cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); - cmisParameters.put(TestParameters.DEFAULT_SECONDARY_TYPE, "P:cm:author"); - cmisParameters.put(TestParameters.DEFAULT_ITEM_TYPE, "I:cm:cmobject"); - clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, - MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), - "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); - overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); - } - - @AfterClass - public static void shutdown() throws Exception - { - } +package org.alfresco.rest.api.tests; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.opencmis.OpenCMISClientContext; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.tck.impl.TestParameters; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.AfterClass; +import org.junit.Before; + +/** + * OpenCMIS TCK unit tests. + * + * @author steveglover + * + */ +public class TestPublicApiAtomPub11TCK extends AbstractEnterpriseOpenCMIS11TCKTest +{ + private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.1/atom"; + protected static final Log logger = LogFactory.getLog(TestPublicApiAtomPub11TCK.class); + + @Before + public void before() throws Exception + { + int port = getTestFixture().getJettyComponent().getPort(); + TestNetwork network = getTestFixture().getRandomNetwork(); + Map cmisParameters = new HashMap(); + cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); + cmisParameters.put(TestParameters.DEFAULT_SECONDARY_TYPE, "P:cm:author"); + cmisParameters.put(TestParameters.DEFAULT_ITEM_TYPE, "I:cm:cmobject"); + clientContext = new OpenCMISClientContext(BindingType.ATOMPUB, + MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), + "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); + overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); + } + + @AfterClass + public static void shutdown() throws Exception + { + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiBrowser11TCK.java b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiBrowser11TCK.java index b61851da87..2fb6809e03 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiBrowser11TCK.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiBrowser11TCK.java @@ -1,40 +1,40 @@ -package org.alfresco.rest.api.tests; - -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.opencmis.OpenCMISClientContext; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.tck.impl.TestParameters; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; - -/** - * OpenCMIS TCK unit tests. - * - * @author steveglover - * - */ -public class TestPublicApiBrowser11TCK extends AbstractEnterpriseOpenCMIS11TCKTest -{ - private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.1/browser"; - protected static final Log logger = LogFactory.getLog(TestPublicApiBrowser11TCK.class); - - @Before - public void before() throws Exception - { - int port = getTestFixture().getJettyComponent().getPort(); - TestNetwork network = getTestFixture().getRandomNetwork(); - Map cmisParameters = new HashMap(); - cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); - cmisParameters.put(TestParameters.DEFAULT_SECONDARY_TYPE, "P:cm:author"); - cmisParameters.put(TestParameters.DEFAULT_ITEM_TYPE, "I:cm:cmobject"); - clientContext = new OpenCMISClientContext(BindingType.BROWSER, - MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), - "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); - overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); - } +package org.alfresco.rest.api.tests; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.opencmis.OpenCMISClientContext; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.tck.impl.TestParameters; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; + +/** + * OpenCMIS TCK unit tests. + * + * @author steveglover + * + */ +public class TestPublicApiBrowser11TCK extends AbstractEnterpriseOpenCMIS11TCKTest +{ + private static final String CMIS_URL = "http://{0}:{1}/{2}/api/{3}/{4}/cmis/versions/1.1/browser"; + protected static final Log logger = LogFactory.getLog(TestPublicApiBrowser11TCK.class); + + @Before + public void before() throws Exception + { + int port = getTestFixture().getJettyComponent().getPort(); + TestNetwork network = getTestFixture().getRandomNetwork(); + Map cmisParameters = new HashMap(); + cmisParameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE, "R:cm:replaces"); + cmisParameters.put(TestParameters.DEFAULT_SECONDARY_TYPE, "P:cm:author"); + cmisParameters.put(TestParameters.DEFAULT_ITEM_TYPE, "I:cm:cmobject"); + clientContext = new OpenCMISClientContext(BindingType.BROWSER, + MessageFormat.format(CMIS_URL, "localhost", String.valueOf(port), "alfresco", network.getId(), "public"), + "admin@" + network.getId(), "admin", cmisParameters, getTestFixture().getJettyComponent().getApplicationContext()); + overrideVersionableAspectProperties(getTestFixture().getJettyComponent().getApplicationContext()); + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiCaching.java b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiCaching.java index 5958fd2af9..5756cad844 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestPublicApiCaching.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestPublicApiCaching.java @@ -1,60 +1,60 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertNotNull; - -import java.util.Iterator; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.client.HttpResponse; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.junit.Test; - -/** - * HTTP cache header public api tests. - * - * @author Gavin Cornwell - * - */ -public class TestPublicApiCaching extends EnterpriseTestApi -{ - @Test - public void testMNT13938() throws Exception - { - Iterator accountsIt = getTestFixture().getNetworksIt(); - final TestNetwork account1 = accountsIt.next(); - Iterator personIt1 = account1.getPersonIds().iterator(); - final String person1 = personIt1.next(); - - // make a request to any API (we'll get our own profile) - { - publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); - HttpResponse response = publicApiClient.get("public", "people", person1, null, null, null); - - int responseCode = response.getStatusCode(); - // make sure request was successful - assertTrue("Response code should be 200", responseCode == HttpServletResponse.SC_OK); - - Map headers = response.getHeaders(); - // assert headers are present - assertNotNull("HTTP headers should be present on response", headers); - - // assert the cache headers are present - String cacheControlHeader = headers.get("Cache-Control"); - assertNotNull("Cache-Control header should be present", cacheControlHeader); - assertTrue("Cache-Control header should be set to no-cache but it was: " + cacheControlHeader, - cacheControlHeader.equals("no-cache")); - - String pragmaHeader = headers.get("Pragma"); - assertNotNull("Pragma header should be present", pragmaHeader); - assertTrue("Pragma header should be set to no-cache but it was: " + pragmaHeader, - pragmaHeader.equals("no-cache")); - - String expiresHeader = headers.get("Expires"); - assertNotNull("Expires header should be present", expiresHeader); - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; + +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.client.HttpResponse; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.junit.Test; + +/** + * HTTP cache header public api tests. + * + * @author Gavin Cornwell + * + */ +public class TestPublicApiCaching extends EnterpriseTestApi +{ + @Test + public void testMNT13938() throws Exception + { + Iterator accountsIt = getTestFixture().getNetworksIt(); + final TestNetwork account1 = accountsIt.next(); + Iterator personIt1 = account1.getPersonIds().iterator(); + final String person1 = personIt1.next(); + + // make a request to any API (we'll get our own profile) + { + publicApiClient.setRequestContext(new RequestContext(account1.getId(), person1)); + HttpResponse response = publicApiClient.get("public", "people", person1, null, null, null); + + int responseCode = response.getStatusCode(); + // make sure request was successful + assertTrue("Response code should be 200", responseCode == HttpServletResponse.SC_OK); + + Map headers = response.getHeaders(); + // assert headers are present + assertNotNull("HTTP headers should be present on response", headers); + + // assert the cache headers are present + String cacheControlHeader = headers.get("Cache-Control"); + assertNotNull("Cache-Control header should be present", cacheControlHeader); + assertTrue("Cache-Control header should be set to no-cache but it was: " + cacheControlHeader, + cacheControlHeader.equals("no-cache")); + + String pragmaHeader = headers.get("Pragma"); + assertNotNull("Pragma header should be present", pragmaHeader); + assertTrue("Pragma header should be set to no-cache but it was: " + pragmaHeader, + pragmaHeader.equals("no-cache")); + + String expiresHeader = headers.get("Expires"); + assertNotNull("Expires header should be present", expiresHeader); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestRemovePermissions.java b/source/test-java/org/alfresco/rest/api/tests/TestRemovePermissions.java index f17cf06ef9..9775c7ffd1 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestRemovePermissions.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestRemovePermissions.java @@ -1,398 +1,398 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.chemistry.opencmis.client.api.Folder; -import org.apache.chemistry.opencmis.client.api.Session; -import org.apache.chemistry.opencmis.client.api.SessionFactory; -import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; -import org.apache.chemistry.opencmis.commons.PropertyIds; -import org.apache.chemistry.opencmis.commons.SessionParameter; -import org.apache.chemistry.opencmis.commons.data.Ace; -import org.apache.chemistry.opencmis.commons.data.Acl; -import org.apache.chemistry.opencmis.commons.enums.AclPropagation; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Test; - -public class TestRemovePermissions extends EnterpriseTestApi -{ - private static Log logger = LogFactory.getLog(TestRemovePermissions.class); - - static public final String ADMIN_USER = "admin"; - static public final String ADMIN_PASSWORD = "admin"; - static public final String DEFAULT_HOSTNAME = "localhost"; - - static public final String ATOMPUB_URL_OC = "http://{0}:{1}/alfresco/cmisatom"; - static public final String ATOMPUB_URL_11 = "http://{0}:{1}/alfresco/api/-default-/public/cmis/versions/1.1/atom"; - - static public final String REPOSITORYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/RepositoryService?wsdl"; - static public final String NAVIGATIONSERVICE_URL = "http://{0}:{1}/alfresco/cmis/NavigationService?wsdl"; - static public final String OBJECTSERVICE_URL = "http://{0}:{1}/alfresco/cmis/ObjectService?wsdl"; - static public final String VERSIONINGSERVICE_URL = "http://{0}:{1}/alfresco/cmis/VersioningService?wsdl"; - static public final String DISCOVERYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/DiscoveryService?wsdl"; - static public final String MULTIFILINGSERVICE_URL = "http://{0}:{1}/alfresco/cmis/MultiFilingService?wsdl"; - static public final String RELATIONSHIPSERVICE_URL = "http://{0}:{1}/alfresco/cmis/RelationshipService?wsdl"; - static public final String ACLSERVICE_URL = "http://{0}:{1}/alfresco/cmis/ACLService?wsdl"; - static public final String POLICYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/PolicyService?wsdl"; - - static public final String REPOSITORYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/cmis?wsdl"; - static public final String NAVIGATIONSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/NavigationService?wsdl"; - static public final String OBJECTSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/ObjectService?wsdl"; - static public final String VERSIONINGSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/VersioningService?wsdl"; - static public final String DISCOVERYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/DiscoveryService?wsdl"; - static public final String MULTIFILINGSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/MultiFilingService?wsdl"; - static public final String RELATIONSHIPSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/RelationshipService?wsdl"; - static public final String ACLSERVICE_OC_URL = "http://{0}:{1}//alfresco/cmisws/ACLService?wsdl"; - static public final String POLICYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/PolicyService?wsdl"; - - static public final String BROWSE_URL_11 = "http://{0}:{1}/alfresco/api/-default-/public/cmis/versions/1.1/browser"; - - protected Session getATOMPUB_10_Session() - { - try - { - Map parameters = new HashMap(); - int port = getTestFixture().getJettyComponent().getPort(); - - parameters.put(SessionParameter.USER, ADMIN_USER); - parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); - parameters.put(SessionParameter.ATOMPUB_URL, MessageFormat.format(ATOMPUB_URL_OC, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); - - SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); - - parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); - return sessionFactory.createSession(parameters); - } - catch (Exception ex) - { - logger.error(ex); - } - return null; - } - - protected Session getATOMPUB_11_Session() - { - try - { - Map parameters = new HashMap(); - int port = getTestFixture().getJettyComponent().getPort(); - - parameters.put(SessionParameter.USER, ADMIN_USER); - parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); - parameters.put(SessionParameter.ATOMPUB_URL, MessageFormat.format(ATOMPUB_URL_11, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); - - SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); - - parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); - return sessionFactory.createSession(parameters); - } - catch (Exception ex) - { - logger.error(ex); - - } - return null; - } - - protected Session getBROWSER_11_Session() - { - try - { - Map parameter = new HashMap(); - int port = getTestFixture().getJettyComponent().getPort(); - - parameter.put(SessionParameter.BINDING_TYPE, BindingType.BROWSER.value()); - parameter.put(SessionParameter.BROWSER_URL, MessageFormat.format(BROWSE_URL_11, DEFAULT_HOSTNAME, String.valueOf(port))); - parameter.put(SessionParameter.COOKIES, "true"); - - parameter.put(SessionParameter.USER, ADMIN_USER); - parameter.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); - - SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); - - parameter.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameter).get(0).getId()); - return sessionFactory.createSession(parameter); - } - catch (Exception ex) - { - logger.error(ex); - - } - return null; - } - - protected Session getWEBSERVICE_10_Session() - { - try - { - SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); - int port = 8080; - - Map parameters = new HashMap(); - - parameters.put(SessionParameter.USER, ADMIN_USER); - parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value()); - - parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, - MessageFormat.format(ACLSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, - MessageFormat.format(DISCOVERYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, - MessageFormat.format(MULTIFILINGSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, - MessageFormat.format(NAVIGATIONSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, - MessageFormat.format(OBJECTSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, - MessageFormat.format(POLICYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, - MessageFormat.format(RELATIONSHIPSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, - MessageFormat.format(REPOSITORYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, - MessageFormat.format(REPOSITORYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); - parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); - - return sessionFactory.createSession(parameters); - } - catch (Exception ex) - { - logger.error(ex); - } - return null; - } - - /** - * cmisws?wsdl is not available using jetty in automated test suite should - * be runned using an external alfresco server - * - */ - // @Test - public void testRemoveAllPermissions_WEBSERVICE_10() - { - Folder testFolder = null; - try - { - Session session = getWEBSERVICE_10_Session(); - if (session == null) - { - fail("WEBSERVICE 1.0 session cannot be null"); - } - testFolder = createFolder(session, "testRemoveAllPermissions_WEBSERVICE_10"); - List acl = create2TestACLs(session); - - // adding new ACE - testFolder.addAcl(acl, AclPropagation.PROPAGATE); - - Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); - int oldSize = allacl.getAces().size(); - - // Removing ALL ACEs - Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); - - int newsize = newAcl.getAces().size(); - - System.out.println("Old ace size -->" + oldSize); - System.out.println("New ace size --> " + newsize); - - assertTrue(newsize == oldSize - acl.size()); - } - catch (Exception ex) - { - fail(ex.getMessage()); - } - finally - { - if (testFolder != null) - { - testFolder.delete(); - } - } - } - - @Test - public void testRemoveAllPermissions_ATOMPUB_10() - { - Folder testFolder = null; - try - { - Session session = getATOMPUB_10_Session(); - if (session == null) - { - fail("ATOMPUB 1.0 session cannot be null"); - } - testFolder = createFolder(session, "testRemoveAllPermissions_ATOMPUB_10"); - List acl = create2TestACLs(session); - - // adding new ACE - testFolder.addAcl(acl, AclPropagation.PROPAGATE); - - Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); - int oldSize = allacl.getAces().size(); - - // Removing ALL ACEs - Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); - - int newsize = newAcl.getAces().size(); - - System.out.println("Old ace size -->" + oldSize); - System.out.println("New ace size --> " + newsize); - - assertTrue(newsize == oldSize - acl.size()); - } - catch (Exception ex) - { - fail(ex.getMessage()); - } - finally - { - if (testFolder != null) - { - testFolder.delete(); - } - } - } - - @Test - public void testRemoveAllPermissions_ATOMPUB_11() - { - Folder testFolder = null; - try - { - Session session = getATOMPUB_11_Session(); - if (session == null) - { - fail("ATOMPUB 1.1 session cannot be null"); - } - testFolder = createFolder(session, "testRemoveAllPermissions_ATOMPUB_11"); - List acl = create2TestACLs(session); - - // adding new ACE - testFolder.addAcl(acl, AclPropagation.PROPAGATE); - - Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); - int oldSize = allacl.getAces().size(); - - // Removing ALL ACEs - Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); - - int newsize = newAcl.getAces().size(); - - System.out.println("Old ace size -->" + oldSize); - System.out.println("New ace size --> " + newsize); - - assertTrue(newsize == oldSize - acl.size()); - } - catch (Exception ex) - { - fail(ex.getMessage()); - } - finally - { - if (testFolder != null) - { - testFolder.delete(); - } - } - - } - - @Test - public void testRemoveAllPermissions_BROWSER_11() - { - Folder testFolder = null; - try - { - Session session = getBROWSER_11_Session(); - if (session == null) - { - fail("ATOMPUB 1.1 session cannot be null"); - } - testFolder = createFolder(session, "testRemoveAllPermissions_BROWSER_11"); - List acl = create2TestACLs(session); - - // adding new ACE - testFolder.addAcl(acl, AclPropagation.PROPAGATE); - - Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); - int oldSize = allacl.getAces().size(); - - // Removing ALL ACEs - - Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); - int newsize = newAcl.getAces().size(); - - System.out.println("Old ace size -->" + oldSize); - System.out.println("New ace size --> " + newsize); - - assertTrue(newsize == oldSize - acl.size()); - } - catch (Exception ex) - { - fail(ex.getMessage()); - } - finally - { - if (testFolder != null) - { - testFolder.delete(); - } - } - - } - - /** - * - * @param session Session - * @param name String - * @return Folder - */ - private Folder createFolder(Session session, String name) - { - Folder testFolder; - Folder folder = session.getRootFolder(); - Map properties = new HashMap(); - properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); - properties.put(PropertyIds.NAME, name); - - testFolder = folder.createFolder(properties); - - return testFolder; - } - - /** - * - * @param session Session - * @return List - */ - private List create2TestACLs(Session session) - { - List newACE = new ArrayList(); - LinkedList permissions1 = new LinkedList(); - permissions1.add("{http://www.alfresco.org/model/system/1.0}base.ReadPermissions"); - - LinkedList permissions2 = new LinkedList(); - permissions2.add("{http://www.alfresco.org/model/system/1.0}base.Unlock"); - - Ace ace1 = session.getObjectFactory().createAce("testUser1", permissions1); - Ace ace2 = session.getObjectFactory().createAce("testUser2", permissions2); - newACE.add(ace1); - newACE.add(ace2); - return newACE; - - } - -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.chemistry.opencmis.client.api.Session; +import org.apache.chemistry.opencmis.client.api.SessionFactory; +import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.SessionParameter; +import org.apache.chemistry.opencmis.commons.data.Ace; +import org.apache.chemistry.opencmis.commons.data.Acl; +import org.apache.chemistry.opencmis.commons.enums.AclPropagation; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Test; + +public class TestRemovePermissions extends EnterpriseTestApi +{ + private static Log logger = LogFactory.getLog(TestRemovePermissions.class); + + static public final String ADMIN_USER = "admin"; + static public final String ADMIN_PASSWORD = "admin"; + static public final String DEFAULT_HOSTNAME = "localhost"; + + static public final String ATOMPUB_URL_OC = "http://{0}:{1}/alfresco/cmisatom"; + static public final String ATOMPUB_URL_11 = "http://{0}:{1}/alfresco/api/-default-/public/cmis/versions/1.1/atom"; + + static public final String REPOSITORYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/RepositoryService?wsdl"; + static public final String NAVIGATIONSERVICE_URL = "http://{0}:{1}/alfresco/cmis/NavigationService?wsdl"; + static public final String OBJECTSERVICE_URL = "http://{0}:{1}/alfresco/cmis/ObjectService?wsdl"; + static public final String VERSIONINGSERVICE_URL = "http://{0}:{1}/alfresco/cmis/VersioningService?wsdl"; + static public final String DISCOVERYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/DiscoveryService?wsdl"; + static public final String MULTIFILINGSERVICE_URL = "http://{0}:{1}/alfresco/cmis/MultiFilingService?wsdl"; + static public final String RELATIONSHIPSERVICE_URL = "http://{0}:{1}/alfresco/cmis/RelationshipService?wsdl"; + static public final String ACLSERVICE_URL = "http://{0}:{1}/alfresco/cmis/ACLService?wsdl"; + static public final String POLICYSERVICE_URL = "http://{0}:{1}/alfresco/cmis/PolicyService?wsdl"; + + static public final String REPOSITORYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/cmis?wsdl"; + static public final String NAVIGATIONSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/NavigationService?wsdl"; + static public final String OBJECTSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/ObjectService?wsdl"; + static public final String VERSIONINGSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/VersioningService?wsdl"; + static public final String DISCOVERYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/DiscoveryService?wsdl"; + static public final String MULTIFILINGSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/MultiFilingService?wsdl"; + static public final String RELATIONSHIPSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/RelationshipService?wsdl"; + static public final String ACLSERVICE_OC_URL = "http://{0}:{1}//alfresco/cmisws/ACLService?wsdl"; + static public final String POLICYSERVICE_OC_URL = "http://{0}:{1}/alfresco/cmisws/PolicyService?wsdl"; + + static public final String BROWSE_URL_11 = "http://{0}:{1}/alfresco/api/-default-/public/cmis/versions/1.1/browser"; + + protected Session getATOMPUB_10_Session() + { + try + { + Map parameters = new HashMap(); + int port = getTestFixture().getJettyComponent().getPort(); + + parameters.put(SessionParameter.USER, ADMIN_USER); + parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); + parameters.put(SessionParameter.ATOMPUB_URL, MessageFormat.format(ATOMPUB_URL_OC, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + + SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); + + parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); + return sessionFactory.createSession(parameters); + } + catch (Exception ex) + { + logger.error(ex); + } + return null; + } + + protected Session getATOMPUB_11_Session() + { + try + { + Map parameters = new HashMap(); + int port = getTestFixture().getJettyComponent().getPort(); + + parameters.put(SessionParameter.USER, ADMIN_USER); + parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); + parameters.put(SessionParameter.ATOMPUB_URL, MessageFormat.format(ATOMPUB_URL_11, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + + SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); + + parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); + return sessionFactory.createSession(parameters); + } + catch (Exception ex) + { + logger.error(ex); + + } + return null; + } + + protected Session getBROWSER_11_Session() + { + try + { + Map parameter = new HashMap(); + int port = getTestFixture().getJettyComponent().getPort(); + + parameter.put(SessionParameter.BINDING_TYPE, BindingType.BROWSER.value()); + parameter.put(SessionParameter.BROWSER_URL, MessageFormat.format(BROWSE_URL_11, DEFAULT_HOSTNAME, String.valueOf(port))); + parameter.put(SessionParameter.COOKIES, "true"); + + parameter.put(SessionParameter.USER, ADMIN_USER); + parameter.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); + + SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); + + parameter.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameter).get(0).getId()); + return sessionFactory.createSession(parameter); + } + catch (Exception ex) + { + logger.error(ex); + + } + return null; + } + + protected Session getWEBSERVICE_10_Session() + { + try + { + SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); + int port = 8080; + + Map parameters = new HashMap(); + + parameters.put(SessionParameter.USER, ADMIN_USER); + parameters.put(SessionParameter.PASSWORD, ADMIN_PASSWORD); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value()); + + parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, + MessageFormat.format(ACLSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, + MessageFormat.format(DISCOVERYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, + MessageFormat.format(MULTIFILINGSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, + MessageFormat.format(NAVIGATIONSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, + MessageFormat.format(OBJECTSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, + MessageFormat.format(POLICYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, + MessageFormat.format(RELATIONSHIPSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, + MessageFormat.format(REPOSITORYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, + MessageFormat.format(REPOSITORYSERVICE_OC_URL, DEFAULT_HOSTNAME, String.valueOf(port))); + parameters.put(SessionParameter.REPOSITORY_ID, sessionFactory.getRepositories(parameters).get(0).getId()); + + return sessionFactory.createSession(parameters); + } + catch (Exception ex) + { + logger.error(ex); + } + return null; + } + + /** + * cmisws?wsdl is not available using jetty in automated test suite should + * be runned using an external alfresco server + * + */ + // @Test + public void testRemoveAllPermissions_WEBSERVICE_10() + { + Folder testFolder = null; + try + { + Session session = getWEBSERVICE_10_Session(); + if (session == null) + { + fail("WEBSERVICE 1.0 session cannot be null"); + } + testFolder = createFolder(session, "testRemoveAllPermissions_WEBSERVICE_10"); + List acl = create2TestACLs(session); + + // adding new ACE + testFolder.addAcl(acl, AclPropagation.PROPAGATE); + + Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); + int oldSize = allacl.getAces().size(); + + // Removing ALL ACEs + Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); + + int newsize = newAcl.getAces().size(); + + System.out.println("Old ace size -->" + oldSize); + System.out.println("New ace size --> " + newsize); + + assertTrue(newsize == oldSize - acl.size()); + } + catch (Exception ex) + { + fail(ex.getMessage()); + } + finally + { + if (testFolder != null) + { + testFolder.delete(); + } + } + } + + @Test + public void testRemoveAllPermissions_ATOMPUB_10() + { + Folder testFolder = null; + try + { + Session session = getATOMPUB_10_Session(); + if (session == null) + { + fail("ATOMPUB 1.0 session cannot be null"); + } + testFolder = createFolder(session, "testRemoveAllPermissions_ATOMPUB_10"); + List acl = create2TestACLs(session); + + // adding new ACE + testFolder.addAcl(acl, AclPropagation.PROPAGATE); + + Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); + int oldSize = allacl.getAces().size(); + + // Removing ALL ACEs + Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); + + int newsize = newAcl.getAces().size(); + + System.out.println("Old ace size -->" + oldSize); + System.out.println("New ace size --> " + newsize); + + assertTrue(newsize == oldSize - acl.size()); + } + catch (Exception ex) + { + fail(ex.getMessage()); + } + finally + { + if (testFolder != null) + { + testFolder.delete(); + } + } + } + + @Test + public void testRemoveAllPermissions_ATOMPUB_11() + { + Folder testFolder = null; + try + { + Session session = getATOMPUB_11_Session(); + if (session == null) + { + fail("ATOMPUB 1.1 session cannot be null"); + } + testFolder = createFolder(session, "testRemoveAllPermissions_ATOMPUB_11"); + List acl = create2TestACLs(session); + + // adding new ACE + testFolder.addAcl(acl, AclPropagation.PROPAGATE); + + Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); + int oldSize = allacl.getAces().size(); + + // Removing ALL ACEs + Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); + + int newsize = newAcl.getAces().size(); + + System.out.println("Old ace size -->" + oldSize); + System.out.println("New ace size --> " + newsize); + + assertTrue(newsize == oldSize - acl.size()); + } + catch (Exception ex) + { + fail(ex.getMessage()); + } + finally + { + if (testFolder != null) + { + testFolder.delete(); + } + } + + } + + @Test + public void testRemoveAllPermissions_BROWSER_11() + { + Folder testFolder = null; + try + { + Session session = getBROWSER_11_Session(); + if (session == null) + { + fail("ATOMPUB 1.1 session cannot be null"); + } + testFolder = createFolder(session, "testRemoveAllPermissions_BROWSER_11"); + List acl = create2TestACLs(session); + + // adding new ACE + testFolder.addAcl(acl, AclPropagation.PROPAGATE); + + Acl allacl = session.getAcl(session.createObjectId(testFolder.getId()), false); + int oldSize = allacl.getAces().size(); + + // Removing ALL ACEs + + Acl newAcl = testFolder.removeAcl(allacl.getAces(), AclPropagation.PROPAGATE); + int newsize = newAcl.getAces().size(); + + System.out.println("Old ace size -->" + oldSize); + System.out.println("New ace size --> " + newsize); + + assertTrue(newsize == oldSize - acl.size()); + } + catch (Exception ex) + { + fail(ex.getMessage()); + } + finally + { + if (testFolder != null) + { + testFolder.delete(); + } + } + + } + + /** + * + * @param session Session + * @param name String + * @return Folder + */ + private Folder createFolder(Session session, String name) + { + Folder testFolder; + Folder folder = session.getRootFolder(); + Map properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"); + properties.put(PropertyIds.NAME, name); + + testFolder = folder.createFolder(properties); + + return testFolder; + } + + /** + * + * @param session Session + * @return List + */ + private List create2TestACLs(Session session) + { + List newACE = new ArrayList(); + LinkedList permissions1 = new LinkedList(); + permissions1.add("{http://www.alfresco.org/model/system/1.0}base.ReadPermissions"); + + LinkedList permissions2 = new LinkedList(); + permissions2.add("{http://www.alfresco.org/model/system/1.0}base.Unlock"); + + Ace ace1 = session.getObjectFactory().createAce("testUser1", permissions1); + Ace ace2 = session.getObjectFactory().createAce("testUser2", permissions2); + newACE.add(ace1); + newACE.add(ace2); + return newACE; + + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestSiteContainers.java b/source/test-java/org/alfresco/rest/api/tests/TestSiteContainers.java index a801db4026..61d7cf8c94 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestSiteContainers.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestSiteContainers.java @@ -1,324 +1,324 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.SiteContainer; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -public class TestSiteContainers extends EnterpriseTestApi -{ - private TestNetwork network1; - private TestNetwork network2; - - private List people1 = new ArrayList(2); - private List people2 = new ArrayList(2); - - private TestPerson person11; // site creator - private TestPerson person12; // same network, not invited to site - private TestPerson person13; // same network, invited to site - private TestPerson person21; // different network, not invited to site - - private TestSite site1; - - @Before - public void setup() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - - assertTrue(networksIt.hasNext()); - this.network1 = networksIt.next(); - - assertTrue(networksIt.hasNext()); - this.network2 = networksIt.next(); - - // Create some users in different networks - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - // add as external user - TestPerson person1 = network1.createUser(); - people1.add(person1); - TestPerson person2 = network1.createUser(); - people1.add(person2); - TestPerson person3 = network1.createUser(); - people1.add(person3); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person1 = network2.createUser(); - people2.add(person1); - - return null; - } - }, network2.getId()); - - this.person11 = people1.get(0); // site creator - this.person12 = people1.get(1); // same network, not invited to site - this.person21 = people2.get(0); // different network, not invited to site - this.person13 = people1.get(2); // same network, invited to site - -// TenantUtil.runAsSystemTenant(new TenantRunAsWork() -// { -// @Override -// public Void doWork() throws Exception -// { -// // add as external user -// TestPerson person1 = network2.createUser(); -// network2People.add(person1); -// -// return null; -// } -// }, network2.getId()); -// -// final TestPerson person3 = network2People.get(0); - - // Create a public site - this.site1 = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite testSite = network1.createSite(SiteVisibility.PUBLIC); - return testSite; - } - }, person11.getId(), network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public Map doWork() throws Exception - { - Map containers = new HashMap(); - containers.put("test1", site1.createContainer("test1")); - containers.put("test2", site1.createContainer("test2")); - containers.put("test3", site1.createContainer("test3")); - return containers; - } - }, person11.getId(), network1.getId()); - } - - @Test - public void testSiteContainers() throws Exception - { - Sites sitesProxy = publicApiClient.sites(); - - List expectedSiteContainers = network1.getSiteContainers(site1.getSiteId(), person11); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - ListResponse resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - skipCount = 2; - maxItems = expectedSiteContainers.size(); - paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - skipCount = 2; - maxItems = expectedSiteContainers.size() + 2; - paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - SiteContainer expectedSiteContainer = new SiteContainer(site1.getSiteId(), "test2", null); - SiteContainer sc = sitesProxy.getSingleSiteContainer(site1.getSiteId(), "test2"); - check(expectedSiteContainer, sc); - } - - // site does not exist - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - sitesProxy.getSingleSiteContainer("gfyuosfgsf8y7s", "documentLibrary"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // container does not exist - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - sitesProxy.getSingleSiteContainer(site1.getSiteId(), "container1"); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // site containers - site does not exist - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - sitesProxy.getSiteContainers(GUID.generate(), createParams(paging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // a user in the same network, not invited to the site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - ListResponse ret = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), ret); - } - - // a user in a different network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // TODO a user in the same network, invited to the site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - ListResponse ret = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), ret); - } - - // person invited to site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13.getId())); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); - ListResponse resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); - checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // invalid methods - try - { - sitesProxy.create("sites", site1.getSiteId(), "containers", null, null, "Unable to POST to site containers"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - sitesProxy.create("sites", site1.getSiteId(), "containers", "documentLibrary", null, "Unable to POST to a site container"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - sitesProxy.update("sites", site1.getSiteId(), "containers", null, null, "Unable to PUT site containers"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - sitesProxy.update("sites", site1.getSiteId(), "containers", "documentLibrary", null, "Unable to PUT a site container"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - sitesProxy.remove("sites", site1.getSiteId(), "containers", null, "Unable to DELETE site containers"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - sitesProxy.remove("sites", site1.getSiteId(), "containers", "documentLibrary", "Unable to DELETE a site container"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // 1481 - // user in external network, list site containers - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.SiteContainer; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +public class TestSiteContainers extends EnterpriseTestApi +{ + private TestNetwork network1; + private TestNetwork network2; + + private List people1 = new ArrayList(2); + private List people2 = new ArrayList(2); + + private TestPerson person11; // site creator + private TestPerson person12; // same network, not invited to site + private TestPerson person13; // same network, invited to site + private TestPerson person21; // different network, not invited to site + + private TestSite site1; + + @Before + public void setup() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + + assertTrue(networksIt.hasNext()); + this.network1 = networksIt.next(); + + assertTrue(networksIt.hasNext()); + this.network2 = networksIt.next(); + + // Create some users in different networks + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + // add as external user + TestPerson person1 = network1.createUser(); + people1.add(person1); + TestPerson person2 = network1.createUser(); + people1.add(person2); + TestPerson person3 = network1.createUser(); + people1.add(person3); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person1 = network2.createUser(); + people2.add(person1); + + return null; + } + }, network2.getId()); + + this.person11 = people1.get(0); // site creator + this.person12 = people1.get(1); // same network, not invited to site + this.person21 = people2.get(0); // different network, not invited to site + this.person13 = people1.get(2); // same network, invited to site + +// TenantUtil.runAsSystemTenant(new TenantRunAsWork() +// { +// @Override +// public Void doWork() throws Exception +// { +// // add as external user +// TestPerson person1 = network2.createUser(); +// network2People.add(person1); +// +// return null; +// } +// }, network2.getId()); +// +// final TestPerson person3 = network2People.get(0); + + // Create a public site + this.site1 = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite testSite = network1.createSite(SiteVisibility.PUBLIC); + return testSite; + } + }, person11.getId(), network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public Map doWork() throws Exception + { + Map containers = new HashMap(); + containers.put("test1", site1.createContainer("test1")); + containers.put("test2", site1.createContainer("test2")); + containers.put("test3", site1.createContainer("test3")); + return containers; + } + }, person11.getId(), network1.getId()); + } + + @Test + public void testSiteContainers() throws Exception + { + Sites sitesProxy = publicApiClient.sites(); + + List expectedSiteContainers = network1.getSiteContainers(site1.getSiteId(), person11); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + ListResponse resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + skipCount = 2; + maxItems = expectedSiteContainers.size(); + paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + skipCount = 2; + maxItems = expectedSiteContainers.size() + 2; + paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + SiteContainer expectedSiteContainer = new SiteContainer(site1.getSiteId(), "test2", null); + SiteContainer sc = sitesProxy.getSingleSiteContainer(site1.getSiteId(), "test2"); + check(expectedSiteContainer, sc); + } + + // site does not exist + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + sitesProxy.getSingleSiteContainer("gfyuosfgsf8y7s", "documentLibrary"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // container does not exist + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + sitesProxy.getSingleSiteContainer(site1.getSiteId(), "container1"); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // site containers - site does not exist + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + sitesProxy.getSiteContainers(GUID.generate(), createParams(paging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // a user in the same network, not invited to the site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + ListResponse ret = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), ret); + } + + // a user in a different network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person21.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // TODO a user in the same network, invited to the site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + ListResponse ret = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), ret); + } + + // person invited to site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13.getId())); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteContainers.size(), expectedSiteContainers.size()); + ListResponse resp = sitesProxy.getSiteContainers(site1.getSiteId(), createParams(paging, null)); + checkList(expectedSiteContainers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // invalid methods + try + { + sitesProxy.create("sites", site1.getSiteId(), "containers", null, null, "Unable to POST to site containers"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + sitesProxy.create("sites", site1.getSiteId(), "containers", "documentLibrary", null, "Unable to POST to a site container"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + sitesProxy.update("sites", site1.getSiteId(), "containers", null, null, "Unable to PUT site containers"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + sitesProxy.update("sites", site1.getSiteId(), "containers", "documentLibrary", null, "Unable to PUT a site container"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + sitesProxy.remove("sites", site1.getSiteId(), "containers", null, "Unable to DELETE site containers"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + sitesProxy.remove("sites", site1.getSiteId(), "containers", "documentLibrary", "Unable to DELETE a site container"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // 1481 + // user in external network, list site containers + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestSiteMembers.java b/source/test-java/org/alfresco/rest/api/tests/TestSiteMembers.java index f10e66c0a8..e64e9119f9 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestSiteMembers.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestSiteMembers.java @@ -1,564 +1,564 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.HttpResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.Site; -import org.alfresco.rest.api.tests.client.data.SiteImpl; -import org.alfresco.rest.api.tests.client.data.SiteMember; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.json.simple.JSONObject; -import org.junit.Test; - -public class TestSiteMembers extends EnterpriseTestApi -{ - // TODO set create member for a user who is a member of the site (not the creator) - @Test - public void testSiteMembers() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - final TestNetwork testNetwork = networksIt.next(); - final List networkPeople = testNetwork.getPersonIds(); - String personId = networkPeople.get(0); - - Sites sitesProxy = publicApiClient.sites(); - - { - final List expectedSiteMembers = new ArrayList(); - - // Create a private site and invite some users - // TODO create site members using public api rather than directly using the services - TestSite testSite = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite testSite = testNetwork.createSite(SiteVisibility.PRIVATE); - for(int i = 1; i <= 5; i++) - { - String inviteeId = networkPeople.get(i); - testSite.inviteToSite(inviteeId, SiteRole.SiteConsumer); - SiteMember sm = new SiteMember(inviteeId, repoService.getPerson(inviteeId), testSite.getSiteId(), SiteRole.SiteConsumer.toString()); - expectedSiteMembers.add(sm); - } - - return testSite; - } - }, personId, testNetwork.getId()); - - { - SiteMember sm = new SiteMember(personId, repoService.getPerson(personId), testSite.getSiteId(), SiteRole.SiteManager.toString()); - expectedSiteMembers.add(sm); - Collections.sort(expectedSiteMembers); - } - - // Test Case cloud-1482 - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - ListResponse siteMembers = sitesProxy.getSiteMembers(testSite.getSiteId(), createParams(paging, null)); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); - } - - { - int skipCount = 2; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - ListResponse siteMembers = sitesProxy.getSiteMembers(testSite.getSiteId(), createParams(paging, null)); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); - - HttpResponse response = sitesProxy.getAll("sites", testSite.getSiteId(), "members", null, createParams(paging,Collections.singletonMap("includeSource", "true")), "Failed to get all site members"); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), SiteMember.parseSiteMembers(testSite.getSiteId(), response.getJsonResponse())); - JSONObject source = sitesProxy.parseListSource(response.getJsonResponse()); - Site sourceSite = SiteImpl.parseSite(source); - assertNotNull(sourceSite); - testSite.expected(sourceSite); - } - - // invalid site id - try - { - int skipCount = 2; - int maxItems = 10; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - sitesProxy.getSiteMembers(GUID.generate(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid methods - try - { - SiteMember siteMember = expectedSiteMembers.get(0); - - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - sitesProxy.update("sites", testSite.getSiteId(), "members", null, siteMember.toJSON().toString(), "Unable to PUT site members"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1965 - try - { - SiteMember siteMember1 = expectedSiteMembers.get(0); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - sitesProxy.create("sites", testSite.getSiteId(), "members", siteMember1.getMemberId(), siteMember1.toJSON().toString(), "Unable to POST to a site member"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - SiteMember siteMember1 = expectedSiteMembers.get(0); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - sitesProxy.update("sites", testSite.getSiteId(), "members", null, siteMember1.toJSON().toString(), "Unable to PUT site members"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - sitesProxy.remove("sites", testSite.getSiteId(), "members", null, "Unable to DELETE site members"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // update site member - { - SiteMember siteMember1 = expectedSiteMembers.get(0); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - SiteMember ret = sitesProxy.updateSiteMember(testSite.getSiteId(), siteMember1); - assertEquals(siteMember1.getRole(), ret.getRole()); - Person expectedSiteMember = repoService.getPerson(siteMember1.getMemberId()); - expectedSiteMember.expected(ret.getMember()); - } - - // GET single site member - { - SiteMember siteMember1 = expectedSiteMembers.get(0); - publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); - SiteMember ret = sitesProxy.getSingleSiteMember(testSite.getSiteId(), siteMember1.getMemberId()); - siteMember1.expected(ret); - } - } - - // test: user is member of different tenant, but has site membership(s) in common with the http request user - { - Iterator accountsIt = getTestFixture().getNetworksIt(); - - assertTrue(accountsIt.hasNext()); - final TestNetwork network1 = accountsIt.next(); - - assertTrue(accountsIt.hasNext()); - final TestNetwork network2 = accountsIt.next(); - - final List people = new ArrayList(); - - // Create users - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - - return null; - } - }, network2.getId()); - - final TestPerson person1 = people.get(0); - final TestPerson person2 = people.get(1); - final TestPerson person3 = people.get(2); - final TestPerson person4 = people.get(3); - - // Create site - final TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PUBLIC); - return site; - } - }, person2.getId(), network1.getId()); - - // invalid role - 400 - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), "dodgyRole")); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // user in network but not site member, try to create site member - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person3.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // unknown invitee - 404 - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember("dodgyUser", SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown site - 404 - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.createSiteMember("dodgySite", new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // inviter is not a member of the site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(e.getMessage(), HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // inviter is not a member of the site nor a member of the tenant - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); // TODO check that 404 is correct here - external user of network can't see public site?? - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - SiteMember sm = new SiteMember(person1.getId(), SiteRole.SiteConsumer.toString()); - SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), sm); - assertEquals(person1.getId(), siteMember.getMemberId()); - assertEquals(SiteRole.SiteConsumer.toString(), siteMember.getRole()); - } - - // already invited - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_CONFLICT, e.getHttpResponse().getStatusCode()); - } - - // inviter is consumer member of the site, should not be able to add site member - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person4.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(e.getMessage(), HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invitee from another network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person4.getId(), SiteRole.SiteContributor.toString())); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(e.getMessage(), HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // check site membership in GET - List expectedSiteMembers = site.getMembers(); - - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); - } - } - - // test: create site membership, remove it, get list of site memberships - { - Iterator accountsIt = getTestFixture().getNetworksIt(); - - assertTrue(accountsIt.hasNext()); - final TestNetwork network1 = accountsIt.next(); - - assertTrue(accountsIt.hasNext()); - - final List people = new ArrayList(); - - // Create user - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - - return null; - } - }, network1.getId()); - - TestPerson person1 = people.get(0); - TestPerson person2 = people.get(1); - - // Create site - TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - return site; - } - }, person2.getId(), network1.getId()); - - // remove site membership - - // for -me- user (PUBLICAPI-90) - { - // create a site member - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - assertEquals(person1.getId(), siteMember.getMemberId()); - assertEquals(SiteRole.SiteContributor.toString(), siteMember.getRole()); - - SiteMember toRemove = new SiteMember("-me-"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - sitesProxy.removeSiteMember(site.getSiteId(), toRemove); - } - - { - // create a site member - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - assertEquals(person1.getId(), siteMember.getMemberId()); - assertEquals(SiteRole.SiteContributor.toString(), siteMember.getRole()); - - // unknown site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.removeSiteMember(GUID.generate(), siteMember); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown user - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.removeSiteMember(site.getSiteId(), new SiteMember(GUID.generate())); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.removeSiteMember(site.getSiteId(), siteMember); - } - - // check site membership in GET - List expectedSiteMembers = site.getMembers(); - assertFalse(expectedSiteMembers.contains(siteMember)); - - { - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); - } - - // update site membership - - // unknown site - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.updateSiteMember(GUID.generate(), siteMember); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown user - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(GUID.generate())); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // invalid role - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(person1.getId(), "invalidRole")); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // user is not a member of the site - 400 - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // successful update - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - - SiteMember sm = new SiteMember(person1.getId(), SiteRole.SiteContributor.toString()); - SiteMember ret = sitesProxy.createSiteMember(site.getSiteId(), sm); - assertEquals(SiteRole.SiteContributor.toString(), ret.getRole()); - person1.expected(ret.getMember()); - - sm = new SiteMember(person1.getId(), SiteRole.SiteCollaborator.toString()); - ret = sitesProxy.updateSiteMember(site.getSiteId(), sm); - assertEquals(SiteRole.SiteCollaborator.toString(), ret.getRole()); - person1.expected(ret.getMember()); - - // check site membership in GET - expectedSiteMembers = site.getMembers(); - SiteMember toCheck = null; - for(SiteMember sm1 : expectedSiteMembers) - { - if(sm1.getMemberId().equals(person1.getId())) - { - toCheck = sm1; - } - } - assertNotNull(toCheck); // check that the update site membership is present - assertEquals(sm.getRole(), toCheck.getRole()); // check that the role is correct - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); - checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); - } - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.HttpResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.Site; +import org.alfresco.rest.api.tests.client.data.SiteImpl; +import org.alfresco.rest.api.tests.client.data.SiteMember; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.json.simple.JSONObject; +import org.junit.Test; + +public class TestSiteMembers extends EnterpriseTestApi +{ + // TODO set create member for a user who is a member of the site (not the creator) + @Test + public void testSiteMembers() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + final TestNetwork testNetwork = networksIt.next(); + final List networkPeople = testNetwork.getPersonIds(); + String personId = networkPeople.get(0); + + Sites sitesProxy = publicApiClient.sites(); + + { + final List expectedSiteMembers = new ArrayList(); + + // Create a private site and invite some users + // TODO create site members using public api rather than directly using the services + TestSite testSite = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite testSite = testNetwork.createSite(SiteVisibility.PRIVATE); + for(int i = 1; i <= 5; i++) + { + String inviteeId = networkPeople.get(i); + testSite.inviteToSite(inviteeId, SiteRole.SiteConsumer); + SiteMember sm = new SiteMember(inviteeId, repoService.getPerson(inviteeId), testSite.getSiteId(), SiteRole.SiteConsumer.toString()); + expectedSiteMembers.add(sm); + } + + return testSite; + } + }, personId, testNetwork.getId()); + + { + SiteMember sm = new SiteMember(personId, repoService.getPerson(personId), testSite.getSiteId(), SiteRole.SiteManager.toString()); + expectedSiteMembers.add(sm); + Collections.sort(expectedSiteMembers); + } + + // Test Case cloud-1482 + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + ListResponse siteMembers = sitesProxy.getSiteMembers(testSite.getSiteId(), createParams(paging, null)); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); + } + + { + int skipCount = 2; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + ListResponse siteMembers = sitesProxy.getSiteMembers(testSite.getSiteId(), createParams(paging, null)); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); + + HttpResponse response = sitesProxy.getAll("sites", testSite.getSiteId(), "members", null, createParams(paging,Collections.singletonMap("includeSource", "true")), "Failed to get all site members"); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), SiteMember.parseSiteMembers(testSite.getSiteId(), response.getJsonResponse())); + JSONObject source = sitesProxy.parseListSource(response.getJsonResponse()); + Site sourceSite = SiteImpl.parseSite(source); + assertNotNull(sourceSite); + testSite.expected(sourceSite); + } + + // invalid site id + try + { + int skipCount = 2; + int maxItems = 10; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + sitesProxy.getSiteMembers(GUID.generate(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid methods + try + { + SiteMember siteMember = expectedSiteMembers.get(0); + + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + sitesProxy.update("sites", testSite.getSiteId(), "members", null, siteMember.toJSON().toString(), "Unable to PUT site members"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1965 + try + { + SiteMember siteMember1 = expectedSiteMembers.get(0); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + sitesProxy.create("sites", testSite.getSiteId(), "members", siteMember1.getMemberId(), siteMember1.toJSON().toString(), "Unable to POST to a site member"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + SiteMember siteMember1 = expectedSiteMembers.get(0); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + sitesProxy.update("sites", testSite.getSiteId(), "members", null, siteMember1.toJSON().toString(), "Unable to PUT site members"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + sitesProxy.remove("sites", testSite.getSiteId(), "members", null, "Unable to DELETE site members"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // update site member + { + SiteMember siteMember1 = expectedSiteMembers.get(0); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + SiteMember ret = sitesProxy.updateSiteMember(testSite.getSiteId(), siteMember1); + assertEquals(siteMember1.getRole(), ret.getRole()); + Person expectedSiteMember = repoService.getPerson(siteMember1.getMemberId()); + expectedSiteMember.expected(ret.getMember()); + } + + // GET single site member + { + SiteMember siteMember1 = expectedSiteMembers.get(0); + publicApiClient.setRequestContext(new RequestContext(testNetwork.getId(), personId)); + SiteMember ret = sitesProxy.getSingleSiteMember(testSite.getSiteId(), siteMember1.getMemberId()); + siteMember1.expected(ret); + } + } + + // test: user is member of different tenant, but has site membership(s) in common with the http request user + { + Iterator accountsIt = getTestFixture().getNetworksIt(); + + assertTrue(accountsIt.hasNext()); + final TestNetwork network1 = accountsIt.next(); + + assertTrue(accountsIt.hasNext()); + final TestNetwork network2 = accountsIt.next(); + + final List people = new ArrayList(); + + // Create users + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + + return null; + } + }, network2.getId()); + + final TestPerson person1 = people.get(0); + final TestPerson person2 = people.get(1); + final TestPerson person3 = people.get(2); + final TestPerson person4 = people.get(3); + + // Create site + final TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PUBLIC); + return site; + } + }, person2.getId(), network1.getId()); + + // invalid role - 400 + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), "dodgyRole")); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // user in network but not site member, try to create site member + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person3.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // unknown invitee - 404 + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember("dodgyUser", SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown site - 404 + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.createSiteMember("dodgySite", new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // inviter is not a member of the site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(e.getMessage(), HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // inviter is not a member of the site nor a member of the tenant + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person4.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); // TODO check that 404 is correct here - external user of network can't see public site?? + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + SiteMember sm = new SiteMember(person1.getId(), SiteRole.SiteConsumer.toString()); + SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), sm); + assertEquals(person1.getId(), siteMember.getMemberId()); + assertEquals(SiteRole.SiteConsumer.toString(), siteMember.getRole()); + } + + // already invited + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_CONFLICT, e.getHttpResponse().getStatusCode()); + } + + // inviter is consumer member of the site, should not be able to add site member + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person4.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(e.getMessage(), HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invitee from another network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person4.getId(), SiteRole.SiteContributor.toString())); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(e.getMessage(), HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // check site membership in GET + List expectedSiteMembers = site.getMembers(); + + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); + } + } + + // test: create site membership, remove it, get list of site memberships + { + Iterator accountsIt = getTestFixture().getNetworksIt(); + + assertTrue(accountsIt.hasNext()); + final TestNetwork network1 = accountsIt.next(); + + assertTrue(accountsIt.hasNext()); + + final List people = new ArrayList(); + + // Create user + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + + return null; + } + }, network1.getId()); + + TestPerson person1 = people.get(0); + TestPerson person2 = people.get(1); + + // Create site + TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + return site; + } + }, person2.getId(), network1.getId()); + + // remove site membership + + // for -me- user (PUBLICAPI-90) + { + // create a site member + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + assertEquals(person1.getId(), siteMember.getMemberId()); + assertEquals(SiteRole.SiteContributor.toString(), siteMember.getRole()); + + SiteMember toRemove = new SiteMember("-me-"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + sitesProxy.removeSiteMember(site.getSiteId(), toRemove); + } + + { + // create a site member + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + SiteMember siteMember = sitesProxy.createSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + assertEquals(person1.getId(), siteMember.getMemberId()); + assertEquals(SiteRole.SiteContributor.toString(), siteMember.getRole()); + + // unknown site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.removeSiteMember(GUID.generate(), siteMember); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown user + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.removeSiteMember(site.getSiteId(), new SiteMember(GUID.generate())); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.removeSiteMember(site.getSiteId(), siteMember); + } + + // check site membership in GET + List expectedSiteMembers = site.getMembers(); + assertFalse(expectedSiteMembers.contains(siteMember)); + + { + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); + } + + // update site membership + + // unknown site + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.updateSiteMember(GUID.generate(), siteMember); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown user + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(GUID.generate())); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // invalid role + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(person1.getId(), "invalidRole")); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // user is not a member of the site - 400 + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + sitesProxy.updateSiteMember(site.getSiteId(), new SiteMember(person1.getId(), SiteRole.SiteContributor.toString())); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // successful update + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + + SiteMember sm = new SiteMember(person1.getId(), SiteRole.SiteContributor.toString()); + SiteMember ret = sitesProxy.createSiteMember(site.getSiteId(), sm); + assertEquals(SiteRole.SiteContributor.toString(), ret.getRole()); + person1.expected(ret.getMember()); + + sm = new SiteMember(person1.getId(), SiteRole.SiteCollaborator.toString()); + ret = sitesProxy.updateSiteMember(site.getSiteId(), sm); + assertEquals(SiteRole.SiteCollaborator.toString(), ret.getRole()); + person1.expected(ret.getMember()); + + // check site membership in GET + expectedSiteMembers = site.getMembers(); + SiteMember toCheck = null; + for(SiteMember sm1 : expectedSiteMembers) + { + if(sm1.getMemberId().equals(person1.getId())) + { + toCheck = sm1; + } + } + assertNotNull(toCheck); // check that the update site membership is present + assertEquals(sm.getRole(), toCheck.getRole()); // check that the role is correct + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembers.size(), null); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + ListResponse siteMembers = sitesProxy.getSiteMembers(site.getSiteId(), createParams(paging, null)); + checkList(expectedSiteMembers.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), siteMembers); + } + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestSiteMembershipRequests.java b/source/test-java/org/alfresco/rest/api/tests/TestSiteMembershipRequests.java index 2b823370d7..811c5991b0 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestSiteMembershipRequests.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestSiteMembershipRequests.java @@ -1,1421 +1,1421 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.SiteMembershipRequests; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.invitation.Invitation; -import org.alfresco.service.cmr.invitation.ModeratedInvitation; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -@SuppressWarnings("unused") -public class TestSiteMembershipRequests extends EnterpriseTestApi -{ - private TestNetwork network1; - private TestNetwork network2; - - private String person11Id; // network1 - private String person12Id; // network1 - private String person13Id; // network1 - private String person14Id; // network1 - private String person15Id; // network1 - - private String person24Id; // network2 - - private List personModeratedSites = new ArrayList(); - private List personPublicSites = new ArrayList(); - private List person1PrivateSites = new ArrayList(); - private List person1ModeratedSites = new ArrayList(); - private List person1MixedCaseModeratedSites = new ArrayList(); - private List person1PublicSites = new ArrayList(); - private List person4ModeratedSites = new ArrayList(); - private List personDocs = new ArrayList(); - private List personFolders = new ArrayList(); - private List person1Docs = new ArrayList(); - private List person1Folders = new ArrayList(); - - private SiteMembershipRequests siteMembershipRequestsProxy; - - private Random random = new Random(System.currentTimeMillis()); - - @Before - public void setup() throws Exception - { - Iterator networksIt = getTestFixture().networksIterator(); - this.network1 = networksIt.next(); - Iterator personIt = network1.getPersonIds().iterator(); - this.person11Id = personIt.next(); - assertNotNull(person11Id); - this.person12Id = personIt.next(); - assertNotNull(person12Id); - this.person13Id = personIt.next(); - assertNotNull(person13Id); - this.person14Id = personIt.next(); - assertNotNull(person14Id); - this.person15Id = personIt.next(); - assertNotNull(person15Id); - - this.network2 = networksIt.next(); - Iterator person1It = network2.getPersonIds().iterator(); - this.person24Id = person1It.next(); - assertNotNull(person24Id); - - // Create some sites, files and folders - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String guid = GUID.generate(); - String[] siteNames = new String[] {"sitex" + guid, "sitea" + guid, "sitef" + guid, "site234" + guid, - "sitey" + guid, "siteb" + guid, "site643" + guid, "site24" + guid, "site8d6sc" + guid}; - - String siteName = siteNames[0]; - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); - TestSite site = network1.createSite(siteInfo); - person1ModeratedSites.add(site); - - for(int i = 1; i < siteNames.length; i++) - { - siteName = siteNames[i]; - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); - site = network1.createSite(siteInfo); - person1ModeratedSites.add(site); - } - - String[] mixedCaseSiteNames = new String[] {"MixedCase" + guid, "mixedCaseA" + guid}; - - for(int i = 0; i < mixedCaseSiteNames.length; i++) - { - siteName = mixedCaseSiteNames[i]; - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); - site = network1.createSite(siteInfo); - person1MixedCaseModeratedSites.add(site); - } - - for(int i = 0; i < 1; i++) - { - siteName = "privatesite" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); - site = network1.createSite(siteInfo); - person1PrivateSites.add(site); - } - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); - person1Docs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); - person1Folders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); - person1Docs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); - person1Folders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); - person1Docs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); - person1Folders.add(nodeRef); - - siteName = "site" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - site = network1.createSite(siteInfo); - person1PublicSites.add(site); - - return null; - } - }, person12Id, network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + System.currentTimeMillis(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); - personFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); - personFolders.add(nodeRef); - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); - personDocs.add(nodeRef); - nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); - personFolders.add(nodeRef); - - return null; - } - }, person11Id, network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + GUID.generate(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - TestSite site = network1.createSite(siteInfo); - personPublicSites.add(site); - - site.inviteToSite(person12Id, SiteRole.SiteCollaborator); - - siteName = "site" + GUID.generate(); - siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); - site = network1.createSite(siteInfo); - personPublicSites.add(site); - - return null; - } - }, person11Id, network1.getId()); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - String siteName = "site" + GUID.generate(); - SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); - TestSite site = network1.createSite(siteInfo); - person4ModeratedSites.add(site); - - return null; - } - }, person24Id, network2.getId()); - - this.siteMembershipRequestsProxy = publicApiClient.siteMembershipRequests(); - } - - private SiteMembershipRequest getSiteMembershipRequest(String networkId, String runAsUserId, String personId) throws PublicApiException, ParseException - { - publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(personId, createParams(paging, null)); - List list = resp.getList(); - int size = list.size(); - assertTrue(size > 0); - int idx = random.nextInt(size); - SiteMembershipRequest request = list.get(idx); - return request; - } - - @Test - public void testInvalidRequests() throws Exception - { - { - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); - - // unknown invitee - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(GUID.generate(), siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); - - // unknown siteId - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(GUID.generate()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); - - // create site membership for another user - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // cloud-2506 - // get requests for another user - try - { - log("cloud-2506"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // get site membership requests for another user - int skipCount = 0; - int maxItems = 4; - Paging paging = getPaging(skipCount, maxItems); - siteMembershipRequestsProxy.getSiteMembershipRequests(person12Id, createParams(paging, null)); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // get site membership requests for unknown user - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - int skipCount = 0; - int maxItems = 4; - Paging paging = getPaging(skipCount, maxItems); - siteMembershipRequestsProxy.getSiteMembershipRequests(GUID.generate(), createParams(paging, null)); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // DELETEs - { - { - // cloud-2524 - // runAs user != target user - log("cloud-2524"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - // create moderated site invitation to delete - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - - SiteMembershipRequest request = getSiteMembershipRequest(network1.getId(), person14Id, person14Id); - - // user from another network - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, request.getId()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // cloud-2525 - // unknown personId - try - { - log("cloud-2525"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(GUID.generate(), request.getId()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // cloud-2526 - // cloud-2527 - // unknown siteId - try - { - log("cloud-2526"); - log("cloud-2527"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - SiteMembershipRequest request = new SiteMembershipRequest(); - request.setId(GUID.generate()); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, request.getId()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown request id - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, GUID.generate()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // PUTs - - // cloud-2519 - PUT to site membership requests - try - { - log("cloud-2519"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - SiteMembershipRequest request = new SiteMembershipRequest(); - request.setId(GUID.generate()); - request.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.update("people", person11Id, "favorites", null, request.toJSON().toString(), "Unable to PUT site membership requests"); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // cloud-2520 - unknown request/site id - try - { - log("cloud-2516"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - SiteMembershipRequest request = new SiteMembershipRequest(); - request.setId(GUID.generate()); - request.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.updateSiteMembershipRequest(person11Id, request); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - } - - @Test - public void testValidRequests() throws Exception - { - final List expectedSiteMembershipRequests = new ArrayList(); - - { - // GET - // cloud-2531 - // user has no site membership requests - { - log("cloud-2531"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - int skipCount = 0; - Paging paging = getPaging(skipCount, null, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // POSTs - // cloud-2502 - // cloud-2510 - { - log("cloud-2502"); - log("cloud-2510"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // moderated site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - final SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest("-me-", siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - siteMembershipRequest.expected(moderatedSiteResponse); - - // public site - siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1PublicSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - siteMembershipRequest.expected(ret); - - // test we have a moderated site request only - // cloud-2532 - { - log("cloud-2532"); - - int skipCount = 0; - int maxItems = 4; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); - } - - // test against the underlying invitation service - List invitations = repoService.getModeratedSiteInvitations(network1.getId(), person11Id, person11Id, null); - assertEquals(1, invitations.size()); - Invitation invitation = invitations.get(0); - assertTrue(invitation instanceof ModeratedInvitation); - ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; - String siteId = moderatedInvitation.getResourceName(); - Invitation.InvitationType invitationType = moderatedInvitation.getInvitationType(); - Invitation.ResourceType resourceType = moderatedInvitation.getResourceType(); - String inviteeId = moderatedInvitation.getInviteeUserName(); - assertEquals(person11Id, inviteeId); - assertEquals(Invitation.ResourceType.WEB_SITE, resourceType); - assertEquals(Invitation.InvitationType.MODERATED, invitationType); - assertEquals(person1ModeratedSites.get(0).getSiteId(), siteId); - - // test that personId is a member of the public site - assertTrue(person1PublicSites.get(0).isMember(person11Id)); - - // cloud-2534 - // approve the moderated site invitation and check that it is gone from the list - { - log("cloud-2534"); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.approveSiteInvitation(person11Id, moderatedSiteResponse.getId()); - expectedSiteMembershipRequests.remove(0); - return null; - } - }, person12Id, network1.getId()); - - // make sure the outstanding request has gone - int skipCount = 0; - int maxItems = 4; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); - } - } - - // user from another network - un-authorised - try - { - log("cloud-2511"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); - - // moderated site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // cloud-2512 - // cloud-2535 - // invitee from another network - { - log("cloud-2512"); - log("cloud-2535"); - log("cloud-2536"); - - final List person4ExpectedSiteMembershipRequests = new ArrayList(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); - - { - // public site - try - { - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1PublicSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - { - // moderated site - try - { - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - siteMembershipRequestsProxy.getSiteMembershipRequests(person24Id, createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - - { - // private site - try - { - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1PrivateSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - try - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - siteMembershipRequestsProxy.getSiteMembershipRequests(person24Id, createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - } - } - - // cloud-2513 - try - { - log("cloud-2513"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // unknown site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(GUID.generate()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // private site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1PrivateSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // moderated site in another network - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person4ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // cloud-2514 - try - { - log("cloud-2514"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // already joined the site - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // already requested to join the site but not yet joined - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // cloud-2538 - // blank message - { - log("cloud-2538"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(1).getSiteId()); - siteMembershipRequest.setMessage(""); - SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(ret); - } - - // GETs - - // cloud-2501 - // cloud-2509 - // test paging - { - log("cloud-2501"); - log("cloud-2509"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // add some more site membership requests to moderated sites - for(int i = 1; i < person1ModeratedSites.size(); i++) - { - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(person1ModeratedSites.get(i).getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - try - { - SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(ret); - siteMembershipRequest.expected(ret); - } - catch(PublicApiException e) - { - // this is ok, already created - } - - } - - Collections.sort(expectedSiteMembershipRequests); - - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - skipCount = 2; - maxItems = 5; - paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - skipCount = 5; - maxItems = 10; - paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - skipCount = 0; - maxItems = expectedSiteMembershipRequests.size(); - paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // skipCount is greater than the number of site membership requests in the list - { - int skipCount = 1000; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(sublist(expectedSiteMembershipRequests, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // cloud-2537 - // -me- user - { - log("cloud-2537"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests("-me-", createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - } - - // DELETEs - // cloud-2504 - { - log("cloud-2504"); - - SiteMembershipRequest request = getSiteMembershipRequest(network1.getId(), person11Id, person11Id); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person11Id, request.getId()); - expectedSiteMembershipRequests.remove(request); - Collections.sort(expectedSiteMembershipRequests); - - // cloud-2533 - // check that the site membership request has gone - log("cloud-2533"); - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); - - // cloud-2528 - // try to cancel the same request - try - { - log("cloud-2528"); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person11Id, request.getId()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // cloud-2529 - // cancel a site membership request that has been rejected - { - log("cloud-2529"); - - final String siteId = person1ModeratedSites.get(1).getSiteId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - Collections.sort(expectedSiteMembershipRequests); - siteMembershipRequest.expected(moderatedSiteResponse); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Invitation invitation = repoService.rejectSiteInvitation(person14Id, siteId); - assertNotNull(invitation); - - return null; - } - }, person12Id, network1.getId()); - - // try to cancel the request - try - { - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, siteId); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // cloud-2530 - // cancel a site membership request that has been approved - { - log("cloud-2530"); - - final String siteId = person1ModeratedSites.get(2).getSiteId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - Collections.sort(expectedSiteMembershipRequests); - siteMembershipRequest.expected(moderatedSiteResponse); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - Invitation invitation = repoService.approveSiteInvitation(person14Id, siteId); - assertNotNull(invitation); - - return null; - } - }, person12Id, network1.getId()); - - // try to cancel the request - try - { - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, siteId); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // PUTs - - // cloud-2503 - // cloud-2517 - // cloud-2518 - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - // merged these tests - // cloud-2503: use -me- pseudo user - // cloud-2517: initially no message - log("cloud-2503"); - log("cloud-2517"); - - // create a request without a message - String siteId = person1ModeratedSites.get(7).getSiteId(); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - SiteMembershipRequest request = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - assertNotNull(request); - - // update it, with a message - request.setMessage("Please can I join your site?"); - SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); - request.expected(updated); - - // check it's updated - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person14Id, createParams(paging, null)); - List requests = resp.getList(); - assertTrue(requests.size() > 0); - int idx = requests.indexOf(request); - SiteMembershipRequest toCheck = requests.get(idx); - updated.expected(toCheck); - - // cloud-2518 - // update it again, with ammended message - - log("cloud-2518"); - - request.setMessage("Please can I join your site, pretty please?"); - updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); - request.expected(updated); - - // check it's updated - skipCount = 0; - maxItems = 2; - paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person14Id, createParams(paging, null)); - requests = resp.getList(); - assertTrue(requests.size() > 0); - idx = requests.indexOf(request); - toCheck = requests.get(idx); - updated.expected(toCheck); - } - - // cloud-2515 - no changes - { - log("cloud-2515"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - // create a request - String siteId = person1ModeratedSites.get(8).getSiteId(); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest request = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - assertNotNull(request); - - // update it, with no changes - SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); - request.expected(updated); // should not have changed - } - - // cloud-2516 - unknown person id - try - { - log("cloud-2516"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - // get an outstanding request - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); - List requests = resp.getList(); - assertTrue(requests.size() > 0); - SiteMembershipRequest request = requests.get(0); - siteMembershipRequestsProxy.updateSiteMembershipRequest(GUID.generate(), request); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // cloud-2521 - unknown site membership request - try - { - log("cloud-2521"); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); - - SiteMembershipRequest request = new SiteMembershipRequest(); - request.setId(GUID.generate()); - siteMembershipRequestsProxy.updateSiteMembershipRequest(person11Id, request); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - - // cloud-2522 - // update a site membership request that has been rejected - { - log("cloud-2522"); - - String siteId = person1ModeratedSites.get(5).getSiteId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - Collections.sort(expectedSiteMembershipRequests); - siteMembershipRequest.expected(moderatedSiteResponse); - - repoService.rejectSiteInvitation(person14Id, siteId); - - // try to update the request - try - { - siteMembershipRequestsProxy.updateSiteMembershipRequest(siteId, moderatedSiteResponse); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // cloud-2523 - // update a site membership request that has been approved - { - log("cloud-2523"); - - String siteId = person1ModeratedSites.get(6).getSiteId(); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - Collections.sort(expectedSiteMembershipRequests); - siteMembershipRequest.expected(moderatedSiteResponse); - - repoService.approveSiteInvitation(person14Id, siteId); - - // try to update the request - try - { - siteMembershipRequestsProxy.updateSiteMembershipRequest(siteId, moderatedSiteResponse); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - { - // cloud-2539 - probing attack tests - - log("cloud-2539"); - - // i) create site membership request to a moderated site - // ii) site owner changes the site to a private site - // iii) re-issue create site membership request should be a 404 - { - final List person2ExpectedSiteMembershipRequests = new ArrayList(); - - final TestSite site = person1ModeratedSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(site.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - site.setSiteVisibility(SiteVisibility.PRIVATE); - return null; - } - }, person12Id, network1.getId()); - - // Can we still GET it? Should be a 404 (private site) - try - { - siteMembershipRequestsProxy.getSiteMembershipRequest(person13Id, siteMembershipRequest.getId()); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // GET should not contain the site - { - int skipCount = 0; - int maxItems = 10; - assertEquals(0, person2ExpectedSiteMembershipRequests.size()); - Paging paging = getPaging(skipCount, maxItems, person2ExpectedSiteMembershipRequests.size(), person2ExpectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person13Id, createParams(paging, null)); - checkList(sublist(person2ExpectedSiteMembershipRequests, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - try - { - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // i) create site membership request to a public site - // ii) site owner changes the site to a private site - // iii) re-issue create site membership request should be a 404 - { - final TestSite site = person1PublicSites.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(site.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - site.setSiteVisibility(SiteVisibility.PRIVATE); - return null; - } - }, person12Id, network1.getId()); - - try - { - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - siteMembershipRequestsProxy.updateSiteMembershipRequest(person13Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - try - { - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person13Id, siteMembershipRequest.getId()); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - } - - // i) create site membership request to a moderated site - // ii) site owner accepts the request -> user is now a member of the site - // iii) site owner changes the site to a private site - // iv) re-issue create site membership request should be a 404 - { - final TestSite site = person1ModeratedSites.get(1); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(site.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - // approve the site invitation request and convert the site to a private site - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - repoService.approveSiteInvitation(person13Id, site.getSiteId()); - - site.setSiteVisibility(SiteVisibility.PRIVATE); - return null; - } - }, person12Id, network1.getId()); - - try - { - siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - - // blank message in POST and PUT - { - final TestSite site = person1ModeratedSites.get(2); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(site.getSiteId()); - siteMembershipRequest.setMessage(""); - SiteMembershipRequest created = siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); - SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person13Id, siteMembershipRequest); - - assertTrue(updated.getModifiedAt().after(created.getCreatedAt())); - } - } - } - - // PUBLICAPI-126, PUBLICAPI-132 - @Test - public void testMixedCase() throws Exception - { - final List expectedSiteMembershipRequests = new ArrayList(); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person15Id)); - - // moderated site - String siteId = person1MixedCaseModeratedSites.get(0).getSiteId().toLowerCase(); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(siteId); // lower case to test mixed case - siteMembershipRequest.setMessage("Please can I join your site?"); - final SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest("-me-", siteMembershipRequest); - expectedSiteMembershipRequests.add(moderatedSiteResponse); - Collections.sort(expectedSiteMembershipRequests); - siteMembershipRequest.expected(moderatedSiteResponse); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); - ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person15Id, createParams(paging, null)); - checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - - SiteMembershipRequest ret = siteMembershipRequestsProxy.getSiteMembershipRequest(person15Id, siteId); - siteMembershipRequest.expected(ret); - - siteMembershipRequestsProxy.cancelSiteMembershipRequest(person15Id, ret.getId()); - - try - { - siteMembershipRequestsProxy.getSiteMembershipRequest(person15Id, siteId); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - } - } - - @Test - public void testALF19332() throws Exception - { - String networkId = network1.getId(); - - final TestNetwork systemNetwork = getRepoService().getSystemNetwork(); - long time = System.currentTimeMillis(); - // note: username for site creator is of the form user@network - PersonInfo personInfo = new PersonInfo("test", "test", "test" + time, "password", null, "test", "test", "test", "test", "test", "test"); - TestPerson person = network1.createUser(personInfo); - personInfo = new PersonInfo("test", "test", "test1" + time, "password", null, "test", "test", "test", "test", "test", "test"); - TestPerson person1 = network1.createUser(personInfo); - - TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public TestSite doWork() throws Exception - { - TestSite site = systemNetwork.createSite(SiteVisibility.PUBLIC); - return site; - } - }, person.getId(), networkId); - - publicApiClient.setRequestContext(new RequestContext("-default-", person1.getId())); - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(site.getSiteId()); - siteMembershipRequest.setMessage("Please can I join your site?"); - SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person1.getId(), siteMembershipRequest); - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.SiteMembershipRequests; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.ModeratedInvitation; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +@SuppressWarnings("unused") +public class TestSiteMembershipRequests extends EnterpriseTestApi +{ + private TestNetwork network1; + private TestNetwork network2; + + private String person11Id; // network1 + private String person12Id; // network1 + private String person13Id; // network1 + private String person14Id; // network1 + private String person15Id; // network1 + + private String person24Id; // network2 + + private List personModeratedSites = new ArrayList(); + private List personPublicSites = new ArrayList(); + private List person1PrivateSites = new ArrayList(); + private List person1ModeratedSites = new ArrayList(); + private List person1MixedCaseModeratedSites = new ArrayList(); + private List person1PublicSites = new ArrayList(); + private List person4ModeratedSites = new ArrayList(); + private List personDocs = new ArrayList(); + private List personFolders = new ArrayList(); + private List person1Docs = new ArrayList(); + private List person1Folders = new ArrayList(); + + private SiteMembershipRequests siteMembershipRequestsProxy; + + private Random random = new Random(System.currentTimeMillis()); + + @Before + public void setup() throws Exception + { + Iterator networksIt = getTestFixture().networksIterator(); + this.network1 = networksIt.next(); + Iterator personIt = network1.getPersonIds().iterator(); + this.person11Id = personIt.next(); + assertNotNull(person11Id); + this.person12Id = personIt.next(); + assertNotNull(person12Id); + this.person13Id = personIt.next(); + assertNotNull(person13Id); + this.person14Id = personIt.next(); + assertNotNull(person14Id); + this.person15Id = personIt.next(); + assertNotNull(person15Id); + + this.network2 = networksIt.next(); + Iterator person1It = network2.getPersonIds().iterator(); + this.person24Id = person1It.next(); + assertNotNull(person24Id); + + // Create some sites, files and folders + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String guid = GUID.generate(); + String[] siteNames = new String[] {"sitex" + guid, "sitea" + guid, "sitef" + guid, "site234" + guid, + "sitey" + guid, "siteb" + guid, "site643" + guid, "site24" + guid, "site8d6sc" + guid}; + + String siteName = siteNames[0]; + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); + TestSite site = network1.createSite(siteInfo); + person1ModeratedSites.add(site); + + for(int i = 1; i < siteNames.length; i++) + { + siteName = siteNames[i]; + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); + site = network1.createSite(siteInfo); + person1ModeratedSites.add(site); + } + + String[] mixedCaseSiteNames = new String[] {"MixedCase" + guid, "mixedCaseA" + guid}; + + for(int i = 0; i < mixedCaseSiteNames.length; i++) + { + siteName = mixedCaseSiteNames[i]; + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); + site = network1.createSite(siteInfo); + person1MixedCaseModeratedSites.add(site); + } + + for(int i = 0; i < 1; i++) + { + siteName = "privatesite" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PRIVATE); + site = network1.createSite(siteInfo); + person1PrivateSites.add(site); + } + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); + person1Docs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); + person1Folders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); + person1Docs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); + person1Folders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); + person1Docs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); + person1Folders.add(nodeRef); + + siteName = "site" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + site = network1.createSite(siteInfo); + person1PublicSites.add(site); + + return null; + } + }, person12Id, network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + System.currentTimeMillis(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc1", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder1"); + personFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc2", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder2"); + personFolders.add(nodeRef); + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc3", "Test Content"); + personDocs.add(nodeRef); + nodeRef = repoService.createFolder(site.getContainerNodeRef("documentLibrary"), "Test Folder3"); + personFolders.add(nodeRef); + + return null; + } + }, person11Id, network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + GUID.generate(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + TestSite site = network1.createSite(siteInfo); + personPublicSites.add(site); + + site.inviteToSite(person12Id, SiteRole.SiteCollaborator); + + siteName = "site" + GUID.generate(); + siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.PUBLIC); + site = network1.createSite(siteInfo); + personPublicSites.add(site); + + return null; + } + }, person11Id, network1.getId()); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + String siteName = "site" + GUID.generate(); + SiteInformation siteInfo = new SiteInformation(siteName, siteName, siteName, SiteVisibility.MODERATED); + TestSite site = network1.createSite(siteInfo); + person4ModeratedSites.add(site); + + return null; + } + }, person24Id, network2.getId()); + + this.siteMembershipRequestsProxy = publicApiClient.siteMembershipRequests(); + } + + private SiteMembershipRequest getSiteMembershipRequest(String networkId, String runAsUserId, String personId) throws PublicApiException, ParseException + { + publicApiClient.setRequestContext(new RequestContext(networkId, runAsUserId)); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(personId, createParams(paging, null)); + List list = resp.getList(); + int size = list.size(); + assertTrue(size > 0); + int idx = random.nextInt(size); + SiteMembershipRequest request = list.get(idx); + return request; + } + + @Test + public void testInvalidRequests() throws Exception + { + { + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); + + // unknown invitee + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(GUID.generate(), siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); + + // unknown siteId + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(GUID.generate()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person12Id)); + + // create site membership for another user + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // cloud-2506 + // get requests for another user + try + { + log("cloud-2506"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // get site membership requests for another user + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + siteMembershipRequestsProxy.getSiteMembershipRequests(person12Id, createParams(paging, null)); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // get site membership requests for unknown user + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + siteMembershipRequestsProxy.getSiteMembershipRequests(GUID.generate(), createParams(paging, null)); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // DELETEs + { + { + // cloud-2524 + // runAs user != target user + log("cloud-2524"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + // create moderated site invitation to delete + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + + SiteMembershipRequest request = getSiteMembershipRequest(network1.getId(), person14Id, person14Id); + + // user from another network + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, request.getId()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // cloud-2525 + // unknown personId + try + { + log("cloud-2525"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(GUID.generate(), request.getId()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // cloud-2526 + // cloud-2527 + // unknown siteId + try + { + log("cloud-2526"); + log("cloud-2527"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + SiteMembershipRequest request = new SiteMembershipRequest(); + request.setId(GUID.generate()); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, request.getId()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown request id + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, GUID.generate()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // PUTs + + // cloud-2519 - PUT to site membership requests + try + { + log("cloud-2519"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + SiteMembershipRequest request = new SiteMembershipRequest(); + request.setId(GUID.generate()); + request.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.update("people", person11Id, "favorites", null, request.toJSON().toString(), "Unable to PUT site membership requests"); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // cloud-2520 - unknown request/site id + try + { + log("cloud-2516"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + SiteMembershipRequest request = new SiteMembershipRequest(); + request.setId(GUID.generate()); + request.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.updateSiteMembershipRequest(person11Id, request); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + } + + @Test + public void testValidRequests() throws Exception + { + final List expectedSiteMembershipRequests = new ArrayList(); + + { + // GET + // cloud-2531 + // user has no site membership requests + { + log("cloud-2531"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + int skipCount = 0; + Paging paging = getPaging(skipCount, null, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // POSTs + // cloud-2502 + // cloud-2510 + { + log("cloud-2502"); + log("cloud-2510"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // moderated site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + final SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest("-me-", siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + siteMembershipRequest.expected(moderatedSiteResponse); + + // public site + siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1PublicSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + siteMembershipRequest.expected(ret); + + // test we have a moderated site request only + // cloud-2532 + { + log("cloud-2532"); + + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); + } + + // test against the underlying invitation service + List invitations = repoService.getModeratedSiteInvitations(network1.getId(), person11Id, person11Id, null); + assertEquals(1, invitations.size()); + Invitation invitation = invitations.get(0); + assertTrue(invitation instanceof ModeratedInvitation); + ModeratedInvitation moderatedInvitation = (ModeratedInvitation)invitation; + String siteId = moderatedInvitation.getResourceName(); + Invitation.InvitationType invitationType = moderatedInvitation.getInvitationType(); + Invitation.ResourceType resourceType = moderatedInvitation.getResourceType(); + String inviteeId = moderatedInvitation.getInviteeUserName(); + assertEquals(person11Id, inviteeId); + assertEquals(Invitation.ResourceType.WEB_SITE, resourceType); + assertEquals(Invitation.InvitationType.MODERATED, invitationType); + assertEquals(person1ModeratedSites.get(0).getSiteId(), siteId); + + // test that personId is a member of the public site + assertTrue(person1PublicSites.get(0).isMember(person11Id)); + + // cloud-2534 + // approve the moderated site invitation and check that it is gone from the list + { + log("cloud-2534"); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.approveSiteInvitation(person11Id, moderatedSiteResponse.getId()); + expectedSiteMembershipRequests.remove(0); + return null; + } + }, person12Id, network1.getId()); + + // make sure the outstanding request has gone + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); + } + } + + // user from another network - un-authorised + try + { + log("cloud-2511"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); + + // moderated site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // cloud-2512 + // cloud-2535 + // invitee from another network + { + log("cloud-2512"); + log("cloud-2535"); + log("cloud-2536"); + + final List person4ExpectedSiteMembershipRequests = new ArrayList(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person24Id)); + + { + // public site + try + { + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1PublicSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + { + // moderated site + try + { + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + siteMembershipRequestsProxy.getSiteMembershipRequests(person24Id, createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + + { + // private site + try + { + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1PrivateSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person24Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + try + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + siteMembershipRequestsProxy.getSiteMembershipRequests(person24Id, createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + } + } + + // cloud-2513 + try + { + log("cloud-2513"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // unknown site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(GUID.generate()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // private site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1PrivateSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // moderated site in another network + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person4ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // cloud-2514 + try + { + log("cloud-2514"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // already joined the site + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // already requested to join the site but not yet joined + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(0).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // cloud-2538 + // blank message + { + log("cloud-2538"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(1).getSiteId()); + siteMembershipRequest.setMessage(""); + SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(ret); + } + + // GETs + + // cloud-2501 + // cloud-2509 + // test paging + { + log("cloud-2501"); + log("cloud-2509"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // add some more site membership requests to moderated sites + for(int i = 1; i < person1ModeratedSites.size(); i++) + { + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(person1ModeratedSites.get(i).getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + try + { + SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person11Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(ret); + siteMembershipRequest.expected(ret); + } + catch(PublicApiException e) + { + // this is ok, already created + } + + } + + Collections.sort(expectedSiteMembershipRequests); + + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + skipCount = 2; + maxItems = 5; + paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + skipCount = 5; + maxItems = 10; + paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + skipCount = 0; + maxItems = expectedSiteMembershipRequests.size(); + paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // skipCount is greater than the number of site membership requests in the list + { + int skipCount = 1000; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(sublist(expectedSiteMembershipRequests, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // cloud-2537 + // -me- user + { + log("cloud-2537"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests("-me-", createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + } + + // DELETEs + // cloud-2504 + { + log("cloud-2504"); + + SiteMembershipRequest request = getSiteMembershipRequest(network1.getId(), person11Id, person11Id); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person11Id, request.getId()); + expectedSiteMembershipRequests.remove(request); + Collections.sort(expectedSiteMembershipRequests); + + // cloud-2533 + // check that the site membership request has gone + log("cloud-2533"); + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests, paging.getExpectedPaging(), resp); + + // cloud-2528 + // try to cancel the same request + try + { + log("cloud-2528"); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person11Id, request.getId()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // cloud-2529 + // cancel a site membership request that has been rejected + { + log("cloud-2529"); + + final String siteId = person1ModeratedSites.get(1).getSiteId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + Collections.sort(expectedSiteMembershipRequests); + siteMembershipRequest.expected(moderatedSiteResponse); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Invitation invitation = repoService.rejectSiteInvitation(person14Id, siteId); + assertNotNull(invitation); + + return null; + } + }, person12Id, network1.getId()); + + // try to cancel the request + try + { + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, siteId); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // cloud-2530 + // cancel a site membership request that has been approved + { + log("cloud-2530"); + + final String siteId = person1ModeratedSites.get(2).getSiteId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + Collections.sort(expectedSiteMembershipRequests); + siteMembershipRequest.expected(moderatedSiteResponse); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + Invitation invitation = repoService.approveSiteInvitation(person14Id, siteId); + assertNotNull(invitation); + + return null; + } + }, person12Id, network1.getId()); + + // try to cancel the request + try + { + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person14Id, siteId); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // PUTs + + // cloud-2503 + // cloud-2517 + // cloud-2518 + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + // merged these tests + // cloud-2503: use -me- pseudo user + // cloud-2517: initially no message + log("cloud-2503"); + log("cloud-2517"); + + // create a request without a message + String siteId = person1ModeratedSites.get(7).getSiteId(); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + SiteMembershipRequest request = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + assertNotNull(request); + + // update it, with a message + request.setMessage("Please can I join your site?"); + SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); + request.expected(updated); + + // check it's updated + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person14Id, createParams(paging, null)); + List requests = resp.getList(); + assertTrue(requests.size() > 0); + int idx = requests.indexOf(request); + SiteMembershipRequest toCheck = requests.get(idx); + updated.expected(toCheck); + + // cloud-2518 + // update it again, with ammended message + + log("cloud-2518"); + + request.setMessage("Please can I join your site, pretty please?"); + updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); + request.expected(updated); + + // check it's updated + skipCount = 0; + maxItems = 2; + paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person14Id, createParams(paging, null)); + requests = resp.getList(); + assertTrue(requests.size() > 0); + idx = requests.indexOf(request); + toCheck = requests.get(idx); + updated.expected(toCheck); + } + + // cloud-2515 - no changes + { + log("cloud-2515"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + // create a request + String siteId = person1ModeratedSites.get(8).getSiteId(); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest request = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + assertNotNull(request); + + // update it, with no changes + SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person14Id, request); + request.expected(updated); // should not have changed + } + + // cloud-2516 - unknown person id + try + { + log("cloud-2516"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + // get an outstanding request + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person11Id, createParams(paging, null)); + List requests = resp.getList(); + assertTrue(requests.size() > 0); + SiteMembershipRequest request = requests.get(0); + siteMembershipRequestsProxy.updateSiteMembershipRequest(GUID.generate(), request); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // cloud-2521 - unknown site membership request + try + { + log("cloud-2521"); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person11Id)); + + SiteMembershipRequest request = new SiteMembershipRequest(); + request.setId(GUID.generate()); + siteMembershipRequestsProxy.updateSiteMembershipRequest(person11Id, request); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + + // cloud-2522 + // update a site membership request that has been rejected + { + log("cloud-2522"); + + String siteId = person1ModeratedSites.get(5).getSiteId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + Collections.sort(expectedSiteMembershipRequests); + siteMembershipRequest.expected(moderatedSiteResponse); + + repoService.rejectSiteInvitation(person14Id, siteId); + + // try to update the request + try + { + siteMembershipRequestsProxy.updateSiteMembershipRequest(siteId, moderatedSiteResponse); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // cloud-2523 + // update a site membership request that has been approved + { + log("cloud-2523"); + + String siteId = person1ModeratedSites.get(6).getSiteId(); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person14Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest(person14Id, siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + Collections.sort(expectedSiteMembershipRequests); + siteMembershipRequest.expected(moderatedSiteResponse); + + repoService.approveSiteInvitation(person14Id, siteId); + + // try to update the request + try + { + siteMembershipRequestsProxy.updateSiteMembershipRequest(siteId, moderatedSiteResponse); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + { + // cloud-2539 - probing attack tests + + log("cloud-2539"); + + // i) create site membership request to a moderated site + // ii) site owner changes the site to a private site + // iii) re-issue create site membership request should be a 404 + { + final List person2ExpectedSiteMembershipRequests = new ArrayList(); + + final TestSite site = person1ModeratedSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(site.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + site.setSiteVisibility(SiteVisibility.PRIVATE); + return null; + } + }, person12Id, network1.getId()); + + // Can we still GET it? Should be a 404 (private site) + try + { + siteMembershipRequestsProxy.getSiteMembershipRequest(person13Id, siteMembershipRequest.getId()); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // GET should not contain the site + { + int skipCount = 0; + int maxItems = 10; + assertEquals(0, person2ExpectedSiteMembershipRequests.size()); + Paging paging = getPaging(skipCount, maxItems, person2ExpectedSiteMembershipRequests.size(), person2ExpectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person13Id, createParams(paging, null)); + checkList(sublist(person2ExpectedSiteMembershipRequests, skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + try + { + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // i) create site membership request to a public site + // ii) site owner changes the site to a private site + // iii) re-issue create site membership request should be a 404 + { + final TestSite site = person1PublicSites.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(site.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + site.setSiteVisibility(SiteVisibility.PRIVATE); + return null; + } + }, person12Id, network1.getId()); + + try + { + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + siteMembershipRequestsProxy.updateSiteMembershipRequest(person13Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + try + { + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person13Id, siteMembershipRequest.getId()); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + } + + // i) create site membership request to a moderated site + // ii) site owner accepts the request -> user is now a member of the site + // iii) site owner changes the site to a private site + // iv) re-issue create site membership request should be a 404 + { + final TestSite site = person1ModeratedSites.get(1); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(site.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + // approve the site invitation request and convert the site to a private site + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + repoService.approveSiteInvitation(person13Id, site.getSiteId()); + + site.setSiteVisibility(SiteVisibility.PRIVATE); + return null; + } + }, person12Id, network1.getId()); + + try + { + siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + + // blank message in POST and PUT + { + final TestSite site = person1ModeratedSites.get(2); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person13Id)); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(site.getSiteId()); + siteMembershipRequest.setMessage(""); + SiteMembershipRequest created = siteMembershipRequestsProxy.createSiteMembershipRequest(person13Id, siteMembershipRequest); + SiteMembershipRequest updated = siteMembershipRequestsProxy.updateSiteMembershipRequest(person13Id, siteMembershipRequest); + + assertTrue(updated.getModifiedAt().after(created.getCreatedAt())); + } + } + } + + // PUBLICAPI-126, PUBLICAPI-132 + @Test + public void testMixedCase() throws Exception + { + final List expectedSiteMembershipRequests = new ArrayList(); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person15Id)); + + // moderated site + String siteId = person1MixedCaseModeratedSites.get(0).getSiteId().toLowerCase(); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(siteId); // lower case to test mixed case + siteMembershipRequest.setMessage("Please can I join your site?"); + final SiteMembershipRequest moderatedSiteResponse = siteMembershipRequestsProxy.createSiteMembershipRequest("-me-", siteMembershipRequest); + expectedSiteMembershipRequests.add(moderatedSiteResponse); + Collections.sort(expectedSiteMembershipRequests); + siteMembershipRequest.expected(moderatedSiteResponse); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSiteMembershipRequests.size(), expectedSiteMembershipRequests.size()); + ListResponse resp = siteMembershipRequestsProxy.getSiteMembershipRequests(person15Id, createParams(paging, null)); + checkList(expectedSiteMembershipRequests.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + + SiteMembershipRequest ret = siteMembershipRequestsProxy.getSiteMembershipRequest(person15Id, siteId); + siteMembershipRequest.expected(ret); + + siteMembershipRequestsProxy.cancelSiteMembershipRequest(person15Id, ret.getId()); + + try + { + siteMembershipRequestsProxy.getSiteMembershipRequest(person15Id, siteId); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + } + } + + @Test + public void testALF19332() throws Exception + { + String networkId = network1.getId(); + + final TestNetwork systemNetwork = getRepoService().getSystemNetwork(); + long time = System.currentTimeMillis(); + // note: username for site creator is of the form user@network + PersonInfo personInfo = new PersonInfo("test", "test", "test" + time, "password", null, "test", "test", "test", "test", "test", "test"); + TestPerson person = network1.createUser(personInfo); + personInfo = new PersonInfo("test", "test", "test1" + time, "password", null, "test", "test", "test", "test", "test", "test"); + TestPerson person1 = network1.createUser(personInfo); + + TestSite site = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public TestSite doWork() throws Exception + { + TestSite site = systemNetwork.createSite(SiteVisibility.PUBLIC); + return site; + } + }, person.getId(), networkId); + + publicApiClient.setRequestContext(new RequestContext("-default-", person1.getId())); + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(site.getSiteId()); + siteMembershipRequest.setMessage("Please can I join your site?"); + SiteMembershipRequest ret = siteMembershipRequestsProxy.createSiteMembershipRequest(person1.getId(), siteMembershipRequest); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestSites.java b/source/test-java/org/alfresco/rest/api/tests/TestSites.java index a7dc23597b..2d859e933c 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestSites.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestSites.java @@ -1,314 +1,314 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.SiteInformation; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Site; -import org.alfresco.rest.api.tests.client.data.SiteImpl; -import org.alfresco.rest.api.tests.client.data.SiteRole; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -/** - * @author sglover - * @author janv - */ -public class TestSites extends EnterpriseTestApi -{ - private TestNetwork network1; - private String person1Id; - private String person2Id; - - private Site site1; - private Site site2; - private Site site3; - - @Before - public void setup() throws Exception - { - // Test: user is member of an account - this.network1 = getTestFixture().getRandomNetwork(); - - Iterator personIt = network1.getPersonIds().iterator(); - - this.person1Id = personIt.next(); - assertNotNull(person1Id); - - this.person2Id = personIt.next(); - assertNotNull(person2Id); - } - - @Test - public void testSites() throws Exception - { - Sites sitesProxy = publicApiClient.sites(); - - // create & get sites (as person 2) - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2Id)); - - String siteTitle = "site 1 " + System.currentTimeMillis(); - Site site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); - site1 = sitesProxy.createSite(site); - - Site ret = sitesProxy.getSite(site1.getSiteId()); - site1.expected(ret); - - siteTitle = "site 2 " + System.currentTimeMillis(); - site = new SiteImpl(siteTitle, SiteVisibility.PUBLIC.toString()); - site2 = sitesProxy.createSite(site); - - ret = sitesProxy.getSite(site2.getSiteId()); - site2.expected(ret); - - siteTitle = "site 3 " + System.currentTimeMillis(); - site = new SiteImpl(siteTitle, SiteVisibility.MODERATED.toString()); - site3 = sitesProxy.createSite(site); - - ret = sitesProxy.getSite(site3.getSiteId()); - site3.expected(ret); - } - - List expectedSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List sites = network1.getSites(person1Id); - return sites; - } - }, person1Id, network1.getId()); - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), expectedSites.size()); - ListResponse resp = sitesProxy.getSites(createParams(paging, null)); - checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - int skipCount = 2; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), expectedSites.size()); - ListResponse resp = sitesProxy.getSites(createParams(paging, null)); - checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // test create and delete site - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - String siteTitle = "my site !*#$ 123"; - String siteDescription = "my site description"; - - SiteImpl site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); - site.setDescription(siteDescription); - - Site ret = sitesProxy.createSite(site); - String siteId = ret.getSiteId(); - - String expectedSiteId = "my-site-123"; - Site siteExp = new SiteImpl(null, expectedSiteId, ret.getGuid(), siteTitle, siteDescription, SiteVisibility.PRIVATE.toString(), null, SiteRole.SiteManager); - siteExp.expected(ret); - - ret = sitesProxy.getSite(siteId); - siteExp.expected(ret); - - sitesProxy.removeSite(siteId); - - // -ve test - ie. cannot get site after it has been deleted - sitesProxy.getSite(siteId, 404); - } - - // test create + permanent delete + create - { - - String siteId = "bbb"; - String siteTitle = "BBB site"; - - Site site = new SiteImpl(null, siteId, null, siteTitle, null, SiteVisibility.PUBLIC.toString(), null, null); - - sitesProxy.createSite(site); - - // permanent site delete (bypass trashcan/archive) - sitesProxy.removeSite(siteId, true, 204); - - sitesProxy.createSite(site); - } - - // test create using site id = "true" (RA-1101) - { - - String siteId = "true"; - String siteTitle = "string"; - String siteDescription = "string"; - - Site site = new SiteImpl(null, siteId, null, siteTitle, siteDescription, SiteVisibility.PUBLIC.toString(), null, null); - - sitesProxy.createSite(site); - } - - // -ve tests - { - // invalid auth - publicApiClient.setRequestContext(new RequestContext(network1.getId(), GUID.generate(), "password")); - sitesProxy.getSite(site1.getSiteId(), 401); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - // -ve - cannot view or delete a private site - sitesProxy.getSite(site1.getSiteId(), 404); - sitesProxy.removeSite(site1.getSiteId(), false, 404); - - // -ve - test cannot delete a public site (but can view it) - sitesProxy.getSite(site2.getSiteId(), 200); - sitesProxy.removeSite(site2.getSiteId(), false, 403); - - // -ve - try to get unknown site - sitesProxy.getSite(GUID.generate(), 404); - - SiteImpl site = new SiteImpl("my site 123", "invalidsitevisibility"); - sitesProxy.createSite(site, 400); - - site = new SiteImpl(null, "invalid site id", null, "my site 123", null, SiteVisibility.PRIVATE.toString(), null, null); - sitesProxy.createSite(site, 400); - - site = new SiteImpl(null, "invalidsiteid*", null, "my site 123", null, SiteVisibility.PRIVATE.toString(), null, null); - sitesProxy.createSite(site, 400); - - site = new SiteImpl(); - site.setSiteId(new String(new char[72]).replace('\0', 'a')); - site.setTitle(new String(new char[256]).replace('\0', 'a')); - site.setDescription(new String(new char[512]).replace('\0', 'a')); - site.setVisibility(SiteVisibility.PUBLIC.toString()); - sitesProxy.createSite(site, 201); - - // -ve - site id too long - site = new SiteImpl(); - site.setSiteId(new String(new char[73]).replace('\0', 'a')); - site.setTitle("ok"); - site.setDescription("ok"); - site.setVisibility(SiteVisibility.PUBLIC.toString()); - sitesProxy.createSite(site, 400); - - // -ve - site title too long - site = new SiteImpl(); - site.setSiteId("ok"); - site.setTitle(new String(new char[257]).replace('\0', 'a')); - site.setDescription("ok"); - site.setVisibility(SiteVisibility.PUBLIC.toString()); - sitesProxy.createSite(site, 400); - - // -ve - site description too long - site = new SiteImpl(); - site.setSiteId("ok"); - site.setTitle("ok"); - site.setDescription(new String(new char[513]).replace('\0', 'a')); - site.setVisibility(SiteVisibility.PUBLIC.toString()); - sitesProxy.createSite(site, 400); - - // site already exists (409) - String siteTitle = "my site 456"; - site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); - String siteId = sitesProxy.createSite(site, 201).getSiteId(); - sitesProxy.createSite(site, 409); - sitesProxy.removeSite(siteId); // cleanup - - sitesProxy.removeSite(GUID.generate(), false, 404); - } - - // -ve - cannot create site with same site id as an existing site (even if it is in the trashcan/archive) - { - String siteId = "aaa"; - String siteTitle = "AAA site"; - - Site site = new SiteImpl(null, siteId, null, siteTitle, null, SiteVisibility.PUBLIC.toString(), null, null); - - String siteNodeId = sitesProxy.createSite(site).getGuid(); - - // -ve - duplicate site id - sitesProxy.createSite(site, 409); - - sitesProxy.removeSite(siteId); - - // -ve - duplicate site id (even if site is in trashcan) - sitesProxy.createSite(site, 409); - - // now purge the site - sitesProxy.remove("deleted-nodes", siteNodeId, null, null, "Cannot purge site"); - - sitesProxy.createSite(site); - } - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); - - // -ve - cannot call POST method on /sites/siteId - try - { - sitesProxy.create("sites", "site", null, null, null, "Unable to POST to a site"); - fail(); - } catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // -ve - cannot call DELETE method on /sites - try - { - sitesProxy.remove("sites", null, null, null, "Unable to DELETE sites"); - fail(); - } catch (PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - - // Test Case cloud-1478 - // Test Case cloud-1479 - // user invited to network and user invited to site - // user invited to network and user not invited to site - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.SiteInformation; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Sites; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Site; +import org.alfresco.rest.api.tests.client.data.SiteImpl; +import org.alfresco.rest.api.tests.client.data.SiteRole; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +/** + * @author sglover + * @author janv + */ +public class TestSites extends EnterpriseTestApi +{ + private TestNetwork network1; + private String person1Id; + private String person2Id; + + private Site site1; + private Site site2; + private Site site3; + + @Before + public void setup() throws Exception + { + // Test: user is member of an account + this.network1 = getTestFixture().getRandomNetwork(); + + Iterator personIt = network1.getPersonIds().iterator(); + + this.person1Id = personIt.next(); + assertNotNull(person1Id); + + this.person2Id = personIt.next(); + assertNotNull(person2Id); + } + + @Test + public void testSites() throws Exception + { + Sites sitesProxy = publicApiClient.sites(); + + // create & get sites (as person 2) + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2Id)); + + String siteTitle = "site 1 " + System.currentTimeMillis(); + Site site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); + site1 = sitesProxy.createSite(site); + + Site ret = sitesProxy.getSite(site1.getSiteId()); + site1.expected(ret); + + siteTitle = "site 2 " + System.currentTimeMillis(); + site = new SiteImpl(siteTitle, SiteVisibility.PUBLIC.toString()); + site2 = sitesProxy.createSite(site); + + ret = sitesProxy.getSite(site2.getSiteId()); + site2.expected(ret); + + siteTitle = "site 3 " + System.currentTimeMillis(); + site = new SiteImpl(siteTitle, SiteVisibility.MODERATED.toString()); + site3 = sitesProxy.createSite(site); + + ret = sitesProxy.getSite(site3.getSiteId()); + site3.expected(ret); + } + + List expectedSites = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List sites = network1.getSites(person1Id); + return sites; + } + }, person1Id, network1.getId()); + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), expectedSites.size()); + ListResponse resp = sitesProxy.getSites(createParams(paging, null)); + checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + int skipCount = 2; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedSites.size(), expectedSites.size()); + ListResponse resp = sitesProxy.getSites(createParams(paging, null)); + checkList(expectedSites.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // test create and delete site + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + String siteTitle = "my site !*#$ 123"; + String siteDescription = "my site description"; + + SiteImpl site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); + site.setDescription(siteDescription); + + Site ret = sitesProxy.createSite(site); + String siteId = ret.getSiteId(); + + String expectedSiteId = "my-site-123"; + Site siteExp = new SiteImpl(null, expectedSiteId, ret.getGuid(), siteTitle, siteDescription, SiteVisibility.PRIVATE.toString(), null, SiteRole.SiteManager); + siteExp.expected(ret); + + ret = sitesProxy.getSite(siteId); + siteExp.expected(ret); + + sitesProxy.removeSite(siteId); + + // -ve test - ie. cannot get site after it has been deleted + sitesProxy.getSite(siteId, 404); + } + + // test create + permanent delete + create + { + + String siteId = "bbb"; + String siteTitle = "BBB site"; + + Site site = new SiteImpl(null, siteId, null, siteTitle, null, SiteVisibility.PUBLIC.toString(), null, null); + + sitesProxy.createSite(site); + + // permanent site delete (bypass trashcan/archive) + sitesProxy.removeSite(siteId, true, 204); + + sitesProxy.createSite(site); + } + + // test create using site id = "true" (RA-1101) + { + + String siteId = "true"; + String siteTitle = "string"; + String siteDescription = "string"; + + Site site = new SiteImpl(null, siteId, null, siteTitle, siteDescription, SiteVisibility.PUBLIC.toString(), null, null); + + sitesProxy.createSite(site); + } + + // -ve tests + { + // invalid auth + publicApiClient.setRequestContext(new RequestContext(network1.getId(), GUID.generate(), "password")); + sitesProxy.getSite(site1.getSiteId(), 401); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + // -ve - cannot view or delete a private site + sitesProxy.getSite(site1.getSiteId(), 404); + sitesProxy.removeSite(site1.getSiteId(), false, 404); + + // -ve - test cannot delete a public site (but can view it) + sitesProxy.getSite(site2.getSiteId(), 200); + sitesProxy.removeSite(site2.getSiteId(), false, 403); + + // -ve - try to get unknown site + sitesProxy.getSite(GUID.generate(), 404); + + SiteImpl site = new SiteImpl("my site 123", "invalidsitevisibility"); + sitesProxy.createSite(site, 400); + + site = new SiteImpl(null, "invalid site id", null, "my site 123", null, SiteVisibility.PRIVATE.toString(), null, null); + sitesProxy.createSite(site, 400); + + site = new SiteImpl(null, "invalidsiteid*", null, "my site 123", null, SiteVisibility.PRIVATE.toString(), null, null); + sitesProxy.createSite(site, 400); + + site = new SiteImpl(); + site.setSiteId(new String(new char[72]).replace('\0', 'a')); + site.setTitle(new String(new char[256]).replace('\0', 'a')); + site.setDescription(new String(new char[512]).replace('\0', 'a')); + site.setVisibility(SiteVisibility.PUBLIC.toString()); + sitesProxy.createSite(site, 201); + + // -ve - site id too long + site = new SiteImpl(); + site.setSiteId(new String(new char[73]).replace('\0', 'a')); + site.setTitle("ok"); + site.setDescription("ok"); + site.setVisibility(SiteVisibility.PUBLIC.toString()); + sitesProxy.createSite(site, 400); + + // -ve - site title too long + site = new SiteImpl(); + site.setSiteId("ok"); + site.setTitle(new String(new char[257]).replace('\0', 'a')); + site.setDescription("ok"); + site.setVisibility(SiteVisibility.PUBLIC.toString()); + sitesProxy.createSite(site, 400); + + // -ve - site description too long + site = new SiteImpl(); + site.setSiteId("ok"); + site.setTitle("ok"); + site.setDescription(new String(new char[513]).replace('\0', 'a')); + site.setVisibility(SiteVisibility.PUBLIC.toString()); + sitesProxy.createSite(site, 400); + + // site already exists (409) + String siteTitle = "my site 456"; + site = new SiteImpl(siteTitle, SiteVisibility.PRIVATE.toString()); + String siteId = sitesProxy.createSite(site, 201).getSiteId(); + sitesProxy.createSite(site, 409); + sitesProxy.removeSite(siteId); // cleanup + + sitesProxy.removeSite(GUID.generate(), false, 404); + } + + // -ve - cannot create site with same site id as an existing site (even if it is in the trashcan/archive) + { + String siteId = "aaa"; + String siteTitle = "AAA site"; + + Site site = new SiteImpl(null, siteId, null, siteTitle, null, SiteVisibility.PUBLIC.toString(), null, null); + + String siteNodeId = sitesProxy.createSite(site).getGuid(); + + // -ve - duplicate site id + sitesProxy.createSite(site, 409); + + sitesProxy.removeSite(siteId); + + // -ve - duplicate site id (even if site is in trashcan) + sitesProxy.createSite(site, 409); + + // now purge the site + sitesProxy.remove("deleted-nodes", siteNodeId, null, null, "Cannot purge site"); + + sitesProxy.createSite(site); + } + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1Id)); + + // -ve - cannot call POST method on /sites/siteId + try + { + sitesProxy.create("sites", "site", null, null, null, "Unable to POST to a site"); + fail(); + } catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // -ve - cannot call DELETE method on /sites + try + { + sitesProxy.remove("sites", null, null, null, "Unable to DELETE sites"); + fail(); + } catch (PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + + // Test Case cloud-1478 + // Test Case cloud-1479 + // user invited to network and user invited to site + // user invited to network and user not invited to site + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestTags.java b/source/test-java/org/alfresco/rest/api/tests/TestTags.java index 530ea9dcf5..0a16b321aa 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestTags.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestTags.java @@ -1,585 +1,585 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.RepoService.TestSite; -import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.Tags; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.site.SiteVisibility; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Test; - -public class TestTags extends EnterpriseTestApi -{ - @Test - public void testTags() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - assertTrue(networksIt.hasNext()); - final TestNetwork network1 = networksIt.next(); - assertTrue(networksIt.hasNext()); - final TestNetwork network2 = networksIt.next(); - - final List people = new ArrayList(3); - - // create users and some preferences - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - return null; - } - }, network2.getId()); - - final TestPerson person1 = people.get(0); - final TestPerson person2 = people.get(1); - final TestPerson person3 = people.get(2); - - final List nodes = new ArrayList(); - final List sites = new ArrayList(); - - // Create site - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestSite site = network1.createSite(SiteVisibility.PRIVATE); - sites.add(site); - - NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc", "Test Content"); - nodes.add(nodeRef); - - nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content 1"); - nodes.add(nodeRef); - - return null; - } - }, person1.getId(), network1.getId()); - - final NodeRef nodeRef1 = nodes.get(0); - final NodeRef nodeRef2 = nodes.get(1); - - Nodes nodesProxy = publicApiClient.nodes(); - Comments commentsProxy = publicApiClient.comments(); - Tags tagsProxy = publicApiClient.tags(); - - final List tags = new ArrayList(); - tags.add(new Tag("tag 1")); - tags.add(new Tag("tag 9")); - tags.add(new Tag("other tag 3")); - tags.add(new Tag("my tag 1")); - tags.add(new Tag("tag 5")); - - // try to add a tag to a comment - try - { - Comment comment = new Comment("Test Comment", "Test Comment"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); - Tag tag = new Tag("testTag"); - nodesProxy.createNodeTag(newComment.getId(), tag); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // try to add a tag to a tag - try - { - Tag tag = new Tag("testTag"); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Tag newTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); - nodesProxy.createNodeTag(newTag.getId(), tag); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-2221 - // Test Case cloud-2222 - // multi-byte characters, special characters, create and update tags - { - Tag[] multiByteTags = new Tag[] - { - new Tag("\u67e5\u770b\u5168\u90e8"), - new Tag("\u67e5\u770b\u5168\u91e8"), - new Tag("%^&%&$^√Ǭ£@") - }; - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - - // first, create tags - Map createdTags = new HashMap(); - for(Tag tag : multiByteTags) - { - Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); - createdTags.put(ret.getId(), ret); - } - - int skipCount = 0; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems); - ListResponse resp = nodesProxy.getNodeTags(nodeRef2.getId(), createParams(paging, null)); - List retTags = resp.getList(); - assertEquals(createdTags.size(), retTags.size()); - for(Tag tag : retTags) - { - String tagId = tag.getId(); - Tag expectedTag = createdTags.get(tagId); - expectedTag.expected(tag); - } - - // special characters and update tags -// { -// Tag[] specialCharacterTags = new Tag[] -// { -// new Tag("\u67e5\u770b\u5168\u90e8"), -// new Tag("\u67e5\u770b\u5168\u91e8") -// }; -// -// createdTags = new HashMap(); -// for(Tag tag : specialCharacterTags) -// { -// Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); -// createdTags.put(ret.getId(), ret); -// } -// -// -// Tag tag = new Tag("%^&%&$^£@"); -// Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); -// createdTags.put(ret.getId(), ret); -// } - - // update tags - - try - { - // update with an empty tag i.e. "" -> bad request - Tag tag = new Tag(""); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.createNodeTag(nodeRef2.getId(), tag); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - List tagUpdates = new ArrayList(createdTags.values()); - tagUpdates.get(0).setTag("\u4e00\u4e01\u4e02\u4e10"); - tagUpdates.get(1).setTag("\u4e00\u4e01\u4e12\u4e11"); - tagUpdates.get(2).setTag("\u4e00\u4e01\u4e12\u4e12"); - Map updatedTags = new HashMap(); - for(Tag tag : tagUpdates) - { - Tag ret = tagsProxy.update(tag); - assertNotNull(ret.getId()); - assertNotNull(ret.getTag()); -// tag.expected(ret); disabled because tag id changes - updatedTags.put(ret.getId(), ret); - } - - // get updated tags - List expectedNodeTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List tags = repoService.getTags(nodeRef2); - return tags; - } - }, person1.getId(), network1.getId()); - - skipCount = 0; - maxItems = tagUpdates.size(); - paging = getPaging(skipCount, maxItems, tagUpdates.size(), tagUpdates.size()); - resp = nodesProxy.getNodeTags(nodeRef2.getId(), createParams(paging, null)); - checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - List createdTags = new ArrayList(); - - // Test Case cloud-1975 - for(Tag tag : tags) - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Tag ret = nodesProxy.createNodeTag(nodeRef1.getId(), tag); - assertEquals(tag.getTag(), ret.getTag()); - assertNotNull(ret.getId()); - createdTags.add(ret); - } - - // update tag, empty string - try - { - Tag tag = new Tag(createdTags.get(0).getId(), ""); - tagsProxy.update(tag); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); - } - - // invalid node id - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.createNodeTag(GUID.generate(), tags.get(0)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1973 - // Test Case cloud-2208 - // Test Case cloud-2219 - // check that the tags are there in the node tags, test paging - List expectedNodeTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List tags = repoService.getTags(nodeRef1); - return tags; - } - }, person1.getId(), network1.getId()); - - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); - ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 2; - int maxItems = Integer.MAX_VALUE; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); - ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // invalid node - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); - ListResponse allTags = nodesProxy.getNodeTags("invalidNode", createParams(paging, null)); - checkList(expectedNodeTags.subList(skipCount, paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // user from another account - 403 - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - Paging expectedPaging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); - nodesProxy.getNodeTags(nodeRef1.getId(), createParams(expectedPaging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); - } - - // another user from the same account - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); - ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); - checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-1519 - // Test Case cloud-2206 - // Test Case cloud-2218 - // check that the tags are there in the network tags, test paging - // TODO for user from another network who is invited to this network - List expectedNetworkTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List tags = repoService.getTags(); - return tags; - } - }, person1.getId(), network1.getId()); - - { - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems, expectedNetworkTags.size(), null); - ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); - checkList(expectedNetworkTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); - } - - { - int skipCount = 2; - int maxItems = Integer.MAX_VALUE; - Paging paging = getPaging(skipCount, maxItems, expectedNetworkTags.size(), null); - ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); - checkList(expectedNetworkTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); - } - } - - { - // Try a create with the same tag value - Tag tag = tags.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.createNodeTag(nodeRef1.getId(), tag); - } - - try - { - // Invalid node id - Tag tag = tags.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.createNodeTag(GUID.generate(), tag); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // Test Case cloud-2183 - // update tags - { - // get a network tag - int skipCount = 0; - int maxItems = 2; - Paging paging = getPaging(skipCount, maxItems); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); - assertTrue(allTags.getList().size() > 0); - - // and update it - Tag tag = allTags.getList().get(0); - String newTagValue = GUID.generate(); - Tag newTag = new Tag(tag.getId(), newTagValue); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Tag ret = tagsProxy.update(newTag); - assertEquals(newTagValue, ret.getTag()); -// assertNotEquals(tag.getId, ret.getId()); // disabled due to CLOUD-628 - } - - // update invalid/unknown tag id - try - { - Tag unknownTag = new Tag(GUID.generate(), GUID.generate()); - tagsProxy.update(unknownTag); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - - // Test Case cloud-1972 - // Test Case cloud-1974 - // not allowed methods - { - List networkTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() - { - @Override - public List doWork() throws Exception - { - List tags = repoService.getTags(); - return tags; - } - }, person1.getId(), network1.getId()); - assertTrue(networkTags.size() > 0); - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.update("nodes", nodeRef1.getId(), "tags", null, null, "Unable to PUT node tags"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.remove("nodes", nodeRef1.getId(), "tags", null, "Unable to DELETE node tags"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.update("nodes", nodeRef1.getId(), "tags", tag.getId(), null, "Unable to PUT node tag"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.create("tags", null, null, null, tag.toJSON().toString(), "Unable to POST to tags"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.update("tags", null, null, null, tag.toJSON().toString(), "Unable to PUT tags"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.remove("tags", null, null, null, "Unable to DELETE tags"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.create("tags", tag.getId(), null, null, tag.toJSON().toString(), "Unable to POST to a tag"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.remove("tags", tag.getId(), null, null, "Unable to DELETE a tag"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - // delete node tag - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.removeNodeTag(nodeRef1.getId(), tag.getId()); - - // check that the tag is gone - ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(getPaging(0, Integer.MAX_VALUE), null)); - List nodeTags = resp.getList(); - assertTrue(!nodeTags.contains(tag)); - } - - try - { - Tag tag = networkTags.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - nodesProxy.getSingle("nodes", nodeRef1.getId(), "tags", tag.getId(), "Unable to GET node tag"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.RepoService.TestSite; +import org.alfresco.rest.api.tests.client.PublicApiClient.Comments; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Nodes; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.Tags; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Test; + +public class TestTags extends EnterpriseTestApi +{ + @Test + public void testTags() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + assertTrue(networksIt.hasNext()); + final TestNetwork network1 = networksIt.next(); + assertTrue(networksIt.hasNext()); + final TestNetwork network2 = networksIt.next(); + + final List people = new ArrayList(3); + + // create users and some preferences + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + return null; + } + }, network2.getId()); + + final TestPerson person1 = people.get(0); + final TestPerson person2 = people.get(1); + final TestPerson person3 = people.get(2); + + final List nodes = new ArrayList(); + final List sites = new ArrayList(); + + // Create site + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestSite site = network1.createSite(SiteVisibility.PRIVATE); + sites.add(site); + + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc", "Test Content"); + nodes.add(nodeRef); + + nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc 1", "Test Content 1"); + nodes.add(nodeRef); + + return null; + } + }, person1.getId(), network1.getId()); + + final NodeRef nodeRef1 = nodes.get(0); + final NodeRef nodeRef2 = nodes.get(1); + + Nodes nodesProxy = publicApiClient.nodes(); + Comments commentsProxy = publicApiClient.comments(); + Tags tagsProxy = publicApiClient.tags(); + + final List tags = new ArrayList(); + tags.add(new Tag("tag 1")); + tags.add(new Tag("tag 9")); + tags.add(new Tag("other tag 3")); + tags.add(new Tag("my tag 1")); + tags.add(new Tag("tag 5")); + + // try to add a tag to a comment + try + { + Comment comment = new Comment("Test Comment", "Test Comment"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Comment newComment = commentsProxy.createNodeComment(nodeRef1.getId(), comment); + Tag tag = new Tag("testTag"); + nodesProxy.createNodeTag(newComment.getId(), tag); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // try to add a tag to a tag + try + { + Tag tag = new Tag("testTag"); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Tag newTag = nodesProxy.createNodeTag(nodeRef1.getId(), tag); + nodesProxy.createNodeTag(newTag.getId(), tag); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-2221 + // Test Case cloud-2222 + // multi-byte characters, special characters, create and update tags + { + Tag[] multiByteTags = new Tag[] + { + new Tag("\u67e5\u770b\u5168\u90e8"), + new Tag("\u67e5\u770b\u5168\u91e8"), + new Tag("%^&%&$^√Ǭ£@") + }; + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + + // first, create tags + Map createdTags = new HashMap(); + for(Tag tag : multiByteTags) + { + Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); + createdTags.put(ret.getId(), ret); + } + + int skipCount = 0; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems); + ListResponse resp = nodesProxy.getNodeTags(nodeRef2.getId(), createParams(paging, null)); + List retTags = resp.getList(); + assertEquals(createdTags.size(), retTags.size()); + for(Tag tag : retTags) + { + String tagId = tag.getId(); + Tag expectedTag = createdTags.get(tagId); + expectedTag.expected(tag); + } + + // special characters and update tags +// { +// Tag[] specialCharacterTags = new Tag[] +// { +// new Tag("\u67e5\u770b\u5168\u90e8"), +// new Tag("\u67e5\u770b\u5168\u91e8") +// }; +// +// createdTags = new HashMap(); +// for(Tag tag : specialCharacterTags) +// { +// Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); +// createdTags.put(ret.getId(), ret); +// } +// +// +// Tag tag = new Tag("%^&%&$^£@"); +// Tag ret = nodesProxy.createNodeTag(nodeRef2.getId(), tag); +// createdTags.put(ret.getId(), ret); +// } + + // update tags + + try + { + // update with an empty tag i.e. "" -> bad request + Tag tag = new Tag(""); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.createNodeTag(nodeRef2.getId(), tag); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + List tagUpdates = new ArrayList(createdTags.values()); + tagUpdates.get(0).setTag("\u4e00\u4e01\u4e02\u4e10"); + tagUpdates.get(1).setTag("\u4e00\u4e01\u4e12\u4e11"); + tagUpdates.get(2).setTag("\u4e00\u4e01\u4e12\u4e12"); + Map updatedTags = new HashMap(); + for(Tag tag : tagUpdates) + { + Tag ret = tagsProxy.update(tag); + assertNotNull(ret.getId()); + assertNotNull(ret.getTag()); +// tag.expected(ret); disabled because tag id changes + updatedTags.put(ret.getId(), ret); + } + + // get updated tags + List expectedNodeTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List tags = repoService.getTags(nodeRef2); + return tags; + } + }, person1.getId(), network1.getId()); + + skipCount = 0; + maxItems = tagUpdates.size(); + paging = getPaging(skipCount, maxItems, tagUpdates.size(), tagUpdates.size()); + resp = nodesProxy.getNodeTags(nodeRef2.getId(), createParams(paging, null)); + checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + List createdTags = new ArrayList(); + + // Test Case cloud-1975 + for(Tag tag : tags) + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Tag ret = nodesProxy.createNodeTag(nodeRef1.getId(), tag); + assertEquals(tag.getTag(), ret.getTag()); + assertNotNull(ret.getId()); + createdTags.add(ret); + } + + // update tag, empty string + try + { + Tag tag = new Tag(createdTags.get(0).getId(), ""); + tagsProxy.update(tag); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getHttpResponse().getStatusCode()); + } + + // invalid node id + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.createNodeTag(GUID.generate(), tags.get(0)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1973 + // Test Case cloud-2208 + // Test Case cloud-2219 + // check that the tags are there in the node tags, test paging + List expectedNodeTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List tags = repoService.getTags(nodeRef1); + return tags; + } + }, person1.getId(), network1.getId()); + + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); + ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 2; + int maxItems = Integer.MAX_VALUE; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); + ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // invalid node + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); + ListResponse allTags = nodesProxy.getNodeTags("invalidNode", createParams(paging, null)); + checkList(expectedNodeTags.subList(skipCount, paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // user from another account - 403 + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + Paging expectedPaging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); + nodesProxy.getNodeTags(nodeRef1.getId(), createParams(expectedPaging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode()); + } + + // another user from the same account + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedNodeTags.size(), expectedNodeTags.size()); + ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(paging, null)); + checkList(expectedNodeTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-1519 + // Test Case cloud-2206 + // Test Case cloud-2218 + // check that the tags are there in the network tags, test paging + // TODO for user from another network who is invited to this network + List expectedNetworkTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List tags = repoService.getTags(); + return tags; + } + }, person1.getId(), network1.getId()); + + { + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems, expectedNetworkTags.size(), null); + ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); + checkList(expectedNetworkTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); + } + + { + int skipCount = 2; + int maxItems = Integer.MAX_VALUE; + Paging paging = getPaging(skipCount, maxItems, expectedNetworkTags.size(), null); + ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); + checkList(expectedNetworkTags.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), allTags); + } + } + + { + // Try a create with the same tag value + Tag tag = tags.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.createNodeTag(nodeRef1.getId(), tag); + } + + try + { + // Invalid node id + Tag tag = tags.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.createNodeTag(GUID.generate(), tag); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // Test Case cloud-2183 + // update tags + { + // get a network tag + int skipCount = 0; + int maxItems = 2; + Paging paging = getPaging(skipCount, maxItems); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + ListResponse allTags = tagsProxy.getTags(createParams(paging, null)); + assertTrue(allTags.getList().size() > 0); + + // and update it + Tag tag = allTags.getList().get(0); + String newTagValue = GUID.generate(); + Tag newTag = new Tag(tag.getId(), newTagValue); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Tag ret = tagsProxy.update(newTag); + assertEquals(newTagValue, ret.getTag()); +// assertNotEquals(tag.getId, ret.getId()); // disabled due to CLOUD-628 + } + + // update invalid/unknown tag id + try + { + Tag unknownTag = new Tag(GUID.generate(), GUID.generate()); + tagsProxy.update(unknownTag); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + + // Test Case cloud-1972 + // Test Case cloud-1974 + // not allowed methods + { + List networkTags = TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public List doWork() throws Exception + { + List tags = repoService.getTags(); + return tags; + } + }, person1.getId(), network1.getId()); + assertTrue(networkTags.size() > 0); + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.update("nodes", nodeRef1.getId(), "tags", null, null, "Unable to PUT node tags"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.remove("nodes", nodeRef1.getId(), "tags", null, "Unable to DELETE node tags"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.update("nodes", nodeRef1.getId(), "tags", tag.getId(), null, "Unable to PUT node tag"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.create("tags", null, null, null, tag.toJSON().toString(), "Unable to POST to tags"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.update("tags", null, null, null, tag.toJSON().toString(), "Unable to PUT tags"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.remove("tags", null, null, null, "Unable to DELETE tags"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.create("tags", tag.getId(), null, null, tag.toJSON().toString(), "Unable to POST to a tag"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.remove("tags", tag.getId(), null, null, "Unable to DELETE a tag"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + // delete node tag + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.removeNodeTag(nodeRef1.getId(), tag.getId()); + + // check that the tag is gone + ListResponse resp = nodesProxy.getNodeTags(nodeRef1.getId(), createParams(getPaging(0, Integer.MAX_VALUE), null)); + List nodeTags = resp.getList(); + assertTrue(!nodeTags.contains(tag)); + } + + try + { + Tag tag = networkTags.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + nodesProxy.getSingle("nodes", nodeRef1.getId(), "tags", tag.getId(), "Unable to GET node tag"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/TestUserPreferences.java b/source/test-java/org/alfresco/rest/api/tests/TestUserPreferences.java index cdbd357595..a5f73bf574 100644 --- a/source/test-java/org/alfresco/rest/api/tests/TestUserPreferences.java +++ b/source/test-java/org/alfresco/rest/api/tests/TestUserPreferences.java @@ -1,301 +1,301 @@ -package org.alfresco.rest.api.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; -import org.alfresco.rest.api.tests.RepoService.TestNetwork; -import org.alfresco.rest.api.tests.RepoService.TestPerson; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.alfresco.rest.api.tests.client.PublicApiClient.People; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.RequestContext; -import org.alfresco.rest.api.tests.client.data.Preference; -import org.alfresco.util.GUID; -import org.apache.commons.httpclient.HttpStatus; -import org.junit.Test; - -public class TestUserPreferences extends EnterpriseTestApi -{ - @Test - public void testUserPreferences() throws Exception - { - Iterator networksIt = getTestFixture().getNetworksIt(); - assertTrue(networksIt.hasNext()); - final TestNetwork network1 = networksIt.next(); - assertTrue(networksIt.hasNext()); - final TestNetwork network2 = networksIt.next(); - - final List people = new ArrayList(3); - - // create users and some preferences - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network1.createUser(); - people.add(person); - person = network1.createUser(); - people.add(person); - return null; - } - }, network1.getId()); - - TenantUtil.runAsSystemTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - TestPerson person = network2.createUser(); - people.add(person); - return null; - } - }, network2.getId()); - - final TestPerson person1 = people.get(0); - final TestPerson person2 = people.get(1); - final TestPerson person3 = people.get(2); - - final List expectedPreferences = new ArrayList(); - expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference2", String.valueOf(true))); - expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference1", String.valueOf(true))); - expectedPreferences.add(new Preference("org.alfresco.share.documentList.sortAscending", String.valueOf(true))); - expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference3", String.valueOf(true))); - - TenantUtil.runAsUserTenant(new TenantRunAsWork() - { - @Override - public Void doWork() throws Exception - { - for(Preference pref : expectedPreferences) - { - // TODO add preferences thru api - repoService.addPreference(person1.getId(), pref.getId(), pref.getValue()); - } - - return null; - } - }, person1.getId(), network1.getId()); - - Collections.sort(expectedPreferences); - - People peopleProxy = publicApiClient.people(); - - // GET preferences - // Test case: cloud-1492 - - // unknown user - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - peopleProxy.getPreferences(GUID.generate(), createParams(paging, null)); - - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // test paging - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); - checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - { - int skipCount = 2; - int maxItems = 10; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); - checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // "-me-" user - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - ListResponse resp = peopleProxy.getPreferences(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); - checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - } - - // invalid user - 404 - try - { - int skipCount = 2; - int maxItems = 10; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - peopleProxy.getPreferences("invalid.user", createParams(paging, null)); - fail(""); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // user from another account - 401 - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); -// ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); -// checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); - peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(e.getHttpResponse().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); - } - - // another user from the same account - 403 - try - { - int skipCount = 0; - int maxItems = 2; - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); - peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); - } - - // get a single preference - // Test Case: cloud-1493 - - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - Preference pref = expectedPreferences.get(0); - Preference ret = peopleProxy.getPreference(person1.getId(), pref.getId()); - pref.expected(ret); - } - - // unknown person id - try - { - Preference pref = expectedPreferences.get(0); - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); - peopleProxy.getPreference(GUID.generate(), pref.getId()); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // unknown preference id - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.getPreference(person1.getId(), GUID.generate()); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); - } - - // Invalid methods - // Test case: cloud-1968 - try - { - Preference pref = expectedPreferences.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.create("people", person1.getId(), "preferences", pref.getId(), pref.toJSON().toString(), "Unable to POST to a preference"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Preference pref = expectedPreferences.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.update("people", person1.getId(), "preferences", pref.getId(), pref.toJSON().toString(), "Unable to PUT a preference"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Preference pref = expectedPreferences.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.remove("people", person1.getId(), "preferences", pref.getId(), "Unable to DELETE a preference"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Preference pref = expectedPreferences.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.create("people", person1.getId(), "preferences", null, pref.toJSON().toString(), "Unable to POST to preferences"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - Preference pref = expectedPreferences.get(0); - - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.update("people", person1.getId(), "preferences", null, pref.toJSON().toString(), "Unable to PUT preferences"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - - try - { - publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); - peopleProxy.remove("people", person1.getId(), "preferences", null, "Unable to DELETE preferences"); - fail(); - } - catch(PublicApiException e) - { - assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); - } - } -} +package org.alfresco.rest.api.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.rest.api.tests.RepoService.TestNetwork; +import org.alfresco.rest.api.tests.RepoService.TestPerson; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiClient.People; +import org.alfresco.rest.api.tests.client.PublicApiException; +import org.alfresco.rest.api.tests.client.RequestContext; +import org.alfresco.rest.api.tests.client.data.Preference; +import org.alfresco.util.GUID; +import org.apache.commons.httpclient.HttpStatus; +import org.junit.Test; + +public class TestUserPreferences extends EnterpriseTestApi +{ + @Test + public void testUserPreferences() throws Exception + { + Iterator networksIt = getTestFixture().getNetworksIt(); + assertTrue(networksIt.hasNext()); + final TestNetwork network1 = networksIt.next(); + assertTrue(networksIt.hasNext()); + final TestNetwork network2 = networksIt.next(); + + final List people = new ArrayList(3); + + // create users and some preferences + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network1.createUser(); + people.add(person); + person = network1.createUser(); + people.add(person); + return null; + } + }, network1.getId()); + + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + TestPerson person = network2.createUser(); + people.add(person); + return null; + } + }, network2.getId()); + + final TestPerson person1 = people.get(0); + final TestPerson person2 = people.get(1); + final TestPerson person3 = people.get(2); + + final List expectedPreferences = new ArrayList(); + expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference2", String.valueOf(true))); + expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference1", String.valueOf(true))); + expectedPreferences.add(new Preference("org.alfresco.share.documentList.sortAscending", String.valueOf(true))); + expectedPreferences.add(new Preference("org.alfresco.share.documentList.testPreference3", String.valueOf(true))); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + for(Preference pref : expectedPreferences) + { + // TODO add preferences thru api + repoService.addPreference(person1.getId(), pref.getId(), pref.getValue()); + } + + return null; + } + }, person1.getId(), network1.getId()); + + Collections.sort(expectedPreferences); + + People peopleProxy = publicApiClient.people(); + + // GET preferences + // Test case: cloud-1492 + + // unknown user + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + peopleProxy.getPreferences(GUID.generate(), createParams(paging, null)); + + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // test paging + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); + checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + { + int skipCount = 2; + int maxItems = 10; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); + checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // "-me-" user + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + ListResponse resp = peopleProxy.getPreferences(org.alfresco.rest.api.People.DEFAULT_USER, createParams(paging, null)); + checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + } + + // invalid user - 404 + try + { + int skipCount = 2; + int maxItems = 10; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + peopleProxy.getPreferences("invalid.user", createParams(paging, null)); + fail(""); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // user from another account - 401 + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person3.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); +// ListResponse resp = peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); +// checkList(expectedPreferences.subList(skipCount, skipCount + paging.getExpectedPaging().getCount()), paging.getExpectedPaging(), resp); + peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(e.getHttpResponse().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); + } + + // another user from the same account - 403 + try + { + int skipCount = 0; + int maxItems = 2; + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + Paging paging = getPaging(skipCount, maxItems, expectedPreferences.size(), expectedPreferences.size()); + peopleProxy.getPreferences(person1.getId(), createParams(paging, null)); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_FORBIDDEN, e.getHttpResponse().getStatusCode()); + } + + // get a single preference + // Test Case: cloud-1493 + + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + Preference pref = expectedPreferences.get(0); + Preference ret = peopleProxy.getPreference(person1.getId(), pref.getId()); + pref.expected(ret); + } + + // unknown person id + try + { + Preference pref = expectedPreferences.get(0); + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person2.getId())); + peopleProxy.getPreference(GUID.generate(), pref.getId()); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // unknown preference id + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.getPreference(person1.getId(), GUID.generate()); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getHttpResponse().getStatusCode()); + } + + // Invalid methods + // Test case: cloud-1968 + try + { + Preference pref = expectedPreferences.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.create("people", person1.getId(), "preferences", pref.getId(), pref.toJSON().toString(), "Unable to POST to a preference"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Preference pref = expectedPreferences.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.update("people", person1.getId(), "preferences", pref.getId(), pref.toJSON().toString(), "Unable to PUT a preference"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Preference pref = expectedPreferences.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.remove("people", person1.getId(), "preferences", pref.getId(), "Unable to DELETE a preference"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Preference pref = expectedPreferences.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.create("people", person1.getId(), "preferences", null, pref.toJSON().toString(), "Unable to POST to preferences"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + Preference pref = expectedPreferences.get(0); + + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.update("people", person1.getId(), "preferences", null, pref.toJSON().toString(), "Unable to PUT preferences"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + + try + { + publicApiClient.setRequestContext(new RequestContext(network1.getId(), person1.getId())); + peopleProxy.remove("people", person1.getId(), "preferences", null, "Unable to DELETE preferences"); + fail(); + } + catch(PublicApiException e) + { + assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, e.getHttpResponse().getStatusCode()); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/AbstractHttp.java b/source/test-java/org/alfresco/rest/api/tests/client/AbstractHttp.java index 6c5e61a640..5d39ce20ab 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/AbstractHttp.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/AbstractHttp.java @@ -1,144 +1,144 @@ -package org.alfresco.rest.api.tests.client; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; - -import org.apache.commons.httpclient.HttpMethod; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -public class AbstractHttp -{ - public static final String JSON_DATA = "data"; - - /** - * Extract the "data" JSON-object from the method's response. - * @param method the method containing the response - * @return the "data" object. Returns null if response is not JSON or no data-object - * is present. - */ - public JSONObject getDataFromResponse(HttpMethod method) - { - JSONObject result = null; - Object object = getObjectFromResponse(method); - - // Extract object for "data" property - object = ((JSONObject) object).get(JSON_DATA); - if(object instanceof JSONObject) - { - result = (JSONObject) object; - } - return result; - } - - /** - * Extract the "data" JSON-array from the method's response. - * @param method the method containing the response - * @return the "data" object. Returns null if response is not JSON or no data-object - * is present. - */ - public JSONArray getDataArrayFromResponse(HttpMethod method) - { - JSONArray result = null; - Object object = getObjectFromResponse(method); - if(object != null) - { - // Extract object for "data" property - object = ((JSONObject) object).get(JSON_DATA); - if(object instanceof JSONArray) - { - result = (JSONArray) object; - } - } - return result; - } - - /** - * Extract JSON-object from the method's response. - * @param method the method containing the response - * @return the json object. Returns null if response is not JSON or no data-object - * is present. - */ - public JSONObject getObjectFromResponse(HttpMethod method) - { - JSONObject result = null; - - try - { - InputStream response = method.getResponseBodyAsStream(); - if(response != null) - { - Object object = new JSONParser().parse(new InputStreamReader(response, Charset.forName("UTF-8"))); - if(object instanceof JSONObject) - { - return (JSONObject) object; - } - } - } - catch (IOException error) - { - // Ignore errors, returning null - } - catch (ParseException error) - { - // Ignore errors, returning null - } - - return result; - } - - /** - * Gets a string-value from the given JSON-object for the given key. - * @param json the json object - * @param key key pointing to the value - * @param defaultValue if value is not set or if value is not of type "String", this value is returned - */ - public String getString(JSONObject json, String key, String defaultValue) - { - String result = defaultValue; - - if(json != null) - { - Object value = json.get(key); - if(value instanceof String) - { - result = (String) value; - } - } - return result; - } - - /** - * @param json JSON to extract array from - * @param key key under which array is present on JSON - * @return the {@link JSONArray}. Returns null, if the value is null or not an array. - */ - public JSONArray getArray(JSONObject json, String key) - { - Object object = json.get(key); - if(object instanceof JSONArray) - { - return (JSONArray) object; - } - return null; - } - - /** - * @param json JSON to extract object from - * @param key key under which object is present on JSON - * @return the {@link JSONObject}. Returns null, if the value is null or not an object. - */ - public JSONObject getObject(JSONObject json, String key) - { - Object object = json.get(key); - if(object instanceof JSONArray) - { - return (JSONObject) object; - } - return null; - } -} +package org.alfresco.rest.api.tests.client; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +import org.apache.commons.httpclient.HttpMethod; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +public class AbstractHttp +{ + public static final String JSON_DATA = "data"; + + /** + * Extract the "data" JSON-object from the method's response. + * @param method the method containing the response + * @return the "data" object. Returns null if response is not JSON or no data-object + * is present. + */ + public JSONObject getDataFromResponse(HttpMethod method) + { + JSONObject result = null; + Object object = getObjectFromResponse(method); + + // Extract object for "data" property + object = ((JSONObject) object).get(JSON_DATA); + if(object instanceof JSONObject) + { + result = (JSONObject) object; + } + return result; + } + + /** + * Extract the "data" JSON-array from the method's response. + * @param method the method containing the response + * @return the "data" object. Returns null if response is not JSON or no data-object + * is present. + */ + public JSONArray getDataArrayFromResponse(HttpMethod method) + { + JSONArray result = null; + Object object = getObjectFromResponse(method); + if(object != null) + { + // Extract object for "data" property + object = ((JSONObject) object).get(JSON_DATA); + if(object instanceof JSONArray) + { + result = (JSONArray) object; + } + } + return result; + } + + /** + * Extract JSON-object from the method's response. + * @param method the method containing the response + * @return the json object. Returns null if response is not JSON or no data-object + * is present. + */ + public JSONObject getObjectFromResponse(HttpMethod method) + { + JSONObject result = null; + + try + { + InputStream response = method.getResponseBodyAsStream(); + if(response != null) + { + Object object = new JSONParser().parse(new InputStreamReader(response, Charset.forName("UTF-8"))); + if(object instanceof JSONObject) + { + return (JSONObject) object; + } + } + } + catch (IOException error) + { + // Ignore errors, returning null + } + catch (ParseException error) + { + // Ignore errors, returning null + } + + return result; + } + + /** + * Gets a string-value from the given JSON-object for the given key. + * @param json the json object + * @param key key pointing to the value + * @param defaultValue if value is not set or if value is not of type "String", this value is returned + */ + public String getString(JSONObject json, String key, String defaultValue) + { + String result = defaultValue; + + if(json != null) + { + Object value = json.get(key); + if(value instanceof String) + { + result = (String) value; + } + } + return result; + } + + /** + * @param json JSON to extract array from + * @param key key under which array is present on JSON + * @return the {@link JSONArray}. Returns null, if the value is null or not an array. + */ + public JSONArray getArray(JSONObject json, String key) + { + Object object = json.get(key); + if(object instanceof JSONArray) + { + return (JSONArray) object; + } + return null; + } + + /** + * @param json JSON to extract object from + * @param key key under which object is present on JSON + * @return the {@link JSONObject}. Returns null, if the value is null or not an object. + */ + public JSONObject getObject(JSONObject json, String key) + { + Object object = json.get(key); + if(object instanceof JSONArray) + { + return (JSONObject) object; + } + return null; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/AuthenticatedHttp.java b/source/test-java/org/alfresco/rest/api/tests/client/AuthenticatedHttp.java index 2c3bec1d0d..3522da53ae 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/AuthenticatedHttp.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/AuthenticatedHttp.java @@ -1,394 +1,394 @@ -package org.alfresco.rest.api.tests.client; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpState; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.URIException; -import org.apache.commons.httpclient.UsernamePasswordCredentials; -import org.apache.commons.httpclient.auth.AuthScope; -import org.apache.commons.httpclient.methods.EntityEnclosingMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.json.simple.JSONObject; - -public class AuthenticatedHttp extends AbstractHttp -{ - private static final String JSON_TICKET_KEY = "ticket"; - private static final String TICKET_CREDENTIAL_PLACEHOLDER = "ROLE_TICKET"; - - /** - * URL for obtaining an alfresco-ticket - */ - private String LOGIN_URL = "/alfresco/service/api/login"; - - private String LOGIN_JSON_USERNAME = "username"; - private String LOGIN_JSON_PASSWORD = "password"; - - public static final String MIME_TYPE_JSON = "application/json"; - public static final String HEADER_ACCEPT = "Accept"; - - private HttpClientProvider httpProvider; - private AuthenticationDetailsProvider authDetailProvider; - private boolean ticketBasedAuthentication; - - /** - * @param httpProvider provider class for http-client - * @param authenticationDetailsProvider provider for authentication details - */ - public AuthenticatedHttp(HttpClientProvider httpProvider, AuthenticationDetailsProvider authenticationDetailsProvider) - { - this.httpProvider = httpProvider; - this.authDetailProvider = authenticationDetailsProvider; - this.ticketBasedAuthentication = false; - } - - /** - * Enable ticket-based authentication. If set to false, BASIC Authentication will - * be used instead. Defaults to false. - * - * @param ticketBasedAuthentication whether or not to use ticket for authentication - */ - public void setTicketBasedAuthentication(boolean ticketBasedAuthentication) - { - this.ticketBasedAuthentication = ticketBasedAuthentication; - } - - /** - * @return the {@link HttpClientProvider} used by this class. - */ - public HttpClientProvider getHttpProvider() - { - return this.httpProvider; - } - - /** - * @return the {@link AuthenticationDetailsProvider} used by this class. - */ - public AuthenticationDetailsProvider getAuthDetailProvider() - { - return this.authDetailProvider; - } - - /** - * Execute the given method, authenticated as the given user. Automatically closes the - * response-stream to release the connection. If response should be extracted, this should be done - * in the {@link HttpRequestCallback}. - * - * @param method method to execute - * @param userName name of user to authenticate - * @param callback called after http-call is executed. When callback returns, the - * response stream is closed, so all respose-related operations should be done in the callback. Can be null. - * @return result returned by the callback or status-code if no callback is given. - */ - public T executeHttpMethodAuthenticated(HttpMethod method, String userName, HttpRequestCallback callback) - { - if(ticketBasedAuthentication) - { - return executeWithTicketAuthentication(method, userName, authDetailProvider.getPasswordForUser(userName), callback); - } - else - { - return executeWithBasicAuthentication(method, userName, authDetailProvider.getPasswordForUser(userName), callback); - } - } - - public T executeHttpMethodAuthenticated(HttpMethod method, String userName, String password, HttpRequestCallback callback) - { - if(ticketBasedAuthentication) - { - return executeWithTicketAuthentication(method, userName, password, callback); - } - else - { - return executeWithBasicAuthentication(method, userName, password, callback); - } - } - - /** - * Execute the given method, authenticated as the Alfresco Administrator. - * - * @param method method to execute - * @param callback called after http-call is executed. When callback returns, the - * response stream is closed, so all respose-related operations should be done in the callback. Can be null. - * @return result returned by the callback or null if no callback is given. - */ - public T executeHttpMethodAsAdmin(HttpMethod method, HttpRequestCallback callback) - { - if(ticketBasedAuthentication) - { - return executeWithTicketAuthentication(method, authDetailProvider.getAdminUserName(), authDetailProvider.getAdminPassword(), callback); - } - else - { - return executeWithBasicAuthentication(method, authDetailProvider.getAdminUserName(), authDetailProvider.getAdminPassword(), callback); - } - } - - /** - * Execute the given method, authenticated as the given user using Basic Authentication. - * @param method method to execute - * @param userName name of user to authenticate (note: if null then attempts to run with no authentication - eq. Quick/Shared Link test) - * @param callback called after http-call is executed. When callback returns, the - * response stream is closed, so all respose-related operations should be done in the callback. Can be null. - * @return result returned by the callback or null if no callback is given. - */ - private T executeWithBasicAuthentication(HttpMethod method, String userName, String password, HttpRequestCallback callback) - { - try - { - HttpState state = new HttpState(); - - if (userName != null) - { - state.setCredentials( - new AuthScope(null, AuthScope.ANY_PORT), - new UsernamePasswordCredentials(userName, password)); - } - - httpProvider.getHttpClient().executeMethod(null, method, state); - - if(callback != null) - { - return callback.onCallSuccess(method); - } - - // No callback used, return null - return null; - } - catch(Throwable t) - { - boolean handled = false; - - // Delegate to callback to handle error. If not available, throw exception - if(callback != null) - { - handled = callback.onError(method, t); - } - - if(!handled) - { - throw new RuntimeException("Error while executing HTTP-call (" + method.getPath() +")", t); - } - - return null; - } - finally - { - method.releaseConnection(); - } - } - - /** - * Execute the given method, authenticated as the given user using ticket-based authentication. - * @param method method to execute - * @param userName name of user to authenticate - * @return status-code resulting from the request - */ - private T executeWithTicketAuthentication(HttpMethod method, String userName, String password, HttpRequestCallback callback) - { - String ticket = authDetailProvider.getTicketForUser(userName); - if(ticket == null) - { - ticket = fetchLoginTicket(userName, password); - authDetailProvider.updateTicketForUser(userName, ticket); - } - - - - try - { - HttpState state = applyTicketToMethod(method, ticket); - - // Try executing the method - int result = httpProvider.getHttpClient().executeMethod(null, method, state); - - if(result == HttpStatus.SC_UNAUTHORIZED || result == HttpStatus.SC_FORBIDDEN) - { - method.releaseConnection(); - if(!method.validate()) - { - throw new RuntimeException("Ticket re-authentication failed for user " + userName + " (HTTPMethod not reusable)"); - } - // Fetch new ticket, store and apply to HttpMethod - ticket = fetchLoginTicket(userName, userName); - authDetailProvider.updateTicketForUser(userName, ticket); - - state = applyTicketToMethod(method, ticket); - - // Run method agian with new ticket - result = httpProvider.getHttpClient().executeMethod(null, method, state); - } - - if(callback != null) - { - return callback.onCallSuccess(method); - } - - return null; - } - catch(Throwable t) - { - boolean handled = false; - // Delegate to callback to handle error. If not available, throw exception - if(callback != null) - { - handled = callback.onError(method, t); - } - - if(!handled) - { - throw new RuntimeException("Error while executing HTTP-call (" + method.getPath() +")", t); - } - return null; - - } - finally - { - method.releaseConnection(); - } - - } - - /** - * Add the ticket to the method. In case of {@link EntityEnclosingMethod}s (which don't - * support Query-parameters), the ticket is added as Username in BASIC Authentication, - * this is a supported way of passing in ticket into Alfresco. - * - * @param method method to apply - * @param ticket ticket to apply - * - * @return a {@link HttpState} object to use. Null, if no specific state should be used. - */ - private HttpState applyTicketToMethod(HttpMethod method, String ticket) throws URIException - { - // POST and PUT methods don't support Query-params, use Basic Authentication to pass - // in the ticket (ROLE_TICKET) for all methods. - HttpState state = new HttpState(); - state.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(TICKET_CREDENTIAL_PLACEHOLDER, ticket)); - return state; - - } - - /** - * Adds the JSON as request-body the the method and sets the correct - * content-type. - * @param method EntityEnclosingMethod - * @param object JSONObject - */ - private void populateRequestBody(EntityEnclosingMethod method, JSONObject object) - { - try - { - method.setRequestEntity(new StringRequestEntity(object.toJSONString(), MIME_TYPE_JSON, "UTF-8")); - } - catch (UnsupportedEncodingException error) - { - // This will never happen! - throw new RuntimeException("All hell broke loose, a JVM that doesn't have UTF-8 encoding..."); - } - } - - /** - * Perform the login-call to obtain a ticket. - * - * @param userName user to log in - * @return ticket to use for authentication. - * @throws RuntimeException when no ticket can be obtained for the user. - */ - @SuppressWarnings("unchecked") - private String fetchLoginTicket(String userName, String password) - { - String url = httpProvider.getFullAlfrescoUrlForPath(LOGIN_URL); - PostMethod loginMethod = null; - try - { - loginMethod = new PostMethod(url); - loginMethod.setRequestHeader(HEADER_ACCEPT, MIME_TYPE_JSON); - - // Populate resuest body - JSONObject requestBody = new JSONObject(); - requestBody.put(LOGIN_JSON_USERNAME, userName); - requestBody.put(LOGIN_JSON_PASSWORD, password); - - populateRequestBody(loginMethod, requestBody); - - HttpClient client = httpProvider.getHttpClient(); - - // Since no authentication info is available yet, no need to use a - // custom HostConfiguration for the login-call - client.executeMethod(loginMethod); - - if(loginMethod.getStatusCode() == HttpStatus.SC_OK) - { - // Extract the ticket - JSONObject data = getDataFromResponse(loginMethod); - if(data == null) - { - throw new RuntimeException("Failed to login to Alfresco with user " + userName + - " (No JSON-data found in response)"); - } - - // Extract the actual ticket - String ticket = getString(data, JSON_TICKET_KEY, null); - if(ticket == null) - { - throw new RuntimeException("Failed to login to Alfresco with user " + userName + - " (No ticket found in JSON-response)"); - } - return ticket; - } - else - { - // Unable to login - throw new RuntimeException("Failed to login to Alfresco with user " + userName + - " (" + loginMethod.getStatusCode() + loginMethod.getStatusLine().getReasonPhrase() + ")"); - } - } - catch (IOException ioe) - { - // Something went wrong when sending request - throw new RuntimeException("Failed to login to Alfresco with user " + userName, ioe); - } - finally - { - if(loginMethod != null) - { - try - { - loginMethod.releaseConnection(); - } - catch(Throwable t) - { - // Ignore this to prevent swallowing potential original exception - } - } - } - } - - /** - * Callback used when executing HTTP-request. After this has been called, - * the response-stream is closed automatically. - * - * @author Frederik Heremans - */ - public interface HttpRequestCallback - { - /** - * Called when call was successful. - * @param method the method executed which can be used to extract response from. - * @return any result extracted from the response body. - */ - T onCallSuccess(HttpMethod method) throws Exception; - /** - * Called when an error occurs when sending the request. - * @param method the method executed - * @param t optional exception that caused the error - * @return true, if error is handled. False, if an exception should be thrown. - */ - boolean onError(HttpMethod method, Throwable t); - } -} +package org.alfresco.rest.api.tests.client; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.URIException; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.EntityEnclosingMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.json.simple.JSONObject; + +public class AuthenticatedHttp extends AbstractHttp +{ + private static final String JSON_TICKET_KEY = "ticket"; + private static final String TICKET_CREDENTIAL_PLACEHOLDER = "ROLE_TICKET"; + + /** + * URL for obtaining an alfresco-ticket + */ + private String LOGIN_URL = "/alfresco/service/api/login"; + + private String LOGIN_JSON_USERNAME = "username"; + private String LOGIN_JSON_PASSWORD = "password"; + + public static final String MIME_TYPE_JSON = "application/json"; + public static final String HEADER_ACCEPT = "Accept"; + + private HttpClientProvider httpProvider; + private AuthenticationDetailsProvider authDetailProvider; + private boolean ticketBasedAuthentication; + + /** + * @param httpProvider provider class for http-client + * @param authenticationDetailsProvider provider for authentication details + */ + public AuthenticatedHttp(HttpClientProvider httpProvider, AuthenticationDetailsProvider authenticationDetailsProvider) + { + this.httpProvider = httpProvider; + this.authDetailProvider = authenticationDetailsProvider; + this.ticketBasedAuthentication = false; + } + + /** + * Enable ticket-based authentication. If set to false, BASIC Authentication will + * be used instead. Defaults to false. + * + * @param ticketBasedAuthentication whether or not to use ticket for authentication + */ + public void setTicketBasedAuthentication(boolean ticketBasedAuthentication) + { + this.ticketBasedAuthentication = ticketBasedAuthentication; + } + + /** + * @return the {@link HttpClientProvider} used by this class. + */ + public HttpClientProvider getHttpProvider() + { + return this.httpProvider; + } + + /** + * @return the {@link AuthenticationDetailsProvider} used by this class. + */ + public AuthenticationDetailsProvider getAuthDetailProvider() + { + return this.authDetailProvider; + } + + /** + * Execute the given method, authenticated as the given user. Automatically closes the + * response-stream to release the connection. If response should be extracted, this should be done + * in the {@link HttpRequestCallback}. + * + * @param method method to execute + * @param userName name of user to authenticate + * @param callback called after http-call is executed. When callback returns, the + * response stream is closed, so all respose-related operations should be done in the callback. Can be null. + * @return result returned by the callback or status-code if no callback is given. + */ + public T executeHttpMethodAuthenticated(HttpMethod method, String userName, HttpRequestCallback callback) + { + if(ticketBasedAuthentication) + { + return executeWithTicketAuthentication(method, userName, authDetailProvider.getPasswordForUser(userName), callback); + } + else + { + return executeWithBasicAuthentication(method, userName, authDetailProvider.getPasswordForUser(userName), callback); + } + } + + public T executeHttpMethodAuthenticated(HttpMethod method, String userName, String password, HttpRequestCallback callback) + { + if(ticketBasedAuthentication) + { + return executeWithTicketAuthentication(method, userName, password, callback); + } + else + { + return executeWithBasicAuthentication(method, userName, password, callback); + } + } + + /** + * Execute the given method, authenticated as the Alfresco Administrator. + * + * @param method method to execute + * @param callback called after http-call is executed. When callback returns, the + * response stream is closed, so all respose-related operations should be done in the callback. Can be null. + * @return result returned by the callback or null if no callback is given. + */ + public T executeHttpMethodAsAdmin(HttpMethod method, HttpRequestCallback callback) + { + if(ticketBasedAuthentication) + { + return executeWithTicketAuthentication(method, authDetailProvider.getAdminUserName(), authDetailProvider.getAdminPassword(), callback); + } + else + { + return executeWithBasicAuthentication(method, authDetailProvider.getAdminUserName(), authDetailProvider.getAdminPassword(), callback); + } + } + + /** + * Execute the given method, authenticated as the given user using Basic Authentication. + * @param method method to execute + * @param userName name of user to authenticate (note: if null then attempts to run with no authentication - eq. Quick/Shared Link test) + * @param callback called after http-call is executed. When callback returns, the + * response stream is closed, so all respose-related operations should be done in the callback. Can be null. + * @return result returned by the callback or null if no callback is given. + */ + private T executeWithBasicAuthentication(HttpMethod method, String userName, String password, HttpRequestCallback callback) + { + try + { + HttpState state = new HttpState(); + + if (userName != null) + { + state.setCredentials( + new AuthScope(null, AuthScope.ANY_PORT), + new UsernamePasswordCredentials(userName, password)); + } + + httpProvider.getHttpClient().executeMethod(null, method, state); + + if(callback != null) + { + return callback.onCallSuccess(method); + } + + // No callback used, return null + return null; + } + catch(Throwable t) + { + boolean handled = false; + + // Delegate to callback to handle error. If not available, throw exception + if(callback != null) + { + handled = callback.onError(method, t); + } + + if(!handled) + { + throw new RuntimeException("Error while executing HTTP-call (" + method.getPath() +")", t); + } + + return null; + } + finally + { + method.releaseConnection(); + } + } + + /** + * Execute the given method, authenticated as the given user using ticket-based authentication. + * @param method method to execute + * @param userName name of user to authenticate + * @return status-code resulting from the request + */ + private T executeWithTicketAuthentication(HttpMethod method, String userName, String password, HttpRequestCallback callback) + { + String ticket = authDetailProvider.getTicketForUser(userName); + if(ticket == null) + { + ticket = fetchLoginTicket(userName, password); + authDetailProvider.updateTicketForUser(userName, ticket); + } + + + + try + { + HttpState state = applyTicketToMethod(method, ticket); + + // Try executing the method + int result = httpProvider.getHttpClient().executeMethod(null, method, state); + + if(result == HttpStatus.SC_UNAUTHORIZED || result == HttpStatus.SC_FORBIDDEN) + { + method.releaseConnection(); + if(!method.validate()) + { + throw new RuntimeException("Ticket re-authentication failed for user " + userName + " (HTTPMethod not reusable)"); + } + // Fetch new ticket, store and apply to HttpMethod + ticket = fetchLoginTicket(userName, userName); + authDetailProvider.updateTicketForUser(userName, ticket); + + state = applyTicketToMethod(method, ticket); + + // Run method agian with new ticket + result = httpProvider.getHttpClient().executeMethod(null, method, state); + } + + if(callback != null) + { + return callback.onCallSuccess(method); + } + + return null; + } + catch(Throwable t) + { + boolean handled = false; + // Delegate to callback to handle error. If not available, throw exception + if(callback != null) + { + handled = callback.onError(method, t); + } + + if(!handled) + { + throw new RuntimeException("Error while executing HTTP-call (" + method.getPath() +")", t); + } + return null; + + } + finally + { + method.releaseConnection(); + } + + } + + /** + * Add the ticket to the method. In case of {@link EntityEnclosingMethod}s (which don't + * support Query-parameters), the ticket is added as Username in BASIC Authentication, + * this is a supported way of passing in ticket into Alfresco. + * + * @param method method to apply + * @param ticket ticket to apply + * + * @return a {@link HttpState} object to use. Null, if no specific state should be used. + */ + private HttpState applyTicketToMethod(HttpMethod method, String ticket) throws URIException + { + // POST and PUT methods don't support Query-params, use Basic Authentication to pass + // in the ticket (ROLE_TICKET) for all methods. + HttpState state = new HttpState(); + state.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(TICKET_CREDENTIAL_PLACEHOLDER, ticket)); + return state; + + } + + /** + * Adds the JSON as request-body the the method and sets the correct + * content-type. + * @param method EntityEnclosingMethod + * @param object JSONObject + */ + private void populateRequestBody(EntityEnclosingMethod method, JSONObject object) + { + try + { + method.setRequestEntity(new StringRequestEntity(object.toJSONString(), MIME_TYPE_JSON, "UTF-8")); + } + catch (UnsupportedEncodingException error) + { + // This will never happen! + throw new RuntimeException("All hell broke loose, a JVM that doesn't have UTF-8 encoding..."); + } + } + + /** + * Perform the login-call to obtain a ticket. + * + * @param userName user to log in + * @return ticket to use for authentication. + * @throws RuntimeException when no ticket can be obtained for the user. + */ + @SuppressWarnings("unchecked") + private String fetchLoginTicket(String userName, String password) + { + String url = httpProvider.getFullAlfrescoUrlForPath(LOGIN_URL); + PostMethod loginMethod = null; + try + { + loginMethod = new PostMethod(url); + loginMethod.setRequestHeader(HEADER_ACCEPT, MIME_TYPE_JSON); + + // Populate resuest body + JSONObject requestBody = new JSONObject(); + requestBody.put(LOGIN_JSON_USERNAME, userName); + requestBody.put(LOGIN_JSON_PASSWORD, password); + + populateRequestBody(loginMethod, requestBody); + + HttpClient client = httpProvider.getHttpClient(); + + // Since no authentication info is available yet, no need to use a + // custom HostConfiguration for the login-call + client.executeMethod(loginMethod); + + if(loginMethod.getStatusCode() == HttpStatus.SC_OK) + { + // Extract the ticket + JSONObject data = getDataFromResponse(loginMethod); + if(data == null) + { + throw new RuntimeException("Failed to login to Alfresco with user " + userName + + " (No JSON-data found in response)"); + } + + // Extract the actual ticket + String ticket = getString(data, JSON_TICKET_KEY, null); + if(ticket == null) + { + throw new RuntimeException("Failed to login to Alfresco with user " + userName + + " (No ticket found in JSON-response)"); + } + return ticket; + } + else + { + // Unable to login + throw new RuntimeException("Failed to login to Alfresco with user " + userName + + " (" + loginMethod.getStatusCode() + loginMethod.getStatusLine().getReasonPhrase() + ")"); + } + } + catch (IOException ioe) + { + // Something went wrong when sending request + throw new RuntimeException("Failed to login to Alfresco with user " + userName, ioe); + } + finally + { + if(loginMethod != null) + { + try + { + loginMethod.releaseConnection(); + } + catch(Throwable t) + { + // Ignore this to prevent swallowing potential original exception + } + } + } + } + + /** + * Callback used when executing HTTP-request. After this has been called, + * the response-stream is closed automatically. + * + * @author Frederik Heremans + */ + public interface HttpRequestCallback + { + /** + * Called when call was successful. + * @param method the method executed which can be used to extract response from. + * @return any result extracted from the response body. + */ + T onCallSuccess(HttpMethod method) throws Exception; + /** + * Called when an error occurs when sending the request. + * @param method the method executed + * @param t optional exception that caused the error + * @return true, if error is handled. False, if an exception should be thrown. + */ + boolean onError(HttpMethod method, Throwable t); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/AuthenticationDetailsProvider.java b/source/test-java/org/alfresco/rest/api/tests/client/AuthenticationDetailsProvider.java index 7b3c24f07b..844b2e7a35 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/AuthenticationDetailsProvider.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/AuthenticationDetailsProvider.java @@ -1,44 +1,44 @@ -package org.alfresco.rest.api.tests.client; - -/** - * Provides details to allow users to authenticate against alfresco. - * - * @author Frederik Heremans - */ -public interface AuthenticationDetailsProvider -{ - - /** - * @param userName String - * @return the password for the given user. Returns null, if user doesn't exist. - */ - String getPasswordForUser(String userName); - - /** - * @param userName String - * @return the password for the given user. Returns null, if no ticket has been stored for - * this user or if the user doesn't exist. - */ - String getTicketForUser(String userName); - - /** - * Update the value of the ticket for the given user. - * @param userName String - * @param ticket String - * @throws IllegalArgumentException when the user does not exist. - */ - void updateTicketForUser(String userName, String ticket) throws IllegalArgumentException; - - - /** - * @return the Alfresco administrator username - */ - String getAdminUserName(); - - - /** - * @return the Alfresco administrator password - */ - String getAdminPassword(); - -} +package org.alfresco.rest.api.tests.client; + +/** + * Provides details to allow users to authenticate against alfresco. + * + * @author Frederik Heremans + */ +public interface AuthenticationDetailsProvider +{ + + /** + * @param userName String + * @return the password for the given user. Returns null, if user doesn't exist. + */ + String getPasswordForUser(String userName); + + /** + * @param userName String + * @return the password for the given user. Returns null, if no ticket has been stored for + * this user or if the user doesn't exist. + */ + String getTicketForUser(String userName); + + /** + * Update the value of the ticket for the given user. + * @param userName String + * @param ticket String + * @throws IllegalArgumentException when the user does not exist. + */ + void updateTicketForUser(String userName, String ticket) throws IllegalArgumentException; + + + /** + * @return the Alfresco administrator username + */ + String getAdminUserName(); + + + /** + * @return the Alfresco administrator password + */ + String getAdminPassword(); + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/HttpClientProvider.java b/source/test-java/org/alfresco/rest/api/tests/client/HttpClientProvider.java index 8a19d81e96..cfd7c73e01 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/HttpClientProvider.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/HttpClientProvider.java @@ -1,22 +1,22 @@ -package org.alfresco.rest.api.tests.client; - -import org.apache.commons.httpclient.HttpClient; - -/** - * Provides {@link HttpClient} instance to be used to perform HTTP-calls. - * - * @author Frederik Heremans - */ -public interface HttpClientProvider -{ - /** - * @return the {@link HttpClient} instance to use for the next HTTP-call. - */ - HttpClient getHttpClient(); - - /** - * @param path relative path of the URL from alfresco host. - * @return full URL including hostname and port for the given path. - */ - String getFullAlfrescoUrlForPath(String path); -} +package org.alfresco.rest.api.tests.client; + +import org.apache.commons.httpclient.HttpClient; + +/** + * Provides {@link HttpClient} instance to be used to perform HTTP-calls. + * + * @author Frederik Heremans + */ +public interface HttpClientProvider +{ + /** + * @return the {@link HttpClient} instance to use for the next HTTP-call. + */ + HttpClient getHttpClient(); + + /** + * @param path relative path of the URL from alfresco host. + * @return full URL including hostname and port for the given path. + */ + String getFullAlfrescoUrlForPath(String path); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java b/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java index cf9cbac76d..3922991c8c 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java @@ -1,192 +1,192 @@ -/* - * Copyright (C) 2005-2015 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 . - */ - -package org.alfresco.rest.api.tests.client; - -import java.util.Map; - -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpMethodBase; -import org.apache.commons.httpclient.URIException; -import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; -import org.apache.commons.httpclient.methods.DeleteMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.PutMethod; -import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.apache.commons.httpclient.util.EncodingUtil; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -public class HttpResponse -{ - protected HttpMethod method; - private String user; - private byte[] responseBytes; - private Map headers; - private long time; - - public HttpResponse(HttpMethod method, String user, byte[] responseBytes, Map headers, long time) - { - this.method = method; - this.user = user; - this.time = time; - this.headers = headers; - this.responseBytes = responseBytes; - } - - public int getStatusCode() - { - return method.getStatusCode(); - } - - public String getResponse() - { - if (responseBytes != null) - { - if (method instanceof HttpMethodBase) - { - // mimic method.getResponseBodyAsString - return EncodingUtil.getString(responseBytes, ((HttpMethodBase)method).getResponseCharSet()); - } - else - { - return new String(responseBytes); - } - } - else - { - return null; - } - } - - public byte[] getResponseAsBytes() - { - return responseBytes; - } - - public Map getHeaders() - { - return headers; - } - - public String toString() - { - StringBuilder sb = new StringBuilder(); - - String requestType = null; - RequestEntity requestEntity = null; - - if (method instanceof GetMethod) - { - requestType = "GET"; - } - else if (method instanceof PutMethod) - { - requestType = "PUT"; - requestEntity = ((PutMethod) method).getRequestEntity(); - } - else if (method instanceof PostMethod) - { - requestType = "POST"; - requestEntity = ((PostMethod)method).getRequestEntity(); - } - else if (method instanceof DeleteMethod) - { - requestType = "DELETE"; - } - - try - { - sb.append(requestType).append(" request ").append(method.getURI()).append("\n"); - } - catch (URIException e) - { - } - - if (requestEntity != null) - { - sb.append("\nRequest body: "); - if (requestEntity instanceof StringRequestEntity) - { - sb.append(((StringRequestEntity)requestEntity).getContent()); - } - else if (requestEntity instanceof ByteArrayRequestEntity) - { - sb.append(" << ").append(((ByteArrayRequestEntity)requestEntity).getContent().length).append(" bytes >>"); - } - sb.append("\n"); - } - - sb.append("user ").append(user).append("\n"); - sb.append("returned ").append(method.getStatusCode()).append(" and took ").append(time).append("ms").append("\n"); - - String contentType = null; - Header hdr = method.getResponseHeader("Content-Type"); - if (hdr != null) - { - contentType = hdr.getValue(); - } - sb.append("Response content type: ").append(contentType).append("\n"); - - if (contentType != null) - { - sb.append("\nResponse body: "); - if (contentType.startsWith("text/plain") || contentType.startsWith("application/json")) - { - sb.append(getResponse()); - sb.append("\n"); - } - else if(getResponseAsBytes() != null) - { - sb.append(" << ").append(getResponseAsBytes().length).append(" bytes >>"); - sb.append("\n"); - } - } - - return sb.toString(); - } - - public JSONObject getJsonResponse() - { - JSONObject result = null; - - try - { - String response = getResponse(); - if (response != null) - { - Object object = new JSONParser().parse(response); - if(object instanceof JSONObject) - { - return (JSONObject) object; - } - } - } - catch (ParseException error) - { - // Ignore errors, returning null - } - - return result; - } -} +/* + * Copyright (C) 2005-2015 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 . + */ + +package org.alfresco.rest.api.tests.client; + +import java.util.Map; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.URIException; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.httpclient.util.EncodingUtil; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +public class HttpResponse +{ + protected HttpMethod method; + private String user; + private byte[] responseBytes; + private Map headers; + private long time; + + public HttpResponse(HttpMethod method, String user, byte[] responseBytes, Map headers, long time) + { + this.method = method; + this.user = user; + this.time = time; + this.headers = headers; + this.responseBytes = responseBytes; + } + + public int getStatusCode() + { + return method.getStatusCode(); + } + + public String getResponse() + { + if (responseBytes != null) + { + if (method instanceof HttpMethodBase) + { + // mimic method.getResponseBodyAsString + return EncodingUtil.getString(responseBytes, ((HttpMethodBase)method).getResponseCharSet()); + } + else + { + return new String(responseBytes); + } + } + else + { + return null; + } + } + + public byte[] getResponseAsBytes() + { + return responseBytes; + } + + public Map getHeaders() + { + return headers; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + + String requestType = null; + RequestEntity requestEntity = null; + + if (method instanceof GetMethod) + { + requestType = "GET"; + } + else if (method instanceof PutMethod) + { + requestType = "PUT"; + requestEntity = ((PutMethod) method).getRequestEntity(); + } + else if (method instanceof PostMethod) + { + requestType = "POST"; + requestEntity = ((PostMethod)method).getRequestEntity(); + } + else if (method instanceof DeleteMethod) + { + requestType = "DELETE"; + } + + try + { + sb.append(requestType).append(" request ").append(method.getURI()).append("\n"); + } + catch (URIException e) + { + } + + if (requestEntity != null) + { + sb.append("\nRequest body: "); + if (requestEntity instanceof StringRequestEntity) + { + sb.append(((StringRequestEntity)requestEntity).getContent()); + } + else if (requestEntity instanceof ByteArrayRequestEntity) + { + sb.append(" << ").append(((ByteArrayRequestEntity)requestEntity).getContent().length).append(" bytes >>"); + } + sb.append("\n"); + } + + sb.append("user ").append(user).append("\n"); + sb.append("returned ").append(method.getStatusCode()).append(" and took ").append(time).append("ms").append("\n"); + + String contentType = null; + Header hdr = method.getResponseHeader("Content-Type"); + if (hdr != null) + { + contentType = hdr.getValue(); + } + sb.append("Response content type: ").append(contentType).append("\n"); + + if (contentType != null) + { + sb.append("\nResponse body: "); + if (contentType.startsWith("text/plain") || contentType.startsWith("application/json")) + { + sb.append(getResponse()); + sb.append("\n"); + } + else if(getResponseAsBytes() != null) + { + sb.append(" << ").append(getResponseAsBytes().length).append(" bytes >>"); + sb.append("\n"); + } + } + + return sb.toString(); + } + + public JSONObject getJsonResponse() + { + JSONObject result = null; + + try + { + String response = getResponse(); + if (response != null) + { + Object object = new JSONParser().parse(response); + if(object instanceof JSONObject) + { + return (JSONObject) object; + } + } + } + catch (ParseException error) + { + // Ignore errors, returning null + } + + return result; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/Pair.java b/source/test-java/org/alfresco/rest/api/tests/client/Pair.java index 9133ecf76d..663ec4fc77 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/Pair.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/Pair.java @@ -1,54 +1,54 @@ -package org.alfresco.rest.api.tests.client; - -public class Pair -{ - private T1 first; - private T2 second; - - public Pair(T1 first, T2 second) - { - super(); - this.first = first; - this.second = second; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((first == null) ? 0 : first.hashCode()); - result = prime * result - + ((second == null) ? 0 : second.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Pair other = (Pair) obj; - if (first == null) { - if (other.first != null) - return false; - } else if (!first.equals(other.first)) - return false; - if (second == null) { - if (other.second != null) - return false; - } else if (!second.equals(other.second)) - return false; - return true; - } - - public T1 getFirst() { - return first; - } - - public T2 getSecond() { - return second; - } -} +package org.alfresco.rest.api.tests.client; + +public class Pair +{ + private T1 first; + private T2 second; + + public Pair(T1 first, T2 second) + { + super(); + this.first = first; + this.second = second; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((first == null) ? 0 : first.hashCode()); + result = prime * result + + ((second == null) ? 0 : second.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Pair other = (Pair) obj; + if (first == null) { + if (other.first != null) + return false; + } else if (!first.equals(other.first)) + return false; + if (second == null) { + if (other.second != null) + return false; + } else if (!second.equals(other.second)) + return false; + return true; + } + + public T1 getFirst() { + return first; + } + + public T2 getSecond() { + return second; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java index e81f0c4918..ca165b7f1a 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java @@ -1,2179 +1,2179 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.tests.client; - -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.math.BigInteger; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl; -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; -import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder; -import org.alfresco.rest.api.tests.client.data.Activities; -import org.alfresco.rest.api.tests.client.data.Activity; -import org.alfresco.rest.api.tests.client.data.CMISNode; -import org.alfresco.rest.api.tests.client.data.Comment; -import org.alfresco.rest.api.tests.client.data.ContentData; -import org.alfresco.rest.api.tests.client.data.Favourite; -import org.alfresco.rest.api.tests.client.data.FavouriteSite; -import org.alfresco.rest.api.tests.client.data.FolderNode; -import org.alfresco.rest.api.tests.client.data.MemberOfSite; -import org.alfresco.rest.api.tests.client.data.NodeRating; -import org.alfresco.rest.api.tests.client.data.Person; -import org.alfresco.rest.api.tests.client.data.PersonNetwork; -import org.alfresco.rest.api.tests.client.data.Preference; -import org.alfresco.rest.api.tests.client.data.Site; -import org.alfresco.rest.api.tests.client.data.SiteContainer; -import org.alfresco.rest.api.tests.client.data.SiteImpl; -import org.alfresco.rest.api.tests.client.data.SiteMember; -import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; -import org.alfresco.rest.api.tests.client.data.Tag; -import org.apache.chemistry.opencmis.client.api.CmisObject; -import org.apache.chemistry.opencmis.client.api.Document; -import org.apache.chemistry.opencmis.client.api.FileableCmisObject; -import org.apache.chemistry.opencmis.client.api.Folder; -import org.apache.chemistry.opencmis.client.api.ItemIterable; -import org.apache.chemistry.opencmis.client.api.ObjectId; -import org.apache.chemistry.opencmis.client.api.ObjectType; -import org.apache.chemistry.opencmis.client.api.OperationContext; -import org.apache.chemistry.opencmis.client.api.QueryResult; -import org.apache.chemistry.opencmis.client.api.Repository; -import org.apache.chemistry.opencmis.client.api.Session; -import org.apache.chemistry.opencmis.client.api.SessionFactory; -import org.apache.chemistry.opencmis.client.api.Tree; -import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; -import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; -import org.apache.chemistry.opencmis.commons.PropertyIds; -import org.apache.chemistry.opencmis.commons.SessionParameter; -import org.apache.chemistry.opencmis.commons.data.AllowableActions; -import org.apache.chemistry.opencmis.commons.data.ContentStream; -import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition; -import org.apache.chemistry.opencmis.commons.enums.BindingType; -import org.apache.chemistry.opencmis.commons.enums.UnfileObject; -import org.apache.chemistry.opencmis.commons.enums.VersioningState; -import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; - -/** - * A client for interacting with the public api and returning Java objects. - * - * @author steveglover - * - */ -public class PublicApiClient -{ - private static final Log logger = LogFactory.getLog(PublicApiClient.class); - - private UserDataService userDataService; - private PublicApiHttpClient client; - - private Sites sites; - private Tags tags; - private Comments comments; - private Nodes nodes; - private People people; - private Favourites favourites; - private SiteMembershipRequests siteMembershipRequests; - private RawProxy rawProxy; - - private ThreadLocal rc = new ThreadLocal(); - - public PublicApiClient(PublicApiHttpClient client, UserDataService userDataService) - { - this.client = client; - this.userDataService = userDataService; - - init(); - } - - public void init() - { - sites = new Sites(); - tags = new Tags(); - comments = new Comments(); - nodes = new Nodes(); - people = new People(); - favourites = new Favourites(); - siteMembershipRequests = new SiteMembershipRequests(); - rawProxy = new RawProxy(); - } - - public void setRequestContext(RequestContext rc) - { - this.rc.set(rc); - } - - public RequestContext getRequestContext() - { - RequestContext context = rc.get(); - if(context == null) - { - throw new RuntimeException("Must set a request context"); - } - return context; - } - - protected UserData findUser(String userName) - { - return userDataService.findUserByUserName(userName); - } - - public RawProxy rawProxy() - { - return rawProxy; - } - - public People people() - { - return people; - } - - public Nodes nodes() - { - return nodes; - } - - public Sites sites() - { - return sites; - } - - public Favourites favourites() - { - return favourites; - } - - public SiteMembershipRequests siteMembershipRequests() - { - return siteMembershipRequests; - } - - public Tags tags() - { - return tags; - } - - public Comments comments() - { - return comments; - } - - public CmisSession createPublicApiCMISSession(Binding binding, String version) - { - return createPublicApiCMISSession(binding, version, null); - } - - public CmisSession createPublicApiCMISSession(Binding binding, String version, String objectFactoryName) - { - CmisSession cmisSession = null; - - RequestContext rc = getRequestContext(); - if(rc == null) - { - throw new RuntimeException("Must set a request context"); - } - - String networkId = rc.getNetworkId(); - String username = rc.getRunAsUser(); - UserData userData = findUser(rc.getRunAsUser()); - if(userData != null) - { - String password = userData.getPassword(); - - // default factory implementation - SessionFactory factory = SessionFactoryImpl.newInstance(); - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, username); - parameters.put(SessionParameter.PASSWORD, password); - - // connection settings - if(binding == Binding.atom) - { - parameters.put(SessionParameter.ATOMPUB_URL, client.getPublicApiCmisUrl(networkId, binding, version, null)); - parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); - } - else if(binding == Binding.browser) - { - parameters.put(SessionParameter.BROWSER_URL, client.getPublicApiCmisUrl(networkId, binding, version, null)); - parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); - } - if(networkId != null) - { - parameters.put(SessionParameter.REPOSITORY_ID, networkId); - } - if(objectFactoryName != null) - { - parameters.put(SessionParameter.OBJECT_FACTORY_CLASS, objectFactoryName); - } - - // create session - Session session = factory.createSession(parameters); - - cmisSession = new CmisSession(session); - } - - return cmisSession; - } - - public CmisSession createCMISSession(String repositoryId, RequestContext rc) - { - CmisSession session = null; - - UserData userData = findUser(rc.getRunAsUser()); - if(userData != null) - { - session = createCMISSession(repositoryId, rc.getRunAsUser(), userData.getPassword()); - } - - return session; - } - - /** - * Get CMIS repositories (Enterprise AtomPub CMIS binding) - * - * @return List - */ - public List getCMISRepositories() - { - List repositories = null; - - RequestContext rc = getRequestContext(); - if(rc == null) - { - throw new RuntimeException("Must set a request context"); - } - - UserData userData = findUser(rc.getRunAsUser()); - if(userData != null) - { - // default factory implementation - SessionFactory factory = SessionFactoryImpl.newInstance(); - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, rc.getRunAsUser()); - parameters.put(SessionParameter.PASSWORD, userData.getPassword()); - - // connection settings - parameters.put(SessionParameter.ATOMPUB_URL, client.getCmisUrl(null, null)); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); - - repositories = factory.getRepositories(parameters); - } - - return repositories; - } - - /** - * Create a CMIS session using Enterprise AtomPub binding. - * - * @param repositoryId String - * @param username String - * @param password String - * @return CmisSession - */ - public CmisSession createCMISSession(String repositoryId, String username, String password) - { - // default factory implementation - SessionFactory factory = SessionFactoryImpl.newInstance(); - Map parameters = new HashMap(); - - // user credentials - parameters.put(SessionParameter.USER, username); - parameters.put(SessionParameter.PASSWORD, password); - - // connection settings - parameters.put(SessionParameter.ATOMPUB_URL, client.getCmisUrl(repositoryId, null)); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); - if(repositoryId != null) - { - parameters.put(SessionParameter.REPOSITORY_ID, repositoryId); - } - parameters.put(SessionParameter.OBJECT_FACTORY_CLASS, AlfrescoObjectFactoryImpl.class.getName()); - - // create session - Session session = factory.createSession(parameters); - - CmisSession cmisSession = new CmisSession(session); - return cmisSession; - } - - public CmisSession getCMISSession(Repository respository) - { - RequestContext rc = getRequestContext(); - if(rc == null) - { - throw new RuntimeException("Must set a request context"); - } - - CmisSession session = createCMISSession(respository.getId(), rc); - return session; - } - - public HttpResponse post(Binding cmisBinding, String version, String cmisOperation, String body) throws PublicApiException - { - try - { - HttpResponse response = client.post(getRequestContext(), cmisBinding, version, cmisOperation, body); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse put(Binding cmisBinding, String version, String cmisOperation, String body) throws PublicApiException - { - try - { - HttpResponse response = client.put(getRequestContext(), cmisBinding, version, cmisOperation, body); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse get(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException - { - try - { - HttpResponse response = client.get(getRequestContext(), cmisBinding, version, cmisOperation, parameters); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse patch(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException - { - try - { - HttpResponse response = client.patch(getRequestContext(), cmisBinding, version, cmisOperation); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse trace(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException - { - try - { - HttpResponse response = client.trace(getRequestContext(), cmisBinding, version, cmisOperation); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse options(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException - { - try - { - HttpResponse response = client.options(getRequestContext(), cmisBinding, version, cmisOperation); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse head(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException - { - try - { - HttpResponse response = client.head(getRequestContext(), cmisBinding, version, cmisOperation); - - logger.debug(response.toString()); - - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, String body) throws IOException - { - HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId != null ? relationshipEntityId.toString() : null, body); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, - String body, String contentType) throws IOException - { - HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId != null ? relationshipEntityId.toString() : null, body, contentType); - - logger.debug(response.toString()); - - return response; - } - - - public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, - byte[] body, String contentType) throws IOException - { - HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId != null ? relationshipEntityId.toString() : null, body, contentType); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse post(String urlSuffix, String body) throws IOException - { - HttpResponse response = client.post(getRequestContext(), urlSuffix, body); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse post(final Class c, Object entityId, Object relationshipEntityId, String body) throws IOException - { - HttpResponse response = client.post(c, getRequestContext(), entityId, relationshipEntityId, body); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse get(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException - { - HttpResponse response = client.get(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse getWithPassword(String scope, String password, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException - { - HttpResponse response = client.get(getRequestContext(), scope, password, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse get(String url, Map params) throws IOException - { - RequestContext rc = getRequestContext(); - HttpResponse response = client.get(url, rc, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse get(final Class c, final Object entityId, final Object relationshipEntityId, Map params) throws IOException - { - HttpResponse response = client.get(c, getRequestContext(), entityId, relationshipEntityId, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse put(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, String body, Map params) throws IOException - { - HttpResponse response = client.put(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse put(final Class c, Object entityId, Object relationshipEntityId, String body) throws IOException - { - HttpResponse response = client.put(c, getRequestContext(), entityId, relationshipEntityId, body); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse putBinary(String scope, int version, String entityCollectionName, Object entityId, String relationCollectionName, - Object relationshipEntityId, BinaryPayload payload, Map params) throws IOException - { - HttpResponse response = client.putBinary(getRequestContext(), scope, version, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, - payload, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse delete(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId) throws IOException - { - return delete(scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, null); - } - - public HttpResponse delete(String scope, int version, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException - { - HttpResponse response = client.delete(getRequestContext(), scope, version, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse put(final Class c, Object entityId, Object relationshipEntityId) throws IOException - { - HttpResponse response = client.delete(c, getRequestContext(), entityId, relationshipEntityId); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse execute(RequestBuilder requestBuilder) throws IOException - { - if (requestBuilder.getRequestContext() == null) - { - throw new RuntimeException("Must set a request context"); - } - HttpResponse response = client.execute(requestBuilder); - - logger.debug(response.toString()); - - return response; - } - - public HttpResponse index(Map params) throws IOException - { - HttpResponse response = get("", params); - return response; - } - - public List getNetworkIds(String version) - { - RequestContext rc = getRequestContext(); - - UserData userData = findUser(rc.getRunAsUser()); - if(userData == null) - { - throw new RuntimeException("Must provide a valid username"); - } - - SessionFactory factory = SessionFactoryImpl.newInstance(); - - Map parameters = new HashMap(); - - // connection settings - parameters.put(SessionParameter.ATOMPUB_URL, client.getPublicApiCmisUrl(null, Binding.atom, version, null)); - parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); - - // user credentials - parameters.put(SessionParameter.USER, rc.getRunAsUser()); - parameters.put(SessionParameter.PASSWORD, userData.getPassword()); - List repositories = factory.getRepositories(parameters); - - List repositoryIds = new ArrayList(repositories.size()); - for(Repository repository : repositories) - { - repositoryIds.add(repository.getId()); - } - - return repositoryIds; - } - - public class AbstractProxy - { - public HttpResponse getAll(String entityCollectionName, String entityId, String relationCollectionName, String relationId, Map params, String errorMessage) throws PublicApiException - { - try - { - HttpResponse response = get("public", entityCollectionName, entityId, relationCollectionName, relationId, params); - - if (HttpServletResponse.SC_OK != response.getStatusCode()) - { - String msg = errorMessage + ": \n" + - " Response: " + response; - throw new PublicApiException(msg, response); - } - else - { - return response; - } - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse getSingle(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage) throws PublicApiException - { - return getSingle(entityCollectionName, entityId, relationCollectionName, relationId, errorMessage, HttpServletResponse.SC_OK); - } - - public HttpResponse getSingle(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage, int expectedStatus) throws PublicApiException - { - try - { - HttpResponse response = get("public", entityCollectionName, entityId, relationCollectionName, relationId, null); - checkStatus(errorMessage, expectedStatus, response); - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse update(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage) throws PublicApiException - { - return update(entityCollectionName, entityId, relationCollectionName, relationId, body, errorMessage, null); - } - - public HttpResponse update(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage, Map params) throws PublicApiException - { - try - { - HttpResponse response = put("public", entityCollectionName, entityId, relationCollectionName, relationId, body, params); - - if (HttpServletResponse.SC_OK != response.getStatusCode()) - { - String msg = errorMessage + ": \n" + - " Response: " + response; - throw new PublicApiException(msg, response); - } - else - { - return response; - } - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse create(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage) throws PublicApiException - { - return create(entityCollectionName, entityId, relationCollectionName, relationId, body, errorMessage, HttpServletResponse.SC_CREATED); - } - - public HttpResponse create(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage, int expectedStatus) throws PublicApiException - { - try - { - HttpResponse response = post("public", entityCollectionName, entityId, relationCollectionName, relationId, body); - checkStatus(errorMessage, expectedStatus, response); - return response; - } - catch (IOException e) - { - throw new PublicApiException(e); - } - } - - public HttpResponse remove(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage) throws PublicApiException - { - return remove(entityCollectionName, entityId, relationCollectionName, relationId, null, errorMessage, HttpServletResponse.SC_NO_CONTENT); - } - - public HttpResponse remove(String entityCollectionName, String entityId, String relationCollectionName, String relationId, Map params, String errorMessage, int expectedStatus) throws PublicApiException - { - try - { - HttpResponse response = delete("public", 1, entityCollectionName, entityId, relationCollectionName, relationId, params); - checkStatus(errorMessage, expectedStatus, response); - return response; - } - catch(IOException e) - { - throw new PublicApiException(e); - } - } - - public JSONObject parseListSource(JSONObject jsonResponse) - { - JSONObject jsonList = (JSONObject)jsonResponse.get("list"); - assertNotNull(jsonList); - - JSONObject source = (JSONObject)jsonList.get("source"); - assertNotNull(source); - return source; - } - - public void checkStatus(String errorMessage, int expectedStatus, HttpResponse response) throws PublicApiException - { - int actualStatus = response.getStatusCode(); - if ((expectedStatus > 0) && (expectedStatus != actualStatus)) - { - String msg = "Status code " + actualStatus + " returned, but expected " + expectedStatus + ": \n"+ - errorMessage + ": \n" + " Response: " + response; - throw new PublicApiException(msg, response); - } - } - } - - public static class ListResponse - { - private ExpectedPaging paging; - private List list; - - public ListResponse(ExpectedPaging paging, List list) - { - super(); - this.paging = paging; - this.list = list; - } - - public ExpectedPaging getPaging() - { - return paging; - } - - public List getList() - { - return list; - } - } - - public class Sites extends AbstractProxy - { - public ListResponse getSites(Map params) throws PublicApiException - { - HttpResponse response = getAll("sites", null, null, null, params, "Failed to get sites"); - return SiteImpl.parseSites(response.getJsonResponse()); - } - - public Site getSite(String siteId) throws PublicApiException - { - return getSite(siteId, 200); - } - - public Site getSite(String siteId, int expectedStatus) throws PublicApiException - { - HttpResponse response = getSingle("sites", siteId, null, null, "Failed to get site " + siteId, expectedStatus); - if ((response != null) && (response.getJsonResponse() != null)) - { - return SiteImpl.parseSite((JSONObject)response.getJsonResponse().get("entry")); - } - else - { - return null; - } - } - - public Site createSite(Site site) throws PublicApiException - { - return createSite(site, 201); - } - - public Site createSite(Site site, int expectedStatus) throws PublicApiException - { - HttpResponse response = create("sites", null, null, null, site.toJSON().toString(), "Failed to create site "+site.getTitle(), expectedStatus); - return SiteImpl.parseSite((JSONObject)response.getJsonResponse().get("entry")); - } - - public void removeSite(String siteId) throws PublicApiException - { - removeSite(siteId, false, 204); - } - - public void removeSite(String siteId, boolean permanent, int expectedStatus) throws PublicApiException - { - Map params = null; - if (permanent) - { - params = Collections.singletonMap("permanent", "true"); - } - remove("sites", siteId, null, null, params, "Failed to remove site", expectedStatus); - } - - public ListResponse getSiteContainers(String siteId, Map params) throws PublicApiException - { - HttpResponse response = getAll("sites", siteId, "containers", null, params, "Failed to get site containers"); - return SiteContainer.parseSiteContainers(response.getJsonResponse()); - } - - public SiteContainer getSingleSiteContainer(String siteId, String containerId) throws PublicApiException - { - HttpResponse response = getSingle("sites", siteId, "containers", containerId, "Failed to get site container"); - SiteContainer siteContainer = SiteContainer.parseSiteContainer(siteId, (JSONObject)response.getJsonResponse().get("entry")); - return siteContainer; - } - - public SiteContainer updateSiteContainer(SiteContainer siteContainer) throws PublicApiException - { - HttpResponse response = update("sites", siteContainer.getSiteId(), "containers", siteContainer.getId(), siteContainer.toJSON().toString(), "Failed to update site container"); - SiteContainer retSiteContainer = SiteContainer.parseSiteContainer(siteContainer.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); - return retSiteContainer; - } - - public SiteContainer createSiteContainer(SiteContainer siteContainer) throws PublicApiException - { - HttpResponse response = create("sites", siteContainer.getSiteId(), "containers", null, siteContainer.toJSON().toString(), "Failed to create site container"); - SiteContainer retSiteContainer = SiteContainer.parseSiteContainer(siteContainer.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); - return retSiteContainer; - } - - public void removeSiteContainer(SiteContainer siteContainer) throws PublicApiException - { - remove("sites", siteContainer.getSiteId(), "containers", siteContainer.getId(), "Failed to remove site container"); - } - - public ListResponse getSiteMembers(String siteId, Map params) throws PublicApiException - { - HttpResponse response = getAll("sites", siteId, "members", null, params, "Failed to get all site members"); - return SiteMember.parseSiteMembers(siteId, response.getJsonResponse()); - } - - public SiteMember getSingleSiteMember(String siteId, String personId) throws PublicApiException - { - HttpResponse response = getSingle("sites", siteId, "members", personId, "Failed to get site member"); - SiteMember retSiteMember = SiteMember.parseSiteMember(siteId, (JSONObject)response.getJsonResponse().get("entry")); - return retSiteMember; - } - - public SiteMember updateSiteMember(String siteId, SiteMember siteMember) throws PublicApiException - { - HttpResponse response = update("sites", siteId, "members", siteMember.getMemberId(), siteMember.toJSON().toString(), "Failed to update site member"); - SiteMember retSiteMember = SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); - return retSiteMember; - } - - public SiteMember createSiteMember(String siteId, SiteMember siteMember) throws PublicApiException - { - HttpResponse response = create("sites", siteId, "members", null, siteMember.postJSON().toString(), "Failed to create site member"); - SiteMember retSiteMember = SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); - return retSiteMember; - } - - public void removeSiteMember(String siteId, SiteMember siteMember) throws PublicApiException - { - remove("sites", siteId, "members", siteMember.getMemberId(), "Failed to remove site member"); - } - - public ListResponse getPersonSites(String personId, Map params) throws PublicApiException - { - HttpResponse response = getAll("people", personId, "sites", null, params, "Failed to get person sites"); - return MemberOfSite.parseMemberOfSites(response.getJsonResponse()); - } - - public MemberOfSite getPersonSite(String personId, String siteId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, "sites", siteId, "Failed to get person site" + siteId); - return MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); - } - - public MemberOfSite updatePersonSite(String personId, SiteMember siteMember) throws PublicApiException - { - HttpResponse response = update("people", personId, "sites", siteMember.getSiteId(), siteMember.toJSON().toString(), "Failed to update person site"); - MemberOfSite retSiteMember = MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); - return retSiteMember; - } - - public MemberOfSite createPersonSite(String personId, SiteMember siteMember) throws PublicApiException - { - HttpResponse response = create("people", personId, "sites", null, siteMember.toJSON().toString(), "Failed to create person site"); - MemberOfSite retSiteMember = MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); - return retSiteMember; - } - - public void removePersonSite(String personId, SiteMember siteMember) throws PublicApiException - { - remove("people", personId, "sites", siteMember.getSiteId(), "Failed to remove person site"); - } - - public ListResponse getFavouriteSites(String personId, Map params) throws PublicApiException - { - HttpResponse response = getAll("people", personId, "favorite-sites", null, params, "Failed to get favourite sites"); - return FavouriteSite.parseFavouriteSites(response.getJsonResponse()); - } - - public FavouriteSite getSingleFavouriteSite(String personId, String siteId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, "favorite-sites", siteId, "Failed to get favourite site"); - FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); - return favouriteSite; - } - - public FavouriteSite updateFavouriteSite(String personId, FavouriteSite site) throws PublicApiException - { - HttpResponse response = update("people", personId, "favorite-sites", site.getSiteId(), site.toJSON().toString(), "Failed to update favourite site"); - FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); - return favouriteSite; - } - - public FavouriteSite createFavouriteSite(String personId, FavouriteSite site) throws PublicApiException - { - HttpResponse response = create("people", personId, "favorite-sites", null, site.toJSON().toString(), "Failed to create favourite site"); - FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); - return favouriteSite; - } - - public void removeFavouriteSite(String personId, FavouriteSite site) throws PublicApiException - { - remove("people", personId, "favorite-sites", site.getSiteId(), "Failed to remove favourite site"); - } - } - - public class SiteMembershipRequests extends AbstractProxy - { - public SiteMembershipRequest getSiteMembershipRequest(String personId, String siteId) throws PublicApiException, ParseException - { - HttpResponse response = getSingle("people", personId, "site-membership-requests", siteId, "Failed to get siteMembershipRequest"); - return SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); - } - - public ListResponse getSiteMembershipRequests(String personId, Map params) throws PublicApiException, ParseException - { - HttpResponse response = getAll("people", personId, "site-membership-requests", null, params, "Failed to get siteMembershipRequests"); - return SiteMembershipRequest.parseSiteMembershipRequests(personId, response.getJsonResponse()); - } - - public SiteMembershipRequest createSiteMembershipRequest(String personId, SiteMembershipRequest siteMembershipRequest) throws PublicApiException, ParseException - { - HttpResponse response = create("people", personId, "site-membership-requests", null, siteMembershipRequest.toJSON().toString(), "Failed to create siteMembershipRequest"); - SiteMembershipRequest ret = SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); - return ret; - } - - public SiteMembershipRequest updateSiteMembershipRequest(String personId, SiteMembershipRequest siteMembershipRequest) throws PublicApiException, ParseException - { - HttpResponse response = update("people", personId, "site-membership-requests", siteMembershipRequest.getId(), siteMembershipRequest.toJSON().toString(), "Failed to update siteMembershipRequest"); - SiteMembershipRequest ret = SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); - return ret; - } - - public void cancelSiteMembershipRequest(String personId, String siteMembershipRequestId) throws PublicApiException - { - remove("people", personId, "site-membership-requests", siteMembershipRequestId, "Failed to cancel siteMembershipRequest"); - } - } - - public class RawProxy extends AbstractProxy - { - } - - public class Favourites extends AbstractProxy - { - public ListResponse getFavourites(String personId, Map params) throws PublicApiException, ParseException - { - HttpResponse response = getAll("people", personId, "favorites", null, params, "Failed to get favourites"); - return Favourite.parseFavourites(response.getJsonResponse()); - } - - public Favourite getFavourite(String personId, String favouriteId) throws PublicApiException, ParseException - { - HttpResponse response = getSingle("people", personId, "favorites", favouriteId, "Failed to get favourite " + favouriteId); - return Favourite.parseFavourite((JSONObject)response.getJsonResponse().get("entry")); - } - - public Favourite createFavourite(String personId, Favourite favourite) throws PublicApiException, ParseException - { - HttpResponse response = create("people", personId, "favorites", null, favourite.toJSON().toString(), "Failed to create favourite"); - Favourite ret = Favourite.parseFavourite((JSONObject)response.getJsonResponse().get("entry")); - return ret; - } - - public void removeFavourite(String personId, String favouriteId) throws PublicApiException - { - remove("people", personId, "favorites", favouriteId, "Failed to remove favourite"); - } - } - - public class People extends AbstractProxy - { - public ListResponse getPeople(Map params) throws PublicApiException - { - HttpResponse response = getAll("people", null, null, null, params, "Failed to get people"); - return Person.parsePeople(response.getJsonResponse()); - } - - public Person getPerson(String personId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, null, null, "Failed to get person"); - - if(logger.isDebugEnabled()) - { - logger.debug(response); - } - System.out.println(response); - - Person site = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); - return site; - } - - public Person update(String personId, Person person, boolean fullVisibility) throws PublicApiException - { - HttpResponse response = update("people", person.getId(), null, null, person.toJSON(fullVisibility).toString(), "Failed to update person"); - Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); - return retSite; - } - - public Person create(Person person, boolean fullVisibility) throws PublicApiException - { - HttpResponse response = create("people", null, null, null, person.toJSON(fullVisibility).toString(), "Failed to create person"); - Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); - return retSite; - } - - public void remove(Person person) throws PublicApiException - { - remove("people", person.getId(), null, null, "Failed to remove person"); - } - - public ListResponse getPreferences(String personId, Map params) throws PublicApiException - { - HttpResponse response = getAll("people", personId, "preferences", null, params, "Failed to get person preferences"); - return Preference.parsePreferences(response.getJsonResponse()); - } - - public Preference getPreference(String personId, String preferenceId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, "preferences", preferenceId, "Failed to get person preference"); - Preference pref = Preference.parsePreference((JSONObject)response.getJsonResponse().get("entry")); - return pref; - } - - public Person updatePreference(String personId, Preference preference) throws PublicApiException - { - HttpResponse response = update("people", personId, "preferences", preference.getId(), preference.toJSON().toString(), "Failed to update person preference"); - Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); - return retSite; - } - - public Person createPreference(String personId, Preference preference) throws PublicApiException - { - HttpResponse response = create("people", personId, "preferences", null, preference.toJSON().toString(), "Failed to create person preference"); - Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); - return retSite; - } - - public void removePreference(String personId, Preference preference) throws PublicApiException - { - remove("people", personId, "preferences", preference.getId(), "Failed to remove person preference"); - } - - public ListResponse getNetworkMemberships(String personId, Map params) throws PublicApiException - { - HttpResponse response = getAll("people", personId, "networks", null, params, "Failed to get network members"); - return PersonNetwork.parseNetworkMembers(response.getJsonResponse()); - } - - public PersonNetwork getNetworkMembership(String personId, String networkId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, "networks", networkId, "Failed to get network member"); - PersonNetwork networkMember = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); - return networkMember; - } - - public PersonNetwork updateNetworkMembership(String personId, PersonNetwork networkMember) throws PublicApiException - { - HttpResponse response = update("people", personId, "networks", networkMember.getId(), networkMember.toJSON().toString(), "Failed to update network member"); - PersonNetwork retNetwork = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); - return retNetwork; - } - - public PersonNetwork createNetworkMembership(String personId, PersonNetwork network) throws PublicApiException - { - HttpResponse response = create("people", personId, "networks", null, network.toJSON().toString(), "Failed to create network member"); - PersonNetwork retNetwork = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); - return retNetwork; - } - - public void removeNetworkMembership(String personId, PersonNetwork networkMember) throws PublicApiException - { - remove("people", personId, "networks", networkMember.getId(), "Failed to remove network member"); - } - - public ListResponse getActivities(String personId, Map params) throws PublicApiException - { - HttpResponse response = getAll("people", personId, "activities", null, params, "Failed to get activities"); - return Activities.parseActivities(response.getJsonResponse()); - } - - public Activity getSingleActivity(String personId, String activityId) throws PublicApiException - { - HttpResponse response = getSingle("people", personId, "activities", activityId, "Failed to get activities"); - Activity activity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); - return activity; - } - - public Activity update(String personId, Activity activity) throws PublicApiException - { - HttpResponse response = update("people", personId, "activities", String.valueOf(activity.getId()), activity.toJSON().toString(), "Failed to update activity"); - Activity retActivity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); - return retActivity; - } - - public Activity create(String personId, Activity activity) throws PublicApiException - { - HttpResponse response = create("people", personId, "activities", String.valueOf(activity.getId()), activity.toJSON().toString(), "Failed to create activity"); - Activity retActivity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); - return retActivity; - } - - public void remove(String personId, Activity activity) throws PublicApiException - { - remove("people", personId, "activities", String.valueOf(activity.getId()), "Failed to remove activity"); - } - } - - public class Comments extends AbstractProxy - { - public ListResponse getTenantComments(Map params) throws PublicApiException - { - HttpResponse response = getAll("comments", null, null, null, params, "Failed to get comments"); - return Comment.parseComments(null, response.getJsonResponse()); - } - - public Comment getTenantComment(String commentId) throws PublicApiException - { - HttpResponse response = getSingle("comments", commentId, null, null, "Failed to get comment"); - Comment comment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); - return comment; - } - - public Comment updateTenantComment(Comment comment) throws PublicApiException - { - HttpResponse response = update("comments", comment.getId(), null, null, comment.toJSON(true).toString(), "Failed to update comment"); - Comment retComment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); - return retComment; - } - - public Comment createTenantComment(Comment comment) throws PublicApiException - { - HttpResponse response = create("comments", null, null, null, comment.toJSON(true).toString(), "Failed to create comment"); - Comment retComment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); - return retComment; - } - - public void removeTenantComment(Comment comment) throws PublicApiException - { - remove("comments", comment.getId(), null, null, "Failed to remove comment"); - } - - public ListResponse getNodeComments(String nodeId, Map params) throws PublicApiException - { - HttpResponse response = getAll("nodes", nodeId, "comments", null, params, "Failed to get comments"); - return Comment.parseComments(nodeId, response.getJsonResponse()); - } - - public Comment getNodeComment(String nodeId) throws PublicApiException - { - HttpResponse response = getSingle("nodes", nodeId, null, null, "Failed to get comment"); - Comment comment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return comment; - } - - public Comment updateNodeComment(String nodeId, String commentId, Comment comment) throws PublicApiException - { - HttpResponse response = update("nodes", nodeId, "comments", commentId, comment.toJSON(true).toString(), "Failed to update comment"); - Comment retComment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return retComment; - } - - public Comment createNodeComment(String nodeId, Comment comment) throws PublicApiException - { - HttpResponse response = create("nodes", nodeId, "comments", null, comment.toJSON(true).toString(), "Failed to create comment"); - Comment retComment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return retComment; - } - - public void removeNodeComment(String nodeId, String commentId) throws PublicApiException - { - remove("nodes", nodeId, "comments", commentId, "Failed to remove comment"); - } - } - - public class Tags extends AbstractProxy - { - public ListResponse getTags(Map params) throws PublicApiException - { - HttpResponse response = getAll("tags", null, null, null, params, "Failed to get tags"); - return Tag.parseTags(null, response.getJsonResponse()); - } - - public Tag getSingle(String tagId) throws PublicApiException - { - HttpResponse response = getSingle("tags", tagId, null, null, "Failed to get tag"); - Tag tag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); - return tag; - } - - public Tag update(Tag tag) throws PublicApiException - { - HttpResponse response = update("tags", tag.getId(), null, null, tag.toJSON().toString(), "Failed to update tag"); - Tag retTag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); - return retTag; - } - -// public Tag create(Tag tag) throws PublicApiException -// { -// HttpResponse response = create("tags", tag.getTagId(), null, null, tag.toJSON().toString(), "Failed to create tag"); -// Tag retTag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); -// return retTag; -// } - - public void remove(Tag tag) throws PublicApiException - { - remove("tags", tag.getId(), null, null, "Failed to remove tag"); - } - } - - public class Nodes extends AbstractProxy - { - public ListResponse getNodeTags(String nodeId, Map params) throws PublicApiException - { - HttpResponse response = getAll("nodes", nodeId, "tags", null, params, "Failed to get node tags"); - return Tag.parseTags(nodeId, response.getJsonResponse()); - } - - public void removeNodeTag(String nodeId, String tagId) throws PublicApiException - { - remove("nodes", nodeId, "tags", tagId, "Failed to remove node tag"); - } - - public Tag createNodeTag(String nodeId, Tag tag) throws PublicApiException - { - HttpResponse response = create("nodes", nodeId, "tags", null, tag.toJSON().toString(), "Failed to create node tag"); - Tag tagRet = Tag.parseTag(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return tagRet; - } - - public NodeRating getNodeRating(String nodeId, String ratingId) throws PublicApiException - { - HttpResponse response = getSingle("nodes", nodeId, "ratings", ratingId, "Failed to get node ratings"); - return NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - } - - public ListResponse getNodeRatings(String nodeId, Map params) throws PublicApiException - { - HttpResponse response = getAll("nodes", nodeId, "ratings", null, params, "Failed to get node ratings"); - return NodeRating.parseNodeRatings(nodeId, response.getJsonResponse()); - } - - public NodeRating updateNodeRating(String nodeId, NodeRating nodeRating) throws PublicApiException - { - HttpResponse response = update("nodes", nodeId, "ratings", nodeRating.getId(), nodeRating.toJSON().toString(), "Failed to update node rating"); - NodeRating nodeRatingRet = NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return nodeRatingRet; - } - - public NodeRating createNodeRating(String nodeId, NodeRating nodeRating) throws PublicApiException - { - HttpResponse response = create("nodes", nodeId, "ratings", null, nodeRating.toJSON().toString(), "Failed to create node rating"); - NodeRating nodeRatingRet = NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); - return nodeRatingRet; - } - - public void removeNodeRating(String nodeId, NodeRating rating) throws PublicApiException - { - remove("nodes", nodeId, "ratings", rating.getId(), "Failed to remove node rating"); - } - } - - public static class ExpectedPaging - { - private int skipCount; - private int maxItems; - private Integer totalItems; - private boolean hasMoreItems; - private int count; - - public ExpectedPaging() - { - } - - public ExpectedPaging(int skipCount, int maxItems, Integer totalItems, boolean hasMoreItems, int count) - { - super(); - this.skipCount = skipCount; - this.maxItems = maxItems; - this.totalItems = totalItems; - this.hasMoreItems = hasMoreItems; - this.count = count; - } - - public Integer getSkipCount() - { - return skipCount; - } - - public Integer getMaxItems() - { - return maxItems; - } - - public Integer getTotalItems() - { - return totalItems; - } - - public Boolean getHasMoreItems() - { - return hasMoreItems; - } - - public Integer getCount() - { - return count; - } - - public void setCount(Integer count) - { - this.count = count; - } - - public void setHasMoreItems(Boolean hasMoreItems) - { - this.hasMoreItems = hasMoreItems; - } - - public void setTotalItems(Integer totalItems) - { - this.totalItems = totalItems; - } - - public void setSkipCount(Integer skipCount) - { - this.skipCount = skipCount; - } - - public void setMaxItems(Integer maxItems) - { - this.maxItems = maxItems; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + count; - result = prime * result + (hasMoreItems ? 1231 : 1237); - result = prime * result + maxItems; - result = prime * result + skipCount; - result = prime * result - + ((totalItems == null) ? 0 : totalItems.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ExpectedPaging other = (ExpectedPaging) obj; - if (count != other.count) - return false; - if (hasMoreItems != other.hasMoreItems) - return false; - if (maxItems != other.maxItems) - return false; - if (skipCount != other.skipCount) - return false; - if (totalItems == null) { - if (other.totalItems != null) - return false; - } else if (!totalItems.equals(other.totalItems)) - return false; - return true; - } - - @Override - public String toString() - { - return "ExpectedPaging [skipCount=" - + skipCount - + ", maxItems=" - + maxItems - + ", " - + (totalItems != null ? "totalItems=" + totalItems + ", " - : "") + "hasMoreItems=" + hasMoreItems + ", count=" - + count + "]"; - } - - public static ExpectedPaging parsePagination(JSONObject jsonList) - { - ExpectedPaging paging = new ExpectedPaging(); - JSONObject jsonPagination = (JSONObject)jsonList.get("pagination"); - if(jsonPagination != null) - { - Long count = (Long)jsonPagination.get("count"); - paging.setCount(count.intValue()); - - Boolean hasMoreItems = (Boolean)jsonPagination.get("hasMoreItems"); - paging.setHasMoreItems(hasMoreItems); - - Long totalItems = (Long)jsonPagination.get("totalItems"); - if(totalItems != null) - { - paging.setTotalItems(totalItems.intValue()); - } - - Long maxItems = (Long)jsonPagination.get("maxItems"); - paging.setMaxItems(maxItems.intValue()); - - Long skipCount = (Long)jsonPagination.get("skipCount"); - paging.setSkipCount(skipCount.intValue()); - } - return paging; - } - - public static ExpectedPaging getExpectedPaging(Integer skipCount, Integer maxItems, int total, Integer expectedTotal) - { - int skip = skipCount != null ? skipCount : org.alfresco.rest.framework.resource.parameters.Paging.DEFAULT_SKIP_COUNT; - int max = maxItems != null ? maxItems : org.alfresco.rest.framework.resource.parameters.Paging.DEFAULT_MAX_ITEMS; - int expectedCount = -1; - int end = skip + max; - if(end < 0 || end > total) - { - // overflow or greater than the total - expectedCount = total - skip; - end = total; - } - else - { - expectedCount = max; - } - if(expectedCount < 0) - { - expectedCount = 0; - } - boolean hasMore = end < total; - ExpectedPaging expectedPaging = new ExpectedPaging(skip, max, expectedTotal, hasMore, expectedCount); - return expectedPaging; - } - } - - public class CmisSession - { - private Session session; - - public CmisSession(Session session) - { - this.session = session; - } - - public Session getCMISSession() - { - return session; - } - - public CmisObject getObject(String objectId) - { - RequestContext rc = getRequestContext(); - OperationContext ctx = rc.getCmisOperationCtxOverride(); - if(ctx == null) - { - ctx = new OperationContextImpl(); - } - - CmisObject res = session.getObject(objectId, ctx); - return res; - } - - public CmisObject getObjectByPath(String path) - { - OperationContextImpl ctx = new OperationContextImpl(); - CmisObject res = session.getObjectByPath(path, ctx); - return res; - } - - public List getObjectParents(String objectId) - { - CmisObject o = session.getObject(objectId); - if(o instanceof FileableCmisObject) - { - FileableCmisObject f = (FileableCmisObject)o; - - OperationContextImpl ctx = new OperationContextImpl(); - List res = f.getParents(ctx); - return res; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a fileable cmis object"); - } - } - - public void deleteContent(String objectId, boolean refresh) - { - CmisObject o = getObject(objectId); - - if(o instanceof Document) - { - Document d = (Document)o; - d.deleteContentStream(refresh); - } - else - { - throw new IllegalArgumentException("Object does not exists or is not a document"); - } - } - - public ContentData getContent(String objectId) throws IOException - { - CmisObject o = getObject(objectId); - if(o instanceof Document) - { - Document d = (Document)o; - ContentStream res = d.getContentStream(); - ContentData c = new ContentData(res); - return c; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a document"); - } - } - - public void putContent(String objectId, String filename, BigInteger length, String mimetype, InputStream content, boolean overwrite) - { - CmisObject o = getObject(objectId); - if(o instanceof Document) - { - Document d = (Document)o; - ContentStream contentStream = new ContentStreamImpl(filename, length, mimetype, content); - try - { - d.setContentStream(contentStream, overwrite); - } - finally - { - try - { - contentStream.getStream().close(); - } - catch (Exception e) - { - } - } - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a document"); - } - } - - public void addChildren(FolderNode f, Tree t) - { - FileableCmisObject fco = t.getItem(); - CMISNode child = CMISNode.createNode(fco); - - if(child instanceof FolderNode) - { - f.addFolder((FolderNode)child); - for(Tree c : t.getChildren()) - { - addChildren((FolderNode)child, c); - } - } - else - { - f.addNode(child); - } - } - - public boolean objectExists(String objectId) - { - CmisObject o = getObject(objectId); - return(o != null); - } - - public FolderNode getRootFolder() - { - Folder rootFolder = session.getRootFolder(); - - FolderNode ret = (FolderNode)CMISNode.createNode(rootFolder); - return ret; - } - - public FolderNode getDescendants(String folderId, int depth) - { - Session session = getCMISSession(); - - CmisObject o = session.getObject(folderId); - if(o instanceof Folder) - { - Folder f = (Folder)o; - - OperationContextImpl ctx = new OperationContextImpl(); - List> res = f.getDescendants(depth, ctx); - FolderNode ret = (FolderNode)CMISNode.createNode(f); - for(Tree t : res) - { - addChildren(ret, t); - } - - return ret; - } - else - { - throw new IllegalArgumentException("Folder does not exist or is not a folder"); - } - } - - public ItemIterable getTypeChildren(String typeId, boolean includePropertyDefinitions) - { - ItemIterable res = session.getTypeChildren(typeId, includePropertyDefinitions); - return res; - } - - public List> getTypeDescendants(String typeId, int depth, boolean includePropertyDefinitions) - { - List> res = session.getTypeDescendants(typeId, depth, includePropertyDefinitions); - return res; - } - - public ObjectType getTypeDefinition(String typeId) - { - ObjectType res = session.getTypeDefinition(typeId); - return res; - } - - public void removeAllVersions(String objectId) - { - CmisObject o = getObject(objectId); - if(o instanceof Document) - { - Document d = (Document)o; - d.deleteAllVersions(); - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a document"); - } - } - - public List query(String query, boolean searchAllVersions, long skipCount, int maxItems) - { - OperationContext ctx = new OperationContextImpl(); - ItemIterable res = session.query(query, searchAllVersions, ctx); - res = res.skipTo(skipCount); - res = res.getPage(maxItems); - - List results = new ArrayList((int)res.getPageNumItems()); - - for(QueryResult r : res) - { - CMISNode n = CMISNode.createNode(r); - results.add(n); - } - - return results; - } - - public void removeObject(String objectId, boolean allVersions) - { - CmisObject o = getObject(objectId); - if(o != null) - { - o.delete(allVersions); - } - else - { - throw new IllegalArgumentException("Object does not exist"); - } - } - - public List removeTree(String objectId, boolean allVersions, UnfileObject unfile, boolean continueOnFailure) - { - CmisObject o = getObject(objectId); - if(o instanceof Folder) - { - Folder f = (Folder)o; - List res = f.deleteTree(allVersions, unfile, continueOnFailure); - return res; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a folder"); - } - } - - public void updateProperties(String objectId, Map properties, boolean refresh) - { - CmisObject o = getObject(objectId); - if(o != null) - { - o.updateProperties(properties, refresh); - } - else - { - throw new IllegalArgumentException("Object does not exist"); - } - } - - public List> getFolderTree(String folderId, int depth) - { - CmisObject o = session.getObject(folderId); - if(o instanceof Folder) - { - Folder f = (Folder)o; - - OperationContextImpl ctx = new OperationContextImpl(); - List> res = f.getFolderTree(depth, ctx); - return res; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a folder"); - } - } - - public FolderNode getChildren(String folderId, int skipCount, int maxItems) - { - CmisObject o = session.getObject(folderId); - if(o instanceof Folder) - { - Folder f = (Folder)o; - FolderNode ret = (FolderNode)CMISNode.createNode(f); - - OperationContextImpl ctx = new OperationContextImpl(); - ItemIterable res = f.getChildren(ctx); - res.skipTo(skipCount); - ItemIterable l = res.getPage(maxItems); - for(CmisObject c : l) - { - CMISNode child = null; - if(c.getBaseType() instanceof FolderTypeDefinition) - { - child = (FolderNode)CMISNode.createNode(c); - ret.addFolder((FolderNode)child); - } - else - { - child = CMISNode.createNode(c); - ret.addNode(child); - } - } - - return ret; - } - else - { - throw new IllegalArgumentException("Folder does not exist or is not a folder"); - } - } - - public ItemIterable getCheckedOutDocs() - { - OperationContextImpl ctx = new OperationContextImpl(); - ItemIterable res = session.getCheckedOutDocs(ctx); - return res; - } - - public List getAllVersions(String objectId) - { - CmisObject o = getObject(objectId); - if(o instanceof Document) - { - Document d = (Document)o; - OperationContext ctx = new OperationContextImpl(); - List res = d.getAllVersions(ctx); - return res; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a document"); - } - } - - public AllowableActions getAllowableActions(String objectId) - { - CmisObject o = getObject(objectId); - AllowableActions res = o.getAllowableActions(); - return res; - } - - public Document createDocument(String parentId, String name, Map properties, ContentStream contentStream, VersioningState versioningState) - { - CmisObject o = getObject(parentId); - - if(o instanceof Folder) - { - Folder f = (Folder)o; - - if(properties == null) - { - properties = new HashMap(); - } - String objectTypeId = (String)properties.get(PropertyIds.OBJECT_TYPE_ID); - String type = "cmis:document"; - if(objectTypeId == null) - { - objectTypeId = type; - } - if(objectTypeId.indexOf(type) == -1) - { - StringBuilder sb = new StringBuilder(objectTypeId); - if(sb.length() > 0) - { - sb.append(","); - } - sb.append(type); - objectTypeId = sb.toString(); - } - - properties.put(PropertyIds.NAME, name); - properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId); - - Document res = f.createDocument(properties, contentStream, versioningState); - return res; - } - else - { - throw new IllegalArgumentException("Parent does not exists or is not a folder"); - } - } - - public Folder createFolder(String folderId, String name, Map properties) - { - CmisObject o = getObject(folderId); - - if(o instanceof Folder) - { - Folder f = (Folder)o; - - if(properties == null) - { - properties = new HashMap(); - } - String objectTypeId = (String)properties.get(PropertyIds.OBJECT_TYPE_ID); - String type = "cmis:folder"; - if(objectTypeId == null) - { - objectTypeId = type; - } - if(objectTypeId.indexOf(type) == -1) - { - StringBuilder sb = new StringBuilder(objectTypeId); - if(sb.length() > 0) - { - sb.append(","); - } - sb.append(type); - objectTypeId = sb.toString(); - } - - properties.put(PropertyIds.NAME, name); - properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId); - - Folder res = f.createFolder(properties); - return res; - } - else - { - throw new IllegalArgumentException("Parent does not exist or is not a folder"); - } - } - - public ObjectId createRelationship(String sourceObjectId, String targetObjectId) - { - Map relProps = new HashMap(); - relProps.put("cmis:sourceId", sourceObjectId); - relProps.put("cmis:targetId", targetObjectId); - relProps.put("cmis:objectTypeId", "cmis:relationship"); - ObjectId res = session.createRelationship(relProps); - return res; - } - - public ObjectId checkoutObject(String objectId) - { - CmisObject o = getObject(objectId); - if(o instanceof Document) - { - Document d = (Document)o; - ObjectId res = d.checkOut(); - return res; - } - else - { - throw new IllegalArgumentException("Object does not exist or is not a document"); - } - } - } - - public static class Paging - { - private Integer skipCount; - private Integer maxItems; - private ExpectedPaging expectedPaging; - - public Paging() - { - } - - public Paging(Integer skipCount, Integer maxItems, ExpectedPaging expectedPaging) - { - super(); - this.skipCount = skipCount; - this.maxItems = maxItems; - this.expectedPaging = expectedPaging; - } - - public ExpectedPaging getExpectedPaging() - { - return expectedPaging; - } - - public void setExpectedPaging(ExpectedPaging expectedPaging) - { - this.expectedPaging = expectedPaging; - } - - public Integer getSkipCount() - { - return skipCount; - } - - public Integer getMaxItems() - { - return maxItems; - } - - public void setSkipCount(Integer skipCount) - { - this.skipCount = skipCount; - } - - public void setMaxItems(Integer maxItems) - { - this.maxItems = maxItems; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((maxItems == null) ? 0 : maxItems.hashCode()); - result = prime * result - + ((skipCount == null) ? 0 : skipCount.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Paging other = (Paging) obj; - if (maxItems == null) { - if (other.maxItems != null) - return false; - } else if (!maxItems.equals(other.maxItems)) - return false; - if (skipCount == null) { - if (other.skipCount != null) - return false; - } else if (!skipCount.equals(other.skipCount)) - return false; - return true; - } - - @Override - public String toString() - { - return "Paging [" - + (skipCount != null ? "skipCount=" + skipCount + ", " : "") - + (maxItems != null ? "maxItems=" + maxItems : "") + "]"; - } - } - - /** - * Representation of an error response. - * - * @author Jamal Kaabi-Mofrad - */ - public static class ExpectedErrorResponse - { - private String errorKey; - private int statusCode; - private String briefSummary; - private String stackTrace; - private Map additionalState; - private String descriptionURL; - private String logId; - - public ExpectedErrorResponse() - { - } - - public ExpectedErrorResponse(String errorKey, int statusCode, String briefSummary, StackTraceElement[] stackTrace, - Map additionalState, String logId) - { - super(); - this.errorKey = errorKey; - this.statusCode = statusCode; - this.briefSummary = briefSummary; - this.stackTrace = Arrays.toString(stackTrace); - this.additionalState = additionalState; - this.logId = logId; - } - - public String getErrorKey() - { - return errorKey; - } - - public ExpectedErrorResponse setErrorKey(String errorKey) - { - this.errorKey = errorKey; - return this; - } - - public int getStatusCode() - { - return statusCode; - } - - public ExpectedErrorResponse setStatusCode(int statusCode) - { - this.statusCode = statusCode; - return this; - } - - public String getBriefSummary() - { - return briefSummary; - } - - public ExpectedErrorResponse setBriefSummary(String briefSummary) - { - this.briefSummary = briefSummary; - return this; - } - - public String getLogId() { - return logId; - } - - public void setLogId(String logId) { - this.logId = logId; - } - - public String getStackTrace() - { - return stackTrace; - } - - public ExpectedErrorResponse setStackTrace(String stackTrace) - { - this.stackTrace = stackTrace; - return this; - } - - public Map getAdditionalState() - { - return additionalState; - } - - public ExpectedErrorResponse setAdditionalState(Map additionalState) - { - this.additionalState = additionalState; - return this; - } - - public String getDescriptionURL() - { - return descriptionURL; - } - - public ExpectedErrorResponse setDescriptionURL(String descriptionURL) - { - this.descriptionURL = descriptionURL; - return this; - } - - @Override - public String toString() - { - final StringBuilder sb = new StringBuilder(250); - sb.append("ExpectedErrorResponse [errorKey='").append(errorKey) - .append(", statusCode=").append(statusCode) - .append(", briefSummary='").append(briefSummary) - .append(", logId='").append(logId) - .append(", stackTrace='").append(stackTrace) - .append(", additionalState=").append(additionalState) - .append(", descriptionURL='").append(descriptionURL) - .append(']'); - return sb.toString(); - } - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.tests.client; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.math.BigInteger; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl; +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder; +import org.alfresco.rest.api.tests.client.data.Activities; +import org.alfresco.rest.api.tests.client.data.Activity; +import org.alfresco.rest.api.tests.client.data.CMISNode; +import org.alfresco.rest.api.tests.client.data.Comment; +import org.alfresco.rest.api.tests.client.data.ContentData; +import org.alfresco.rest.api.tests.client.data.Favourite; +import org.alfresco.rest.api.tests.client.data.FavouriteSite; +import org.alfresco.rest.api.tests.client.data.FolderNode; +import org.alfresco.rest.api.tests.client.data.MemberOfSite; +import org.alfresco.rest.api.tests.client.data.NodeRating; +import org.alfresco.rest.api.tests.client.data.Person; +import org.alfresco.rest.api.tests.client.data.PersonNetwork; +import org.alfresco.rest.api.tests.client.data.Preference; +import org.alfresco.rest.api.tests.client.data.Site; +import org.alfresco.rest.api.tests.client.data.SiteContainer; +import org.alfresco.rest.api.tests.client.data.SiteImpl; +import org.alfresco.rest.api.tests.client.data.SiteMember; +import org.alfresco.rest.api.tests.client.data.SiteMembershipRequest; +import org.alfresco.rest.api.tests.client.data.Tag; +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.chemistry.opencmis.client.api.Document; +import org.apache.chemistry.opencmis.client.api.FileableCmisObject; +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.chemistry.opencmis.client.api.ItemIterable; +import org.apache.chemistry.opencmis.client.api.ObjectId; +import org.apache.chemistry.opencmis.client.api.ObjectType; +import org.apache.chemistry.opencmis.client.api.OperationContext; +import org.apache.chemistry.opencmis.client.api.QueryResult; +import org.apache.chemistry.opencmis.client.api.Repository; +import org.apache.chemistry.opencmis.client.api.Session; +import org.apache.chemistry.opencmis.client.api.SessionFactory; +import org.apache.chemistry.opencmis.client.api.Tree; +import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; +import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.SessionParameter; +import org.apache.chemistry.opencmis.commons.data.AllowableActions; +import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.commons.enums.UnfileObject; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONObject; + +/** + * A client for interacting with the public api and returning Java objects. + * + * @author steveglover + * + */ +public class PublicApiClient +{ + private static final Log logger = LogFactory.getLog(PublicApiClient.class); + + private UserDataService userDataService; + private PublicApiHttpClient client; + + private Sites sites; + private Tags tags; + private Comments comments; + private Nodes nodes; + private People people; + private Favourites favourites; + private SiteMembershipRequests siteMembershipRequests; + private RawProxy rawProxy; + + private ThreadLocal rc = new ThreadLocal(); + + public PublicApiClient(PublicApiHttpClient client, UserDataService userDataService) + { + this.client = client; + this.userDataService = userDataService; + + init(); + } + + public void init() + { + sites = new Sites(); + tags = new Tags(); + comments = new Comments(); + nodes = new Nodes(); + people = new People(); + favourites = new Favourites(); + siteMembershipRequests = new SiteMembershipRequests(); + rawProxy = new RawProxy(); + } + + public void setRequestContext(RequestContext rc) + { + this.rc.set(rc); + } + + public RequestContext getRequestContext() + { + RequestContext context = rc.get(); + if(context == null) + { + throw new RuntimeException("Must set a request context"); + } + return context; + } + + protected UserData findUser(String userName) + { + return userDataService.findUserByUserName(userName); + } + + public RawProxy rawProxy() + { + return rawProxy; + } + + public People people() + { + return people; + } + + public Nodes nodes() + { + return nodes; + } + + public Sites sites() + { + return sites; + } + + public Favourites favourites() + { + return favourites; + } + + public SiteMembershipRequests siteMembershipRequests() + { + return siteMembershipRequests; + } + + public Tags tags() + { + return tags; + } + + public Comments comments() + { + return comments; + } + + public CmisSession createPublicApiCMISSession(Binding binding, String version) + { + return createPublicApiCMISSession(binding, version, null); + } + + public CmisSession createPublicApiCMISSession(Binding binding, String version, String objectFactoryName) + { + CmisSession cmisSession = null; + + RequestContext rc = getRequestContext(); + if(rc == null) + { + throw new RuntimeException("Must set a request context"); + } + + String networkId = rc.getNetworkId(); + String username = rc.getRunAsUser(); + UserData userData = findUser(rc.getRunAsUser()); + if(userData != null) + { + String password = userData.getPassword(); + + // default factory implementation + SessionFactory factory = SessionFactoryImpl.newInstance(); + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, username); + parameters.put(SessionParameter.PASSWORD, password); + + // connection settings + if(binding == Binding.atom) + { + parameters.put(SessionParameter.ATOMPUB_URL, client.getPublicApiCmisUrl(networkId, binding, version, null)); + parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); + } + else if(binding == Binding.browser) + { + parameters.put(SessionParameter.BROWSER_URL, client.getPublicApiCmisUrl(networkId, binding, version, null)); + parameters.put(SessionParameter.BINDING_TYPE, binding.getOpenCmisBinding().value()); + } + if(networkId != null) + { + parameters.put(SessionParameter.REPOSITORY_ID, networkId); + } + if(objectFactoryName != null) + { + parameters.put(SessionParameter.OBJECT_FACTORY_CLASS, objectFactoryName); + } + + // create session + Session session = factory.createSession(parameters); + + cmisSession = new CmisSession(session); + } + + return cmisSession; + } + + public CmisSession createCMISSession(String repositoryId, RequestContext rc) + { + CmisSession session = null; + + UserData userData = findUser(rc.getRunAsUser()); + if(userData != null) + { + session = createCMISSession(repositoryId, rc.getRunAsUser(), userData.getPassword()); + } + + return session; + } + + /** + * Get CMIS repositories (Enterprise AtomPub CMIS binding) + * + * @return List + */ + public List getCMISRepositories() + { + List repositories = null; + + RequestContext rc = getRequestContext(); + if(rc == null) + { + throw new RuntimeException("Must set a request context"); + } + + UserData userData = findUser(rc.getRunAsUser()); + if(userData != null) + { + // default factory implementation + SessionFactory factory = SessionFactoryImpl.newInstance(); + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, rc.getRunAsUser()); + parameters.put(SessionParameter.PASSWORD, userData.getPassword()); + + // connection settings + parameters.put(SessionParameter.ATOMPUB_URL, client.getCmisUrl(null, null)); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + + repositories = factory.getRepositories(parameters); + } + + return repositories; + } + + /** + * Create a CMIS session using Enterprise AtomPub binding. + * + * @param repositoryId String + * @param username String + * @param password String + * @return CmisSession + */ + public CmisSession createCMISSession(String repositoryId, String username, String password) + { + // default factory implementation + SessionFactory factory = SessionFactoryImpl.newInstance(); + Map parameters = new HashMap(); + + // user credentials + parameters.put(SessionParameter.USER, username); + parameters.put(SessionParameter.PASSWORD, password); + + // connection settings + parameters.put(SessionParameter.ATOMPUB_URL, client.getCmisUrl(repositoryId, null)); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + if(repositoryId != null) + { + parameters.put(SessionParameter.REPOSITORY_ID, repositoryId); + } + parameters.put(SessionParameter.OBJECT_FACTORY_CLASS, AlfrescoObjectFactoryImpl.class.getName()); + + // create session + Session session = factory.createSession(parameters); + + CmisSession cmisSession = new CmisSession(session); + return cmisSession; + } + + public CmisSession getCMISSession(Repository respository) + { + RequestContext rc = getRequestContext(); + if(rc == null) + { + throw new RuntimeException("Must set a request context"); + } + + CmisSession session = createCMISSession(respository.getId(), rc); + return session; + } + + public HttpResponse post(Binding cmisBinding, String version, String cmisOperation, String body) throws PublicApiException + { + try + { + HttpResponse response = client.post(getRequestContext(), cmisBinding, version, cmisOperation, body); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse put(Binding cmisBinding, String version, String cmisOperation, String body) throws PublicApiException + { + try + { + HttpResponse response = client.put(getRequestContext(), cmisBinding, version, cmisOperation, body); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse get(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException + { + try + { + HttpResponse response = client.get(getRequestContext(), cmisBinding, version, cmisOperation, parameters); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse patch(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException + { + try + { + HttpResponse response = client.patch(getRequestContext(), cmisBinding, version, cmisOperation); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse trace(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException + { + try + { + HttpResponse response = client.trace(getRequestContext(), cmisBinding, version, cmisOperation); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse options(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException + { + try + { + HttpResponse response = client.options(getRequestContext(), cmisBinding, version, cmisOperation); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse head(Binding cmisBinding, String version, String cmisOperation, Map parameters) throws PublicApiException + { + try + { + HttpResponse response = client.head(getRequestContext(), cmisBinding, version, cmisOperation); + + logger.debug(response.toString()); + + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, String body) throws IOException + { + HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId != null ? relationshipEntityId.toString() : null, body); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, + String body, String contentType) throws IOException + { + HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId != null ? relationshipEntityId.toString() : null, body, contentType); + + logger.debug(response.toString()); + + return response; + } + + + public HttpResponse post(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, + byte[] body, String contentType) throws IOException + { + HttpResponse response = client.post(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId != null ? relationshipEntityId.toString() : null, body, contentType); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse post(String urlSuffix, String body) throws IOException + { + HttpResponse response = client.post(getRequestContext(), urlSuffix, body); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse post(final Class c, Object entityId, Object relationshipEntityId, String body) throws IOException + { + HttpResponse response = client.post(c, getRequestContext(), entityId, relationshipEntityId, body); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse get(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException + { + HttpResponse response = client.get(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse getWithPassword(String scope, String password, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException + { + HttpResponse response = client.get(getRequestContext(), scope, password, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse get(String url, Map params) throws IOException + { + RequestContext rc = getRequestContext(); + HttpResponse response = client.get(url, rc, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse get(final Class c, final Object entityId, final Object relationshipEntityId, Map params) throws IOException + { + HttpResponse response = client.get(c, getRequestContext(), entityId, relationshipEntityId, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse put(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, String body, Map params) throws IOException + { + HttpResponse response = client.put(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse put(final Class c, Object entityId, Object relationshipEntityId, String body) throws IOException + { + HttpResponse response = client.put(c, getRequestContext(), entityId, relationshipEntityId, body); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse putBinary(String scope, int version, String entityCollectionName, Object entityId, String relationCollectionName, + Object relationshipEntityId, BinaryPayload payload, Map params) throws IOException + { + HttpResponse response = client.putBinary(getRequestContext(), scope, version, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, + payload, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse delete(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId) throws IOException + { + return delete(scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, null); + } + + public HttpResponse delete(String scope, int version, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId, Map params) throws IOException + { + HttpResponse response = client.delete(getRequestContext(), scope, version, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse put(final Class c, Object entityId, Object relationshipEntityId) throws IOException + { + HttpResponse response = client.delete(c, getRequestContext(), entityId, relationshipEntityId); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse execute(RequestBuilder requestBuilder) throws IOException + { + if (requestBuilder.getRequestContext() == null) + { + throw new RuntimeException("Must set a request context"); + } + HttpResponse response = client.execute(requestBuilder); + + logger.debug(response.toString()); + + return response; + } + + public HttpResponse index(Map params) throws IOException + { + HttpResponse response = get("", params); + return response; + } + + public List getNetworkIds(String version) + { + RequestContext rc = getRequestContext(); + + UserData userData = findUser(rc.getRunAsUser()); + if(userData == null) + { + throw new RuntimeException("Must provide a valid username"); + } + + SessionFactory factory = SessionFactoryImpl.newInstance(); + + Map parameters = new HashMap(); + + // connection settings + parameters.put(SessionParameter.ATOMPUB_URL, client.getPublicApiCmisUrl(null, Binding.atom, version, null)); + parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + + // user credentials + parameters.put(SessionParameter.USER, rc.getRunAsUser()); + parameters.put(SessionParameter.PASSWORD, userData.getPassword()); + List repositories = factory.getRepositories(parameters); + + List repositoryIds = new ArrayList(repositories.size()); + for(Repository repository : repositories) + { + repositoryIds.add(repository.getId()); + } + + return repositoryIds; + } + + public class AbstractProxy + { + public HttpResponse getAll(String entityCollectionName, String entityId, String relationCollectionName, String relationId, Map params, String errorMessage) throws PublicApiException + { + try + { + HttpResponse response = get("public", entityCollectionName, entityId, relationCollectionName, relationId, params); + + if (HttpServletResponse.SC_OK != response.getStatusCode()) + { + String msg = errorMessage + ": \n" + + " Response: " + response; + throw new PublicApiException(msg, response); + } + else + { + return response; + } + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse getSingle(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage) throws PublicApiException + { + return getSingle(entityCollectionName, entityId, relationCollectionName, relationId, errorMessage, HttpServletResponse.SC_OK); + } + + public HttpResponse getSingle(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage, int expectedStatus) throws PublicApiException + { + try + { + HttpResponse response = get("public", entityCollectionName, entityId, relationCollectionName, relationId, null); + checkStatus(errorMessage, expectedStatus, response); + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse update(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage) throws PublicApiException + { + return update(entityCollectionName, entityId, relationCollectionName, relationId, body, errorMessage, null); + } + + public HttpResponse update(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage, Map params) throws PublicApiException + { + try + { + HttpResponse response = put("public", entityCollectionName, entityId, relationCollectionName, relationId, body, params); + + if (HttpServletResponse.SC_OK != response.getStatusCode()) + { + String msg = errorMessage + ": \n" + + " Response: " + response; + throw new PublicApiException(msg, response); + } + else + { + return response; + } + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse create(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage) throws PublicApiException + { + return create(entityCollectionName, entityId, relationCollectionName, relationId, body, errorMessage, HttpServletResponse.SC_CREATED); + } + + public HttpResponse create(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String body, String errorMessage, int expectedStatus) throws PublicApiException + { + try + { + HttpResponse response = post("public", entityCollectionName, entityId, relationCollectionName, relationId, body); + checkStatus(errorMessage, expectedStatus, response); + return response; + } + catch (IOException e) + { + throw new PublicApiException(e); + } + } + + public HttpResponse remove(String entityCollectionName, String entityId, String relationCollectionName, String relationId, String errorMessage) throws PublicApiException + { + return remove(entityCollectionName, entityId, relationCollectionName, relationId, null, errorMessage, HttpServletResponse.SC_NO_CONTENT); + } + + public HttpResponse remove(String entityCollectionName, String entityId, String relationCollectionName, String relationId, Map params, String errorMessage, int expectedStatus) throws PublicApiException + { + try + { + HttpResponse response = delete("public", 1, entityCollectionName, entityId, relationCollectionName, relationId, params); + checkStatus(errorMessage, expectedStatus, response); + return response; + } + catch(IOException e) + { + throw new PublicApiException(e); + } + } + + public JSONObject parseListSource(JSONObject jsonResponse) + { + JSONObject jsonList = (JSONObject)jsonResponse.get("list"); + assertNotNull(jsonList); + + JSONObject source = (JSONObject)jsonList.get("source"); + assertNotNull(source); + return source; + } + + public void checkStatus(String errorMessage, int expectedStatus, HttpResponse response) throws PublicApiException + { + int actualStatus = response.getStatusCode(); + if ((expectedStatus > 0) && (expectedStatus != actualStatus)) + { + String msg = "Status code " + actualStatus + " returned, but expected " + expectedStatus + ": \n"+ + errorMessage + ": \n" + " Response: " + response; + throw new PublicApiException(msg, response); + } + } + } + + public static class ListResponse + { + private ExpectedPaging paging; + private List list; + + public ListResponse(ExpectedPaging paging, List list) + { + super(); + this.paging = paging; + this.list = list; + } + + public ExpectedPaging getPaging() + { + return paging; + } + + public List getList() + { + return list; + } + } + + public class Sites extends AbstractProxy + { + public ListResponse getSites(Map params) throws PublicApiException + { + HttpResponse response = getAll("sites", null, null, null, params, "Failed to get sites"); + return SiteImpl.parseSites(response.getJsonResponse()); + } + + public Site getSite(String siteId) throws PublicApiException + { + return getSite(siteId, 200); + } + + public Site getSite(String siteId, int expectedStatus) throws PublicApiException + { + HttpResponse response = getSingle("sites", siteId, null, null, "Failed to get site " + siteId, expectedStatus); + if ((response != null) && (response.getJsonResponse() != null)) + { + return SiteImpl.parseSite((JSONObject)response.getJsonResponse().get("entry")); + } + else + { + return null; + } + } + + public Site createSite(Site site) throws PublicApiException + { + return createSite(site, 201); + } + + public Site createSite(Site site, int expectedStatus) throws PublicApiException + { + HttpResponse response = create("sites", null, null, null, site.toJSON().toString(), "Failed to create site "+site.getTitle(), expectedStatus); + return SiteImpl.parseSite((JSONObject)response.getJsonResponse().get("entry")); + } + + public void removeSite(String siteId) throws PublicApiException + { + removeSite(siteId, false, 204); + } + + public void removeSite(String siteId, boolean permanent, int expectedStatus) throws PublicApiException + { + Map params = null; + if (permanent) + { + params = Collections.singletonMap("permanent", "true"); + } + remove("sites", siteId, null, null, params, "Failed to remove site", expectedStatus); + } + + public ListResponse getSiteContainers(String siteId, Map params) throws PublicApiException + { + HttpResponse response = getAll("sites", siteId, "containers", null, params, "Failed to get site containers"); + return SiteContainer.parseSiteContainers(response.getJsonResponse()); + } + + public SiteContainer getSingleSiteContainer(String siteId, String containerId) throws PublicApiException + { + HttpResponse response = getSingle("sites", siteId, "containers", containerId, "Failed to get site container"); + SiteContainer siteContainer = SiteContainer.parseSiteContainer(siteId, (JSONObject)response.getJsonResponse().get("entry")); + return siteContainer; + } + + public SiteContainer updateSiteContainer(SiteContainer siteContainer) throws PublicApiException + { + HttpResponse response = update("sites", siteContainer.getSiteId(), "containers", siteContainer.getId(), siteContainer.toJSON().toString(), "Failed to update site container"); + SiteContainer retSiteContainer = SiteContainer.parseSiteContainer(siteContainer.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); + return retSiteContainer; + } + + public SiteContainer createSiteContainer(SiteContainer siteContainer) throws PublicApiException + { + HttpResponse response = create("sites", siteContainer.getSiteId(), "containers", null, siteContainer.toJSON().toString(), "Failed to create site container"); + SiteContainer retSiteContainer = SiteContainer.parseSiteContainer(siteContainer.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); + return retSiteContainer; + } + + public void removeSiteContainer(SiteContainer siteContainer) throws PublicApiException + { + remove("sites", siteContainer.getSiteId(), "containers", siteContainer.getId(), "Failed to remove site container"); + } + + public ListResponse getSiteMembers(String siteId, Map params) throws PublicApiException + { + HttpResponse response = getAll("sites", siteId, "members", null, params, "Failed to get all site members"); + return SiteMember.parseSiteMembers(siteId, response.getJsonResponse()); + } + + public SiteMember getSingleSiteMember(String siteId, String personId) throws PublicApiException + { + HttpResponse response = getSingle("sites", siteId, "members", personId, "Failed to get site member"); + SiteMember retSiteMember = SiteMember.parseSiteMember(siteId, (JSONObject)response.getJsonResponse().get("entry")); + return retSiteMember; + } + + public SiteMember updateSiteMember(String siteId, SiteMember siteMember) throws PublicApiException + { + HttpResponse response = update("sites", siteId, "members", siteMember.getMemberId(), siteMember.toJSON().toString(), "Failed to update site member"); + SiteMember retSiteMember = SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); + return retSiteMember; + } + + public SiteMember createSiteMember(String siteId, SiteMember siteMember) throws PublicApiException + { + HttpResponse response = create("sites", siteId, "members", null, siteMember.postJSON().toString(), "Failed to create site member"); + SiteMember retSiteMember = SiteMember.parseSiteMember(siteMember.getSiteId(), (JSONObject)response.getJsonResponse().get("entry")); + return retSiteMember; + } + + public void removeSiteMember(String siteId, SiteMember siteMember) throws PublicApiException + { + remove("sites", siteId, "members", siteMember.getMemberId(), "Failed to remove site member"); + } + + public ListResponse getPersonSites(String personId, Map params) throws PublicApiException + { + HttpResponse response = getAll("people", personId, "sites", null, params, "Failed to get person sites"); + return MemberOfSite.parseMemberOfSites(response.getJsonResponse()); + } + + public MemberOfSite getPersonSite(String personId, String siteId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, "sites", siteId, "Failed to get person site" + siteId); + return MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); + } + + public MemberOfSite updatePersonSite(String personId, SiteMember siteMember) throws PublicApiException + { + HttpResponse response = update("people", personId, "sites", siteMember.getSiteId(), siteMember.toJSON().toString(), "Failed to update person site"); + MemberOfSite retSiteMember = MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); + return retSiteMember; + } + + public MemberOfSite createPersonSite(String personId, SiteMember siteMember) throws PublicApiException + { + HttpResponse response = create("people", personId, "sites", null, siteMember.toJSON().toString(), "Failed to create person site"); + MemberOfSite retSiteMember = MemberOfSite.parseMemberOfSite((JSONObject)response.getJsonResponse().get("entry")); + return retSiteMember; + } + + public void removePersonSite(String personId, SiteMember siteMember) throws PublicApiException + { + remove("people", personId, "sites", siteMember.getSiteId(), "Failed to remove person site"); + } + + public ListResponse getFavouriteSites(String personId, Map params) throws PublicApiException + { + HttpResponse response = getAll("people", personId, "favorite-sites", null, params, "Failed to get favourite sites"); + return FavouriteSite.parseFavouriteSites(response.getJsonResponse()); + } + + public FavouriteSite getSingleFavouriteSite(String personId, String siteId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, "favorite-sites", siteId, "Failed to get favourite site"); + FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); + return favouriteSite; + } + + public FavouriteSite updateFavouriteSite(String personId, FavouriteSite site) throws PublicApiException + { + HttpResponse response = update("people", personId, "favorite-sites", site.getSiteId(), site.toJSON().toString(), "Failed to update favourite site"); + FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); + return favouriteSite; + } + + public FavouriteSite createFavouriteSite(String personId, FavouriteSite site) throws PublicApiException + { + HttpResponse response = create("people", personId, "favorite-sites", null, site.toJSON().toString(), "Failed to create favourite site"); + FavouriteSite favouriteSite = FavouriteSite.parseFavouriteSite((JSONObject)response.getJsonResponse().get("entry")); + return favouriteSite; + } + + public void removeFavouriteSite(String personId, FavouriteSite site) throws PublicApiException + { + remove("people", personId, "favorite-sites", site.getSiteId(), "Failed to remove favourite site"); + } + } + + public class SiteMembershipRequests extends AbstractProxy + { + public SiteMembershipRequest getSiteMembershipRequest(String personId, String siteId) throws PublicApiException, ParseException + { + HttpResponse response = getSingle("people", personId, "site-membership-requests", siteId, "Failed to get siteMembershipRequest"); + return SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); + } + + public ListResponse getSiteMembershipRequests(String personId, Map params) throws PublicApiException, ParseException + { + HttpResponse response = getAll("people", personId, "site-membership-requests", null, params, "Failed to get siteMembershipRequests"); + return SiteMembershipRequest.parseSiteMembershipRequests(personId, response.getJsonResponse()); + } + + public SiteMembershipRequest createSiteMembershipRequest(String personId, SiteMembershipRequest siteMembershipRequest) throws PublicApiException, ParseException + { + HttpResponse response = create("people", personId, "site-membership-requests", null, siteMembershipRequest.toJSON().toString(), "Failed to create siteMembershipRequest"); + SiteMembershipRequest ret = SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); + return ret; + } + + public SiteMembershipRequest updateSiteMembershipRequest(String personId, SiteMembershipRequest siteMembershipRequest) throws PublicApiException, ParseException + { + HttpResponse response = update("people", personId, "site-membership-requests", siteMembershipRequest.getId(), siteMembershipRequest.toJSON().toString(), "Failed to update siteMembershipRequest"); + SiteMembershipRequest ret = SiteMembershipRequest.parseSiteMembershipRequest(personId, (JSONObject)response.getJsonResponse().get("entry")); + return ret; + } + + public void cancelSiteMembershipRequest(String personId, String siteMembershipRequestId) throws PublicApiException + { + remove("people", personId, "site-membership-requests", siteMembershipRequestId, "Failed to cancel siteMembershipRequest"); + } + } + + public class RawProxy extends AbstractProxy + { + } + + public class Favourites extends AbstractProxy + { + public ListResponse getFavourites(String personId, Map params) throws PublicApiException, ParseException + { + HttpResponse response = getAll("people", personId, "favorites", null, params, "Failed to get favourites"); + return Favourite.parseFavourites(response.getJsonResponse()); + } + + public Favourite getFavourite(String personId, String favouriteId) throws PublicApiException, ParseException + { + HttpResponse response = getSingle("people", personId, "favorites", favouriteId, "Failed to get favourite " + favouriteId); + return Favourite.parseFavourite((JSONObject)response.getJsonResponse().get("entry")); + } + + public Favourite createFavourite(String personId, Favourite favourite) throws PublicApiException, ParseException + { + HttpResponse response = create("people", personId, "favorites", null, favourite.toJSON().toString(), "Failed to create favourite"); + Favourite ret = Favourite.parseFavourite((JSONObject)response.getJsonResponse().get("entry")); + return ret; + } + + public void removeFavourite(String personId, String favouriteId) throws PublicApiException + { + remove("people", personId, "favorites", favouriteId, "Failed to remove favourite"); + } + } + + public class People extends AbstractProxy + { + public ListResponse getPeople(Map params) throws PublicApiException + { + HttpResponse response = getAll("people", null, null, null, params, "Failed to get people"); + return Person.parsePeople(response.getJsonResponse()); + } + + public Person getPerson(String personId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, null, null, "Failed to get person"); + + if(logger.isDebugEnabled()) + { + logger.debug(response); + } + System.out.println(response); + + Person site = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); + return site; + } + + public Person update(String personId, Person person, boolean fullVisibility) throws PublicApiException + { + HttpResponse response = update("people", person.getId(), null, null, person.toJSON(fullVisibility).toString(), "Failed to update person"); + Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); + return retSite; + } + + public Person create(Person person, boolean fullVisibility) throws PublicApiException + { + HttpResponse response = create("people", null, null, null, person.toJSON(fullVisibility).toString(), "Failed to create person"); + Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); + return retSite; + } + + public void remove(Person person) throws PublicApiException + { + remove("people", person.getId(), null, null, "Failed to remove person"); + } + + public ListResponse getPreferences(String personId, Map params) throws PublicApiException + { + HttpResponse response = getAll("people", personId, "preferences", null, params, "Failed to get person preferences"); + return Preference.parsePreferences(response.getJsonResponse()); + } + + public Preference getPreference(String personId, String preferenceId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, "preferences", preferenceId, "Failed to get person preference"); + Preference pref = Preference.parsePreference((JSONObject)response.getJsonResponse().get("entry")); + return pref; + } + + public Person updatePreference(String personId, Preference preference) throws PublicApiException + { + HttpResponse response = update("people", personId, "preferences", preference.getId(), preference.toJSON().toString(), "Failed to update person preference"); + Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); + return retSite; + } + + public Person createPreference(String personId, Preference preference) throws PublicApiException + { + HttpResponse response = create("people", personId, "preferences", null, preference.toJSON().toString(), "Failed to create person preference"); + Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); + return retSite; + } + + public void removePreference(String personId, Preference preference) throws PublicApiException + { + remove("people", personId, "preferences", preference.getId(), "Failed to remove person preference"); + } + + public ListResponse getNetworkMemberships(String personId, Map params) throws PublicApiException + { + HttpResponse response = getAll("people", personId, "networks", null, params, "Failed to get network members"); + return PersonNetwork.parseNetworkMembers(response.getJsonResponse()); + } + + public PersonNetwork getNetworkMembership(String personId, String networkId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, "networks", networkId, "Failed to get network member"); + PersonNetwork networkMember = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); + return networkMember; + } + + public PersonNetwork updateNetworkMembership(String personId, PersonNetwork networkMember) throws PublicApiException + { + HttpResponse response = update("people", personId, "networks", networkMember.getId(), networkMember.toJSON().toString(), "Failed to update network member"); + PersonNetwork retNetwork = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); + return retNetwork; + } + + public PersonNetwork createNetworkMembership(String personId, PersonNetwork network) throws PublicApiException + { + HttpResponse response = create("people", personId, "networks", null, network.toJSON().toString(), "Failed to create network member"); + PersonNetwork retNetwork = PersonNetwork.parseNetworkMember((JSONObject)response.getJsonResponse().get("entry")); + return retNetwork; + } + + public void removeNetworkMembership(String personId, PersonNetwork networkMember) throws PublicApiException + { + remove("people", personId, "networks", networkMember.getId(), "Failed to remove network member"); + } + + public ListResponse getActivities(String personId, Map params) throws PublicApiException + { + HttpResponse response = getAll("people", personId, "activities", null, params, "Failed to get activities"); + return Activities.parseActivities(response.getJsonResponse()); + } + + public Activity getSingleActivity(String personId, String activityId) throws PublicApiException + { + HttpResponse response = getSingle("people", personId, "activities", activityId, "Failed to get activities"); + Activity activity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); + return activity; + } + + public Activity update(String personId, Activity activity) throws PublicApiException + { + HttpResponse response = update("people", personId, "activities", String.valueOf(activity.getId()), activity.toJSON().toString(), "Failed to update activity"); + Activity retActivity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); + return retActivity; + } + + public Activity create(String personId, Activity activity) throws PublicApiException + { + HttpResponse response = create("people", personId, "activities", String.valueOf(activity.getId()), activity.toJSON().toString(), "Failed to create activity"); + Activity retActivity = Activity.parseActivity((JSONObject)response.getJsonResponse().get("entry")); + return retActivity; + } + + public void remove(String personId, Activity activity) throws PublicApiException + { + remove("people", personId, "activities", String.valueOf(activity.getId()), "Failed to remove activity"); + } + } + + public class Comments extends AbstractProxy + { + public ListResponse getTenantComments(Map params) throws PublicApiException + { + HttpResponse response = getAll("comments", null, null, null, params, "Failed to get comments"); + return Comment.parseComments(null, response.getJsonResponse()); + } + + public Comment getTenantComment(String commentId) throws PublicApiException + { + HttpResponse response = getSingle("comments", commentId, null, null, "Failed to get comment"); + Comment comment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); + return comment; + } + + public Comment updateTenantComment(Comment comment) throws PublicApiException + { + HttpResponse response = update("comments", comment.getId(), null, null, comment.toJSON(true).toString(), "Failed to update comment"); + Comment retComment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); + return retComment; + } + + public Comment createTenantComment(Comment comment) throws PublicApiException + { + HttpResponse response = create("comments", null, null, null, comment.toJSON(true).toString(), "Failed to create comment"); + Comment retComment = Comment.parseComment(null, (JSONObject)response.getJsonResponse().get("entry")); + return retComment; + } + + public void removeTenantComment(Comment comment) throws PublicApiException + { + remove("comments", comment.getId(), null, null, "Failed to remove comment"); + } + + public ListResponse getNodeComments(String nodeId, Map params) throws PublicApiException + { + HttpResponse response = getAll("nodes", nodeId, "comments", null, params, "Failed to get comments"); + return Comment.parseComments(nodeId, response.getJsonResponse()); + } + + public Comment getNodeComment(String nodeId) throws PublicApiException + { + HttpResponse response = getSingle("nodes", nodeId, null, null, "Failed to get comment"); + Comment comment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return comment; + } + + public Comment updateNodeComment(String nodeId, String commentId, Comment comment) throws PublicApiException + { + HttpResponse response = update("nodes", nodeId, "comments", commentId, comment.toJSON(true).toString(), "Failed to update comment"); + Comment retComment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return retComment; + } + + public Comment createNodeComment(String nodeId, Comment comment) throws PublicApiException + { + HttpResponse response = create("nodes", nodeId, "comments", null, comment.toJSON(true).toString(), "Failed to create comment"); + Comment retComment = Comment.parseComment(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return retComment; + } + + public void removeNodeComment(String nodeId, String commentId) throws PublicApiException + { + remove("nodes", nodeId, "comments", commentId, "Failed to remove comment"); + } + } + + public class Tags extends AbstractProxy + { + public ListResponse getTags(Map params) throws PublicApiException + { + HttpResponse response = getAll("tags", null, null, null, params, "Failed to get tags"); + return Tag.parseTags(null, response.getJsonResponse()); + } + + public Tag getSingle(String tagId) throws PublicApiException + { + HttpResponse response = getSingle("tags", tagId, null, null, "Failed to get tag"); + Tag tag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); + return tag; + } + + public Tag update(Tag tag) throws PublicApiException + { + HttpResponse response = update("tags", tag.getId(), null, null, tag.toJSON().toString(), "Failed to update tag"); + Tag retTag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); + return retTag; + } + +// public Tag create(Tag tag) throws PublicApiException +// { +// HttpResponse response = create("tags", tag.getTagId(), null, null, tag.toJSON().toString(), "Failed to create tag"); +// Tag retTag = Tag.parseTag(null, (JSONObject)response.getJsonResponse().get("entry")); +// return retTag; +// } + + public void remove(Tag tag) throws PublicApiException + { + remove("tags", tag.getId(), null, null, "Failed to remove tag"); + } + } + + public class Nodes extends AbstractProxy + { + public ListResponse getNodeTags(String nodeId, Map params) throws PublicApiException + { + HttpResponse response = getAll("nodes", nodeId, "tags", null, params, "Failed to get node tags"); + return Tag.parseTags(nodeId, response.getJsonResponse()); + } + + public void removeNodeTag(String nodeId, String tagId) throws PublicApiException + { + remove("nodes", nodeId, "tags", tagId, "Failed to remove node tag"); + } + + public Tag createNodeTag(String nodeId, Tag tag) throws PublicApiException + { + HttpResponse response = create("nodes", nodeId, "tags", null, tag.toJSON().toString(), "Failed to create node tag"); + Tag tagRet = Tag.parseTag(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return tagRet; + } + + public NodeRating getNodeRating(String nodeId, String ratingId) throws PublicApiException + { + HttpResponse response = getSingle("nodes", nodeId, "ratings", ratingId, "Failed to get node ratings"); + return NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + } + + public ListResponse getNodeRatings(String nodeId, Map params) throws PublicApiException + { + HttpResponse response = getAll("nodes", nodeId, "ratings", null, params, "Failed to get node ratings"); + return NodeRating.parseNodeRatings(nodeId, response.getJsonResponse()); + } + + public NodeRating updateNodeRating(String nodeId, NodeRating nodeRating) throws PublicApiException + { + HttpResponse response = update("nodes", nodeId, "ratings", nodeRating.getId(), nodeRating.toJSON().toString(), "Failed to update node rating"); + NodeRating nodeRatingRet = NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return nodeRatingRet; + } + + public NodeRating createNodeRating(String nodeId, NodeRating nodeRating) throws PublicApiException + { + HttpResponse response = create("nodes", nodeId, "ratings", null, nodeRating.toJSON().toString(), "Failed to create node rating"); + NodeRating nodeRatingRet = NodeRating.parseNodeRating(nodeId, (JSONObject)response.getJsonResponse().get("entry")); + return nodeRatingRet; + } + + public void removeNodeRating(String nodeId, NodeRating rating) throws PublicApiException + { + remove("nodes", nodeId, "ratings", rating.getId(), "Failed to remove node rating"); + } + } + + public static class ExpectedPaging + { + private int skipCount; + private int maxItems; + private Integer totalItems; + private boolean hasMoreItems; + private int count; + + public ExpectedPaging() + { + } + + public ExpectedPaging(int skipCount, int maxItems, Integer totalItems, boolean hasMoreItems, int count) + { + super(); + this.skipCount = skipCount; + this.maxItems = maxItems; + this.totalItems = totalItems; + this.hasMoreItems = hasMoreItems; + this.count = count; + } + + public Integer getSkipCount() + { + return skipCount; + } + + public Integer getMaxItems() + { + return maxItems; + } + + public Integer getTotalItems() + { + return totalItems; + } + + public Boolean getHasMoreItems() + { + return hasMoreItems; + } + + public Integer getCount() + { + return count; + } + + public void setCount(Integer count) + { + this.count = count; + } + + public void setHasMoreItems(Boolean hasMoreItems) + { + this.hasMoreItems = hasMoreItems; + } + + public void setTotalItems(Integer totalItems) + { + this.totalItems = totalItems; + } + + public void setSkipCount(Integer skipCount) + { + this.skipCount = skipCount; + } + + public void setMaxItems(Integer maxItems) + { + this.maxItems = maxItems; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + count; + result = prime * result + (hasMoreItems ? 1231 : 1237); + result = prime * result + maxItems; + result = prime * result + skipCount; + result = prime * result + + ((totalItems == null) ? 0 : totalItems.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ExpectedPaging other = (ExpectedPaging) obj; + if (count != other.count) + return false; + if (hasMoreItems != other.hasMoreItems) + return false; + if (maxItems != other.maxItems) + return false; + if (skipCount != other.skipCount) + return false; + if (totalItems == null) { + if (other.totalItems != null) + return false; + } else if (!totalItems.equals(other.totalItems)) + return false; + return true; + } + + @Override + public String toString() + { + return "ExpectedPaging [skipCount=" + + skipCount + + ", maxItems=" + + maxItems + + ", " + + (totalItems != null ? "totalItems=" + totalItems + ", " + : "") + "hasMoreItems=" + hasMoreItems + ", count=" + + count + "]"; + } + + public static ExpectedPaging parsePagination(JSONObject jsonList) + { + ExpectedPaging paging = new ExpectedPaging(); + JSONObject jsonPagination = (JSONObject)jsonList.get("pagination"); + if(jsonPagination != null) + { + Long count = (Long)jsonPagination.get("count"); + paging.setCount(count.intValue()); + + Boolean hasMoreItems = (Boolean)jsonPagination.get("hasMoreItems"); + paging.setHasMoreItems(hasMoreItems); + + Long totalItems = (Long)jsonPagination.get("totalItems"); + if(totalItems != null) + { + paging.setTotalItems(totalItems.intValue()); + } + + Long maxItems = (Long)jsonPagination.get("maxItems"); + paging.setMaxItems(maxItems.intValue()); + + Long skipCount = (Long)jsonPagination.get("skipCount"); + paging.setSkipCount(skipCount.intValue()); + } + return paging; + } + + public static ExpectedPaging getExpectedPaging(Integer skipCount, Integer maxItems, int total, Integer expectedTotal) + { + int skip = skipCount != null ? skipCount : org.alfresco.rest.framework.resource.parameters.Paging.DEFAULT_SKIP_COUNT; + int max = maxItems != null ? maxItems : org.alfresco.rest.framework.resource.parameters.Paging.DEFAULT_MAX_ITEMS; + int expectedCount = -1; + int end = skip + max; + if(end < 0 || end > total) + { + // overflow or greater than the total + expectedCount = total - skip; + end = total; + } + else + { + expectedCount = max; + } + if(expectedCount < 0) + { + expectedCount = 0; + } + boolean hasMore = end < total; + ExpectedPaging expectedPaging = new ExpectedPaging(skip, max, expectedTotal, hasMore, expectedCount); + return expectedPaging; + } + } + + public class CmisSession + { + private Session session; + + public CmisSession(Session session) + { + this.session = session; + } + + public Session getCMISSession() + { + return session; + } + + public CmisObject getObject(String objectId) + { + RequestContext rc = getRequestContext(); + OperationContext ctx = rc.getCmisOperationCtxOverride(); + if(ctx == null) + { + ctx = new OperationContextImpl(); + } + + CmisObject res = session.getObject(objectId, ctx); + return res; + } + + public CmisObject getObjectByPath(String path) + { + OperationContextImpl ctx = new OperationContextImpl(); + CmisObject res = session.getObjectByPath(path, ctx); + return res; + } + + public List getObjectParents(String objectId) + { + CmisObject o = session.getObject(objectId); + if(o instanceof FileableCmisObject) + { + FileableCmisObject f = (FileableCmisObject)o; + + OperationContextImpl ctx = new OperationContextImpl(); + List res = f.getParents(ctx); + return res; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a fileable cmis object"); + } + } + + public void deleteContent(String objectId, boolean refresh) + { + CmisObject o = getObject(objectId); + + if(o instanceof Document) + { + Document d = (Document)o; + d.deleteContentStream(refresh); + } + else + { + throw new IllegalArgumentException("Object does not exists or is not a document"); + } + } + + public ContentData getContent(String objectId) throws IOException + { + CmisObject o = getObject(objectId); + if(o instanceof Document) + { + Document d = (Document)o; + ContentStream res = d.getContentStream(); + ContentData c = new ContentData(res); + return c; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a document"); + } + } + + public void putContent(String objectId, String filename, BigInteger length, String mimetype, InputStream content, boolean overwrite) + { + CmisObject o = getObject(objectId); + if(o instanceof Document) + { + Document d = (Document)o; + ContentStream contentStream = new ContentStreamImpl(filename, length, mimetype, content); + try + { + d.setContentStream(contentStream, overwrite); + } + finally + { + try + { + contentStream.getStream().close(); + } + catch (Exception e) + { + } + } + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a document"); + } + } + + public void addChildren(FolderNode f, Tree t) + { + FileableCmisObject fco = t.getItem(); + CMISNode child = CMISNode.createNode(fco); + + if(child instanceof FolderNode) + { + f.addFolder((FolderNode)child); + for(Tree c : t.getChildren()) + { + addChildren((FolderNode)child, c); + } + } + else + { + f.addNode(child); + } + } + + public boolean objectExists(String objectId) + { + CmisObject o = getObject(objectId); + return(o != null); + } + + public FolderNode getRootFolder() + { + Folder rootFolder = session.getRootFolder(); + + FolderNode ret = (FolderNode)CMISNode.createNode(rootFolder); + return ret; + } + + public FolderNode getDescendants(String folderId, int depth) + { + Session session = getCMISSession(); + + CmisObject o = session.getObject(folderId); + if(o instanceof Folder) + { + Folder f = (Folder)o; + + OperationContextImpl ctx = new OperationContextImpl(); + List> res = f.getDescendants(depth, ctx); + FolderNode ret = (FolderNode)CMISNode.createNode(f); + for(Tree t : res) + { + addChildren(ret, t); + } + + return ret; + } + else + { + throw new IllegalArgumentException("Folder does not exist or is not a folder"); + } + } + + public ItemIterable getTypeChildren(String typeId, boolean includePropertyDefinitions) + { + ItemIterable res = session.getTypeChildren(typeId, includePropertyDefinitions); + return res; + } + + public List> getTypeDescendants(String typeId, int depth, boolean includePropertyDefinitions) + { + List> res = session.getTypeDescendants(typeId, depth, includePropertyDefinitions); + return res; + } + + public ObjectType getTypeDefinition(String typeId) + { + ObjectType res = session.getTypeDefinition(typeId); + return res; + } + + public void removeAllVersions(String objectId) + { + CmisObject o = getObject(objectId); + if(o instanceof Document) + { + Document d = (Document)o; + d.deleteAllVersions(); + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a document"); + } + } + + public List query(String query, boolean searchAllVersions, long skipCount, int maxItems) + { + OperationContext ctx = new OperationContextImpl(); + ItemIterable res = session.query(query, searchAllVersions, ctx); + res = res.skipTo(skipCount); + res = res.getPage(maxItems); + + List results = new ArrayList((int)res.getPageNumItems()); + + for(QueryResult r : res) + { + CMISNode n = CMISNode.createNode(r); + results.add(n); + } + + return results; + } + + public void removeObject(String objectId, boolean allVersions) + { + CmisObject o = getObject(objectId); + if(o != null) + { + o.delete(allVersions); + } + else + { + throw new IllegalArgumentException("Object does not exist"); + } + } + + public List removeTree(String objectId, boolean allVersions, UnfileObject unfile, boolean continueOnFailure) + { + CmisObject o = getObject(objectId); + if(o instanceof Folder) + { + Folder f = (Folder)o; + List res = f.deleteTree(allVersions, unfile, continueOnFailure); + return res; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a folder"); + } + } + + public void updateProperties(String objectId, Map properties, boolean refresh) + { + CmisObject o = getObject(objectId); + if(o != null) + { + o.updateProperties(properties, refresh); + } + else + { + throw new IllegalArgumentException("Object does not exist"); + } + } + + public List> getFolderTree(String folderId, int depth) + { + CmisObject o = session.getObject(folderId); + if(o instanceof Folder) + { + Folder f = (Folder)o; + + OperationContextImpl ctx = new OperationContextImpl(); + List> res = f.getFolderTree(depth, ctx); + return res; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a folder"); + } + } + + public FolderNode getChildren(String folderId, int skipCount, int maxItems) + { + CmisObject o = session.getObject(folderId); + if(o instanceof Folder) + { + Folder f = (Folder)o; + FolderNode ret = (FolderNode)CMISNode.createNode(f); + + OperationContextImpl ctx = new OperationContextImpl(); + ItemIterable res = f.getChildren(ctx); + res.skipTo(skipCount); + ItemIterable l = res.getPage(maxItems); + for(CmisObject c : l) + { + CMISNode child = null; + if(c.getBaseType() instanceof FolderTypeDefinition) + { + child = (FolderNode)CMISNode.createNode(c); + ret.addFolder((FolderNode)child); + } + else + { + child = CMISNode.createNode(c); + ret.addNode(child); + } + } + + return ret; + } + else + { + throw new IllegalArgumentException("Folder does not exist or is not a folder"); + } + } + + public ItemIterable getCheckedOutDocs() + { + OperationContextImpl ctx = new OperationContextImpl(); + ItemIterable res = session.getCheckedOutDocs(ctx); + return res; + } + + public List getAllVersions(String objectId) + { + CmisObject o = getObject(objectId); + if(o instanceof Document) + { + Document d = (Document)o; + OperationContext ctx = new OperationContextImpl(); + List res = d.getAllVersions(ctx); + return res; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a document"); + } + } + + public AllowableActions getAllowableActions(String objectId) + { + CmisObject o = getObject(objectId); + AllowableActions res = o.getAllowableActions(); + return res; + } + + public Document createDocument(String parentId, String name, Map properties, ContentStream contentStream, VersioningState versioningState) + { + CmisObject o = getObject(parentId); + + if(o instanceof Folder) + { + Folder f = (Folder)o; + + if(properties == null) + { + properties = new HashMap(); + } + String objectTypeId = (String)properties.get(PropertyIds.OBJECT_TYPE_ID); + String type = "cmis:document"; + if(objectTypeId == null) + { + objectTypeId = type; + } + if(objectTypeId.indexOf(type) == -1) + { + StringBuilder sb = new StringBuilder(objectTypeId); + if(sb.length() > 0) + { + sb.append(","); + } + sb.append(type); + objectTypeId = sb.toString(); + } + + properties.put(PropertyIds.NAME, name); + properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId); + + Document res = f.createDocument(properties, contentStream, versioningState); + return res; + } + else + { + throw new IllegalArgumentException("Parent does not exists or is not a folder"); + } + } + + public Folder createFolder(String folderId, String name, Map properties) + { + CmisObject o = getObject(folderId); + + if(o instanceof Folder) + { + Folder f = (Folder)o; + + if(properties == null) + { + properties = new HashMap(); + } + String objectTypeId = (String)properties.get(PropertyIds.OBJECT_TYPE_ID); + String type = "cmis:folder"; + if(objectTypeId == null) + { + objectTypeId = type; + } + if(objectTypeId.indexOf(type) == -1) + { + StringBuilder sb = new StringBuilder(objectTypeId); + if(sb.length() > 0) + { + sb.append(","); + } + sb.append(type); + objectTypeId = sb.toString(); + } + + properties.put(PropertyIds.NAME, name); + properties.put(PropertyIds.OBJECT_TYPE_ID, objectTypeId); + + Folder res = f.createFolder(properties); + return res; + } + else + { + throw new IllegalArgumentException("Parent does not exist or is not a folder"); + } + } + + public ObjectId createRelationship(String sourceObjectId, String targetObjectId) + { + Map relProps = new HashMap(); + relProps.put("cmis:sourceId", sourceObjectId); + relProps.put("cmis:targetId", targetObjectId); + relProps.put("cmis:objectTypeId", "cmis:relationship"); + ObjectId res = session.createRelationship(relProps); + return res; + } + + public ObjectId checkoutObject(String objectId) + { + CmisObject o = getObject(objectId); + if(o instanceof Document) + { + Document d = (Document)o; + ObjectId res = d.checkOut(); + return res; + } + else + { + throw new IllegalArgumentException("Object does not exist or is not a document"); + } + } + } + + public static class Paging + { + private Integer skipCount; + private Integer maxItems; + private ExpectedPaging expectedPaging; + + public Paging() + { + } + + public Paging(Integer skipCount, Integer maxItems, ExpectedPaging expectedPaging) + { + super(); + this.skipCount = skipCount; + this.maxItems = maxItems; + this.expectedPaging = expectedPaging; + } + + public ExpectedPaging getExpectedPaging() + { + return expectedPaging; + } + + public void setExpectedPaging(ExpectedPaging expectedPaging) + { + this.expectedPaging = expectedPaging; + } + + public Integer getSkipCount() + { + return skipCount; + } + + public Integer getMaxItems() + { + return maxItems; + } + + public void setSkipCount(Integer skipCount) + { + this.skipCount = skipCount; + } + + public void setMaxItems(Integer maxItems) + { + this.maxItems = maxItems; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((maxItems == null) ? 0 : maxItems.hashCode()); + result = prime * result + + ((skipCount == null) ? 0 : skipCount.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Paging other = (Paging) obj; + if (maxItems == null) { + if (other.maxItems != null) + return false; + } else if (!maxItems.equals(other.maxItems)) + return false; + if (skipCount == null) { + if (other.skipCount != null) + return false; + } else if (!skipCount.equals(other.skipCount)) + return false; + return true; + } + + @Override + public String toString() + { + return "Paging [" + + (skipCount != null ? "skipCount=" + skipCount + ", " : "") + + (maxItems != null ? "maxItems=" + maxItems : "") + "]"; + } + } + + /** + * Representation of an error response. + * + * @author Jamal Kaabi-Mofrad + */ + public static class ExpectedErrorResponse + { + private String errorKey; + private int statusCode; + private String briefSummary; + private String stackTrace; + private Map additionalState; + private String descriptionURL; + private String logId; + + public ExpectedErrorResponse() + { + } + + public ExpectedErrorResponse(String errorKey, int statusCode, String briefSummary, StackTraceElement[] stackTrace, + Map additionalState, String logId) + { + super(); + this.errorKey = errorKey; + this.statusCode = statusCode; + this.briefSummary = briefSummary; + this.stackTrace = Arrays.toString(stackTrace); + this.additionalState = additionalState; + this.logId = logId; + } + + public String getErrorKey() + { + return errorKey; + } + + public ExpectedErrorResponse setErrorKey(String errorKey) + { + this.errorKey = errorKey; + return this; + } + + public int getStatusCode() + { + return statusCode; + } + + public ExpectedErrorResponse setStatusCode(int statusCode) + { + this.statusCode = statusCode; + return this; + } + + public String getBriefSummary() + { + return briefSummary; + } + + public ExpectedErrorResponse setBriefSummary(String briefSummary) + { + this.briefSummary = briefSummary; + return this; + } + + public String getLogId() { + return logId; + } + + public void setLogId(String logId) { + this.logId = logId; + } + + public String getStackTrace() + { + return stackTrace; + } + + public ExpectedErrorResponse setStackTrace(String stackTrace) + { + this.stackTrace = stackTrace; + return this; + } + + public Map getAdditionalState() + { + return additionalState; + } + + public ExpectedErrorResponse setAdditionalState(Map additionalState) + { + this.additionalState = additionalState; + return this; + } + + public String getDescriptionURL() + { + return descriptionURL; + } + + public ExpectedErrorResponse setDescriptionURL(String descriptionURL) + { + this.descriptionURL = descriptionURL; + return this; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(250); + sb.append("ExpectedErrorResponse [errorKey='").append(errorKey) + .append(", statusCode=").append(statusCode) + .append(", briefSummary='").append(briefSummary) + .append(", logId='").append(logId) + .append(", stackTrace='").append(stackTrace) + .append(", additionalState=").append(additionalState) + .append(", descriptionURL='").append(descriptionURL) + .append(']'); + return sb.toString(); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiException.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiException.java index 63e1c1f262..cc7b75ead4 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiException.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiException.java @@ -1,25 +1,25 @@ -package org.alfresco.rest.api.tests.client; - -public class PublicApiException extends Exception -{ - private static final long serialVersionUID = 2622686430090577966L; - - private HttpResponse httpResponse; - - public PublicApiException(Exception e) - { - super(e); - } - - public PublicApiException(String message, HttpResponse httpResponse) - { - super(message + "/n" + httpResponse.toString()); - this.httpResponse = httpResponse; - } - - public HttpResponse getHttpResponse() - { - return httpResponse; - } - -} +package org.alfresco.rest.api.tests.client; + +public class PublicApiException extends Exception +{ + private static final long serialVersionUID = 2622686430090577966L; + + private HttpResponse httpResponse; + + public PublicApiException(Exception e) + { + super(e); + } + + public PublicApiException(String message, HttpResponse httpResponse) + { + super(message + "/n" + httpResponse.toString()); + this.httpResponse = httpResponse; + } + + public HttpResponse getHttpResponse() + { + return httpResponse; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java index 5cfd05c1de..2ad989b894 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java @@ -1,1283 +1,1283 @@ -package org.alfresco.rest.api.tests.client; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.repo.tenant.TenantUtil; -import org.alfresco.repo.web.scripts.BaseWebScriptTest.PatchMethod; -import org.alfresco.rest.api.tests.client.AuthenticatedHttp.HttpRequestCallback; -import org.alfresco.rest.framework.Api; -import org.alfresco.rest.framework.Api.SCOPE; -import org.alfresco.rest.framework.core.ResourceInspector; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.RelationshipResource; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.util.Pair; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpMethodBase; -import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; -import org.apache.commons.httpclient.methods.DeleteMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.HeadMethod; -import org.apache.commons.httpclient.methods.OptionsMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.PutMethod; -import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.apache.commons.httpclient.methods.TraceMethod; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; - -/** - * A http client for talking to the rest apis. The caller can pass in a rest api - * implementation class to the http method (get, post, put, delete supported) - * and the url will be generated. - * - * @author steveglover - */ -public class PublicApiHttpClient -{ - private static final Log logger = LogFactory.getLog(PublicApiHttpClient.class); - - private static final String OLD_BASE_URL = "{0}://{1}:{2}{3}{4}{5}/api/"; - private static final String INDEX_URL = "{0}://{1}:{2}{3}{4}"; - private static final String BASE_URL = "{0}://{1}:{2}{3}{4}{5}/{6}/{7}/versions/{8}"; - private static final String PUBLICAPI_CMIS_SERVICE_URL = "{0}://{1}:{2}{3}{4}cmis/versions/{5}/{6}"; - private static final String PUBLICAPI_CMIS_URL = "{0}://{1}:{2}{3}{4}{5}/{6}/cmis/versions/{7}/{8}"; - private static final String PUBLICAPI_CMIS_URL_SUFFIX = "{0}/{1}/cmis/versions/{2}/{3}"; - private static final String ATOM_PUB_URL = "{0}://{1}:{2}{3}cmisatom"; - - private String scheme = "http"; - private String host = "localhost"; - private int port = 8081; - - private String contextPath; - private String servletName; - private AuthenticatedHttp authenticatedHttp; - - private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); - - // can be overriden by other clients like the workflow client - protected String apiName = "alfresco"; - - public PublicApiHttpClient(String host, int port, String contextPath, String servletName, AuthenticatedHttp authenticatedHttp) - { - this("http", host, port, contextPath, servletName, authenticatedHttp); - } - - public PublicApiHttpClient(String scheme, String host, int port, String contextPath, String servletName, AuthenticatedHttp authenticatedHttp) - { - super(); - this.scheme = scheme; - this.host = host; - this.port = port; - this.contextPath = contextPath; - if (this.contextPath != null && !this.contextPath.isEmpty() && !this.contextPath.endsWith("/")) - { - this.contextPath = this.contextPath + "/"; - } - if (this.contextPath != null && !this.contextPath.startsWith("/")) - { - this.contextPath = "/" + this.contextPath; - } - this.servletName = servletName; - if (this.servletName != null && !this.servletName.isEmpty() && !this.servletName.endsWith("/")) - { - this.servletName = this.servletName + "/"; - } - this.authenticatedHttp = authenticatedHttp; - } - - public String getCmisUrl(String repositoryId, String operation) - { - StringBuilder url = new StringBuilder(); - if (repositoryId == null) - { - url.append(MessageFormat.format(ATOM_PUB_URL, new Object[] { scheme, host, String.valueOf(port), contextPath })); - } - else - { - url.append(MessageFormat.format(ATOM_PUB_URL, new Object[] { scheme, host, String.valueOf(port), contextPath })); - url.append("/"); - url.append(repositoryId); - } - - if (operation != null) - { - url.append("/"); - url.append(operation); - } - - return url.toString(); - } - - public String getPublicApiCmisUrl(String networkId, Binding binding, String version, String operation) - { - StringBuilder url = new StringBuilder(); - if (networkId == null) - { - url.append(MessageFormat.format(PUBLICAPI_CMIS_SERVICE_URL, - new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, version, binding.toString().toLowerCase() })); - } - else - { - url.append(MessageFormat.format(PUBLICAPI_CMIS_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, - networkId, "public", version, binding.toString().toLowerCase() })); - } - - if (operation != null) - { - url.append("/"); - url.append(operation); - } - - return url.toString(); - } - - public String getPublicApiCmisUrlSuffix(String networkId, Binding binding, String version, String operation) - { - StringBuilder url = new StringBuilder(); - - url.append(MessageFormat.format(PUBLICAPI_CMIS_URL_SUFFIX, new Object[] { networkId, "public", version, binding.toString().toLowerCase() })); - - if (operation != null) - { - url.append("/"); - url.append(operation); - } - - return url.toString(); - } - - public void setHost(String host) - { - this.host = host; - } - - public void setPort(int port) - { - this.port = port; - } - - public void setContextPath(String contextPath) - { - this.contextPath = contextPath; - } - - public void init() - { - } - - private void log(String msg) - { - if (logger.isDebugEnabled()) - { - logger.debug(msg); - } - } - - protected AnnotationMetadata getAnnotationMetadata(String classname) throws IOException - { - MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(classname); - AnnotationMetadata annotationMetaData = metadataReader.getAnnotationMetadata(); - return annotationMetaData; - } - - public HttpResponse submitRequest(HttpMethod req, final RequestContext rq) throws HttpException, IOException - { - try - { - final long start = System.currentTimeMillis(); - - final HttpRequestCallback callback = new HttpRequestCallback() - { - @Override - public HttpResponse onCallSuccess(HttpMethod method) throws Exception - { - long end = System.currentTimeMillis(); - - Map headersMap = null; - Header[] headers = method.getResponseHeaders(); - if (headers != null) - { - headersMap = new HashMap(headers.length); - for (Header header : headers) - { - headersMap.put(header.getName(), header.getValue()); - } - } - - return new HttpResponse(method, rq.getRunAsUser(), method.getResponseBody(), headersMap, (end - start)); - } - - @Override - public boolean onError(HttpMethod method, Throwable t) - { - return false; - } - }; - - HttpResponse response = null; - if (rq.getPassword() != null) - { - response = authenticatedHttp.executeHttpMethodAuthenticated(req, rq.getRunAsUser(), rq.getPassword(), callback); - } - else - { - response = authenticatedHttp.executeHttpMethodAuthenticated(req, rq.getRunAsUser(), callback); - } - return response; - } - finally - { - if (req != null) - { - req.releaseConnection(); - } - } - } - - public HttpResponse get(final RequestContext rq, final String urlSuffix, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), urlSuffix, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse get(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, - Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse get(final RequestContext rq, String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException - { - return get(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); - } - - public HttpResponse get(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse get(final RequestContext rq, String scope, String password, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException - { - return get(rq, scope, 1, password, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); - } - - public HttpResponse get(final RequestContext rq, final String scope, final int version, final String password, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse get(final String urlSuffix, final RequestContext rq, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(urlSuffix, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse getWithPassword(final String urlSuffix, final RequestContext rq, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(urlSuffix, params); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse post(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, final String body) - throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if (body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse post(final RequestContext rq, final String urlSuffix, String body) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), urlSuffix, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if (body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse post(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, final String body) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if (body != null) - { - StringRequestEntity requestEntity = null; - if (cmisBinding.equals(Binding.atom)) - { - requestEntity = new StringRequestEntity(body, "text/xml", "UTF-8"); - } - else if (cmisBinding.equals(Binding.browser)) - { - requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - } - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse put(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, final String body) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url.toString()); - if (body != null) - { - StringRequestEntity requestEntity = null; - if (cmisBinding.equals(Binding.atom)) - { - requestEntity = new StringRequestEntity(body, "text/xml", "UTF-8"); - } - else if (cmisBinding.equals(Binding.browser)) - { - requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - } - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse get(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, Map parameters) - throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, parameters); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse delete(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - DeleteMethod req = new DeleteMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse head(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - HeadMethod req = new HeadMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse options(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - OptionsMethod req = new OptionsMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse trace(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - TraceMethod req = new TraceMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse patch(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); - String url = endpoint.getUrl(); - - PatchMethod req = new PatchMethod(url.toString()); - return submitRequest(req, rq); - } - - public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final String body) throws IOException - { - return post(rq, scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, "application/json"); - } - - public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final String body, String contentType) throws IOException - { - return post(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, contentType); - } - - public HttpResponse post(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final String body, String contentType) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if (body != null) - { - if (contentType == null || contentType.isEmpty()) - { - contentType = "application/json"; - } - StringRequestEntity requestEntity = new StringRequestEntity(body, contentType, "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final byte[] body, String contentType) throws IOException - { - return post(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, contentType); - } - - public HttpResponse post(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final byte[] body, String contentType) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, null); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - if (body != null) - { - if (contentType == null || contentType.isEmpty()) - { - contentType = "application/octet-stream"; - } - ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(body, contentType); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse delete(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); - String url = endpoint.getUrl(); - - DeleteMethod req = new DeleteMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse delete(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId) throws IOException - { - return delete(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, null); - } - - public HttpResponse delete(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, params); - String url = endpoint.getUrl(); - - DeleteMethod req = new DeleteMethod(url); - return submitRequest(req, rq); - } - - public HttpResponse put(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, final String body) - throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url); - if (body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse put(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final String body, final Map params) throws IOException - { - return put(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, params); - } - - public HttpResponse put(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, - final String relationCollectionName, final Object relationshipEntityId, final String body, Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, params); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url); - if (body != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse putBinary(final RequestContext rq, final String scope, final int version, final String entityCollectionName, - final Object entityId, final String relationCollectionName, final Object relationshipEntityId, final BinaryPayload payload, - final Map params) throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, - relationshipEntityId, params); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url); - if (payload != null) - { - BinaryRequestEntity requestEntity = new BinaryRequestEntity(payload.getFile(), payload.getMimeType(), payload.getCharset()); - req.setRequestEntity(requestEntity); - } - return submitRequest(req, rq); - } - - public HttpResponse execute(RequestBuilder requestBuilder) throws IOException - { - return submitRequest(requestBuilder.getHttpMethod(), requestBuilder.getRequestContext()); - } - - /* - * Encapsulates information relating to a rest api end point, generating and - * encoding urls based on the rest api implementation class. - */ - private class RestApiEndpoint - { - private String url; - - RestApiEndpoint(String url, Map params) throws IOException - { - StringBuilder sb = new StringBuilder( - MessageFormat.format(INDEX_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName })); - if (url != null) - { - sb.append(url); - } - - addParams(sb, params); - - this.url = sb.toString(); - } - - RestApiEndpoint(String tenantDomain, String url, Map params) throws IOException - { - StringBuilder sb = new StringBuilder(MessageFormat.format(OLD_BASE_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, - servletName, tenantDomain == null ? TenantUtil.DEFAULT_TENANT : tenantDomain })); - sb.append("/"); - sb.append(url); - - addParams(sb, params); - - this.url = sb.toString(); - } - - RestApiEndpoint(Class resourceClass, String tenantDomain, Object collectionEntityId, Object relationEntityId, Map params) - throws IOException - { - StringBuilder sb = new StringBuilder(); - - Api api = ResourceInspector.inspectApi(resourceClass); - SCOPE scope = api.getScope(); - int version = api.getVersion(); - String name = api.getName(); - if (StringUtils.isEmpty(name)) - { - name = apiName; - } - - Pair relationshipCollectionInfo = getRelationCollectionInfo(resourceClass); - - sb.append(MessageFormat.format(BASE_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, - tenantDomain == null ? TenantUtil.DEFAULT_TENANT : tenantDomain, scope.toString(), name, version })); - - if (relationshipCollectionInfo != null) - { - String entityCollectionName = relationshipCollectionInfo.getFirst(); - String relationshipCollectionName = relationshipCollectionInfo.getSecond(); - String relationEntityIdString = encodeToString(relationEntityId); - String collectionEntityIdString = encodeToString(collectionEntityId); - - sb.append('/'); - sb.append(entityCollectionName); - sb.append('/'); - if (collectionEntityIdString != null) - { - sb.append(collectionEntityIdString); - sb.append('/'); - } - - sb.append(relationshipCollectionName); - sb.append('/'); - if (relationEntityIdString != null) - { - sb.append(relationEntityIdString); - sb.append('/'); - } - } - else - { - String entityCollectionName = getEntityCollectionInfo(resourceClass); - if (entityCollectionName != null) - { - String collectionEntityIdString = encodeToString(collectionEntityId); - - sb.append('/'); - sb.append(entityCollectionName); - sb.append('/'); - if (collectionEntityIdString != null) - { - sb.append(collectionEntityIdString); - sb.append('/'); - } - } - else - { - throw new RuntimeException(); - } - } - - addParams(sb, params); - - this.url = sb.toString(); - } - - RestApiEndpoint(String networkId, Binding cmisBinding, String version, String cmisOperation, Map params) throws IOException - { - StringBuilder sb = new StringBuilder(); - - if (networkId != null) - { - sb.append(getPublicApiCmisUrl(networkId, cmisBinding, version, cmisOperation)); - } - else - { - throw new IllegalArgumentException(); - } - - addParams(sb, params); - - this.url = sb.toString(); - } - - RestApiEndpoint(String tenantDomain, String scope, int version, String collectionName, Object collectionEntityId, String relationName, - Object relationEntityId, Map params) throws IOException - { - this(tenantDomain, scope, apiName, version, collectionName, collectionEntityId, relationName, relationEntityId, params); - } - - RestApiEndpoint(String tenantDomain, String scope, String apiName, int version, String collectionName, Object collectionEntityId, - String relationName, Object relationEntityId, Map params) throws IOException - { - StringBuilder sb = new StringBuilder(); - - if (tenantDomain == null || tenantDomain.equals(TenantService.DEFAULT_DOMAIN)) - { - tenantDomain = TenantUtil.DEFAULT_TENANT; - } - - if (StringUtils.isEmpty(apiName)) - { - apiName = PublicApiHttpClient.this.apiName; - } - - sb.append(MessageFormat.format(BASE_URL, - new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, tenantDomain, scope, apiName, version })); - - if (collectionName != null) - { - sb.append('/'); - sb.append(collectionName); - if (collectionEntityId != null) - { - sb.append('/'); - sb.append(collectionEntityId); - } - } - - if (relationName != null) - { - sb.append('/'); - sb.append(relationName); - if (relationEntityId != null) - { - sb.append('/'); - sb.append(relationEntityId); - } - } - - addParams(sb, params); - - this.url = sb.toString(); - } - - RestApiEndpoint(String tenantDomain, String scope, String collectionName, Object collectionEntityId, String relationName, - Object relationEntityId, Map params) throws IOException - { - this(tenantDomain, scope, 1, collectionName, collectionEntityId, relationName, relationEntityId, params); - } - - private void addParams(StringBuilder sb, Map params) throws UnsupportedEncodingException - { - if (params != null && params.size() > 0) - { - sb.append("?"); - - for (String paramName : params.keySet()) - { - sb.append(URLEncoder.encode(paramName, "UTF-8")); - sb.append("="); - sb.append(URLEncoder.encode(params.get(paramName), "UTF-8")); - sb.append("&"); - } - - sb.deleteCharAt(sb.length() - 1); - } - } - - private String encodeToString(Object o) throws UnsupportedEncodingException - { - String ret = null; - - if (o instanceof NodeRef) - { - NodeRef nodeRef = (NodeRef) o; - ret = (o != null ? nodeRef.getId() : null); - } - else - { - ret = (o != null ? o.toString() : null); - } - - return ret; - } - - private Pair getRelationCollectionInfo(Class resourceClass) throws IOException - { - AnnotationMetadata annotationMetaData = getAnnotationMetadata(resourceClass.getCanonicalName()); - if (annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) - { - if (annotationMetaData.getAnnotationTypes().contains(RelationshipResource.class.getCanonicalName())) - { - Map attrs = annotationMetaData.getAnnotationAttributes(RelationshipResource.class.getName()); - String relationshipCollectionName = (String) attrs.get("name"); - Class entityResource = (Class) attrs.get("entityResource"); - - String entityCollectionName = getEntityCollectionInfo(entityResource.getCanonicalName()); - - Pair ret = new Pair(entityCollectionName, relationshipCollectionName); - return ret; - } - else - { - return null; - } - } - else - { - throw new AlfrescoRuntimeException(""); - } - } - - private String getEntityCollectionInfo(Class resourceClass) throws IOException - { - return getEntityCollectionInfo(resourceClass.getCanonicalName()); - } - - private String getEntityCollectionInfo(String className) throws IOException - { - AnnotationMetadata annotationMetaData = getAnnotationMetadata(className); - if (annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) - { - if (annotationMetaData.getAnnotationTypes().contains(EntityResource.class.getCanonicalName())) - { - Map attrs = annotationMetaData.getAnnotationAttributes(EntityResource.class.getName()); - return (String) attrs.get("name"); - } - else - { - return null; - } - } - else - { - throw new AlfrescoRuntimeException(""); - } - } - - public String getUrl() throws UnsupportedEncodingException - { - return url; - } - } - - /** - * @author Jamal Kaabi-Mofrad - */ - public static class BinaryRequestEntity implements RequestEntity - { - private final File file; - private final String mimeType; - private final String charset; - - public BinaryRequestEntity(File file, String mimeType, String charset) - { - this.file = file; - this.mimeType = mimeType; - this.charset = charset; - } - - @Override - public boolean isRepeatable() - { - return true; - } - - @Override - public void writeRequest(OutputStream out) throws IOException - { - InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); - try - { - int len; - byte[] buffer = new byte[8190]; - while ((len = inputStream.read(buffer)) != -1) - { - out.write(buffer, 0, len); - } - } - finally - { - inputStream.close(); - } - } - - @Override - public long getContentLength() - { - return file.length(); - } - - @Override - public String getContentType() - { - if (charset == null) - { - return mimeType; - } - if (mimeType == null) - { - return null; - } - return mimeType + "; charset=" + charset; - } - } - - /** - * @author Jamal Kaabi-Mofrad - */ - public static class BinaryPayload - { - private File file; - private String mimeType; - private String charset; - - public BinaryPayload(File file, String mimeType, String charset) - { - this.file = file; - this.mimeType = mimeType; - this.charset = charset; - } - - public BinaryPayload(File file, String mimeType) - { - this(file, mimeType, null); - } - - public BinaryPayload(File file) - { - this(file, null, null); - } - - public File getFile() - { - return file; - } - - public String getMimeType() - { - return mimeType; - } - - public String getCharset() - { - return charset; - } - } - - /** - * @author Jamal Kaabi-Mofrad - */ - public abstract class RequestBuilder - { - private RequestContext requestContext; - private String scope; - private String apiName = "alfresco"; // default api namespace - private int version = 1; - private String entityCollectionName; - private Object entityId; - private String relationCollectionName; - private Object relationshipEntityId; - private Map params; - private Map headers; - - public abstract T getHttpMethod() throws IOException; - - protected void setRequestHeaderIfAny(T methodBase) - { - if (headers != null) - { - for (Entry headerNameValue : headers.entrySet()) - { - methodBase.addRequestHeader(headerNameValue.getKey(), headerNameValue.getValue()); - } - } - } - - public RequestContext getRequestContext() - { - return requestContext; - } - - public RequestBuilder setRequestContext(RequestContext requestContext) - { - this.requestContext = requestContext; - return this; - } - - public String getScope() - { - return scope; - } - - public RequestBuilder setScope(String scope) - { - this.scope = scope; - return this; - } - - public String getApiName() - { - return apiName; - } - - public RequestBuilder setApiName(String apiName) - { - this.apiName = apiName; - return this; - } - - public int getVersion() - { - return version; - } - - public RequestBuilder setVersion(int version) - { - this.version = version; - return this; - } - - public String getEntityCollectionName() - { - return entityCollectionName; - } - - public RequestBuilder setEntityCollectionName(String entityCollectionName) - { - this.entityCollectionName = entityCollectionName; - return this; - } - - public Object getEntityId() - { - return entityId; - } - - public RequestBuilder setEntityId(Object entityId) - { - this.entityId = entityId; - return this; - } - - public String getRelationCollectionName() - { - return relationCollectionName; - } - - public RequestBuilder setRelationCollectionName(String relationCollectionName) - { - this.relationCollectionName = relationCollectionName; - return this; - } - - public Object getRelationshipEntityId() - { - return relationshipEntityId; - } - - public RequestBuilder setRelationshipEntityId(Object relationshipEntityId) - { - this.relationshipEntityId = relationshipEntityId; - return this; - } - - public Map getParams() - { - return params; - } - - public RequestBuilder setParams(Map params) - { - this.params = params; - return this; - } - - public Map getHeaders() - { - return headers; - } - - public RequestBuilder setHeaders(Map headers) - { - this.headers = headers; - return this; - } - } - - public class GetRequestBuilder extends RequestBuilder - { - private String password; - - public String getPassword() - { - return password; - } - - public GetRequestBuilder setPassword(String password) - { - this.password = password; - return this; - } - - @Override - public GetMethod getHttpMethod() throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), - getScope(), getApiName(), getVersion(), getEntityCollectionName(), - getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); - String url = endpoint.getUrl(); - - GetMethod req = new GetMethod(url); - setRequestHeaderIfAny(req); - return req; - } - } - - public class DeleteRequestBuilder extends RequestBuilder - { - @Override - public DeleteMethod getHttpMethod() throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), - getScope(), getApiName(), getVersion(), getEntityCollectionName(), - getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); - String url = endpoint.getUrl(); - - DeleteMethod req = new DeleteMethod(url); - setRequestHeaderIfAny(req); - return req; - } - } - - public abstract class PostPutRequestBuilder extends RequestBuilder - { - private String bodyAsString; - private byte[] bodyAsByteArray; - private String contentType; - - public String getBodyAsString() - { - return bodyAsString; - } - - public PostPutRequestBuilder setBodyAsString(String bodyAsString) - { - this.bodyAsString = bodyAsString; - return this; - } - - public byte[] getBodyAsByteArray() - { - return bodyAsByteArray; - } - - public PostPutRequestBuilder setBodyAsByteArray(byte[] bodyAsByteArray) - { - this.bodyAsByteArray = bodyAsByteArray; - return this; - } - - public String getContentType() - { - return contentType; - } - - public PostPutRequestBuilder setContentType(String contentType) - { - this.contentType = contentType; - return this; - } - } - - public class PostRequestBuilder extends PostPutRequestBuilder - { - - @Override - public PostMethod getHttpMethod() throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), - getScope(), getApiName(), getVersion(), getEntityCollectionName(), - getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); - String url = endpoint.getUrl(); - - PostMethod req = new PostMethod(url.toString()); - String contentType = getContentType(); - if (getBodyAsString() != null) - { - - if (contentType == null || contentType.isEmpty()) - { - contentType = "application/json"; - } - StringRequestEntity requestEntity = new StringRequestEntity(getBodyAsString(), contentType, "UTF-8"); - req.setRequestEntity(requestEntity); - } - else if (getBodyAsByteArray() != null) - { - if (contentType == null || contentType.isEmpty()) - { - contentType = "application/octet-stream"; - } - ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(getBodyAsByteArray(), contentType); - req.setRequestEntity(requestEntity); - } - setRequestHeaderIfAny(req); - return req; - } - } - - public class PutRequestBuilder extends PostPutRequestBuilder - { - private BinaryPayload binaryPayload; - - public BinaryPayload getBinaryPayload() - { - return binaryPayload; - } - - public PutRequestBuilder setBinaryPayload(BinaryPayload binaryPayload) - { - this.binaryPayload = binaryPayload; - return this; - } - - @Override - public PutMethod getHttpMethod() throws IOException - { - RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), - getScope(), getApiName(), getVersion(), getEntityCollectionName(), - getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); - String url = endpoint.getUrl(); - - PutMethod req = new PutMethod(url); - if (getBodyAsString() != null) - { - StringRequestEntity requestEntity = new StringRequestEntity(getBodyAsString(), "application/json", "UTF-8"); - req.setRequestEntity(requestEntity); - } - else if (binaryPayload != null) - { - BinaryRequestEntity requestEntity = new BinaryRequestEntity(binaryPayload.getFile(), binaryPayload.getMimeType(), - binaryPayload.getCharset()); - req.setRequestEntity(requestEntity); - } - setRequestHeaderIfAny(req); - return req; - } - } -} +package org.alfresco.rest.api.tests.client; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.web.scripts.BaseWebScriptTest.PatchMethod; +import org.alfresco.rest.api.tests.client.AuthenticatedHttp.HttpRequestCallback; +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.Api.SCOPE; +import org.alfresco.rest.framework.core.ResourceInspector; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.RelationshipResource; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.Pair; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.HeadMethod; +import org.apache.commons.httpclient.methods.OptionsMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.httpclient.methods.TraceMethod; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; + +/** + * A http client for talking to the rest apis. The caller can pass in a rest api + * implementation class to the http method (get, post, put, delete supported) + * and the url will be generated. + * + * @author steveglover + */ +public class PublicApiHttpClient +{ + private static final Log logger = LogFactory.getLog(PublicApiHttpClient.class); + + private static final String OLD_BASE_URL = "{0}://{1}:{2}{3}{4}{5}/api/"; + private static final String INDEX_URL = "{0}://{1}:{2}{3}{4}"; + private static final String BASE_URL = "{0}://{1}:{2}{3}{4}{5}/{6}/{7}/versions/{8}"; + private static final String PUBLICAPI_CMIS_SERVICE_URL = "{0}://{1}:{2}{3}{4}cmis/versions/{5}/{6}"; + private static final String PUBLICAPI_CMIS_URL = "{0}://{1}:{2}{3}{4}{5}/{6}/cmis/versions/{7}/{8}"; + private static final String PUBLICAPI_CMIS_URL_SUFFIX = "{0}/{1}/cmis/versions/{2}/{3}"; + private static final String ATOM_PUB_URL = "{0}://{1}:{2}{3}cmisatom"; + + private String scheme = "http"; + private String host = "localhost"; + private int port = 8081; + + private String contextPath; + private String servletName; + private AuthenticatedHttp authenticatedHttp; + + private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); + + // can be overriden by other clients like the workflow client + protected String apiName = "alfresco"; + + public PublicApiHttpClient(String host, int port, String contextPath, String servletName, AuthenticatedHttp authenticatedHttp) + { + this("http", host, port, contextPath, servletName, authenticatedHttp); + } + + public PublicApiHttpClient(String scheme, String host, int port, String contextPath, String servletName, AuthenticatedHttp authenticatedHttp) + { + super(); + this.scheme = scheme; + this.host = host; + this.port = port; + this.contextPath = contextPath; + if (this.contextPath != null && !this.contextPath.isEmpty() && !this.contextPath.endsWith("/")) + { + this.contextPath = this.contextPath + "/"; + } + if (this.contextPath != null && !this.contextPath.startsWith("/")) + { + this.contextPath = "/" + this.contextPath; + } + this.servletName = servletName; + if (this.servletName != null && !this.servletName.isEmpty() && !this.servletName.endsWith("/")) + { + this.servletName = this.servletName + "/"; + } + this.authenticatedHttp = authenticatedHttp; + } + + public String getCmisUrl(String repositoryId, String operation) + { + StringBuilder url = new StringBuilder(); + if (repositoryId == null) + { + url.append(MessageFormat.format(ATOM_PUB_URL, new Object[] { scheme, host, String.valueOf(port), contextPath })); + } + else + { + url.append(MessageFormat.format(ATOM_PUB_URL, new Object[] { scheme, host, String.valueOf(port), contextPath })); + url.append("/"); + url.append(repositoryId); + } + + if (operation != null) + { + url.append("/"); + url.append(operation); + } + + return url.toString(); + } + + public String getPublicApiCmisUrl(String networkId, Binding binding, String version, String operation) + { + StringBuilder url = new StringBuilder(); + if (networkId == null) + { + url.append(MessageFormat.format(PUBLICAPI_CMIS_SERVICE_URL, + new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, version, binding.toString().toLowerCase() })); + } + else + { + url.append(MessageFormat.format(PUBLICAPI_CMIS_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, + networkId, "public", version, binding.toString().toLowerCase() })); + } + + if (operation != null) + { + url.append("/"); + url.append(operation); + } + + return url.toString(); + } + + public String getPublicApiCmisUrlSuffix(String networkId, Binding binding, String version, String operation) + { + StringBuilder url = new StringBuilder(); + + url.append(MessageFormat.format(PUBLICAPI_CMIS_URL_SUFFIX, new Object[] { networkId, "public", version, binding.toString().toLowerCase() })); + + if (operation != null) + { + url.append("/"); + url.append(operation); + } + + return url.toString(); + } + + public void setHost(String host) + { + this.host = host; + } + + public void setPort(int port) + { + this.port = port; + } + + public void setContextPath(String contextPath) + { + this.contextPath = contextPath; + } + + public void init() + { + } + + private void log(String msg) + { + if (logger.isDebugEnabled()) + { + logger.debug(msg); + } + } + + protected AnnotationMetadata getAnnotationMetadata(String classname) throws IOException + { + MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(classname); + AnnotationMetadata annotationMetaData = metadataReader.getAnnotationMetadata(); + return annotationMetaData; + } + + public HttpResponse submitRequest(HttpMethod req, final RequestContext rq) throws HttpException, IOException + { + try + { + final long start = System.currentTimeMillis(); + + final HttpRequestCallback callback = new HttpRequestCallback() + { + @Override + public HttpResponse onCallSuccess(HttpMethod method) throws Exception + { + long end = System.currentTimeMillis(); + + Map headersMap = null; + Header[] headers = method.getResponseHeaders(); + if (headers != null) + { + headersMap = new HashMap(headers.length); + for (Header header : headers) + { + headersMap.put(header.getName(), header.getValue()); + } + } + + return new HttpResponse(method, rq.getRunAsUser(), method.getResponseBody(), headersMap, (end - start)); + } + + @Override + public boolean onError(HttpMethod method, Throwable t) + { + return false; + } + }; + + HttpResponse response = null; + if (rq.getPassword() != null) + { + response = authenticatedHttp.executeHttpMethodAuthenticated(req, rq.getRunAsUser(), rq.getPassword(), callback); + } + else + { + response = authenticatedHttp.executeHttpMethodAuthenticated(req, rq.getRunAsUser(), callback); + } + return response; + } + finally + { + if (req != null) + { + req.releaseConnection(); + } + } + } + + public HttpResponse get(final RequestContext rq, final String urlSuffix, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), urlSuffix, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse get(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, + Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse get(final RequestContext rq, String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException + { + return get(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); + } + + public HttpResponse get(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse get(final RequestContext rq, String scope, String password, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException + { + return get(rq, scope, 1, password, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, params); + } + + public HttpResponse get(final RequestContext rq, final String scope, final int version, final String password, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse get(final String urlSuffix, final RequestContext rq, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(urlSuffix, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse getWithPassword(final String urlSuffix, final RequestContext rq, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(urlSuffix, params); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse post(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, final String body) + throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if (body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse post(final RequestContext rq, final String urlSuffix, String body) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), urlSuffix, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if (body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse post(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, final String body) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if (body != null) + { + StringRequestEntity requestEntity = null; + if (cmisBinding.equals(Binding.atom)) + { + requestEntity = new StringRequestEntity(body, "text/xml", "UTF-8"); + } + else if (cmisBinding.equals(Binding.browser)) + { + requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + } + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse put(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, final String body) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url.toString()); + if (body != null) + { + StringRequestEntity requestEntity = null; + if (cmisBinding.equals(Binding.atom)) + { + requestEntity = new StringRequestEntity(body, "text/xml", "UTF-8"); + } + else if (cmisBinding.equals(Binding.browser)) + { + requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + } + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse get(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation, Map parameters) + throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, parameters); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse delete(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + DeleteMethod req = new DeleteMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse head(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + HeadMethod req = new HeadMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse options(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + OptionsMethod req = new OptionsMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse trace(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + TraceMethod req = new TraceMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse patch(final RequestContext rq, Binding cmisBinding, String version, String cmisOperation) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), cmisBinding, version, cmisOperation, null); + String url = endpoint.getUrl(); + + PatchMethod req = new PatchMethod(url.toString()); + return submitRequest(req, rq); + } + + public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final String body) throws IOException + { + return post(rq, scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, "application/json"); + } + + public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final String body, String contentType) throws IOException + { + return post(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, contentType); + } + + public HttpResponse post(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final String body, String contentType) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if (body != null) + { + if (contentType == null || contentType.isEmpty()) + { + contentType = "application/json"; + } + StringRequestEntity requestEntity = new StringRequestEntity(body, contentType, "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse post(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final byte[] body, String contentType) throws IOException + { + return post(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, contentType); + } + + public HttpResponse post(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final byte[] body, String contentType) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, null); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + if (body != null) + { + if (contentType == null || contentType.isEmpty()) + { + contentType = "application/octet-stream"; + } + ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(body, contentType); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse delete(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); + String url = endpoint.getUrl(); + + DeleteMethod req = new DeleteMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse delete(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId) throws IOException + { + return delete(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, null); + } + + public HttpResponse delete(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + DeleteMethod req = new DeleteMethod(url); + return submitRequest(req, rq); + } + + public HttpResponse put(final Class c, final RequestContext rq, final Object entityId, final Object relationshipEntityId, final String body) + throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(c, rq.getNetworkId(), entityId, relationshipEntityId, null); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if (body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse put(final RequestContext rq, final String scope, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final String body, final Map params) throws IOException + { + return put(rq, scope, 1, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, body, params); + } + + public HttpResponse put(final RequestContext rq, final String scope, final int version, final String entityCollectionName, final Object entityId, + final String relationCollectionName, final Object relationshipEntityId, final String body, Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if (body != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(body, "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse putBinary(final RequestContext rq, final String scope, final int version, final String entityCollectionName, + final Object entityId, final String relationCollectionName, final Object relationshipEntityId, final BinaryPayload payload, + final Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if (payload != null) + { + BinaryRequestEntity requestEntity = new BinaryRequestEntity(payload.getFile(), payload.getMimeType(), payload.getCharset()); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + + public HttpResponse execute(RequestBuilder requestBuilder) throws IOException + { + return submitRequest(requestBuilder.getHttpMethod(), requestBuilder.getRequestContext()); + } + + /* + * Encapsulates information relating to a rest api end point, generating and + * encoding urls based on the rest api implementation class. + */ + private class RestApiEndpoint + { + private String url; + + RestApiEndpoint(String url, Map params) throws IOException + { + StringBuilder sb = new StringBuilder( + MessageFormat.format(INDEX_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName })); + if (url != null) + { + sb.append(url); + } + + addParams(sb, params); + + this.url = sb.toString(); + } + + RestApiEndpoint(String tenantDomain, String url, Map params) throws IOException + { + StringBuilder sb = new StringBuilder(MessageFormat.format(OLD_BASE_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, + servletName, tenantDomain == null ? TenantUtil.DEFAULT_TENANT : tenantDomain })); + sb.append("/"); + sb.append(url); + + addParams(sb, params); + + this.url = sb.toString(); + } + + RestApiEndpoint(Class resourceClass, String tenantDomain, Object collectionEntityId, Object relationEntityId, Map params) + throws IOException + { + StringBuilder sb = new StringBuilder(); + + Api api = ResourceInspector.inspectApi(resourceClass); + SCOPE scope = api.getScope(); + int version = api.getVersion(); + String name = api.getName(); + if (StringUtils.isEmpty(name)) + { + name = apiName; + } + + Pair relationshipCollectionInfo = getRelationCollectionInfo(resourceClass); + + sb.append(MessageFormat.format(BASE_URL, new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, + tenantDomain == null ? TenantUtil.DEFAULT_TENANT : tenantDomain, scope.toString(), name, version })); + + if (relationshipCollectionInfo != null) + { + String entityCollectionName = relationshipCollectionInfo.getFirst(); + String relationshipCollectionName = relationshipCollectionInfo.getSecond(); + String relationEntityIdString = encodeToString(relationEntityId); + String collectionEntityIdString = encodeToString(collectionEntityId); + + sb.append('/'); + sb.append(entityCollectionName); + sb.append('/'); + if (collectionEntityIdString != null) + { + sb.append(collectionEntityIdString); + sb.append('/'); + } + + sb.append(relationshipCollectionName); + sb.append('/'); + if (relationEntityIdString != null) + { + sb.append(relationEntityIdString); + sb.append('/'); + } + } + else + { + String entityCollectionName = getEntityCollectionInfo(resourceClass); + if (entityCollectionName != null) + { + String collectionEntityIdString = encodeToString(collectionEntityId); + + sb.append('/'); + sb.append(entityCollectionName); + sb.append('/'); + if (collectionEntityIdString != null) + { + sb.append(collectionEntityIdString); + sb.append('/'); + } + } + else + { + throw new RuntimeException(); + } + } + + addParams(sb, params); + + this.url = sb.toString(); + } + + RestApiEndpoint(String networkId, Binding cmisBinding, String version, String cmisOperation, Map params) throws IOException + { + StringBuilder sb = new StringBuilder(); + + if (networkId != null) + { + sb.append(getPublicApiCmisUrl(networkId, cmisBinding, version, cmisOperation)); + } + else + { + throw new IllegalArgumentException(); + } + + addParams(sb, params); + + this.url = sb.toString(); + } + + RestApiEndpoint(String tenantDomain, String scope, int version, String collectionName, Object collectionEntityId, String relationName, + Object relationEntityId, Map params) throws IOException + { + this(tenantDomain, scope, apiName, version, collectionName, collectionEntityId, relationName, relationEntityId, params); + } + + RestApiEndpoint(String tenantDomain, String scope, String apiName, int version, String collectionName, Object collectionEntityId, + String relationName, Object relationEntityId, Map params) throws IOException + { + StringBuilder sb = new StringBuilder(); + + if (tenantDomain == null || tenantDomain.equals(TenantService.DEFAULT_DOMAIN)) + { + tenantDomain = TenantUtil.DEFAULT_TENANT; + } + + if (StringUtils.isEmpty(apiName)) + { + apiName = PublicApiHttpClient.this.apiName; + } + + sb.append(MessageFormat.format(BASE_URL, + new Object[] { scheme, host, String.valueOf(port), contextPath, servletName, tenantDomain, scope, apiName, version })); + + if (collectionName != null) + { + sb.append('/'); + sb.append(collectionName); + if (collectionEntityId != null) + { + sb.append('/'); + sb.append(collectionEntityId); + } + } + + if (relationName != null) + { + sb.append('/'); + sb.append(relationName); + if (relationEntityId != null) + { + sb.append('/'); + sb.append(relationEntityId); + } + } + + addParams(sb, params); + + this.url = sb.toString(); + } + + RestApiEndpoint(String tenantDomain, String scope, String collectionName, Object collectionEntityId, String relationName, + Object relationEntityId, Map params) throws IOException + { + this(tenantDomain, scope, 1, collectionName, collectionEntityId, relationName, relationEntityId, params); + } + + private void addParams(StringBuilder sb, Map params) throws UnsupportedEncodingException + { + if (params != null && params.size() > 0) + { + sb.append("?"); + + for (String paramName : params.keySet()) + { + sb.append(URLEncoder.encode(paramName, "UTF-8")); + sb.append("="); + sb.append(URLEncoder.encode(params.get(paramName), "UTF-8")); + sb.append("&"); + } + + sb.deleteCharAt(sb.length() - 1); + } + } + + private String encodeToString(Object o) throws UnsupportedEncodingException + { + String ret = null; + + if (o instanceof NodeRef) + { + NodeRef nodeRef = (NodeRef) o; + ret = (o != null ? nodeRef.getId() : null); + } + else + { + ret = (o != null ? o.toString() : null); + } + + return ret; + } + + private Pair getRelationCollectionInfo(Class resourceClass) throws IOException + { + AnnotationMetadata annotationMetaData = getAnnotationMetadata(resourceClass.getCanonicalName()); + if (annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) + { + if (annotationMetaData.getAnnotationTypes().contains(RelationshipResource.class.getCanonicalName())) + { + Map attrs = annotationMetaData.getAnnotationAttributes(RelationshipResource.class.getName()); + String relationshipCollectionName = (String) attrs.get("name"); + Class entityResource = (Class) attrs.get("entityResource"); + + String entityCollectionName = getEntityCollectionInfo(entityResource.getCanonicalName()); + + Pair ret = new Pair(entityCollectionName, relationshipCollectionName); + return ret; + } + else + { + return null; + } + } + else + { + throw new AlfrescoRuntimeException(""); + } + } + + private String getEntityCollectionInfo(Class resourceClass) throws IOException + { + return getEntityCollectionInfo(resourceClass.getCanonicalName()); + } + + private String getEntityCollectionInfo(String className) throws IOException + { + AnnotationMetadata annotationMetaData = getAnnotationMetadata(className); + if (annotationMetaData.isConcrete() && annotationMetaData.isIndependent()) + { + if (annotationMetaData.getAnnotationTypes().contains(EntityResource.class.getCanonicalName())) + { + Map attrs = annotationMetaData.getAnnotationAttributes(EntityResource.class.getName()); + return (String) attrs.get("name"); + } + else + { + return null; + } + } + else + { + throw new AlfrescoRuntimeException(""); + } + } + + public String getUrl() throws UnsupportedEncodingException + { + return url; + } + } + + /** + * @author Jamal Kaabi-Mofrad + */ + public static class BinaryRequestEntity implements RequestEntity + { + private final File file; + private final String mimeType; + private final String charset; + + public BinaryRequestEntity(File file, String mimeType, String charset) + { + this.file = file; + this.mimeType = mimeType; + this.charset = charset; + } + + @Override + public boolean isRepeatable() + { + return true; + } + + @Override + public void writeRequest(OutputStream out) throws IOException + { + InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); + try + { + int len; + byte[] buffer = new byte[8190]; + while ((len = inputStream.read(buffer)) != -1) + { + out.write(buffer, 0, len); + } + } + finally + { + inputStream.close(); + } + } + + @Override + public long getContentLength() + { + return file.length(); + } + + @Override + public String getContentType() + { + if (charset == null) + { + return mimeType; + } + if (mimeType == null) + { + return null; + } + return mimeType + "; charset=" + charset; + } + } + + /** + * @author Jamal Kaabi-Mofrad + */ + public static class BinaryPayload + { + private File file; + private String mimeType; + private String charset; + + public BinaryPayload(File file, String mimeType, String charset) + { + this.file = file; + this.mimeType = mimeType; + this.charset = charset; + } + + public BinaryPayload(File file, String mimeType) + { + this(file, mimeType, null); + } + + public BinaryPayload(File file) + { + this(file, null, null); + } + + public File getFile() + { + return file; + } + + public String getMimeType() + { + return mimeType; + } + + public String getCharset() + { + return charset; + } + } + + /** + * @author Jamal Kaabi-Mofrad + */ + public abstract class RequestBuilder + { + private RequestContext requestContext; + private String scope; + private String apiName = "alfresco"; // default api namespace + private int version = 1; + private String entityCollectionName; + private Object entityId; + private String relationCollectionName; + private Object relationshipEntityId; + private Map params; + private Map headers; + + public abstract T getHttpMethod() throws IOException; + + protected void setRequestHeaderIfAny(T methodBase) + { + if (headers != null) + { + for (Entry headerNameValue : headers.entrySet()) + { + methodBase.addRequestHeader(headerNameValue.getKey(), headerNameValue.getValue()); + } + } + } + + public RequestContext getRequestContext() + { + return requestContext; + } + + public RequestBuilder setRequestContext(RequestContext requestContext) + { + this.requestContext = requestContext; + return this; + } + + public String getScope() + { + return scope; + } + + public RequestBuilder setScope(String scope) + { + this.scope = scope; + return this; + } + + public String getApiName() + { + return apiName; + } + + public RequestBuilder setApiName(String apiName) + { + this.apiName = apiName; + return this; + } + + public int getVersion() + { + return version; + } + + public RequestBuilder setVersion(int version) + { + this.version = version; + return this; + } + + public String getEntityCollectionName() + { + return entityCollectionName; + } + + public RequestBuilder setEntityCollectionName(String entityCollectionName) + { + this.entityCollectionName = entityCollectionName; + return this; + } + + public Object getEntityId() + { + return entityId; + } + + public RequestBuilder setEntityId(Object entityId) + { + this.entityId = entityId; + return this; + } + + public String getRelationCollectionName() + { + return relationCollectionName; + } + + public RequestBuilder setRelationCollectionName(String relationCollectionName) + { + this.relationCollectionName = relationCollectionName; + return this; + } + + public Object getRelationshipEntityId() + { + return relationshipEntityId; + } + + public RequestBuilder setRelationshipEntityId(Object relationshipEntityId) + { + this.relationshipEntityId = relationshipEntityId; + return this; + } + + public Map getParams() + { + return params; + } + + public RequestBuilder setParams(Map params) + { + this.params = params; + return this; + } + + public Map getHeaders() + { + return headers; + } + + public RequestBuilder setHeaders(Map headers) + { + this.headers = headers; + return this; + } + } + + public class GetRequestBuilder extends RequestBuilder + { + private String password; + + public String getPassword() + { + return password; + } + + public GetRequestBuilder setPassword(String password) + { + this.password = password; + return this; + } + + @Override + public GetMethod getHttpMethod() throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), + getScope(), getApiName(), getVersion(), getEntityCollectionName(), + getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); + String url = endpoint.getUrl(); + + GetMethod req = new GetMethod(url); + setRequestHeaderIfAny(req); + return req; + } + } + + public class DeleteRequestBuilder extends RequestBuilder + { + @Override + public DeleteMethod getHttpMethod() throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), + getScope(), getApiName(), getVersion(), getEntityCollectionName(), + getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); + String url = endpoint.getUrl(); + + DeleteMethod req = new DeleteMethod(url); + setRequestHeaderIfAny(req); + return req; + } + } + + public abstract class PostPutRequestBuilder extends RequestBuilder + { + private String bodyAsString; + private byte[] bodyAsByteArray; + private String contentType; + + public String getBodyAsString() + { + return bodyAsString; + } + + public PostPutRequestBuilder setBodyAsString(String bodyAsString) + { + this.bodyAsString = bodyAsString; + return this; + } + + public byte[] getBodyAsByteArray() + { + return bodyAsByteArray; + } + + public PostPutRequestBuilder setBodyAsByteArray(byte[] bodyAsByteArray) + { + this.bodyAsByteArray = bodyAsByteArray; + return this; + } + + public String getContentType() + { + return contentType; + } + + public PostPutRequestBuilder setContentType(String contentType) + { + this.contentType = contentType; + return this; + } + } + + public class PostRequestBuilder extends PostPutRequestBuilder + { + + @Override + public PostMethod getHttpMethod() throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), + getScope(), getApiName(), getVersion(), getEntityCollectionName(), + getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); + String url = endpoint.getUrl(); + + PostMethod req = new PostMethod(url.toString()); + String contentType = getContentType(); + if (getBodyAsString() != null) + { + + if (contentType == null || contentType.isEmpty()) + { + contentType = "application/json"; + } + StringRequestEntity requestEntity = new StringRequestEntity(getBodyAsString(), contentType, "UTF-8"); + req.setRequestEntity(requestEntity); + } + else if (getBodyAsByteArray() != null) + { + if (contentType == null || contentType.isEmpty()) + { + contentType = "application/octet-stream"; + } + ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(getBodyAsByteArray(), contentType); + req.setRequestEntity(requestEntity); + } + setRequestHeaderIfAny(req); + return req; + } + } + + public class PutRequestBuilder extends PostPutRequestBuilder + { + private BinaryPayload binaryPayload; + + public BinaryPayload getBinaryPayload() + { + return binaryPayload; + } + + public PutRequestBuilder setBinaryPayload(BinaryPayload binaryPayload) + { + this.binaryPayload = binaryPayload; + return this; + } + + @Override + public PutMethod getHttpMethod() throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(getRequestContext().getNetworkId(), + getScope(), getApiName(), getVersion(), getEntityCollectionName(), + getEntityId(), getRelationCollectionName(), getRelationshipEntityId(), getParams()); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if (getBodyAsString() != null) + { + StringRequestEntity requestEntity = new StringRequestEntity(getBodyAsString(), "application/json", "UTF-8"); + req.setRequestEntity(requestEntity); + } + else if (binaryPayload != null) + { + BinaryRequestEntity requestEntity = new BinaryRequestEntity(binaryPayload.getFile(), binaryPayload.getMimeType(), + binaryPayload.getCharset()); + req.setRequestEntity(requestEntity); + } + setRequestHeaderIfAny(req); + return req; + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/RequestContext.java b/source/test-java/org/alfresco/rest/api/tests/client/RequestContext.java index 7fc1e0699f..4ffca27ac1 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/RequestContext.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/RequestContext.java @@ -1,75 +1,75 @@ -package org.alfresco.rest.api.tests.client; - -import org.apache.chemistry.opencmis.client.api.OperationContext; - -public class RequestContext -{ - private String networkId; - private String runAsUser; - private String password; - private OperationContext cmisOperationCtxOverride = null; - - public RequestContext(String runAsUser) - { - super(); - this.runAsUser = runAsUser; - } - - public RequestContext(String networkId, String runAsUser) - { - this(runAsUser); - this.networkId = networkId; - this.password = null; - } - - public RequestContext(String networkId, String runAsUser, OperationContext cmisOperationCtxOverride) - { - this(runAsUser); - this.networkId = networkId; - this.password = null; - this.cmisOperationCtxOverride = cmisOperationCtxOverride; - } - - public RequestContext(String networkId, String runAsUser, String password) - { - this(runAsUser); - this.networkId = networkId; - this.password = password; - } - - public void setOperationContext(OperationContext ctx) - { - this.cmisOperationCtxOverride = ctx; - } - - public OperationContext getCmisOperationCtxOverride() - { - return cmisOperationCtxOverride; - } - - public String getPassword() - { - return password; - } - - public String getNetworkId() - { - return networkId; - } - - public String getRunAsUser() - { - return runAsUser; - } - - public void setNetworkId(String networkId) - { - this.networkId = networkId; - } - - public void setRunAsUser(String runAsUser) - { - this.runAsUser = runAsUser; - } - -} +package org.alfresco.rest.api.tests.client; + +import org.apache.chemistry.opencmis.client.api.OperationContext; + +public class RequestContext +{ + private String networkId; + private String runAsUser; + private String password; + private OperationContext cmisOperationCtxOverride = null; + + public RequestContext(String runAsUser) + { + super(); + this.runAsUser = runAsUser; + } + + public RequestContext(String networkId, String runAsUser) + { + this(runAsUser); + this.networkId = networkId; + this.password = null; + } + + public RequestContext(String networkId, String runAsUser, OperationContext cmisOperationCtxOverride) + { + this(runAsUser); + this.networkId = networkId; + this.password = null; + this.cmisOperationCtxOverride = cmisOperationCtxOverride; + } + + public RequestContext(String networkId, String runAsUser, String password) + { + this(runAsUser); + this.networkId = networkId; + this.password = password; + } + + public void setOperationContext(OperationContext ctx) + { + this.cmisOperationCtxOverride = ctx; + } + + public OperationContext getCmisOperationCtxOverride() + { + return cmisOperationCtxOverride; + } + + public String getPassword() + { + return password; + } + + public String getNetworkId() + { + return networkId; + } + + public String getRunAsUser() + { + return runAsUser; + } + + public void setNetworkId(String networkId) + { + this.networkId = networkId; + } + + public void setRunAsUser(String runAsUser) + { + this.runAsUser = runAsUser; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/SharedHttpClientProvider.java b/source/test-java/org/alfresco/rest/api/tests/client/SharedHttpClientProvider.java index f672396be0..ee66a298c4 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/SharedHttpClientProvider.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/SharedHttpClientProvider.java @@ -1,75 +1,75 @@ -package org.alfresco.rest.api.tests.client; - -import org.apache.commons.httpclient.HostConfiguration; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.params.HttpConnectionManagerParams; - -/** - * - * A class responsible for managing one shared {@link HttpClient} instance. This uses a - * thread-safe connection-manager instead of creating a new istance on every call. - * - * This is done for the folowing reasons: - *
- *
    - *
  • Creating new HTTPClient instances for each request has memory-overhead and most - * important, opens a new connection for each request. Even though the connection is released - * they are kept in 'CLOSE_WAIT' state by the OS. This can, on high usage, empty out available outgoing TCP-ports and - * influence the testing on the client, having impact on the results.
  • - *
  • Using a single HTTPClient allows creating a pool of connections that can be kept alive to - * a certain route (route = combination of host and port) for a max number of time. This eliminates connection - * setup and additional server round-trips, raising the overall throughput of http-calls (Browsers use - * this mechanism all the time to lower loading-times).
  • - *
- * - * @author Frederik Heremans - */ -public final class SharedHttpClientProvider implements HttpClientProvider -{ - private HttpClient client; - private String alfrescoUrl; - - // Private constructor to prevent instantiation - public SharedHttpClientProvider(String alfrescoUrl, int maxNumberOfConnections) - { - setAlfrescoUrl(alfrescoUrl); - - // Initialize manager - MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager(); - HttpConnectionManagerParams params = new HttpConnectionManagerParams(); - params.setMaxTotalConnections(maxNumberOfConnections); - params.setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, maxNumberOfConnections); - - // Create the client - client = new HttpClient(manager); - client.getParams().setAuthenticationPreemptive(true); - } - - /** - * @param alfrescoUrl the URL where alfresco repo is running on. - */ - private void setAlfrescoUrl(String alfrescoUrl) - { - this.alfrescoUrl = alfrescoUrl; - // Ensure path ends with forward slash - if(alfrescoUrl != null && !alfrescoUrl.endsWith("/")) - { - this.alfrescoUrl = alfrescoUrl.concat("/"); - } - } - - public String getFullAlfrescoUrlForPath(String path) - { - if(path.startsWith("/")) - { - return alfrescoUrl.concat(path.substring(1, path.length())); - } - return alfrescoUrl.concat(path); - } - - public HttpClient getHttpClient() - { - return client; - } -} +package org.alfresco.rest.api.tests.client; + +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; + +/** + * + * A class responsible for managing one shared {@link HttpClient} instance. This uses a + * thread-safe connection-manager instead of creating a new istance on every call. + * + * This is done for the folowing reasons: + *
+ *
    + *
  • Creating new HTTPClient instances for each request has memory-overhead and most + * important, opens a new connection for each request. Even though the connection is released + * they are kept in 'CLOSE_WAIT' state by the OS. This can, on high usage, empty out available outgoing TCP-ports and + * influence the testing on the client, having impact on the results.
  • + *
  • Using a single HTTPClient allows creating a pool of connections that can be kept alive to + * a certain route (route = combination of host and port) for a max number of time. This eliminates connection + * setup and additional server round-trips, raising the overall throughput of http-calls (Browsers use + * this mechanism all the time to lower loading-times).
  • + *
+ * + * @author Frederik Heremans + */ +public final class SharedHttpClientProvider implements HttpClientProvider +{ + private HttpClient client; + private String alfrescoUrl; + + // Private constructor to prevent instantiation + public SharedHttpClientProvider(String alfrescoUrl, int maxNumberOfConnections) + { + setAlfrescoUrl(alfrescoUrl); + + // Initialize manager + MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager(); + HttpConnectionManagerParams params = new HttpConnectionManagerParams(); + params.setMaxTotalConnections(maxNumberOfConnections); + params.setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, maxNumberOfConnections); + + // Create the client + client = new HttpClient(manager); + client.getParams().setAuthenticationPreemptive(true); + } + + /** + * @param alfrescoUrl the URL where alfresco repo is running on. + */ + private void setAlfrescoUrl(String alfrescoUrl) + { + this.alfrescoUrl = alfrescoUrl; + // Ensure path ends with forward slash + if(alfrescoUrl != null && !alfrescoUrl.endsWith("/")) + { + this.alfrescoUrl = alfrescoUrl.concat("/"); + } + } + + public String getFullAlfrescoUrlForPath(String path) + { + if(path.startsWith("/")) + { + return alfrescoUrl.concat(path.substring(1, path.length())); + } + return alfrescoUrl.concat(path); + } + + public HttpClient getHttpClient() + { + return client; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/UserAuthenticationDetailsProviderImpl.java b/source/test-java/org/alfresco/rest/api/tests/client/UserAuthenticationDetailsProviderImpl.java index ec18670e8a..532713e0fb 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/UserAuthenticationDetailsProviderImpl.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/UserAuthenticationDetailsProviderImpl.java @@ -1,73 +1,73 @@ -package org.alfresco.rest.api.tests.client; - - -public class UserAuthenticationDetailsProviderImpl implements AuthenticationDetailsProvider -{ - private String adminUserName; - private String adminPassword; - - private UserDataService userDataService; - - /** - * @param userDataService service to use for {@link UserData} related operations - */ - public UserAuthenticationDetailsProviderImpl(UserDataService userDataService, String adminUserName, String adminPassword) - { - this.userDataService = userDataService; - this.adminUserName = adminUserName; - this.adminPassword = adminPassword; - } - - - public String getPasswordForUser(String userName) - { - if (userName != null) - { - UserData user = userDataService.findUserByUserName(userName); - if (user != null) - { - return user.getPassword(); - } - } - return null; - } - - public String getTicketForUser(String userName) - { - if (userName != null) - { - UserData user = userDataService.findUserByUserName(userName); - if (user != null) - { - return user.getTicket(); - } - } - return null; - } - - public String getAdminUserName() - { - return this.adminUserName; - } - - public String getAdminPassword() - { - return this.adminPassword; - } - - - @Override - public void updateTicketForUser(String userName, String ticket) throws IllegalArgumentException - { - UserData user = userDataService.findUserByUserName(userName); - if(user != null) - { - user.setTicket(ticket); - } - else - { - // TODO - } - } - -} +package org.alfresco.rest.api.tests.client; + + +public class UserAuthenticationDetailsProviderImpl implements AuthenticationDetailsProvider +{ + private String adminUserName; + private String adminPassword; + + private UserDataService userDataService; + + /** + * @param userDataService service to use for {@link UserData} related operations + */ + public UserAuthenticationDetailsProviderImpl(UserDataService userDataService, String adminUserName, String adminPassword) + { + this.userDataService = userDataService; + this.adminUserName = adminUserName; + this.adminPassword = adminPassword; + } + + + public String getPasswordForUser(String userName) + { + if (userName != null) + { + UserData user = userDataService.findUserByUserName(userName); + if (user != null) + { + return user.getPassword(); + } + } + return null; + } + + public String getTicketForUser(String userName) + { + if (userName != null) + { + UserData user = userDataService.findUserByUserName(userName); + if (user != null) + { + return user.getTicket(); + } + } + return null; + } + + public String getAdminUserName() + { + return this.adminUserName; + } + + public String getAdminPassword() + { + return this.adminPassword; + } + + + @Override + public void updateTicketForUser(String userName, String ticket) throws IllegalArgumentException + { + UserData user = userDataService.findUserByUserName(userName); + if(user != null) + { + user.setTicket(ticket); + } + else + { + // TODO + } + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/UserData.java b/source/test-java/org/alfresco/rest/api/tests/client/UserData.java index 9fc7516ae5..d1af9fb5cc 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/UserData.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/UserData.java @@ -1,80 +1,80 @@ -package org.alfresco.rest.api.tests.client; - -import java.io.Serializable; - -/** - * Data representing a single user. - * - * @author Frederik Heremans - * @since 1.1 - */ -public class UserData implements Serializable -{ - private static final long serialVersionUID = -4741893659787720414L; - - public static final String FIELD_ID = "id"; - public static final String FIELD_USERNAME = "userName"; - public static final String FIELD_PASSWORD = "password"; - public static final String FIELD_TICKET = "ticket"; - public static final String FIELD_DOMAIN = "domain"; - - private String id; - private String userName; - private String domain; - private String password; - private String ticket; - - public UserData() - { - } - - public String getDomain() - { - return domain; - } - - public String getUserName() - { - return this.userName; - } - - public void setUserName(String userName) - { - this.userName = userName; - int idx = userName.indexOf("@"); - if(idx != -1) - { - this.domain = userName.substring(idx + 1); - } - } - - public String getPassword() - { - return this.password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public String getTicket() - { - return this.ticket; - } - - public void setTicket(String ticket) - { - this.ticket = ticket; - } - - public String getId() - { - return this.id; - } - - public void setId(String id) - { - this.id = id; - } -} +package org.alfresco.rest.api.tests.client; + +import java.io.Serializable; + +/** + * Data representing a single user. + * + * @author Frederik Heremans + * @since 1.1 + */ +public class UserData implements Serializable +{ + private static final long serialVersionUID = -4741893659787720414L; + + public static final String FIELD_ID = "id"; + public static final String FIELD_USERNAME = "userName"; + public static final String FIELD_PASSWORD = "password"; + public static final String FIELD_TICKET = "ticket"; + public static final String FIELD_DOMAIN = "domain"; + + private String id; + private String userName; + private String domain; + private String password; + private String ticket; + + public UserData() + { + } + + public String getDomain() + { + return domain; + } + + public String getUserName() + { + return this.userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + int idx = userName.indexOf("@"); + if(idx != -1) + { + this.domain = userName.substring(idx + 1); + } + } + + public String getPassword() + { + return this.password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getTicket() + { + return this.ticket; + } + + public void setTicket(String ticket) + { + this.ticket = ticket; + } + + public String getId() + { + return this.id; + } + + public void setId(String id) + { + this.id = id; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/UserDataService.java b/source/test-java/org/alfresco/rest/api/tests/client/UserDataService.java index a6b0b5b103..178997aec6 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/UserDataService.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/UserDataService.java @@ -1,7 +1,7 @@ -package org.alfresco.rest.api.tests.client; - - -public interface UserDataService -{ - public UserData findUserByUserName(String userName); -} +package org.alfresco.rest.api.tests.client; + + +public interface UserDataService +{ + public UserData findUserByUserName(String userName); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Activities.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Activities.java index 7a5c0b065d..77c959fad3 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Activities.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Activities.java @@ -1,87 +1,87 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class Activities implements Serializable -{ - private static final long serialVersionUID = -6280142299994200394L; - - private String userId; - private ActivitiesParameters activitiesParams; - - public Activities() - { - } - - public Activities(String userId, ActivitiesParameters activitiesParams) - { - super(); - if(userId == null) - { - throw new IllegalArgumentException(); - } - this.userId = userId; - this.activitiesParams = activitiesParams; - } - - public void setUserId(String userId) - { - this.userId = userId; - } - - public String getUserId() - { - return userId; - } - - public ActivitiesParameters getActivitiesParams() - { - return activitiesParams; - } - - public void setActivitiesParams(ActivitiesParameters activitiesParams) - { - this.activitiesParams = activitiesParams; - } - - @Override - public String toString() - { - return "Activities [userId=" + userId + ", activitiesParams=" - + activitiesParams + "]"; - } - - public static ListResponse parseActivities(JSONObject jsonObject) - { - List activities = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - activities.add(Activity.parseActivity(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - return new ListResponse(paging, activities); - } - - - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class Activities implements Serializable +{ + private static final long serialVersionUID = -6280142299994200394L; + + private String userId; + private ActivitiesParameters activitiesParams; + + public Activities() + { + } + + public Activities(String userId, ActivitiesParameters activitiesParams) + { + super(); + if(userId == null) + { + throw new IllegalArgumentException(); + } + this.userId = userId; + this.activitiesParams = activitiesParams; + } + + public void setUserId(String userId) + { + this.userId = userId; + } + + public String getUserId() + { + return userId; + } + + public ActivitiesParameters getActivitiesParams() + { + return activitiesParams; + } + + public void setActivitiesParams(ActivitiesParameters activitiesParams) + { + this.activitiesParams = activitiesParams; + } + + @Override + public String toString() + { + return "Activities [userId=" + userId + ", activitiesParams=" + + activitiesParams + "]"; + } + + public static ListResponse parseActivities(JSONObject jsonObject) + { + List activities = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + activities.add(Activity.parseActivity(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + return new ListResponse(paging, activities); + } + + + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/ActivitiesParameters.java b/source/test-java/org/alfresco/rest/api/tests/client/data/ActivitiesParameters.java index 544f89a49f..4423b676c9 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/ActivitiesParameters.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/ActivitiesParameters.java @@ -1,29 +1,29 @@ -package org.alfresco.rest.api.tests.client.data; - -import java.io.Serializable; - -public class ActivitiesParameters implements Serializable -{ - private static final long serialVersionUID = 13166440680499285L; - - private String siteId; - private String who; - - public ActivitiesParameters(String siteId, String who) - { - super(); - this.siteId = siteId; - this.who = who; - } - - public String getSiteId() - { - return siteId; - } - - public String getWho() - { - return who; - } - -} +package org.alfresco.rest.api.tests.client.data; + +import java.io.Serializable; + +public class ActivitiesParameters implements Serializable +{ + private static final long serialVersionUID = 13166440680499285L; + + private String siteId; + private String who; + + public ActivitiesParameters(String siteId, String who) + { + super(); + this.siteId = siteId; + this.who = who; + } + + public String getSiteId() + { + return siteId; + } + + public String getWho() + { + return who; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Activity.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Activity.java index ab61becc96..60095e1cb7 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Activity.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Activity.java @@ -1,194 +1,194 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.json.simple.JSONObject; - -public class Activity implements Serializable, ExpectedComparison -{ - private static final long serialVersionUID = 1869724448167732060L; - - private Long id; - private String networkId; - private String siteId; - private String feedPersonId; - private String postPersonId; - private String postedAt; - private String activityType; - private Map summary; - - public Activity(Long id, String networkId, String siteId, String feedPersonId, - String postPersonId, String postedAt, String activityType, - Map summary) { - super(); - this.id = id; - this.networkId = networkId; - this.siteId = siteId; - this.feedPersonId = feedPersonId; - this.postPersonId = postPersonId; - this.postedAt = postedAt; - this.activityType = activityType; - this.summary = summary; - } - - public Long getId() { - return id; - } - - public String getSiteId() { - return siteId; - } - - public String getFeedPersonId() { - return feedPersonId; - } - - public String getPostPersonId() { - return postPersonId; - } - - public String getPostedAt() { - return postedAt; - } - - public String getActivityType() { - return activityType; - } - - public Map getSummary() { - return summary; - } - - public String getNetworkId() - { - return networkId; - } - - @Override - public String toString() - { - return "Activity [id=" + id + ", networkId=" + networkId + ", siteId=" - + siteId + ", feedPersonId=" + feedPersonId + ", postPersonId=" - + postPersonId + ", postedAt=" + postedAt + ", activityType=" - + activityType + ", summary=" + summary + "]"; - } - - @SuppressWarnings("unchecked") - public static Activity parseActivity(JSONObject jsonObject) - { - Long id = (Long)jsonObject.get("id"); - String networkId = (String)jsonObject.get("networkId"); - String siteId = (String)jsonObject.get("siteId"); - String feedPersonId = (String)jsonObject.get("feedPersonId"); - String postPersonId = (String)jsonObject.get("postPersonId"); - String postedAt = (String)jsonObject.get("postedAt"); - String activityType = (String)jsonObject.get("activityType"); - JSONObject summary = (JSONObject)jsonObject.get("activitySummary"); - Activity activity = new Activity(id, networkId, siteId, feedPersonId, postPersonId, postedAt, activityType, summary); - return activity; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("id", String.valueOf(getId())); - jsonObject.put("networkId", getNetworkId()); - jsonObject.put("siteId", getSiteId()); - jsonObject.put("feedPersonId", getFeedPersonId()); - jsonObject.put("postPersonId", getPostPersonId()); - jsonObject.put("postedAt", getPostedAt()); - jsonObject.put("activityType", getActivityType()); - jsonObject.put("activitySummary", getSummary()); - return jsonObject; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Activity other = (Activity) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Activity); - - Activity other = (Activity)o; - AssertUtil.assertEquals("id", id, other.getId()); - AssertUtil.assertEquals("siteId", networkId, other.getNetworkId()); - AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); - AssertUtil.assertEquals("feedPersonId", feedPersonId, other.getFeedPersonId()); - AssertUtil.assertEquals("postPersonId", postPersonId, other.getPostPersonId()); - AssertUtil.assertEquals("postedAt", postedAt, other.getPostedAt()); - AssertUtil.assertEquals("activityType", activityType, other.getActivityType()); - AssertUtil.assertEquals("summary", summary, other.getSummary()); - } - - public static Map getActivitySummary(JSONObject activitySummary, String activityType) - { - Map summary = new HashMap(); - - if(activityType.equals("org.alfresco.documentlibrary.file-added")) - { - String nodeRefStr = (String)activitySummary.remove("nodeRef"); - if(NodeRef.isNodeRef(nodeRefStr)) - { - summary.put("objectId", new NodeRef(nodeRefStr).getId()); - } - else - { - throw new RuntimeException("nodeRef " + nodeRefStr + " in activity feed is not a valid NodeRef"); - } - String parentNodeRefStr = (String)activitySummary.remove("parentNodeRef"); - if(NodeRef.isNodeRef(parentNodeRefStr)) - { - summary.put("parentObjectId", new NodeRef(parentNodeRefStr).getId()); - } - else - { - throw new RuntimeException("parentNodeRef " + parentNodeRefStr + " in activity feed is not a valid NodeRef"); - } - summary.put("lastName", activitySummary.get("lastName")); - summary.put("firstName", activitySummary.get("firstName")); - summary.put("title", activitySummary.get("title")); - } else if(activityType.equals("org.alfresco.site.user-joined")) - { - summary.put("lastName", activitySummary.get("lastName")); - summary.put("firstName", activitySummary.get("firstName")); - summary.put("memberLastName", activitySummary.get("memberLastName")); - summary.put("memberFirstName", activitySummary.get("memberFirstName")); - summary.put("memberPersonId", activitySummary.get("memberUserName")); - summary.put("role", activitySummary.get("role")); - summary.put("title", activitySummary.get("title")); - } - - return summary; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.json.simple.JSONObject; + +public class Activity implements Serializable, ExpectedComparison +{ + private static final long serialVersionUID = 1869724448167732060L; + + private Long id; + private String networkId; + private String siteId; + private String feedPersonId; + private String postPersonId; + private String postedAt; + private String activityType; + private Map summary; + + public Activity(Long id, String networkId, String siteId, String feedPersonId, + String postPersonId, String postedAt, String activityType, + Map summary) { + super(); + this.id = id; + this.networkId = networkId; + this.siteId = siteId; + this.feedPersonId = feedPersonId; + this.postPersonId = postPersonId; + this.postedAt = postedAt; + this.activityType = activityType; + this.summary = summary; + } + + public Long getId() { + return id; + } + + public String getSiteId() { + return siteId; + } + + public String getFeedPersonId() { + return feedPersonId; + } + + public String getPostPersonId() { + return postPersonId; + } + + public String getPostedAt() { + return postedAt; + } + + public String getActivityType() { + return activityType; + } + + public Map getSummary() { + return summary; + } + + public String getNetworkId() + { + return networkId; + } + + @Override + public String toString() + { + return "Activity [id=" + id + ", networkId=" + networkId + ", siteId=" + + siteId + ", feedPersonId=" + feedPersonId + ", postPersonId=" + + postPersonId + ", postedAt=" + postedAt + ", activityType=" + + activityType + ", summary=" + summary + "]"; + } + + @SuppressWarnings("unchecked") + public static Activity parseActivity(JSONObject jsonObject) + { + Long id = (Long)jsonObject.get("id"); + String networkId = (String)jsonObject.get("networkId"); + String siteId = (String)jsonObject.get("siteId"); + String feedPersonId = (String)jsonObject.get("feedPersonId"); + String postPersonId = (String)jsonObject.get("postPersonId"); + String postedAt = (String)jsonObject.get("postedAt"); + String activityType = (String)jsonObject.get("activityType"); + JSONObject summary = (JSONObject)jsonObject.get("activitySummary"); + Activity activity = new Activity(id, networkId, siteId, feedPersonId, postPersonId, postedAt, activityType, summary); + return activity; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id", String.valueOf(getId())); + jsonObject.put("networkId", getNetworkId()); + jsonObject.put("siteId", getSiteId()); + jsonObject.put("feedPersonId", getFeedPersonId()); + jsonObject.put("postPersonId", getPostPersonId()); + jsonObject.put("postedAt", getPostedAt()); + jsonObject.put("activityType", getActivityType()); + jsonObject.put("activitySummary", getSummary()); + return jsonObject; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Activity other = (Activity) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Activity); + + Activity other = (Activity)o; + AssertUtil.assertEquals("id", id, other.getId()); + AssertUtil.assertEquals("siteId", networkId, other.getNetworkId()); + AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); + AssertUtil.assertEquals("feedPersonId", feedPersonId, other.getFeedPersonId()); + AssertUtil.assertEquals("postPersonId", postPersonId, other.getPostPersonId()); + AssertUtil.assertEquals("postedAt", postedAt, other.getPostedAt()); + AssertUtil.assertEquals("activityType", activityType, other.getActivityType()); + AssertUtil.assertEquals("summary", summary, other.getSummary()); + } + + public static Map getActivitySummary(JSONObject activitySummary, String activityType) + { + Map summary = new HashMap(); + + if(activityType.equals("org.alfresco.documentlibrary.file-added")) + { + String nodeRefStr = (String)activitySummary.remove("nodeRef"); + if(NodeRef.isNodeRef(nodeRefStr)) + { + summary.put("objectId", new NodeRef(nodeRefStr).getId()); + } + else + { + throw new RuntimeException("nodeRef " + nodeRefStr + " in activity feed is not a valid NodeRef"); + } + String parentNodeRefStr = (String)activitySummary.remove("parentNodeRef"); + if(NodeRef.isNodeRef(parentNodeRefStr)) + { + summary.put("parentObjectId", new NodeRef(parentNodeRefStr).getId()); + } + else + { + throw new RuntimeException("parentNodeRef " + parentNodeRefStr + " in activity feed is not a valid NodeRef"); + } + summary.put("lastName", activitySummary.get("lastName")); + summary.put("firstName", activitySummary.get("firstName")); + summary.put("title", activitySummary.get("title")); + } else if(activityType.equals("org.alfresco.site.user-joined")) + { + summary.put("lastName", activitySummary.get("lastName")); + summary.put("firstName", activitySummary.get("firstName")); + summary.put("memberLastName", activitySummary.get("memberLastName")); + summary.put("memberFirstName", activitySummary.get("memberFirstName")); + summary.put("memberPersonId", activitySummary.get("memberUserName")); + summary.put("role", activitySummary.get("role")); + summary.put("title", activitySummary.get("title")); + } + + return summary; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/AssertUtil.java b/source/test-java/org/alfresco/rest/api/tests/client/data/AssertUtil.java index 6946a16479..72b75cb131 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/AssertUtil.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/AssertUtil.java @@ -1,33 +1,33 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; - -import org.junit.Assert; - -public class AssertUtil -{ - private AssertUtil() - { - } - - public static void assertEquals(String propertyName, String expected, String actual) - { - if(expected != null) - { - if(!expected.equals("")) - { - assertNotNull(propertyName + " expected " + expected + ", but was null", actual); - Assert.assertEquals(expected, actual); - } - } - } - - public static void assertEquals(String propertyName, Object expected, Object actual) - { - if(expected != null) - { - assertNotNull(propertyName + " expected " + expected + ", but was null", actual); - Assert.assertEquals(propertyName + " expected " + expected + ", but was " + actual, expected, actual); - } - } +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Assert; + +public class AssertUtil +{ + private AssertUtil() + { + } + + public static void assertEquals(String propertyName, String expected, String actual) + { + if(expected != null) + { + if(!expected.equals("")) + { + assertNotNull(propertyName + " expected " + expected + ", but was null", actual); + Assert.assertEquals(expected, actual); + } + } + } + + public static void assertEquals(String propertyName, Object expected, Object actual) + { + if(expected != null) + { + assertNotNull(propertyName + " expected " + expected + ", but was null", actual); + Assert.assertEquals(propertyName + " expected " + expected + ", but was " + actual, expected, actual); + } + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/CMISNode.java b/source/test-java/org/alfresco/rest/api/tests/client/data/CMISNode.java index fb0d84c8dd..ac3766c454 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/CMISNode.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/CMISNode.java @@ -1,221 +1,221 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.service.namespace.QName; -import org.apache.chemistry.opencmis.client.api.CmisObject; -import org.apache.chemistry.opencmis.client.api.Property; -import org.apache.chemistry.opencmis.client.api.QueryResult; -import org.apache.chemistry.opencmis.commons.PropertyIds; -import org.apache.chemistry.opencmis.commons.data.Properties; -import org.apache.chemistry.opencmis.commons.data.PropertyData; -import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition; -import org.json.simple.JSONObject; - -public class CMISNode implements Serializable, ExpectedComparison -{ - private static final long serialVersionUID = -5027938359868278498L; - - protected String nodeId; - protected String guid; - protected Map properties; - - /** - * For POSTs - * @param guid String - */ - public CMISNode(String guid) - { - this.guid = guid; - } - - public CMISNode(String id, String guid) - { - this.nodeId = id; - this.guid = guid; - } - - public CMISNode(String nodeId, String guid, Map properties) - { - this.nodeId = nodeId; - this.guid = nodeId; - this.properties = properties; - } - - public void setGuid(String guid) - { - this.guid = guid; - } - - public String getGuid() - { - return guid; - } - - public String getRawNodeId() - { - return nodeId; - } - - public String getNodeId() - { - return nodeId; - } - - public boolean isFolder() - { - return false; - } - - public static Map getProperties(Map properties) - { - Map propertiesMap = new HashMap(); - for(QName propName : properties.keySet()) - { - propertiesMap.put(propName.toPrefixString(), properties.get(propName)); - } - return propertiesMap; - } - - public static Map getProperties(List> properties) - { - Map propertiesMap = new HashMap(); - for(Property p : properties) - { - propertiesMap.put(p.getId(), p.getValueAsString()); - } - return propertiesMap; - } - - public static Map getProperties(Properties properties) - { - Map propertiesMap = new HashMap(); - for(PropertyData p : properties.getPropertyList()) - { - propertiesMap.put(p.getId(), p.getFirstValue().toString()); - } - return propertiesMap; - } - - public Serializable getProperty(String name) - { - return properties.get(name); - } - - public Map getProperties() - { - return properties; - } - - // TODO getFirstValue replace with getValues - // how to determine type of result to choose Node or FolderNode - public static CMISNode createNode(QueryResult qr) - { - List> props = qr.getProperties(); - Map properties = new HashMap(); - - for(PropertyData p : props) - { - properties.put(p.getId(), (Serializable)p.getFirstValue()); - } - - String objectId = (String)qr.getPropertyById(PropertyIds.OBJECT_ID).getFirstValue(); - CMISNode n = new CMISNode(objectId, objectId, properties); - return n; - } - - public static CMISNode createNode(CmisObject o) - { - CMISNode n = null; - - Map properties = CMISNode.getProperties(o.getProperties()); - - if(o.getBaseType() instanceof FolderTypeDefinition) - { - n = new FolderNode(o.getId(), o.getId(), properties); - } - else - { - n = new CMISNode(o.getId(), o.getId(), properties); - } - - return n; - } - - public static CMISNode createNode(String objectId) - { - Map properties = new HashMap(); - CMISNode n = new CMISNode(objectId, objectId, properties); - return n; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CMISNode other = (CMISNode) obj; - if (nodeId == null) { - if (other.nodeId != null) - return false; - } else if (!nodeId.equals(other.nodeId)) - return false; - if (properties == null) { - if (other.properties != null) - return false; - } else if (!properties.equals(other.properties)) - return false; - return true; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject json = new JSONObject(); - json.put("guid", getGuid()); - json.put("id", getNodeId()); - return json; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof CMISNode); - - CMISNode other = (CMISNode)o; - - AssertUtil.assertEquals("id", nodeId, other.getNodeId()); - AssertUtil.assertEquals("guid", guid, other.getGuid()); - for(String propertyName : properties.keySet()) - { - Serializable expected = properties.get(propertyName); - Serializable actual = other.getProperty(propertyName); - AssertUtil.assertEquals(propertyName, expected, actual); - } - } - - @Override - public String toString() - { - return "CMISNode [nodeId=" + nodeId + ", guid=" + guid + ", properties=" - + properties + "]"; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.chemistry.opencmis.client.api.Property; +import org.apache.chemistry.opencmis.client.api.QueryResult; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.data.Properties; +import org.apache.chemistry.opencmis.commons.data.PropertyData; +import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition; +import org.json.simple.JSONObject; + +public class CMISNode implements Serializable, ExpectedComparison +{ + private static final long serialVersionUID = -5027938359868278498L; + + protected String nodeId; + protected String guid; + protected Map properties; + + /** + * For POSTs + * @param guid String + */ + public CMISNode(String guid) + { + this.guid = guid; + } + + public CMISNode(String id, String guid) + { + this.nodeId = id; + this.guid = guid; + } + + public CMISNode(String nodeId, String guid, Map properties) + { + this.nodeId = nodeId; + this.guid = nodeId; + this.properties = properties; + } + + public void setGuid(String guid) + { + this.guid = guid; + } + + public String getGuid() + { + return guid; + } + + public String getRawNodeId() + { + return nodeId; + } + + public String getNodeId() + { + return nodeId; + } + + public boolean isFolder() + { + return false; + } + + public static Map getProperties(Map properties) + { + Map propertiesMap = new HashMap(); + for(QName propName : properties.keySet()) + { + propertiesMap.put(propName.toPrefixString(), properties.get(propName)); + } + return propertiesMap; + } + + public static Map getProperties(List> properties) + { + Map propertiesMap = new HashMap(); + for(Property p : properties) + { + propertiesMap.put(p.getId(), p.getValueAsString()); + } + return propertiesMap; + } + + public static Map getProperties(Properties properties) + { + Map propertiesMap = new HashMap(); + for(PropertyData p : properties.getPropertyList()) + { + propertiesMap.put(p.getId(), p.getFirstValue().toString()); + } + return propertiesMap; + } + + public Serializable getProperty(String name) + { + return properties.get(name); + } + + public Map getProperties() + { + return properties; + } + + // TODO getFirstValue replace with getValues + // how to determine type of result to choose Node or FolderNode + public static CMISNode createNode(QueryResult qr) + { + List> props = qr.getProperties(); + Map properties = new HashMap(); + + for(PropertyData p : props) + { + properties.put(p.getId(), (Serializable)p.getFirstValue()); + } + + String objectId = (String)qr.getPropertyById(PropertyIds.OBJECT_ID).getFirstValue(); + CMISNode n = new CMISNode(objectId, objectId, properties); + return n; + } + + public static CMISNode createNode(CmisObject o) + { + CMISNode n = null; + + Map properties = CMISNode.getProperties(o.getProperties()); + + if(o.getBaseType() instanceof FolderTypeDefinition) + { + n = new FolderNode(o.getId(), o.getId(), properties); + } + else + { + n = new CMISNode(o.getId(), o.getId(), properties); + } + + return n; + } + + public static CMISNode createNode(String objectId) + { + Map properties = new HashMap(); + CMISNode n = new CMISNode(objectId, objectId, properties); + return n; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CMISNode other = (CMISNode) obj; + if (nodeId == null) { + if (other.nodeId != null) + return false; + } else if (!nodeId.equals(other.nodeId)) + return false; + if (properties == null) { + if (other.properties != null) + return false; + } else if (!properties.equals(other.properties)) + return false; + return true; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject json = new JSONObject(); + json.put("guid", getGuid()); + json.put("id", getNodeId()); + return json; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof CMISNode); + + CMISNode other = (CMISNode)o; + + AssertUtil.assertEquals("id", nodeId, other.getNodeId()); + AssertUtil.assertEquals("guid", guid, other.getGuid()); + for(String propertyName : properties.keySet()) + { + Serializable expected = properties.get(propertyName); + Serializable actual = other.getProperty(propertyName); + AssertUtil.assertEquals(propertyName, expected, actual); + } + } + + @Override + public String toString() + { + return "CMISNode [nodeId=" + nodeId + ", guid=" + guid + ", properties=" + + properties + "]"; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Comment.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Comment.java index f59f387d8d..7d5fda391f 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Comment.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Comment.java @@ -1,334 +1,334 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.alfresco.rest.api.tests.PublicApiDateFormat; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class Comment implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = -1804591941972808543L; - - private String nodeId; - private String id; - private String title; - private String content; - private Boolean edited; - private Person createdBy; - private String createdAt; - private String modifiedAt; - private Person modifiedBy; - private Boolean updated; -// private Boolean canEdit; -// private Boolean canDelete; - - public Comment() - { - } - - public Comment(Comment c) - { - this(c.getNodeId(), c.getId(), c.getTitle(), c.getContent(), c.getCreatedBy(), c.getCreatedAt(), c.getModifiedBy(), c.getModifiedAt(), c.getUpdated(), c.getEdited()); - } - - public Comment(String title, String content, Boolean edited, Boolean updated, Person createdBy, Person modifiedBy) - { - this.title = title; - this.content = content; - this.edited = edited; - this.updated = updated; - this.createdBy = createdBy; - this.modifiedBy = modifiedBy; - - DateFormat format = PublicApiDateFormat.getDateFormat(); - this.createdAt = format.format(new Date()); - this.modifiedAt = format.format(new Date()); - - } - - public Comment(String title, String content) - { - this.title = title; - this.content = content; - } - - public Comment(String nodeId, String id, String title, String content, Person createdBy, String createdAt, Person modifiedBy, String modifiedAt, Boolean updated, Boolean edited) - { - this.nodeId = nodeId; - this.id = id; - this.title = title; - this.content = content; - this.createdBy = createdBy; - this.createdAt = createdAt; - this.modifiedBy = modifiedBy; - this.modifiedAt = modifiedAt; - this.updated = updated; - this.edited = edited; - } - - public Boolean getEdited() - { - return edited; - } - - public String getNodeId() - { - return nodeId; - } - - public String getId() - { - return id; - } - - public String getTitle() - { - return title; - } - - public String getContent() - { - return content; - } - - public void setId(String id) - { - this.id = id; - } - - public void setTitle(String title) - { - this.title = title; - } - - public void setContent(String content) - { - this.content = content; - } - - public Person getCreatedBy() { - return createdBy; - } - - public void setCreatedBy(Person createdBy) { - this.createdBy = createdBy; - } - - public String getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - public String getModifiedAt() { - return modifiedAt; - } - - public void setModifiedAt(String modifiedAt) { - this.modifiedAt = modifiedAt; - } - - public Person getModifiedBy() { - return modifiedBy; - } - - public void setModifiedBy(Person modifiedBy) { - this.modifiedBy = modifiedBy; - } - - public Boolean getUpdated() { - return updated; - } - - public void setUpdated(Boolean updated) { - this.updated = updated; - } - - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } - - public Boolean isEdited() { - return edited; - } - - public void setEdited(Boolean edited) { - this.edited = edited; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON(boolean createdByVisibility) - { - JSONObject commentJson = new JSONObject(); -// commentJson.put("id", getId()); - commentJson.put("title", getTitle()); - commentJson.put("content", getContent()); -// if(createdBy != null) -// { -// commentJson.put("createdBy", createdBy.toJSON(createdByVisibility)); -// } -// commentJson.put("createdAt", getCreatedAt()); -// if(modifiedBy != null) -// { -// commentJson.put("modifiedBy", modifiedBy.toJSON(createdByVisibility)); -// } -// commentJson.put("modifiedAt", getModifiedAt()); -// commentJson.put("edited", isEdited()); - return commentJson; - } - - @Override - public String toString() - { - return "Comment [nodeId=" + nodeId + ", id=" + id + ", title=" + title - + ", content=" + content + ", createdBy=" + createdBy - + ", createdAt=" + createdAt + ", modifiedAt=" + modifiedAt - + ", modifiedBy=" + modifiedBy + ", updated=" + updated + "]"; - } - - public static Comment parseComment(String nodeId, JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - String title = (String)jsonObject.get("title"); - String content = (String)jsonObject.get("content"); - JSONObject createdByJson = (JSONObject)jsonObject.get("createdBy"); - Person createdBy = null; - if(createdByJson != null) - { - createdBy = Person.parsePerson(createdByJson); - } - String createdAt = (String)jsonObject.get("createdAt"); - JSONObject modifiedByJson = (JSONObject)jsonObject.get("modifiedBy"); - Person modifiedBy = null; - if(modifiedByJson != null) - { - modifiedBy = Person.parsePerson(modifiedByJson); - } - String modifiedAt = (String)jsonObject.get("modifiedAt"); - Boolean edited = (Boolean)jsonObject.get("edited"); - Boolean updated = (Boolean)jsonObject.get("updated"); - Comment comment = new Comment(nodeId, id, title, content, createdBy, createdAt, modifiedBy, modifiedAt, updated, edited); - return comment; - } - - public static ListResponse parseComments(String nodeId, JSONObject jsonObject) - { - List comments = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - comments.add(Comment.parseComment(nodeId, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - return new ListResponse(paging, comments); - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Comment); - - Comment other = (Comment)o; - - AssertUtil.assertEquals("content", content, other.getContent()); - AssertUtil.assertEquals("id", id, other.getId()); - AssertUtil.assertEquals("title", title, other.getTitle()); - AssertUtil.assertEquals("edited", edited, other.isEdited()); - if(createdBy != null) - { - createdBy.expected(other.getCreatedBy()); - } - - String modifiedAtStr = getModifiedAt(); - if(modifiedAtStr != null) - { - try - { - Date modifiedAt = PublicApiDateFormat.getDateFormat().parse(modifiedAtStr); - Date otherModifiedAt = PublicApiDateFormat.getDateFormat().parse(other.getModifiedAt()); - assertTrue(otherModifiedAt.after(modifiedAt) || otherModifiedAt.equals(modifiedAt)); - } - catch(ParseException e) - { - throw new RuntimeException(e); - } - } - - String createdAtStr = getCreatedAt(); - if(createdAtStr != null) - { - try - { - Date createdAt = PublicApiDateFormat.getDateFormat().parse(createdAtStr); - Date otherCreatedAt = PublicApiDateFormat.getDateFormat().parse(other.getCreatedAt()); - assertTrue(otherCreatedAt.after(createdAt) || otherCreatedAt.equals(createdAt)); - } - catch(ParseException e) - { - throw new RuntimeException(e); - } - } - - if(modifiedBy != null) - { - modifiedBy.expected(other.getModifiedBy()); - } - AssertUtil.assertEquals("updated", updated, other.getUpdated()); - } - - @Override - public int compareTo(Comment o) - { - // reverse chronological order - return o.getCreatedAt().compareTo(createdAt); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Comment other = (Comment) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.alfresco.rest.api.tests.PublicApiDateFormat; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class Comment implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = -1804591941972808543L; + + private String nodeId; + private String id; + private String title; + private String content; + private Boolean edited; + private Person createdBy; + private String createdAt; + private String modifiedAt; + private Person modifiedBy; + private Boolean updated; +// private Boolean canEdit; +// private Boolean canDelete; + + public Comment() + { + } + + public Comment(Comment c) + { + this(c.getNodeId(), c.getId(), c.getTitle(), c.getContent(), c.getCreatedBy(), c.getCreatedAt(), c.getModifiedBy(), c.getModifiedAt(), c.getUpdated(), c.getEdited()); + } + + public Comment(String title, String content, Boolean edited, Boolean updated, Person createdBy, Person modifiedBy) + { + this.title = title; + this.content = content; + this.edited = edited; + this.updated = updated; + this.createdBy = createdBy; + this.modifiedBy = modifiedBy; + + DateFormat format = PublicApiDateFormat.getDateFormat(); + this.createdAt = format.format(new Date()); + this.modifiedAt = format.format(new Date()); + + } + + public Comment(String title, String content) + { + this.title = title; + this.content = content; + } + + public Comment(String nodeId, String id, String title, String content, Person createdBy, String createdAt, Person modifiedBy, String modifiedAt, Boolean updated, Boolean edited) + { + this.nodeId = nodeId; + this.id = id; + this.title = title; + this.content = content; + this.createdBy = createdBy; + this.createdAt = createdAt; + this.modifiedBy = modifiedBy; + this.modifiedAt = modifiedAt; + this.updated = updated; + this.edited = edited; + } + + public Boolean getEdited() + { + return edited; + } + + public String getNodeId() + { + return nodeId; + } + + public String getId() + { + return id; + } + + public String getTitle() + { + return title; + } + + public String getContent() + { + return content; + } + + public void setId(String id) + { + this.id = id; + } + + public void setTitle(String title) + { + this.title = title; + } + + public void setContent(String content) + { + this.content = content; + } + + public Person getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(Person createdBy) { + this.createdBy = createdBy; + } + + public String getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + public String getModifiedAt() { + return modifiedAt; + } + + public void setModifiedAt(String modifiedAt) { + this.modifiedAt = modifiedAt; + } + + public Person getModifiedBy() { + return modifiedBy; + } + + public void setModifiedBy(Person modifiedBy) { + this.modifiedBy = modifiedBy; + } + + public Boolean getUpdated() { + return updated; + } + + public void setUpdated(Boolean updated) { + this.updated = updated; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public Boolean isEdited() { + return edited; + } + + public void setEdited(Boolean edited) { + this.edited = edited; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON(boolean createdByVisibility) + { + JSONObject commentJson = new JSONObject(); +// commentJson.put("id", getId()); + commentJson.put("title", getTitle()); + commentJson.put("content", getContent()); +// if(createdBy != null) +// { +// commentJson.put("createdBy", createdBy.toJSON(createdByVisibility)); +// } +// commentJson.put("createdAt", getCreatedAt()); +// if(modifiedBy != null) +// { +// commentJson.put("modifiedBy", modifiedBy.toJSON(createdByVisibility)); +// } +// commentJson.put("modifiedAt", getModifiedAt()); +// commentJson.put("edited", isEdited()); + return commentJson; + } + + @Override + public String toString() + { + return "Comment [nodeId=" + nodeId + ", id=" + id + ", title=" + title + + ", content=" + content + ", createdBy=" + createdBy + + ", createdAt=" + createdAt + ", modifiedAt=" + modifiedAt + + ", modifiedBy=" + modifiedBy + ", updated=" + updated + "]"; + } + + public static Comment parseComment(String nodeId, JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + String title = (String)jsonObject.get("title"); + String content = (String)jsonObject.get("content"); + JSONObject createdByJson = (JSONObject)jsonObject.get("createdBy"); + Person createdBy = null; + if(createdByJson != null) + { + createdBy = Person.parsePerson(createdByJson); + } + String createdAt = (String)jsonObject.get("createdAt"); + JSONObject modifiedByJson = (JSONObject)jsonObject.get("modifiedBy"); + Person modifiedBy = null; + if(modifiedByJson != null) + { + modifiedBy = Person.parsePerson(modifiedByJson); + } + String modifiedAt = (String)jsonObject.get("modifiedAt"); + Boolean edited = (Boolean)jsonObject.get("edited"); + Boolean updated = (Boolean)jsonObject.get("updated"); + Comment comment = new Comment(nodeId, id, title, content, createdBy, createdAt, modifiedBy, modifiedAt, updated, edited); + return comment; + } + + public static ListResponse parseComments(String nodeId, JSONObject jsonObject) + { + List comments = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + comments.add(Comment.parseComment(nodeId, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + return new ListResponse(paging, comments); + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Comment); + + Comment other = (Comment)o; + + AssertUtil.assertEquals("content", content, other.getContent()); + AssertUtil.assertEquals("id", id, other.getId()); + AssertUtil.assertEquals("title", title, other.getTitle()); + AssertUtil.assertEquals("edited", edited, other.isEdited()); + if(createdBy != null) + { + createdBy.expected(other.getCreatedBy()); + } + + String modifiedAtStr = getModifiedAt(); + if(modifiedAtStr != null) + { + try + { + Date modifiedAt = PublicApiDateFormat.getDateFormat().parse(modifiedAtStr); + Date otherModifiedAt = PublicApiDateFormat.getDateFormat().parse(other.getModifiedAt()); + assertTrue(otherModifiedAt.after(modifiedAt) || otherModifiedAt.equals(modifiedAt)); + } + catch(ParseException e) + { + throw new RuntimeException(e); + } + } + + String createdAtStr = getCreatedAt(); + if(createdAtStr != null) + { + try + { + Date createdAt = PublicApiDateFormat.getDateFormat().parse(createdAtStr); + Date otherCreatedAt = PublicApiDateFormat.getDateFormat().parse(other.getCreatedAt()); + assertTrue(otherCreatedAt.after(createdAt) || otherCreatedAt.equals(createdAt)); + } + catch(ParseException e) + { + throw new RuntimeException(e); + } + } + + if(modifiedBy != null) + { + modifiedBy.expected(other.getModifiedBy()); + } + AssertUtil.assertEquals("updated", updated, other.getUpdated()); + } + + @Override + public int compareTo(Comment o) + { + // reverse chronological order + return o.getCreatedAt().compareTo(createdAt); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Comment other = (Comment) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Company.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Company.java index 5668961556..30df1cd557 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Company.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Company.java @@ -1,112 +1,112 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import org.json.simple.JSONObject; - -public class Company implements ExpectedComparison -{ - private String organization; - private String address1; - private String address2; - private String address3; - private String postcode; - private String telephone; - private String fax; - private String email; - - public Company(String organization, String address1, String address2, String address3, - String postcode, String telephone, String fax, String email) - { - super(); - this.organization = organization; - this.address1 = address1; - this.address2 = address2; - this.address3 = address3; - this.postcode = postcode; - this.telephone = telephone; - this.fax = fax; - this.email = email; - } - - public String getOrganization() - { - return organization; - } - - public String getAddress1() - { - return address1; - } - - public String getAddress2() - { - return address2; - } - - public String getAddress3() - { - return address3; - } - - public String getPostcode() - { - return postcode; - } - - public String getTelephone() - { - return telephone; - } - - public String getFax() - { - return fax; - } - - public String getEmail() - { - return email; - } - - @Override - public String toString() - { - return "Company [address1=" + address1 + ", address2=" + address2 - + ", address3=" + address3 + ", postcode=" + postcode - + ", telephone=" + telephone + ", fax=" + fax + ", email=" - + email + "]"; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject companyJson = new JSONObject(); - companyJson.put("organization", getOrganization()); - companyJson.put("address1", getAddress1()); - companyJson.put("address2", getAddress2()); - companyJson.put("address3", getAddress3()); - companyJson.put("postcode", getPostcode()); - companyJson.put("telephone", getPostcode()); - companyJson.put("fax", getFax()); - companyJson.put("email", getEmail()); - return companyJson; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Company); - - Company other = (Company)o; - - AssertUtil.assertEquals("organization", organization, other.getOrganization()); - AssertUtil.assertEquals("address1", address1, other.getAddress1()); - AssertUtil.assertEquals("address2", address2, other.getAddress2()); - AssertUtil.assertEquals("address3", address3, other.getAddress3()); - AssertUtil.assertEquals("postcode", postcode, other.getPostcode()); - AssertUtil.assertEquals("telephone", telephone, other.getTelephone()); - AssertUtil.assertEquals("fax", fax, other.getFax()); - AssertUtil.assertEquals("email", email, other.getEmail()); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import org.json.simple.JSONObject; + +public class Company implements ExpectedComparison +{ + private String organization; + private String address1; + private String address2; + private String address3; + private String postcode; + private String telephone; + private String fax; + private String email; + + public Company(String organization, String address1, String address2, String address3, + String postcode, String telephone, String fax, String email) + { + super(); + this.organization = organization; + this.address1 = address1; + this.address2 = address2; + this.address3 = address3; + this.postcode = postcode; + this.telephone = telephone; + this.fax = fax; + this.email = email; + } + + public String getOrganization() + { + return organization; + } + + public String getAddress1() + { + return address1; + } + + public String getAddress2() + { + return address2; + } + + public String getAddress3() + { + return address3; + } + + public String getPostcode() + { + return postcode; + } + + public String getTelephone() + { + return telephone; + } + + public String getFax() + { + return fax; + } + + public String getEmail() + { + return email; + } + + @Override + public String toString() + { + return "Company [address1=" + address1 + ", address2=" + address2 + + ", address3=" + address3 + ", postcode=" + postcode + + ", telephone=" + telephone + ", fax=" + fax + ", email=" + + email + "]"; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject companyJson = new JSONObject(); + companyJson.put("organization", getOrganization()); + companyJson.put("address1", getAddress1()); + companyJson.put("address2", getAddress2()); + companyJson.put("address3", getAddress3()); + companyJson.put("postcode", getPostcode()); + companyJson.put("telephone", getPostcode()); + companyJson.put("fax", getFax()); + companyJson.put("email", getEmail()); + return companyJson; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Company); + + Company other = (Company)o; + + AssertUtil.assertEquals("organization", organization, other.getOrganization()); + AssertUtil.assertEquals("address1", address1, other.getAddress1()); + AssertUtil.assertEquals("address2", address2, other.getAddress2()); + AssertUtil.assertEquals("address3", address3, other.getAddress3()); + AssertUtil.assertEquals("postcode", postcode, other.getPostcode()); + AssertUtil.assertEquals("telephone", telephone, other.getTelephone()); + AssertUtil.assertEquals("fax", fax, other.getFax()); + AssertUtil.assertEquals("email", email, other.getEmail()); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/ContentData.java b/source/test-java/org/alfresco/rest/api/tests/client/data/ContentData.java index b7122e51ce..0b36ccc08f 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/ContentData.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/ContentData.java @@ -1,78 +1,78 @@ -package org.alfresco.rest.api.tests.client.data; - -import java.io.IOException; -import java.io.Serializable; - -import org.apache.chemistry.opencmis.commons.data.ContentStream; -import org.springframework.util.FileCopyUtils; - -public class ContentData implements Serializable -{ - private static final long serialVersionUID = 5757465330657144283L; - - private long length; - private String mimeType; - private String fileName; - private byte[] bytes; - - public ContentData(ContentStream cs) throws IOException - { - length = cs.getLength(); - mimeType = cs.getMimeType(); - fileName = cs.getFileName(); - bytes = FileCopyUtils.copyToByteArray(cs.getStream()); - } - -// public ContentData(long length, String mimeType, String fileName, -// InputStream inputStream) -// { -// super(); -// this.length = length; -// this.mimeType = mimeType; -// this.fileName = fileName; -// this.inputStream = inputStream; -// } - - public long getLength() - { - return length; - } - - /** - * Returns the MIME type of the stream. - * - * @return the MIME type of the stream or null if the MIME type - * is unknown - */ - public String getMimeType() - { - return mimeType; - } - - /** - * Returns the file name of the stream. - * - * @return the file name of the stream or null if the file name - * is unknown - */ - public String getFileName() - { - return fileName; - } - - /** - * Returns the stream. - * - * It is important to close this stream properly! - */ - public byte[] getBytes() - { - return bytes; - } - -// public static ContentData getContentData(ContentStream contentStream) throws IOException -// { -// ContentData contentData = new ContentData(contentStream); -// return contentData; -// } -} +package org.alfresco.rest.api.tests.client.data; + +import java.io.IOException; +import java.io.Serializable; + +import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.springframework.util.FileCopyUtils; + +public class ContentData implements Serializable +{ + private static final long serialVersionUID = 5757465330657144283L; + + private long length; + private String mimeType; + private String fileName; + private byte[] bytes; + + public ContentData(ContentStream cs) throws IOException + { + length = cs.getLength(); + mimeType = cs.getMimeType(); + fileName = cs.getFileName(); + bytes = FileCopyUtils.copyToByteArray(cs.getStream()); + } + +// public ContentData(long length, String mimeType, String fileName, +// InputStream inputStream) +// { +// super(); +// this.length = length; +// this.mimeType = mimeType; +// this.fileName = fileName; +// this.inputStream = inputStream; +// } + + public long getLength() + { + return length; + } + + /** + * Returns the MIME type of the stream. + * + * @return the MIME type of the stream or null if the MIME type + * is unknown + */ + public String getMimeType() + { + return mimeType; + } + + /** + * Returns the file name of the stream. + * + * @return the file name of the stream or null if the file name + * is unknown + */ + public String getFileName() + { + return fileName; + } + + /** + * Returns the stream. + * + * It is important to close this stream properly! + */ + public byte[] getBytes() + { + return bytes; + } + +// public static ContentData getContentData(ContentStream contentStream) throws IOException +// { +// ContentData contentData = new ContentData(contentStream); +// return contentData; +// } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Document.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Document.java index a72adacf39..bdc0453c84 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Document.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Document.java @@ -1,42 +1,42 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -/** - * Representation of a document node - initially for client tests for Nodes (aka File Folder) API - * - * @author janv - * - */ -public class Document extends Node -{ - public Document() { - super(); - } - - @Override - public void expected(Object o) - { - super.expected(o); - - assertTrue(o instanceof Document); - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +/** + * Representation of a document node - initially for client tests for Nodes (aka File Folder) API + * + * @author janv + * + */ +public class Document extends Node +{ + public Document() { + super(); + } + + @Override + public void expected(Object o) + { + super.expected(o); + + assertTrue(o instanceof Document); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/ExpectedComparison.java b/source/test-java/org/alfresco/rest/api/tests/client/data/ExpectedComparison.java index 70239d3353..93f865926a 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/ExpectedComparison.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/ExpectedComparison.java @@ -1,6 +1,6 @@ -package org.alfresco.rest.api.tests.client.data; - -public interface ExpectedComparison -{ - public void expected(Object other); -} +package org.alfresco.rest.api.tests.client.data; + +public interface ExpectedComparison +{ + public void expected(Object other); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Favourite.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Favourite.java index 6c0768f397..d289171db1 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Favourite.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Favourite.java @@ -1,257 +1,257 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.Serializable; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.alfresco.rest.api.tests.PublicApiDateFormat; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.service.cmr.favourites.FavouritesService.Type; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class Favourite implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = 2812585719477560349L; - - private String username; - private String targetGuid; - private Date createdAt; - private Date modifiedAt; - private FavouritesTarget target; - private Type type; - - public Favourite(FavouritesTarget target) throws ParseException - { - this((Date)null, (Date)null, target); - } - - public Favourite(Date createdAt, Date modifiedAt, FavouritesTarget target) throws ParseException - { - if(target != null) - { - this.targetGuid = target.getTargetGuid(); - } - this.username = null; - this.createdAt = createdAt; - this.modifiedAt = modifiedAt; - this.target = target; - if(target instanceof FileFavouriteTarget) - { - this.type = Type.FILE; - } - else if(target instanceof FolderFavouriteTarget) - { - this.type = Type.FOLDER; - } - else if(target instanceof SiteFavouriteTarget) - { - this.type = Type.SITE; - } - else - { - this.type = null; - } - } - - public Favourite(String createdAt, String modifiedAt, FavouritesTarget target) throws ParseException - { - this(getDate(createdAt), getDate(modifiedAt), target); - } - - private static Date getDate(String dateStr) throws ParseException - { - Date date = (dateStr != null ? PublicApiDateFormat.getDateFormat().parse(dateStr) : null); - return date; - } - - public String getTargetGuid() - { - return targetGuid; - } - - public String getUsername() - { - return username; - } - - public Date getCreatedAt() - { - return createdAt; - } - - public FavouritesTarget getTarget() - { - return target; - } - - public Date getModifiedAt() - { - return modifiedAt; - } - - public Type getType() - { - Type type = null; - if(target instanceof FileFavouriteTarget) - { - type = Type.FILE; - } - else if(target instanceof FolderFavouriteTarget) - { - type = Type.FOLDER; - } - else if(target instanceof SiteFavouriteTarget) - { - type = Type.SITE; - } - return type; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject favouriteJson = new JSONObject(); - if(target != null) - { - favouriteJson.put("target", target.toJSON()); - } - return favouriteJson; - } - - public static FavouritesTarget parseTarget(JSONObject jsonObject) throws ParseException - { - FavouritesTarget ret = null; - - if(jsonObject.containsKey("site")) - { - JSONObject siteJSON = (JSONObject)jsonObject.get("site"); - Site site = SiteImpl.parseSite(siteJSON); - ret = new SiteFavouriteTarget(site); - - } - else if(jsonObject.containsKey("file")) - { - JSONObject documentJSON = (JSONObject)jsonObject.get("file"); - FavouriteDocument document = FavouriteDocument.parseDocument(documentJSON); - ret = new FileFavouriteTarget(document); - - } - else if(jsonObject.containsKey("folder")) - { - JSONObject folderJSON = (JSONObject)jsonObject.get("folder"); - FavouriteFolder folder = FavouriteFolder.parseFolder(folderJSON); - ret = new FolderFavouriteTarget(folder); - } - - return ret; - } - - public static Favourite parseFavourite(JSONObject jsonObject) throws ParseException - { - String createdAt = (String)jsonObject.get("createdAt"); - String modifiedAt = (String)jsonObject.get("modifiedAt"); - JSONObject jsonTarget = (JSONObject)jsonObject.get("target"); - FavouritesTarget target = parseTarget(jsonTarget); - Favourite favourite = new Favourite(createdAt, modifiedAt, target); - return favourite; - } - - public static ListResponse parseFavourites(JSONObject jsonObject) throws ParseException - { - List favourites = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - favourites.add(Favourite.parseFavourite(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - return new ListResponse(paging, favourites); - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Favourite); - - Favourite other = (Favourite)o; - - if(target == null) - { - fail(); - } - target.expected(other.getTarget()); - if(createdAt != null) - { - assertTrue(other.getCreatedAt().equals(createdAt) || other.getCreatedAt().after(createdAt)); - } - if(modifiedAt != null) - { - AssertUtil.assertEquals("modifiedAt", modifiedAt, other.getModifiedAt()); - } - AssertUtil.assertEquals("targetGuid", targetGuid, other.getTargetGuid()); - } - - @Override - public String toString() - { - return "Favourite [username=" + username + ", targetGuid=" + targetGuid - + ", createdAt=" + createdAt + ", modifiedAt = " + modifiedAt + ", target=" + target + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((targetGuid == null) ? 0 : targetGuid.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Favourite other = (Favourite) obj; - if (targetGuid == null) { - if (other.targetGuid != null) - return false; - } else if (!targetGuid.equals(other.targetGuid)) - return false; - return true; - } - - @Override - public int compareTo(Favourite o) - { - int idx = (type != null ? type.compareTo(o.getType()) : 0); - if(idx == 0) - { - idx = o.getCreatedAt().compareTo(createdAt); - } - - return idx; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.alfresco.rest.api.tests.PublicApiDateFormat; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.service.cmr.favourites.FavouritesService.Type; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class Favourite implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = 2812585719477560349L; + + private String username; + private String targetGuid; + private Date createdAt; + private Date modifiedAt; + private FavouritesTarget target; + private Type type; + + public Favourite(FavouritesTarget target) throws ParseException + { + this((Date)null, (Date)null, target); + } + + public Favourite(Date createdAt, Date modifiedAt, FavouritesTarget target) throws ParseException + { + if(target != null) + { + this.targetGuid = target.getTargetGuid(); + } + this.username = null; + this.createdAt = createdAt; + this.modifiedAt = modifiedAt; + this.target = target; + if(target instanceof FileFavouriteTarget) + { + this.type = Type.FILE; + } + else if(target instanceof FolderFavouriteTarget) + { + this.type = Type.FOLDER; + } + else if(target instanceof SiteFavouriteTarget) + { + this.type = Type.SITE; + } + else + { + this.type = null; + } + } + + public Favourite(String createdAt, String modifiedAt, FavouritesTarget target) throws ParseException + { + this(getDate(createdAt), getDate(modifiedAt), target); + } + + private static Date getDate(String dateStr) throws ParseException + { + Date date = (dateStr != null ? PublicApiDateFormat.getDateFormat().parse(dateStr) : null); + return date; + } + + public String getTargetGuid() + { + return targetGuid; + } + + public String getUsername() + { + return username; + } + + public Date getCreatedAt() + { + return createdAt; + } + + public FavouritesTarget getTarget() + { + return target; + } + + public Date getModifiedAt() + { + return modifiedAt; + } + + public Type getType() + { + Type type = null; + if(target instanceof FileFavouriteTarget) + { + type = Type.FILE; + } + else if(target instanceof FolderFavouriteTarget) + { + type = Type.FOLDER; + } + else if(target instanceof SiteFavouriteTarget) + { + type = Type.SITE; + } + return type; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject favouriteJson = new JSONObject(); + if(target != null) + { + favouriteJson.put("target", target.toJSON()); + } + return favouriteJson; + } + + public static FavouritesTarget parseTarget(JSONObject jsonObject) throws ParseException + { + FavouritesTarget ret = null; + + if(jsonObject.containsKey("site")) + { + JSONObject siteJSON = (JSONObject)jsonObject.get("site"); + Site site = SiteImpl.parseSite(siteJSON); + ret = new SiteFavouriteTarget(site); + + } + else if(jsonObject.containsKey("file")) + { + JSONObject documentJSON = (JSONObject)jsonObject.get("file"); + FavouriteDocument document = FavouriteDocument.parseDocument(documentJSON); + ret = new FileFavouriteTarget(document); + + } + else if(jsonObject.containsKey("folder")) + { + JSONObject folderJSON = (JSONObject)jsonObject.get("folder"); + FavouriteFolder folder = FavouriteFolder.parseFolder(folderJSON); + ret = new FolderFavouriteTarget(folder); + } + + return ret; + } + + public static Favourite parseFavourite(JSONObject jsonObject) throws ParseException + { + String createdAt = (String)jsonObject.get("createdAt"); + String modifiedAt = (String)jsonObject.get("modifiedAt"); + JSONObject jsonTarget = (JSONObject)jsonObject.get("target"); + FavouritesTarget target = parseTarget(jsonTarget); + Favourite favourite = new Favourite(createdAt, modifiedAt, target); + return favourite; + } + + public static ListResponse parseFavourites(JSONObject jsonObject) throws ParseException + { + List favourites = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + favourites.add(Favourite.parseFavourite(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + return new ListResponse(paging, favourites); + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Favourite); + + Favourite other = (Favourite)o; + + if(target == null) + { + fail(); + } + target.expected(other.getTarget()); + if(createdAt != null) + { + assertTrue(other.getCreatedAt().equals(createdAt) || other.getCreatedAt().after(createdAt)); + } + if(modifiedAt != null) + { + AssertUtil.assertEquals("modifiedAt", modifiedAt, other.getModifiedAt()); + } + AssertUtil.assertEquals("targetGuid", targetGuid, other.getTargetGuid()); + } + + @Override + public String toString() + { + return "Favourite [username=" + username + ", targetGuid=" + targetGuid + + ", createdAt=" + createdAt + ", modifiedAt = " + modifiedAt + ", target=" + target + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((targetGuid == null) ? 0 : targetGuid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Favourite other = (Favourite) obj; + if (targetGuid == null) { + if (other.targetGuid != null) + return false; + } else if (!targetGuid.equals(other.targetGuid)) + return false; + return true; + } + + @Override + public int compareTo(Favourite o) + { + int idx = (type != null ? type.compareTo(o.getType()) : 0); + if(idx == 0) + { + idx = o.getCreatedAt().compareTo(createdAt); + } + + return idx; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/FavouriteSite.java b/source/test-java/org/alfresco/rest/api/tests/client/data/FavouriteSite.java index ed81422a91..2f253a7db7 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/FavouriteSite.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/FavouriteSite.java @@ -1,73 +1,73 @@ -package org.alfresco.rest.api.tests.client.data; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class FavouriteSite extends SiteImpl implements Serializable -{ - private static final long serialVersionUID = 6106140056062813842L; - - public FavouriteSite(String siteId) - { - this.siteId = siteId; - } - - public FavouriteSite(Site site) - { - super(null, site.getSiteId(), site.getGuid(), site.getTitle(), site.getDescription(), site.getVisibility(), site.getType(), site.getRole()); - } - - public FavouriteSite(String networkId, String siteId, String siteGuid, String title, String description, - String visibility, String type, SiteRole role) - { - super(networkId, siteId, siteGuid, title, description, visibility, type, role); - } - - public static FavouriteSite parseFavouriteSite(JSONObject entry) - { - Site site = SiteImpl.parseSite(entry); - FavouriteSite favouriteSite = new FavouriteSite(site); - return favouriteSite; - } - - public static ListResponse parseFavouriteSites(JSONObject jsonObject) - { - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - List favouriteSites = new ArrayList(jsonList.size()); - if(jsonList != null) - { - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - if(jsonEntries != null) - { - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - favouriteSites.add(parseFavouriteSite(entry)); - } - } - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - return new ListResponse(paging, favouriteSites); - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - FavouriteSite other = (FavouriteSite) obj; - return getSiteId().equals(other.getSiteId()); - } -} +package org.alfresco.rest.api.tests.client.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class FavouriteSite extends SiteImpl implements Serializable +{ + private static final long serialVersionUID = 6106140056062813842L; + + public FavouriteSite(String siteId) + { + this.siteId = siteId; + } + + public FavouriteSite(Site site) + { + super(null, site.getSiteId(), site.getGuid(), site.getTitle(), site.getDescription(), site.getVisibility(), site.getType(), site.getRole()); + } + + public FavouriteSite(String networkId, String siteId, String siteGuid, String title, String description, + String visibility, String type, SiteRole role) + { + super(networkId, siteId, siteGuid, title, description, visibility, type, role); + } + + public static FavouriteSite parseFavouriteSite(JSONObject entry) + { + Site site = SiteImpl.parseSite(entry); + FavouriteSite favouriteSite = new FavouriteSite(site); + return favouriteSite; + } + + public static ListResponse parseFavouriteSites(JSONObject jsonObject) + { + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + List favouriteSites = new ArrayList(jsonList.size()); + if(jsonList != null) + { + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + if(jsonEntries != null) + { + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + favouriteSites.add(parseFavouriteSite(entry)); + } + } + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + return new ListResponse(paging, favouriteSites); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + FavouriteSite other = (FavouriteSite) obj; + return getSiteId().equals(other.getSiteId()); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/FavouritesTarget.java b/source/test-java/org/alfresco/rest/api/tests/client/data/FavouritesTarget.java index 7775d7ad2d..07342ab7d9 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/FavouritesTarget.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/FavouritesTarget.java @@ -1,9 +1,9 @@ -package org.alfresco.rest.api.tests.client.data; - -import org.json.simple.JSONObject; - -public interface FavouritesTarget extends ExpectedComparison -{ - JSONObject toJSON(); - String getTargetGuid(); -} +package org.alfresco.rest.api.tests.client.data; + +import org.json.simple.JSONObject; + +public interface FavouritesTarget extends ExpectedComparison +{ + JSONObject toJSON(); + String getTargetGuid(); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/FileFavouriteTarget.java b/source/test-java/org/alfresco/rest/api/tests/client/data/FileFavouriteTarget.java index 7dcbc9d830..b6a87b9674 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/FileFavouriteTarget.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/FileFavouriteTarget.java @@ -1,51 +1,51 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import org.json.simple.JSONObject; - -public class FileFavouriteTarget implements FavouritesTarget -{ - private FavouriteDocument document; - - public FileFavouriteTarget(FavouriteDocument document) - { - super(); - this.document = document; - } - - public FavouriteDocument getDocument() - { - return document; - } - - @Override - public String toString() - { - return "FileFavouriteTarget [document=" + document + "]"; - } - - @SuppressWarnings("unchecked") - @Override - public JSONObject toJSON() - { - JSONObject favouriteJson = new JSONObject(); - favouriteJson.put("file", getDocument().toJSON()); - return favouriteJson; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof FileFavouriteTarget); - - FileFavouriteTarget other = (FileFavouriteTarget)o; - - document.expected(other.getDocument()); - } - - public String getTargetGuid() - { - return document.getGuid(); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import org.json.simple.JSONObject; + +public class FileFavouriteTarget implements FavouritesTarget +{ + private FavouriteDocument document; + + public FileFavouriteTarget(FavouriteDocument document) + { + super(); + this.document = document; + } + + public FavouriteDocument getDocument() + { + return document; + } + + @Override + public String toString() + { + return "FileFavouriteTarget [document=" + document + "]"; + } + + @SuppressWarnings("unchecked") + @Override + public JSONObject toJSON() + { + JSONObject favouriteJson = new JSONObject(); + favouriteJson.put("file", getDocument().toJSON()); + return favouriteJson; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof FileFavouriteTarget); + + FileFavouriteTarget other = (FileFavouriteTarget)o; + + document.expected(other.getDocument()); + } + + public String getTargetGuid() + { + return document.getGuid(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Folder.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Folder.java index e40e912168..aa610858b1 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Folder.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Folder.java @@ -1,43 +1,43 @@ -/* - * Copyright (C) 2005-2016 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 . - */ - -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -/** - * Representation of a folder node - initially for client tests for Nodes (aka File Folder) API - * - * @author janv - */ -public class Folder extends Node -{ - public Folder() - { - super(); - } - - @Override - public void expected(Object o) - { - super.expected(o); - - assertTrue(o instanceof Folder); - } -} +/* + * Copyright (C) 2005-2016 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 . + */ + +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +/** + * Representation of a folder node - initially for client tests for Nodes (aka File Folder) API + * + * @author janv + */ +public class Folder extends Node +{ + public Folder() + { + super(); + } + + @Override + public void expected(Object o) + { + super.expected(o); + + assertTrue(o instanceof Folder); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/FolderFavouriteTarget.java b/source/test-java/org/alfresco/rest/api/tests/client/data/FolderFavouriteTarget.java index ef96feff3f..ad02558107 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/FolderFavouriteTarget.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/FolderFavouriteTarget.java @@ -1,50 +1,50 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import org.json.simple.JSONObject; - -public class FolderFavouriteTarget implements FavouritesTarget -{ - private FavouriteFolder folder; - - public FolderFavouriteTarget(FavouriteFolder folder) - { - super(); - this.folder = folder; - } - - public FavouriteFolder getFolder() - { - return folder; - } - - @Override - public String toString() - { - return "FolderFavouriteTarget [folder=" + folder + "]"; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject json = new JSONObject(); - json.put("folder", getFolder().toJSON()); - return json; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof FolderFavouriteTarget); - - FolderFavouriteTarget other = (FolderFavouriteTarget)o; - - folder.expected(other.getFolder()); - } - - public String getTargetGuid() - { - return folder.getGuid(); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import org.json.simple.JSONObject; + +public class FolderFavouriteTarget implements FavouritesTarget +{ + private FavouriteFolder folder; + + public FolderFavouriteTarget(FavouriteFolder folder) + { + super(); + this.folder = folder; + } + + public FavouriteFolder getFolder() + { + return folder; + } + + @Override + public String toString() + { + return "FolderFavouriteTarget [folder=" + folder + "]"; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject json = new JSONObject(); + json.put("folder", getFolder().toJSON()); + return json; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof FolderFavouriteTarget); + + FolderFavouriteTarget other = (FolderFavouriteTarget)o; + + folder.expected(other.getFolder()); + } + + public String getTargetGuid() + { + return folder.getGuid(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/FolderNode.java b/source/test-java/org/alfresco/rest/api/tests/client/data/FolderNode.java index 374e339545..43a10e4be9 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/FolderNode.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/FolderNode.java @@ -1,223 +1,223 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.chemistry.opencmis.client.api.CmisObject; -import org.apache.chemistry.opencmis.client.api.FileableCmisObject; -import org.apache.chemistry.opencmis.client.api.ItemIterable; -import org.apache.chemistry.opencmis.client.api.Tree; - -public class FolderNode extends CMISNode implements Serializable -{ - private static final long serialVersionUID = -7069586854942264572L; - - private Map folderNodes = new HashMap(); - private Map documentNodes = new HashMap(); - - private Random random = new Random(); - - public FolderNode(String nodeId, String guid, Map properties) - { - super(nodeId, guid, properties); - } - - public boolean isFolder() - { - return true; - } - - public void addFolder(FolderNode folder) - { - folderNodes.put(getBareObjectId(folder.getNodeId()), folder); - } - - public void addNode(CMISNode node) - { - documentNodes.put(getBareObjectId(node.getNodeId()), node); - } - - public Map getFolderNodes() - { - return folderNodes; - } - - public Map getDocumentNodes() - { - return documentNodes; - } - - private FolderNode getFolderNode(String objectId) - { - FolderNode n = folderNodes.get(getBareObjectId(objectId)); - return n; - } - - private CMISNode getDocumentNode(String objectId) - { - CMISNode n = documentNodes.get(getBareObjectId(objectId)); - return n; - } - - public CMISNode selectRandomFolderNode() - { - int idx = random.nextInt(folderNodes.size()); - return folderNodes.get(idx); - } - - public CMISNode selectRandomDocumentNode() - { - int idx = random.nextInt(documentNodes.size()); - return documentNodes.get(idx); - } - - @Override - public String toString() - { - return "FolderNode [folderNodes=" + folderNodes + ", documentNodes=" - + documentNodes + ", nodeId=" + nodeId + ", properties=" - + properties + "]"; - } - - private String getBareObjectId(String objectId) - { - int idx = objectId.indexOf(";"); - String bareObjectId = null; - if(idx == -1) - { - bareObjectId = objectId; - } - else - { - bareObjectId = objectId.substring(0, idx); - } - return bareObjectId; - } - - private Tree findTree(String nodeId, List> nodes) - { - Tree ret = null; - - for(Tree tree : nodes) - { - FileableCmisObject item = tree.getItem(); - // compare only the "bare" object id i.e. without the version suffix - if(getBareObjectId(nodeId).equals(getBareObjectId(item.getId()))) - { - ret = tree; - break; - } - } - - return ret; - } - - private void checkChildrenImpl(Map expectedFolderNodes, Map expectedDocumentNodes) - { - for(FolderNode expectedFolderNode : expectedFolderNodes.values()) - { - FolderNode actualFolderNode = getFolderNode(expectedFolderNode.getNodeId()); - assertNotNull("Unable to find node " + expectedFolderNode, actualFolderNode); - - // check a few basic properties - Map expectedProperties = expectedFolderNode.getProperties(); - Map actualProperties = actualFolderNode.getProperties(); - AssertUtil.assertEquals("cmis:objectTypeId", expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); - AssertUtil.assertEquals("cmis:path", expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); - AssertUtil.assertEquals("cmis:name", expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); - } - - for(CMISNode expectedDocumentNode : expectedDocumentNodes.values()) - { - CMISNode actualDocumentNode = getDocumentNode(expectedDocumentNode.getNodeId()); - assertNotNull("Unable to find node " + expectedDocumentNode.getNodeId(), actualDocumentNode); - - // check a few basic properties - Map expectedProperties = expectedDocumentNode.getProperties(); - Map actualProperties = actualDocumentNode.getProperties(); - AssertUtil.assertEquals("cmis:objectTypeId", expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); - AssertUtil.assertEquals("cmis:path", expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); - AssertUtil.assertEquals("cmis:name", expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); - } - } - - public void checkChildren(ItemIterable expectedChildren) - { - Map expectedFolderNodes = new HashMap(); - Map expectedDocumentNodes = new HashMap(); - for(CmisObject child : expectedChildren) - { - CMISNode dn = CMISNode.createNode(child); - if(dn instanceof FolderNode) - { - expectedFolderNodes.put(getBareObjectId(dn.getNodeId()), (FolderNode)dn); - } - else - { - expectedDocumentNodes.put(getBareObjectId(dn.getNodeId()), dn); - } - } - checkChildrenImpl(expectedFolderNodes, expectedDocumentNodes); - } - - public void checkChildren(List expectedChildFolderIds, List expectedChildDocumentIds) - { - Map expectedFolderNodes = new HashMap(); - for(String childObjectId : expectedChildFolderIds) - { - CMISNode n = CMISNode.createNode(getBareObjectId(childObjectId)); - if(n instanceof FolderNode) - { - FolderNode node = (FolderNode)n; - expectedFolderNodes.put(getBareObjectId(node.getNodeId()), node); - } - } - Map expectedDocumentNodes = new HashMap(); - for(String childObjectId : expectedChildDocumentIds) - { - CMISNode node = CMISNode.createNode(getBareObjectId(childObjectId)); - expectedDocumentNodes.put(getBareObjectId(node.getNodeId()), node); - } - - checkChildrenImpl(expectedFolderNodes, expectedDocumentNodes); - } - - public void checkDescendants(List> descendants) - { - for(FolderNode expectedFolderNode : folderNodes.values()) - { - Tree item = findTree(expectedFolderNode.getNodeId(), descendants); - assertNotNull(item); - FolderNode actualFolderNode = (FolderNode)CMISNode.createNode(item.getItem()); - - // check a few basic properties - Map expectedProperties = expectedFolderNode.getProperties(); - Map actualProperties = actualFolderNode.getProperties(); - assertEquals(expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); - assertEquals(expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); - assertEquals(expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); - - expectedFolderNode.checkDescendants(item.getChildren()); - } - - for(CMISNode expectedDocumentNode : documentNodes.values()) - { - Tree item = findTree(expectedDocumentNode.getNodeId(), descendants); - assertNotNull(item); - CMISNode actualNode = CMISNode.createNode(item.getItem()); - - // check a few basic properties - Map expectedProperties = expectedDocumentNode.getProperties(); - Map actualProperties = actualNode.getProperties(); - assertEquals(expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); - assertEquals(expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); - assertEquals(expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); - } - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.chemistry.opencmis.client.api.FileableCmisObject; +import org.apache.chemistry.opencmis.client.api.ItemIterable; +import org.apache.chemistry.opencmis.client.api.Tree; + +public class FolderNode extends CMISNode implements Serializable +{ + private static final long serialVersionUID = -7069586854942264572L; + + private Map folderNodes = new HashMap(); + private Map documentNodes = new HashMap(); + + private Random random = new Random(); + + public FolderNode(String nodeId, String guid, Map properties) + { + super(nodeId, guid, properties); + } + + public boolean isFolder() + { + return true; + } + + public void addFolder(FolderNode folder) + { + folderNodes.put(getBareObjectId(folder.getNodeId()), folder); + } + + public void addNode(CMISNode node) + { + documentNodes.put(getBareObjectId(node.getNodeId()), node); + } + + public Map getFolderNodes() + { + return folderNodes; + } + + public Map getDocumentNodes() + { + return documentNodes; + } + + private FolderNode getFolderNode(String objectId) + { + FolderNode n = folderNodes.get(getBareObjectId(objectId)); + return n; + } + + private CMISNode getDocumentNode(String objectId) + { + CMISNode n = documentNodes.get(getBareObjectId(objectId)); + return n; + } + + public CMISNode selectRandomFolderNode() + { + int idx = random.nextInt(folderNodes.size()); + return folderNodes.get(idx); + } + + public CMISNode selectRandomDocumentNode() + { + int idx = random.nextInt(documentNodes.size()); + return documentNodes.get(idx); + } + + @Override + public String toString() + { + return "FolderNode [folderNodes=" + folderNodes + ", documentNodes=" + + documentNodes + ", nodeId=" + nodeId + ", properties=" + + properties + "]"; + } + + private String getBareObjectId(String objectId) + { + int idx = objectId.indexOf(";"); + String bareObjectId = null; + if(idx == -1) + { + bareObjectId = objectId; + } + else + { + bareObjectId = objectId.substring(0, idx); + } + return bareObjectId; + } + + private Tree findTree(String nodeId, List> nodes) + { + Tree ret = null; + + for(Tree tree : nodes) + { + FileableCmisObject item = tree.getItem(); + // compare only the "bare" object id i.e. without the version suffix + if(getBareObjectId(nodeId).equals(getBareObjectId(item.getId()))) + { + ret = tree; + break; + } + } + + return ret; + } + + private void checkChildrenImpl(Map expectedFolderNodes, Map expectedDocumentNodes) + { + for(FolderNode expectedFolderNode : expectedFolderNodes.values()) + { + FolderNode actualFolderNode = getFolderNode(expectedFolderNode.getNodeId()); + assertNotNull("Unable to find node " + expectedFolderNode, actualFolderNode); + + // check a few basic properties + Map expectedProperties = expectedFolderNode.getProperties(); + Map actualProperties = actualFolderNode.getProperties(); + AssertUtil.assertEquals("cmis:objectTypeId", expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); + AssertUtil.assertEquals("cmis:path", expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); + AssertUtil.assertEquals("cmis:name", expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); + } + + for(CMISNode expectedDocumentNode : expectedDocumentNodes.values()) + { + CMISNode actualDocumentNode = getDocumentNode(expectedDocumentNode.getNodeId()); + assertNotNull("Unable to find node " + expectedDocumentNode.getNodeId(), actualDocumentNode); + + // check a few basic properties + Map expectedProperties = expectedDocumentNode.getProperties(); + Map actualProperties = actualDocumentNode.getProperties(); + AssertUtil.assertEquals("cmis:objectTypeId", expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); + AssertUtil.assertEquals("cmis:path", expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); + AssertUtil.assertEquals("cmis:name", expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); + } + } + + public void checkChildren(ItemIterable expectedChildren) + { + Map expectedFolderNodes = new HashMap(); + Map expectedDocumentNodes = new HashMap(); + for(CmisObject child : expectedChildren) + { + CMISNode dn = CMISNode.createNode(child); + if(dn instanceof FolderNode) + { + expectedFolderNodes.put(getBareObjectId(dn.getNodeId()), (FolderNode)dn); + } + else + { + expectedDocumentNodes.put(getBareObjectId(dn.getNodeId()), dn); + } + } + checkChildrenImpl(expectedFolderNodes, expectedDocumentNodes); + } + + public void checkChildren(List expectedChildFolderIds, List expectedChildDocumentIds) + { + Map expectedFolderNodes = new HashMap(); + for(String childObjectId : expectedChildFolderIds) + { + CMISNode n = CMISNode.createNode(getBareObjectId(childObjectId)); + if(n instanceof FolderNode) + { + FolderNode node = (FolderNode)n; + expectedFolderNodes.put(getBareObjectId(node.getNodeId()), node); + } + } + Map expectedDocumentNodes = new HashMap(); + for(String childObjectId : expectedChildDocumentIds) + { + CMISNode node = CMISNode.createNode(getBareObjectId(childObjectId)); + expectedDocumentNodes.put(getBareObjectId(node.getNodeId()), node); + } + + checkChildrenImpl(expectedFolderNodes, expectedDocumentNodes); + } + + public void checkDescendants(List> descendants) + { + for(FolderNode expectedFolderNode : folderNodes.values()) + { + Tree item = findTree(expectedFolderNode.getNodeId(), descendants); + assertNotNull(item); + FolderNode actualFolderNode = (FolderNode)CMISNode.createNode(item.getItem()); + + // check a few basic properties + Map expectedProperties = expectedFolderNode.getProperties(); + Map actualProperties = actualFolderNode.getProperties(); + assertEquals(expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); + assertEquals(expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); + assertEquals(expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); + + expectedFolderNode.checkDescendants(item.getChildren()); + } + + for(CMISNode expectedDocumentNode : documentNodes.values()) + { + Tree item = findTree(expectedDocumentNode.getNodeId(), descendants); + assertNotNull(item); + CMISNode actualNode = CMISNode.createNode(item.getItem()); + + // check a few basic properties + Map expectedProperties = expectedDocumentNode.getProperties(); + Map actualProperties = actualNode.getProperties(); + assertEquals(expectedProperties.get("cmis:objectTypeId"), actualProperties.get("cmis:objectTypeId")); + assertEquals(expectedProperties.get("cmis:path"), actualProperties.get("cmis:path")); + assertEquals(expectedProperties.get("cmis:name"), actualProperties.get("cmis:name")); + } + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/InvalidFavouriteTarget.java b/source/test-java/org/alfresco/rest/api/tests/client/data/InvalidFavouriteTarget.java index c8aa5f7ad7..b55dd0508a 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/InvalidFavouriteTarget.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/InvalidFavouriteTarget.java @@ -1,110 +1,110 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import org.json.simple.JSONObject; - -public class InvalidFavouriteTarget implements FavouritesTarget -{ - private String name; - private Object entity; - private String targetGuid; - - public static class GenericFavourite - { - private String guid; - - public String getGuid() - { - return guid; - } - - public void setGuid(String guid) - { - this.guid = guid; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject json = new JSONObject(); - json.put("guid", guid); - return json; - } - - @Override - public String toString() - { - return "GenericFavourite [guid=" + guid + "]"; - } - } - - public InvalidFavouriteTarget(String name, Object entity, String targetGuid) - { - super(); - this.name = name; - this.entity = entity; - this.targetGuid = targetGuid; - } - - public Object getEntity() - { - return entity; - } - - public void setEntity(Object entity) - { - this.entity = entity; - } - - @Override - public String toString() - { - return "InvalidFavouriteTarget [entity=" + entity + "]"; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof InvalidFavouriteTarget); - - InvalidFavouriteTarget other = (InvalidFavouriteTarget) o; - Object entity1 = getEntity(); - Object entity2 = other.getEntity(); - if(entity1 instanceof ExpectedComparison && entity2 instanceof ExpectedComparison) - { - ExpectedComparison expected1 = (ExpectedComparison)entity1; - ExpectedComparison expected2 = (ExpectedComparison)entity2; - expected1.expected(expected2); - } - else - { - throw new RuntimeException("Entities cannot be compared"); - } - } - - @SuppressWarnings("unchecked") - @Override - public JSONObject toJSON() - { - JSONObject json = new JSONObject(); - - if(entity instanceof JSONAble) - { - JSONAble jsonAble = (JSONAble)entity; - JSONObject entityJSON = jsonAble.toJSON(); - json.put(name, entityJSON); - } - else - { - throw new RuntimeException("Favourite target cannot be converted to JSON"); - } - - return json; - } - - public String getTargetGuid() - { - return targetGuid; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import org.json.simple.JSONObject; + +public class InvalidFavouriteTarget implements FavouritesTarget +{ + private String name; + private Object entity; + private String targetGuid; + + public static class GenericFavourite + { + private String guid; + + public String getGuid() + { + return guid; + } + + public void setGuid(String guid) + { + this.guid = guid; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject json = new JSONObject(); + json.put("guid", guid); + return json; + } + + @Override + public String toString() + { + return "GenericFavourite [guid=" + guid + "]"; + } + } + + public InvalidFavouriteTarget(String name, Object entity, String targetGuid) + { + super(); + this.name = name; + this.entity = entity; + this.targetGuid = targetGuid; + } + + public Object getEntity() + { + return entity; + } + + public void setEntity(Object entity) + { + this.entity = entity; + } + + @Override + public String toString() + { + return "InvalidFavouriteTarget [entity=" + entity + "]"; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof InvalidFavouriteTarget); + + InvalidFavouriteTarget other = (InvalidFavouriteTarget) o; + Object entity1 = getEntity(); + Object entity2 = other.getEntity(); + if(entity1 instanceof ExpectedComparison && entity2 instanceof ExpectedComparison) + { + ExpectedComparison expected1 = (ExpectedComparison)entity1; + ExpectedComparison expected2 = (ExpectedComparison)entity2; + expected1.expected(expected2); + } + else + { + throw new RuntimeException("Entities cannot be compared"); + } + } + + @SuppressWarnings("unchecked") + @Override + public JSONObject toJSON() + { + JSONObject json = new JSONObject(); + + if(entity instanceof JSONAble) + { + JSONAble jsonAble = (JSONAble)entity; + JSONObject entityJSON = jsonAble.toJSON(); + json.put(name, entityJSON); + } + else + { + throw new RuntimeException("Favourite target cannot be converted to JSON"); + } + + return json; + } + + public String getTargetGuid() + { + return targetGuid; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/JSONAble.java b/source/test-java/org/alfresco/rest/api/tests/client/data/JSONAble.java index 436e4721f2..caa9cf04ac 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/JSONAble.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/JSONAble.java @@ -1,8 +1,8 @@ -package org.alfresco.rest.api.tests.client.data; - -import org.json.simple.JSONObject; - -public interface JSONAble -{ - JSONObject toJSON(); -} +package org.alfresco.rest.api.tests.client.data; + +import org.json.simple.JSONObject; + +public interface JSONAble +{ + JSONObject toJSON(); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/MemberOfSite.java b/source/test-java/org/alfresco/rest/api/tests/client/data/MemberOfSite.java index 3c907355cf..9cbe7c4f2e 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/MemberOfSite.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/MemberOfSite.java @@ -1,215 +1,215 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class MemberOfSite implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = -5834300883854366123L; - - private SiteRole role; - private String siteId; - private String siteGuid; - private Site site; - - public MemberOfSite() - { - } - - public MemberOfSite(String siteId, String siteGuid, SiteRole role) - { - super(); - if(siteId == null) - { - throw new IllegalArgumentException(); - } - if(siteGuid == null) - { - throw new IllegalArgumentException(); - } - if(role == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - this.siteId = siteId; - this.siteGuid = siteGuid; - } - - public MemberOfSite(Site site, SiteRole role) - { - super(); - if(site == null) - { - throw new IllegalArgumentException(); - } - if(role == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - this.site = site; - this.siteId = site.getSiteId(); - this.siteGuid = site.getGuid(); - } - - public String getSiteId() - { - return siteId; - } - - public String getGuid() - { - return siteGuid; - } - - public Site getSite() - { - return site; - } - - public SiteRole getRole() - { - return role; - } - - public void setRole(SiteRole role) - { - if(role == null) - { - throw new IllegalArgumentException(); - } - this.role = role; - } - - public void setSite(SiteImpl site) - { - if(site == null) - { - throw new IllegalArgumentException(); - } - this.site = site; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((role == null) ? 0 : role.hashCode()); - result = prime * result - + site.getSiteId().hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - - if (obj == null) - { - return false; - } - - if (getClass() != obj.getClass()) - { - return false; - } - - MemberOfSite other = (MemberOfSite) obj; - if (role != other.role) - { - return false; - } - - return site.equals(other.site); - } - - public static MemberOfSite parseMemberOfSite(JSONObject jsonObject) - { - String role = (String)jsonObject.get("role"); - JSONObject siteJSON = (JSONObject)jsonObject.get("site"); - Site site = SiteImpl.parseSite(siteJSON); - MemberOfSite siteMember = new MemberOfSite(site, SiteRole.valueOf(role)); - return siteMember; - } - - public static ListResponse parseMemberOfSites(JSONObject jsonObject) - { - List siteMembers = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - siteMembers.add(parseMemberOfSite(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - - ListResponse resp = new ListResponse(paging, siteMembers); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject memberOfSiteJson = new JSONObject(); - memberOfSiteJson.put("role", getRole()); - memberOfSiteJson.put("id", getSiteId()); - memberOfSiteJson.put("guid", getGuid()); - return memberOfSiteJson; - } - - @Override - public String toString() - { - return "MemberOfSite [role=" + role + ", siteShortName=" - + site + "]"; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof MemberOfSite); - - MemberOfSite other = (MemberOfSite)o; - - if(siteId != null) - { - AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); - } - AssertUtil.assertEquals("role", role, other.getRole()); - site.expected(other.getSite()); - } - - @Override - public int compareTo(MemberOfSite o) - { - int i = site.getTitle().compareTo(o.getSite().getTitle()); - if(i == 0) - { - i = role.compareTo(o.getRole()); - } - return i; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class MemberOfSite implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = -5834300883854366123L; + + private SiteRole role; + private String siteId; + private String siteGuid; + private Site site; + + public MemberOfSite() + { + } + + public MemberOfSite(String siteId, String siteGuid, SiteRole role) + { + super(); + if(siteId == null) + { + throw new IllegalArgumentException(); + } + if(siteGuid == null) + { + throw new IllegalArgumentException(); + } + if(role == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + this.siteId = siteId; + this.siteGuid = siteGuid; + } + + public MemberOfSite(Site site, SiteRole role) + { + super(); + if(site == null) + { + throw new IllegalArgumentException(); + } + if(role == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + this.site = site; + this.siteId = site.getSiteId(); + this.siteGuid = site.getGuid(); + } + + public String getSiteId() + { + return siteId; + } + + public String getGuid() + { + return siteGuid; + } + + public Site getSite() + { + return site; + } + + public SiteRole getRole() + { + return role; + } + + public void setRole(SiteRole role) + { + if(role == null) + { + throw new IllegalArgumentException(); + } + this.role = role; + } + + public void setSite(SiteImpl site) + { + if(site == null) + { + throw new IllegalArgumentException(); + } + this.site = site; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((role == null) ? 0 : role.hashCode()); + result = prime * result + + site.getSiteId().hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + MemberOfSite other = (MemberOfSite) obj; + if (role != other.role) + { + return false; + } + + return site.equals(other.site); + } + + public static MemberOfSite parseMemberOfSite(JSONObject jsonObject) + { + String role = (String)jsonObject.get("role"); + JSONObject siteJSON = (JSONObject)jsonObject.get("site"); + Site site = SiteImpl.parseSite(siteJSON); + MemberOfSite siteMember = new MemberOfSite(site, SiteRole.valueOf(role)); + return siteMember; + } + + public static ListResponse parseMemberOfSites(JSONObject jsonObject) + { + List siteMembers = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + siteMembers.add(parseMemberOfSite(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + + ListResponse resp = new ListResponse(paging, siteMembers); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject memberOfSiteJson = new JSONObject(); + memberOfSiteJson.put("role", getRole()); + memberOfSiteJson.put("id", getSiteId()); + memberOfSiteJson.put("guid", getGuid()); + return memberOfSiteJson; + } + + @Override + public String toString() + { + return "MemberOfSite [role=" + role + ", siteShortName=" + + site + "]"; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof MemberOfSite); + + MemberOfSite other = (MemberOfSite)o; + + if(siteId != null) + { + AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); + } + AssertUtil.assertEquals("role", role, other.getRole()); + site.expected(other.getSite()); + } + + @Override + public int compareTo(MemberOfSite o) + { + int i = site.getTitle().compareTo(o.getSite().getTitle()); + if(i == 0) + { + i = role.compareTo(o.getRole()); + } + return i; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Network.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Network.java index 36f69793ac..366c8031e5 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Network.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Network.java @@ -1,13 +1,13 @@ -package org.alfresco.rest.api.tests.client.data; - -import java.util.List; - -public interface Network -{ - String getId(); - Boolean getIsEnabled(); - String getCreatedAt(); - List getQuotas(); - String getSubscriptionLevel(); - Boolean isPaidNetwork(); -} +package org.alfresco.rest.api.tests.client.data; + +import java.util.List; + +public interface Network +{ + String getId(); + Boolean getIsEnabled(); + String getCreatedAt(); + List getQuotas(); + String getSubscriptionLevel(); + Boolean isPaidNetwork(); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/NetworkImpl.java b/source/test-java/org/alfresco/rest/api/tests/client/data/NetworkImpl.java index da6e2fa7a9..780d7f3055 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/NetworkImpl.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/NetworkImpl.java @@ -1,215 +1,215 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import org.alfresco.rest.api.tests.PublicApiDateFormat; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class NetworkImpl implements Network, Serializable, ExpectedComparison -{ - private static final long serialVersionUID = -5748677903173568273L; - - protected String id; - protected Boolean isEnabled; - protected String createdAt; - protected List quotas = new LinkedList(); - protected String subscriptionLevel; - protected Boolean paidNetwork; - - public NetworkImpl(org.alfresco.repo.tenant.Network network) - { - this.id = network.getTenantDomain(); - this.createdAt = (network.getCreatedAt() != null ? PublicApiDateFormat.getDateFormat().format(network.getCreatedAt()) : null); - this.isEnabled = network.isEnabled(); - this.paidNetwork = network.getPaidNetwork(); - this.subscriptionLevel = network.getSubscriptionLevel(); - } - - public NetworkImpl(String id, Boolean isEnabled) - { - super(); - this.id = id; - this.isEnabled = isEnabled; - } - - public NetworkImpl(String id, Boolean isEnabled, String createdAt, - List quotas, String subscriptionLevel, Boolean paidNetwork) - { - super(); - this.id = id; - this.isEnabled = isEnabled; - this.createdAt = createdAt; - this.quotas = quotas; - this.subscriptionLevel = subscriptionLevel; - this.paidNetwork = paidNetwork; - } - - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public Boolean getIsEnabled() - { - return isEnabled; - } - - public void setIsEnabled(Boolean isEnabled) - { - this.isEnabled = isEnabled; - } - - public Boolean getPaidNetwork() - { - return paidNetwork; - } - - public void setPaidNetwork(Boolean paidNetwork) - { - this.paidNetwork = paidNetwork; - } - - public void setCreatedAt(String createdAt) - { - this.createdAt = createdAt; - } - - public void setQuotas(List quotas) - { - this.quotas = quotas; - } - - public void setSubscriptionLevel(String subscriptionLevel) - { - this.subscriptionLevel = subscriptionLevel; - } - - @SuppressWarnings("rawtypes") - public static NetworkImpl parseNetwork(JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - Boolean isEnabled = (Boolean)jsonObject.get("isEnabled"); - Boolean paidNetwork = (Boolean)jsonObject.get("paidNetwork"); - String createdAt = (String)jsonObject.get("createdAt"); - String subscriptionLevel = (String)jsonObject.get("subscriptionLevel"); - JSONArray quotasJSON = (JSONArray)jsonObject.get("quotas"); - List quotas = new ArrayList(quotasJSON.size()); - Iterator it = quotasJSON.iterator(); - while(it.hasNext()) - { - JSONObject quotaJSON = (JSONObject)it.next(); - org.alfresco.rest.api.tests.client.data.Quota quota = org.alfresco.rest.api.tests.client.data.Quota.parseQuota(quotaJSON); - quotas.add(quota); - } - NetworkImpl network = new NetworkImpl(id, isEnabled, createdAt, quotas, subscriptionLevel, paidNetwork); - return network; - } - - public String getCreatedAt() - { - return createdAt; - } - - public List getQuotas() - { - return quotas; - } - - public String getSubscriptionLevel() - { - return subscriptionLevel; - } - - public Boolean isPaidNetwork() - { - return paidNetwork; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject networkJson = new JSONObject(); - networkJson.put("id", getId()); - networkJson.put("isEnabled", getIsEnabled()); - - return networkJson; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NetworkImpl other = (NetworkImpl) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - - @Override - public void expected(Object o) - { - assertTrue(o instanceof NetworkImpl); - - NetworkImpl other = (NetworkImpl)o; - - AssertUtil.assertEquals("id", id, other.getId()); - AssertUtil.assertEquals("isEnabled", isEnabled, other.isEnabled); - AssertUtil.assertEquals("paidNetwork", paidNetwork, other.paidNetwork); - AssertUtil.assertEquals("subscriptionLevel", subscriptionLevel, other.subscriptionLevel); - - if(createdAt != null) - { - try - { - Date created = PublicApiDateFormat.getDateFormat().parse(createdAt); - Date otherCreatedAt = PublicApiDateFormat.getDateFormat().parse(other.getCreatedAt()); - assertTrue(otherCreatedAt.after(created) || otherCreatedAt.equals(created)); - } - catch(ParseException e) - { - throw new RuntimeException(e); - } - } - } - - @Override - public String toString() - { - return "NetworkImpl [id=" + id + ", isEnabled=" + isEnabled - + ", createdAt=" + createdAt + ", quotas=" + quotas - + ", subscriptionLevel=" + subscriptionLevel + ", paidNetwork=" - + paidNetwork + "]"; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.rest.api.tests.PublicApiDateFormat; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class NetworkImpl implements Network, Serializable, ExpectedComparison +{ + private static final long serialVersionUID = -5748677903173568273L; + + protected String id; + protected Boolean isEnabled; + protected String createdAt; + protected List quotas = new LinkedList(); + protected String subscriptionLevel; + protected Boolean paidNetwork; + + public NetworkImpl(org.alfresco.repo.tenant.Network network) + { + this.id = network.getTenantDomain(); + this.createdAt = (network.getCreatedAt() != null ? PublicApiDateFormat.getDateFormat().format(network.getCreatedAt()) : null); + this.isEnabled = network.isEnabled(); + this.paidNetwork = network.getPaidNetwork(); + this.subscriptionLevel = network.getSubscriptionLevel(); + } + + public NetworkImpl(String id, Boolean isEnabled) + { + super(); + this.id = id; + this.isEnabled = isEnabled; + } + + public NetworkImpl(String id, Boolean isEnabled, String createdAt, + List quotas, String subscriptionLevel, Boolean paidNetwork) + { + super(); + this.id = id; + this.isEnabled = isEnabled; + this.createdAt = createdAt; + this.quotas = quotas; + this.subscriptionLevel = subscriptionLevel; + this.paidNetwork = paidNetwork; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Boolean getIsEnabled() + { + return isEnabled; + } + + public void setIsEnabled(Boolean isEnabled) + { + this.isEnabled = isEnabled; + } + + public Boolean getPaidNetwork() + { + return paidNetwork; + } + + public void setPaidNetwork(Boolean paidNetwork) + { + this.paidNetwork = paidNetwork; + } + + public void setCreatedAt(String createdAt) + { + this.createdAt = createdAt; + } + + public void setQuotas(List quotas) + { + this.quotas = quotas; + } + + public void setSubscriptionLevel(String subscriptionLevel) + { + this.subscriptionLevel = subscriptionLevel; + } + + @SuppressWarnings("rawtypes") + public static NetworkImpl parseNetwork(JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + Boolean isEnabled = (Boolean)jsonObject.get("isEnabled"); + Boolean paidNetwork = (Boolean)jsonObject.get("paidNetwork"); + String createdAt = (String)jsonObject.get("createdAt"); + String subscriptionLevel = (String)jsonObject.get("subscriptionLevel"); + JSONArray quotasJSON = (JSONArray)jsonObject.get("quotas"); + List quotas = new ArrayList(quotasJSON.size()); + Iterator it = quotasJSON.iterator(); + while(it.hasNext()) + { + JSONObject quotaJSON = (JSONObject)it.next(); + org.alfresco.rest.api.tests.client.data.Quota quota = org.alfresco.rest.api.tests.client.data.Quota.parseQuota(quotaJSON); + quotas.add(quota); + } + NetworkImpl network = new NetworkImpl(id, isEnabled, createdAt, quotas, subscriptionLevel, paidNetwork); + return network; + } + + public String getCreatedAt() + { + return createdAt; + } + + public List getQuotas() + { + return quotas; + } + + public String getSubscriptionLevel() + { + return subscriptionLevel; + } + + public Boolean isPaidNetwork() + { + return paidNetwork; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject networkJson = new JSONObject(); + networkJson.put("id", getId()); + networkJson.put("isEnabled", getIsEnabled()); + + return networkJson; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NetworkImpl other = (NetworkImpl) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + + @Override + public void expected(Object o) + { + assertTrue(o instanceof NetworkImpl); + + NetworkImpl other = (NetworkImpl)o; + + AssertUtil.assertEquals("id", id, other.getId()); + AssertUtil.assertEquals("isEnabled", isEnabled, other.isEnabled); + AssertUtil.assertEquals("paidNetwork", paidNetwork, other.paidNetwork); + AssertUtil.assertEquals("subscriptionLevel", subscriptionLevel, other.subscriptionLevel); + + if(createdAt != null) + { + try + { + Date created = PublicApiDateFormat.getDateFormat().parse(createdAt); + Date otherCreatedAt = PublicApiDateFormat.getDateFormat().parse(other.getCreatedAt()); + assertTrue(otherCreatedAt.after(created) || otherCreatedAt.equals(created)); + } + catch(ParseException e) + { + throw new RuntimeException(e); + } + } + } + + @Override + public String toString() + { + return "NetworkImpl [id=" + id + ", isEnabled=" + isEnabled + + ", createdAt=" + createdAt + ", quotas=" + quotas + + ", subscriptionLevel=" + subscriptionLevel + ", paidNetwork=" + + paidNetwork + "]"; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Node.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Node.java index f5ef8e8a16..ebb18ae911 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Node.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Node.java @@ -1,420 +1,420 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.tests.client.data; - -import org.alfresco.rest.api.model.AssocChild; -import org.alfresco.rest.api.model.AssocTarget; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -import static junit.framework.TestCase.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Representation of a node - initially for client tests for Nodes (aka File Folder) API - * - * TODO push null check down into AssertUtil (making sure that no other existing tests break) - * - * @author janv - */ -public class Node -{ - protected String id; - protected String name; - - protected Date createdAt; - protected Date modifiedAt; - protected UserInfo createdByUser; - protected UserInfo modifiedByUser; - - protected Date archivedAt; - protected UserInfo archivedByUser; - - protected Boolean isFolder; - protected Boolean isFile; - protected Boolean isLink; - - protected String parentId; - protected PathInfo path; - protected String nodeType; - - protected List aspectNames; - - protected Map properties; - - protected ContentInfo contentInfo; - - protected List allowableOperations; - - // please note: these are currently only used (optionally) for node create request - protected String relativePath; - protected List secondaryChildren; - protected List targets; - - public Node() - { - } - - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public Date getCreatedAt() - { - return createdAt; - } - - public Date getModifiedAt() - { - return modifiedAt; - } - - public UserInfo getCreatedByUser() - { - return createdByUser; - } - - public void setCreatedByUser(UserInfo createdByUser) - { - this.createdByUser = createdByUser; - } - - public UserInfo getModifiedByUser() - { - return modifiedByUser; - } - - public void setModifiedByUser(UserInfo modifiedByUser) - { - this.modifiedByUser = modifiedByUser; - } - - public Date getArchivedAt() - { - return archivedAt; - } - - public void setArchivedAt(Date archivedAt) - { - this.archivedAt = archivedAt; - } - - public UserInfo getArchivedByUser() - { - return archivedByUser; - } - - public void setArchivedByUser(UserInfo archivedByUser) - { - this.archivedByUser = archivedByUser; - } - - public Boolean getIsFolder() - { - return isFolder; - } - - public void setIsFolder(Boolean isFolder) - { - this.isFolder = isFolder; - } - - public Boolean getIsFile() - { - return isFile; - } - - public void setIsFile(Boolean isFile) - { - this.isFile = isFile; - } - - public Boolean getIsLink() - { - return isLink; - } - - public void setIsLink(Boolean link) - { - isLink = link; - } - - public String getParentId() - { - return parentId; - } - - public void setParentId(String parentId) - { - this.parentId = parentId; - } - - public PathInfo getPath() - { - return path; - } - - public void setPath(PathInfo path) - { - this.path = path; - } - - public String getNodeType() - { - return nodeType; - } - - public void setNodeType(String nodeType) - { - this.nodeType = nodeType; - } - - public List getAspectNames() - { - return aspectNames; - } - - public void setAspectNames(List aspectNames) - { - this.aspectNames = aspectNames; - } - - public Map getProperties() - { - return properties; - } - - public void setProperties(Map properties) - { - this.properties = properties; - } - - public void setContent(ContentInfo contentInfo) - { - this.contentInfo = contentInfo; - } - - public ContentInfo getContent() - { - return this.contentInfo; - } - - public List getAllowableOperations() - { - return allowableOperations; - } - - public void setAllowableOperations(List allowableOperations) - { - this.allowableOperations = allowableOperations; - } - - - public String getRelativePath() - { - return relativePath; - } - - public void setRelativePath(String relativePath) - { - this.relativePath = relativePath; - } - - public List getSecondaryChildren() - { - return secondaryChildren; - } - - public void setSecondaryChildren(List secondaryChildren) - { - this.secondaryChildren = secondaryChildren; - } - - public List getTargets() - { - return targets; - } - - public void setTargets(List targets) - { - this.targets = targets; - } - - - // note: can be child or peer (latter has assocType only) - protected Association association; - - public Association getAssociation() - { - return association; - } - - public void setAssociation(Association association) - { - this.association = association; - } - - public void expected(Object o) - { - Node other = (Node) o; - - if (id != null) - { - AssertUtil.assertEquals("id", id, other.getId()); - } - else - { - assertNotNull(other.id); - } - - AssertUtil.assertEquals("parentId", parentId, other.getParentId()); - AssertUtil.assertEquals("name", name, other.getName()); - AssertUtil.assertEquals("nodeType", nodeType, other.getNodeType()); - - if (createdAt != null) - { - AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); - } - else - { - assertNotNull(other.createdAt); - } - - if (createdByUser != null) - { - createdByUser.expected(other.getCreatedByUser()); - } - else - { - assertNotNull(other.createdByUser); - } - - if (modifiedAt != null) - { - assertTrue(modifiedAt.before(other.getModifiedAt()) || modifiedAt.equals(other.getModifiedAt())); - } - else - { - assertNotNull(other.modifiedAt); - } - - if (modifiedByUser != null) - { - modifiedByUser.expected(other.getModifiedByUser()); - } - else - { - assertNotNull(other.modifiedByUser); - } - - if (aspectNames != null) - { - assertNotNull(other.getAspectNames()); - assertEquals("Expected: "+aspectNames+", actual: "+other.getAspectNames(), aspectNames.size(), other.getAspectNames().size()); - for (String aspectName : aspectNames) - { - assertTrue(other.getAspectNames().contains(aspectName)); - } - } - else - { - assertNull(other.getAspectNames()); - } - - if (properties != null) - { - assertNotNull(other.getProperties()); - assertEquals(properties.size(), other.getProperties().size()); - for (Map.Entry e : properties.entrySet()) - { - Object otherObj = other.getProperties().get(e.getKey()); - assertEquals(e.getValue(), otherObj); // TODO fix ! - } - } - else - { - assertNull(other.getProperties()); - } - - AssertUtil.assertEquals("isFolder", isFolder, other.getIsFolder()); - AssertUtil.assertEquals("isFile", isFile, other.getIsFile()); - AssertUtil.assertEquals("isLink", isLink, other.getIsLink()); - - if (path != null) - { - path.expected(other.getPath()); - } - else - { - assertNull(other.getPath()); - } - - if (contentInfo != null) - { - contentInfo.expected(other.getContent()); - } - else - { - assertNull(other.getContent()); - } - - if (allowableOperations != null) - { - assertNotNull(other.getAllowableOperations()); - assertEquals("Expected: "+allowableOperations+", actual: "+other.getAllowableOperations(), allowableOperations.size(), other.getAllowableOperations().size()); - for (String allowableOperation : allowableOperations) - { - assertTrue(other.getAllowableOperations().contains(allowableOperation)); - } - } - else - { - assertNull(other.getAllowableOperations()); - } - - if (relativePath != null) - { - assertEquals(relativePath, other.getRelativePath()); - } - else - { - assertNull(other.getRelativePath()); - } - } +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.tests.client.data; + +import org.alfresco.rest.api.model.AssocChild; +import org.alfresco.rest.api.model.AssocTarget; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Representation of a node - initially for client tests for Nodes (aka File Folder) API + * + * TODO push null check down into AssertUtil (making sure that no other existing tests break) + * + * @author janv + */ +public class Node +{ + protected String id; + protected String name; + + protected Date createdAt; + protected Date modifiedAt; + protected UserInfo createdByUser; + protected UserInfo modifiedByUser; + + protected Date archivedAt; + protected UserInfo archivedByUser; + + protected Boolean isFolder; + protected Boolean isFile; + protected Boolean isLink; + + protected String parentId; + protected PathInfo path; + protected String nodeType; + + protected List aspectNames; + + protected Map properties; + + protected ContentInfo contentInfo; + + protected List allowableOperations; + + // please note: these are currently only used (optionally) for node create request + protected String relativePath; + protected List secondaryChildren; + protected List targets; + + public Node() + { + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Date getCreatedAt() + { + return createdAt; + } + + public Date getModifiedAt() + { + return modifiedAt; + } + + public UserInfo getCreatedByUser() + { + return createdByUser; + } + + public void setCreatedByUser(UserInfo createdByUser) + { + this.createdByUser = createdByUser; + } + + public UserInfo getModifiedByUser() + { + return modifiedByUser; + } + + public void setModifiedByUser(UserInfo modifiedByUser) + { + this.modifiedByUser = modifiedByUser; + } + + public Date getArchivedAt() + { + return archivedAt; + } + + public void setArchivedAt(Date archivedAt) + { + this.archivedAt = archivedAt; + } + + public UserInfo getArchivedByUser() + { + return archivedByUser; + } + + public void setArchivedByUser(UserInfo archivedByUser) + { + this.archivedByUser = archivedByUser; + } + + public Boolean getIsFolder() + { + return isFolder; + } + + public void setIsFolder(Boolean isFolder) + { + this.isFolder = isFolder; + } + + public Boolean getIsFile() + { + return isFile; + } + + public void setIsFile(Boolean isFile) + { + this.isFile = isFile; + } + + public Boolean getIsLink() + { + return isLink; + } + + public void setIsLink(Boolean link) + { + isLink = link; + } + + public String getParentId() + { + return parentId; + } + + public void setParentId(String parentId) + { + this.parentId = parentId; + } + + public PathInfo getPath() + { + return path; + } + + public void setPath(PathInfo path) + { + this.path = path; + } + + public String getNodeType() + { + return nodeType; + } + + public void setNodeType(String nodeType) + { + this.nodeType = nodeType; + } + + public List getAspectNames() + { + return aspectNames; + } + + public void setAspectNames(List aspectNames) + { + this.aspectNames = aspectNames; + } + + public Map getProperties() + { + return properties; + } + + public void setProperties(Map properties) + { + this.properties = properties; + } + + public void setContent(ContentInfo contentInfo) + { + this.contentInfo = contentInfo; + } + + public ContentInfo getContent() + { + return this.contentInfo; + } + + public List getAllowableOperations() + { + return allowableOperations; + } + + public void setAllowableOperations(List allowableOperations) + { + this.allowableOperations = allowableOperations; + } + + + public String getRelativePath() + { + return relativePath; + } + + public void setRelativePath(String relativePath) + { + this.relativePath = relativePath; + } + + public List getSecondaryChildren() + { + return secondaryChildren; + } + + public void setSecondaryChildren(List secondaryChildren) + { + this.secondaryChildren = secondaryChildren; + } + + public List getTargets() + { + return targets; + } + + public void setTargets(List targets) + { + this.targets = targets; + } + + + // note: can be child or peer (latter has assocType only) + protected Association association; + + public Association getAssociation() + { + return association; + } + + public void setAssociation(Association association) + { + this.association = association; + } + + public void expected(Object o) + { + Node other = (Node) o; + + if (id != null) + { + AssertUtil.assertEquals("id", id, other.getId()); + } + else + { + assertNotNull(other.id); + } + + AssertUtil.assertEquals("parentId", parentId, other.getParentId()); + AssertUtil.assertEquals("name", name, other.getName()); + AssertUtil.assertEquals("nodeType", nodeType, other.getNodeType()); + + if (createdAt != null) + { + AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); + } + else + { + assertNotNull(other.createdAt); + } + + if (createdByUser != null) + { + createdByUser.expected(other.getCreatedByUser()); + } + else + { + assertNotNull(other.createdByUser); + } + + if (modifiedAt != null) + { + assertTrue(modifiedAt.before(other.getModifiedAt()) || modifiedAt.equals(other.getModifiedAt())); + } + else + { + assertNotNull(other.modifiedAt); + } + + if (modifiedByUser != null) + { + modifiedByUser.expected(other.getModifiedByUser()); + } + else + { + assertNotNull(other.modifiedByUser); + } + + if (aspectNames != null) + { + assertNotNull(other.getAspectNames()); + assertEquals("Expected: "+aspectNames+", actual: "+other.getAspectNames(), aspectNames.size(), other.getAspectNames().size()); + for (String aspectName : aspectNames) + { + assertTrue(other.getAspectNames().contains(aspectName)); + } + } + else + { + assertNull(other.getAspectNames()); + } + + if (properties != null) + { + assertNotNull(other.getProperties()); + assertEquals(properties.size(), other.getProperties().size()); + for (Map.Entry e : properties.entrySet()) + { + Object otherObj = other.getProperties().get(e.getKey()); + assertEquals(e.getValue(), otherObj); // TODO fix ! + } + } + else + { + assertNull(other.getProperties()); + } + + AssertUtil.assertEquals("isFolder", isFolder, other.getIsFolder()); + AssertUtil.assertEquals("isFile", isFile, other.getIsFile()); + AssertUtil.assertEquals("isLink", isLink, other.getIsLink()); + + if (path != null) + { + path.expected(other.getPath()); + } + else + { + assertNull(other.getPath()); + } + + if (contentInfo != null) + { + contentInfo.expected(other.getContent()); + } + else + { + assertNull(other.getContent()); + } + + if (allowableOperations != null) + { + assertNotNull(other.getAllowableOperations()); + assertEquals("Expected: "+allowableOperations+", actual: "+other.getAllowableOperations(), allowableOperations.size(), other.getAllowableOperations().size()); + for (String allowableOperation : allowableOperations) + { + assertTrue(other.getAllowableOperations().contains(allowableOperation)); + } + } + else + { + assertNull(other.getAllowableOperations()); + } + + if (relativePath != null) + { + assertEquals(relativePath, other.getRelativePath()); + } + else + { + assertNull(other.getRelativePath()); + } + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/NodeRating.java b/source/test-java/org/alfresco/rest/api/tests/client/data/NodeRating.java index a88fc389c2..4a9efbf5a7 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/NodeRating.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/NodeRating.java @@ -1,264 +1,264 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.alfresco.rest.api.tests.PublicApiDateFormat; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class NodeRating implements Serializable, Comparable, ExpectedComparison -{ - private static final long serialVersionUID = 2855422270577730898L; - - private String nodeId; - private String ratingScheme; - private String ratedAt; - private Object myRating; - private Aggregate aggregate; - - public NodeRating(String ratingScheme, Object myRating) - { - this.ratingScheme = ratingScheme; - this.myRating = myRating; - } - - public NodeRating(String ratingScheme, Object myRating, Aggregate aggregate) - { - this.ratingScheme = ratingScheme; - this.myRating = myRating; - this.aggregate = aggregate; - } - - public NodeRating(String nodeId, String ratingScheme, String ratedAt, Object myRating, Aggregate aggregate) - { - this.nodeId = nodeId; - this.ratingScheme = ratingScheme; - this.ratedAt = ratedAt; - this.myRating = myRating; - this.aggregate = aggregate; - } - - public Aggregate getAggregate() - { - return aggregate; - } - - public Object getMyRating() - { - return myRating; - } - - public String getNodeId() - { - return nodeId; - } - - public String getId() - { - return ratingScheme; - } - - public String getRatedAt() - { - return ratedAt; - } - - @Override - public String toString() - { - return "NodeRating [ratingScheme=" + ratingScheme + ", ratedAt=" - + ratedAt + "]"; - } - - public static NodeRating parseNodeRating(String nodeId, JSONObject jsonObject) - { - String ratingScheme = (String)jsonObject.get("id"); - String ratedAt = (String)jsonObject.get("ratedAt"); - Object myRating = jsonObject.get("myRating"); - - JSONObject aggregateJSON = (JSONObject)jsonObject.get("aggregate"); - Long numRatings = (Long)aggregateJSON.get("numberOfRatings"); - Double average = (Double)aggregateJSON.get("average"); - Aggregate aggregate = new Aggregate(numRatings != null ? numRatings.intValue() : null, average != null ? average.floatValue(): null); - NodeRating nodeRating = new NodeRating(nodeId, ratingScheme, ratedAt, myRating, aggregate); - return nodeRating; - } - - public static ListResponse parseNodeRatings(String nodeId, JSONObject jsonObject) - { - List nodeRatings = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - nodeRatings.add(NodeRating.parseNodeRating(nodeId, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - - ListResponse resp = new ListResponse(paging, nodeRatings); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject nodeRatingJSON = new JSONObject(); - - nodeRatingJSON.put("myRating", getMyRating()); - nodeRatingJSON.put("id", getId()); - - return nodeRatingJSON; - } - - public static class Aggregate implements ExpectedComparison - { - private Integer numberOfRatings; - private Float average; - - public Aggregate(Integer numberOfRatings, Float average) - { - super(); - this.numberOfRatings = numberOfRatings; - this.average = average; - } - - public Integer getNumberOfRatings() - { - return numberOfRatings; - } - - public Float getAverage() - { - return average; - } - - @Override - public String toString() - { - return "Aggregate [numberOfRatings=" + numberOfRatings - + ", average=" + average + "]"; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Aggregate); - - Aggregate other = (Aggregate)o; - - AssertUtil.assertEquals("numberOfRatings", numberOfRatings, other.getNumberOfRatings()); - AssertUtil.assertEquals("average", average, other.getAverage()); - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Aggregate other = (Aggregate) obj; - if (average == null) { - if (other.average != null) - return false; - } else if (!average.equals(other.average)) - return false; - if (numberOfRatings == null) { - if (other.numberOfRatings != null) - return false; - } else if (!numberOfRatings.equals(other.numberOfRatings)) - return false; - return true; - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode()); - result = prime * result - + ((ratingScheme == null) ? 0 : ratingScheme.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NodeRating other = (NodeRating) obj; - if (nodeId == null) { - if (other.nodeId != null) - return false; - } else if (!nodeId.equals(other.nodeId)) - return false; - if (ratingScheme == null) { - if (other.ratingScheme != null) - return false; - } else if (!ratingScheme.equals(other.ratingScheme)) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof NodeRating); - - NodeRating other = (NodeRating)o; - - AssertUtil.assertEquals("nodeId", nodeId, other.getNodeId()); - AssertUtil.assertEquals("ratingScheme", ratingScheme, other.getId()); - - DateFormat dateFormat = PublicApiDateFormat.getDateFormat(); - try - { - if(getRatedAt() != null) - { - Date date1 = dateFormat.parse(getRatedAt()); - Date date2 = dateFormat.parse(other.getRatedAt()); - assertTrue(date2.equals(date1) || date2.after(date1)); - } - } - catch (ParseException e) - { - throw new RuntimeException(e); - } - - AssertUtil.assertEquals("myRating", myRating, other.getMyRating()); - if(aggregate != null) - { - aggregate.expected(other.getAggregate()); - } - } - - @Override - public int compareTo(NodeRating other) - { - return ratingScheme.compareTo(other.getId()); - } +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.alfresco.rest.api.tests.PublicApiDateFormat; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class NodeRating implements Serializable, Comparable, ExpectedComparison +{ + private static final long serialVersionUID = 2855422270577730898L; + + private String nodeId; + private String ratingScheme; + private String ratedAt; + private Object myRating; + private Aggregate aggregate; + + public NodeRating(String ratingScheme, Object myRating) + { + this.ratingScheme = ratingScheme; + this.myRating = myRating; + } + + public NodeRating(String ratingScheme, Object myRating, Aggregate aggregate) + { + this.ratingScheme = ratingScheme; + this.myRating = myRating; + this.aggregate = aggregate; + } + + public NodeRating(String nodeId, String ratingScheme, String ratedAt, Object myRating, Aggregate aggregate) + { + this.nodeId = nodeId; + this.ratingScheme = ratingScheme; + this.ratedAt = ratedAt; + this.myRating = myRating; + this.aggregate = aggregate; + } + + public Aggregate getAggregate() + { + return aggregate; + } + + public Object getMyRating() + { + return myRating; + } + + public String getNodeId() + { + return nodeId; + } + + public String getId() + { + return ratingScheme; + } + + public String getRatedAt() + { + return ratedAt; + } + + @Override + public String toString() + { + return "NodeRating [ratingScheme=" + ratingScheme + ", ratedAt=" + + ratedAt + "]"; + } + + public static NodeRating parseNodeRating(String nodeId, JSONObject jsonObject) + { + String ratingScheme = (String)jsonObject.get("id"); + String ratedAt = (String)jsonObject.get("ratedAt"); + Object myRating = jsonObject.get("myRating"); + + JSONObject aggregateJSON = (JSONObject)jsonObject.get("aggregate"); + Long numRatings = (Long)aggregateJSON.get("numberOfRatings"); + Double average = (Double)aggregateJSON.get("average"); + Aggregate aggregate = new Aggregate(numRatings != null ? numRatings.intValue() : null, average != null ? average.floatValue(): null); + NodeRating nodeRating = new NodeRating(nodeId, ratingScheme, ratedAt, myRating, aggregate); + return nodeRating; + } + + public static ListResponse parseNodeRatings(String nodeId, JSONObject jsonObject) + { + List nodeRatings = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + nodeRatings.add(NodeRating.parseNodeRating(nodeId, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + + ListResponse resp = new ListResponse(paging, nodeRatings); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject nodeRatingJSON = new JSONObject(); + + nodeRatingJSON.put("myRating", getMyRating()); + nodeRatingJSON.put("id", getId()); + + return nodeRatingJSON; + } + + public static class Aggregate implements ExpectedComparison + { + private Integer numberOfRatings; + private Float average; + + public Aggregate(Integer numberOfRatings, Float average) + { + super(); + this.numberOfRatings = numberOfRatings; + this.average = average; + } + + public Integer getNumberOfRatings() + { + return numberOfRatings; + } + + public Float getAverage() + { + return average; + } + + @Override + public String toString() + { + return "Aggregate [numberOfRatings=" + numberOfRatings + + ", average=" + average + "]"; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Aggregate); + + Aggregate other = (Aggregate)o; + + AssertUtil.assertEquals("numberOfRatings", numberOfRatings, other.getNumberOfRatings()); + AssertUtil.assertEquals("average", average, other.getAverage()); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Aggregate other = (Aggregate) obj; + if (average == null) { + if (other.average != null) + return false; + } else if (!average.equals(other.average)) + return false; + if (numberOfRatings == null) { + if (other.numberOfRatings != null) + return false; + } else if (!numberOfRatings.equals(other.numberOfRatings)) + return false; + return true; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode()); + result = prime * result + + ((ratingScheme == null) ? 0 : ratingScheme.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NodeRating other = (NodeRating) obj; + if (nodeId == null) { + if (other.nodeId != null) + return false; + } else if (!nodeId.equals(other.nodeId)) + return false; + if (ratingScheme == null) { + if (other.ratingScheme != null) + return false; + } else if (!ratingScheme.equals(other.ratingScheme)) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof NodeRating); + + NodeRating other = (NodeRating)o; + + AssertUtil.assertEquals("nodeId", nodeId, other.getNodeId()); + AssertUtil.assertEquals("ratingScheme", ratingScheme, other.getId()); + + DateFormat dateFormat = PublicApiDateFormat.getDateFormat(); + try + { + if(getRatedAt() != null) + { + Date date1 = dateFormat.parse(getRatedAt()); + Date date2 = dateFormat.parse(other.getRatedAt()); + assertTrue(date2.equals(date1) || date2.after(date1)); + } + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + + AssertUtil.assertEquals("myRating", myRating, other.getMyRating()); + if(aggregate != null) + { + aggregate.expected(other.getAggregate()); + } + } + + @Override + public int compareTo(NodeRating other) + { + return ratingScheme.compareTo(other.getId()); + } } \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java index 66066f2ead..767e028a01 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java @@ -1,479 +1,479 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.text.Collator; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.service.namespace.QName; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -import com.sun.star.uno.RuntimeException; - -public class Person implements Serializable, Comparable, ExpectedComparison -{ - private static final long serialVersionUID = 3185698391792389751L; - - private String id; - private Boolean enabled; - private String username; - private String firstName; - private String lastName; - private Company company; - private String skype; - private String location; - private String tel; - private String mob; - private String instantmsg; - private String google; - private String description; - - private static Collator collator = Collator.getInstance(); - - public Person(String id, String username, Boolean enabled, String firstName, String lastName, - Company company, String skype, String location, String tel, - String mob, String instantmsg, String google, String description) - { - super(); - if(id == null) - { - throw new IllegalArgumentException(); - } - this.id = id; - this.username = username; - this.enabled = enabled; - this.firstName = firstName; - this.lastName = lastName; - this.company = company; - this.skype = skype; - this.location = location; - this.tel = tel; - this.mob = mob; - this.instantmsg = instantmsg; - this.google = google; - this.description = description; - } - - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public String getEmail() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getSkype() { - return skype; - } - - public void setSkype(String skype) { - this.skype = skype; - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - public String getTel() { - return tel; - } - - public void setTel(String tel) { - this.tel = tel; - } - - public String getMob() { - return mob; - } - - public void setMob(String mob) { - this.mob = mob; - } - - public String getInstantmsg() { - return instantmsg; - } - - public void setInstantmsg(String instantmsg) { - this.instantmsg = instantmsg; - } - - public String getGoogle() { - return google; - } - - public void setGoogle(String google) { - this.google = google; - } - - public String getFirstName() - { - return firstName; - } - - public Company getCompany() - { - return company; - } - - public void setCompany(Company company) - { - this.company = company; - } - - public void setFirstName(String firstName) - { - this.firstName = firstName; - } - - public String getLastName() - { - return lastName; - } - - public void setLastName(String lastName) - { - this.lastName = lastName; - } - - public String getDescription() - { - return description; - } - - @Override - public String toString() - { - return "Person [" + (id != null ? "id=" + id + ", " : "") - + (enabled != null ? "enabled=" + enabled + ", " : "") - + (username != null ? "email=" + username + ", " : "") - + (firstName != null ? "firstName=" + firstName + ", " : "") - + (lastName != null ? "lastName=" + lastName + ", " : "") - + (company != null ? "company=" + company + ", " : "") - + (skype != null ? "skype=" + skype + ", " : "") - + (location != null ? "location=" + location + ", " : "") - + (tel != null ? "tel=" + tel + ", " : "") - + (mob != null ? "mob=" + mob + ", " : "") - + (instantmsg != null ? "instantmsg=" + instantmsg + ", " : "") - + (google != null ? "google=" + google + ", " : "") - + (description != null ? "description=" + description + ", " : "") - + "]"; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON(boolean fullVisibility) - { - JSONObject personJson = new JSONObject(); - personJson.put("id", getId()); - personJson.put("firstName", getFirstName()); - personJson.put("lastName", getLastName()); - if(fullVisibility) - { - personJson.put("skypeId", "skype"); - personJson.put("location", "location"); - personJson.put("telephone", "tel"); - personJson.put("mobile", "mob"); - personJson.put("instantMessageId", "instantmsg"); - personJson.put("googleId", "google"); - - personJson.put("company", company.toJSON()); - - } - return personJson; - } - - public static Person parsePerson(JSONObject jsonObject) - { - Boolean enabled = (Boolean)jsonObject.get("enabled"); - String location = (String)jsonObject.get("location"); - String instantMessageId = (String)jsonObject.get("instantMessageId"); - String googleId = (String)jsonObject.get("googleId"); - String skypeId = (String)jsonObject.get("skypeId"); - String email = (String)jsonObject.get("email"); - String telephone = (String)jsonObject.get("telephone"); - String mobile = (String)jsonObject.get("mobile"); - String userId = (String)jsonObject.get("id"); - String firstName = (String)jsonObject.get("firstName"); - String lastName = (String)jsonObject.get("lastName"); - String description = (String)jsonObject.get("description"); - - JSONObject companyJSON = (JSONObject)jsonObject.get("company"); - Company company = null; - if(companyJSON != null) - { - String organization = (String)companyJSON.get("organization"); - String address1 = (String)companyJSON.get("address1"); - String address2 = (String)companyJSON.get("address2"); - String address3 = (String)companyJSON.get("address3"); - String postcode = (String)companyJSON.get("postcode"); - String companyTelephone = (String)companyJSON.get("telephone"); - String fax = (String)companyJSON.get("fax"); - String companyEmail = (String)companyJSON.get("email"); - company = new Company(organization, address1, address2, address3, postcode, companyTelephone, fax, companyEmail); - } - Person person = new Person(userId, email, enabled, firstName, lastName, company, skypeId, location, telephone, mobile, instantMessageId, googleId, description); - return person; - } - - public Person restriced() - { - Person p = new Person(getId(), getEmail(), getEnabled(), getFirstName(), getLastName(), null, null, null, null, null, null, null, null); - return p; - } - - private static class UserContext - { - private String networkId; - private String personId; - - UserContext(String networkId, String personId) - { - super(); - this.networkId = networkId; - this.personId = personId; - } - - String getNetworkId() - { - return networkId; - } - - String getPersonId() - { - return personId; - } - } - - private static ThreadLocal userContext = new ThreadLocal(); - public static void setUserContext(String personId) - { - String networkId = Person.getNetworkId(personId); - userContext.set(new UserContext(networkId, personId)); - } - - public static void clearUserContext() - { - userContext.set(null); - } - - public static UserContext gettUserContext() - { - return userContext.get(); - } - - public static String getNetworkId(String personId) - { - int idx = personId.indexOf("@"); - return(idx == -1 ? TenantService.DEFAULT_DOMAIN : personId.substring(idx + 1)); - } - - private String getNetworkId() - { - return Person.getNetworkId(id); - } - - public boolean isVisible() - { - boolean ret = true; - - UserContext uc = gettUserContext(); - String networkId = getNetworkId(); - if(uc != null) - { - if(!networkId.equals(uc.getNetworkId())) - { - ret = false; - } - } - - return ret; - } - - @Override - public void expected(Object o) - { - assertTrue("o is an instance of " + o.getClass(), o instanceof Person); - - Person other = (Person)o; - - AssertUtil.assertEquals("userId", id, other.getId()); - AssertUtil.assertEquals("firstName", firstName, other.getFirstName()); - AssertUtil.assertEquals("lastName", lastName, other.getLastName()); - AssertUtil.assertEquals("enabled", enabled, other.getEnabled()); - - if(isVisible()) - { - AssertUtil.assertEquals("skype", skype, other.getSkype()); - AssertUtil.assertEquals("location", location, other.getLocation()); - AssertUtil.assertEquals("tel", tel, other.getTel()); - AssertUtil.assertEquals("mobile", mob, other.getMob()); - AssertUtil.assertEquals("instanceMessageId", instantmsg, other.getInstantmsg()); - AssertUtil.assertEquals("googleId", google, other.getGoogle()); - if(company != null) - { - company.expected(getCompany()); - } - } - } - - public Map getProperties() - { - final Map props = new HashMap(); - - if(firstName != null) - { - props.put(ContentModel.PROP_FIRSTNAME, firstName); - } - - if(lastName != null) - { - props.put(ContentModel.PROP_LASTNAME, lastName); - } - - if(skype != null) - { - props.put(ContentModel.PROP_SKYPE, skype); - } - - if(location != null) - { - props.put(ContentModel.PROP_LOCATION, location); - } - - if(tel != null) - { - props.put(ContentModel.PROP_TELEPHONE, tel); - } - - if(username != null) - { - props.put(ContentModel.PROP_USERNAME, username); - } - - if(mob != null) - { - props.put(ContentModel.PROP_MOBILE, mob); - } - - if(instantmsg != null) - { - props.put(ContentModel.PROP_INSTANTMSG, instantmsg); - } - - if(google != null) - { - props.put(ContentModel.PROP_GOOGLEUSERNAME, google); - } - - if(company != null) - { - if(company.getOrganization() != null) - { - props.put(ContentModel.PROP_ORGANIZATION, company.getOrganization()); - } - - if(company.getAddress1() != null) - { - props.put(ContentModel.PROP_COMPANYADDRESS1, company.getAddress1()); - } - - if(company.getAddress2() != null) - { - props.put(ContentModel.PROP_COMPANYADDRESS2, company.getAddress2()); - } - - if(company.getAddress3() != null) - { - props.put(ContentModel.PROP_COMPANYADDRESS3, company.getAddress3()); - } - - if(company.getPostcode() != null) - { - props.put(ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode()); - } - - if(company.getTelephone() != null) - { - props.put(ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone()); - } - - if(company.getFax() != null) - { - props.put(ContentModel.PROP_COMPANYFAX, company.getFax()); - } - - if(company.getEmail() != null) - { - props.put(ContentModel.PROP_COMPANYEMAIL, company.getEmail()); - } - } - - return props; - } - - @Override - public int compareTo(Person o) - { - int ret = Person.collator.compare(lastName, o.getLastName()); - if(ret == 0) - { - ret = Person.collator.compare(firstName, o.getFirstName()); - } - return ret; - } - - public static ListResponse parsePeople(JSONObject jsonObject) - { - List people = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - people.add(parsePerson(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - ListResponse resp = new ListResponse(paging, people); - return resp; - } - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.Collator; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.service.namespace.QName; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sun.star.uno.RuntimeException; + +public class Person implements Serializable, Comparable, ExpectedComparison +{ + private static final long serialVersionUID = 3185698391792389751L; + + private String id; + private Boolean enabled; + private String username; + private String firstName; + private String lastName; + private Company company; + private String skype; + private String location; + private String tel; + private String mob; + private String instantmsg; + private String google; + private String description; + + private static Collator collator = Collator.getInstance(); + + public Person(String id, String username, Boolean enabled, String firstName, String lastName, + Company company, String skype, String location, String tel, + String mob, String instantmsg, String google, String description) + { + super(); + if(id == null) + { + throw new IllegalArgumentException(); + } + this.id = id; + this.username = username; + this.enabled = enabled; + this.firstName = firstName; + this.lastName = lastName; + this.company = company; + this.skype = skype; + this.location = location; + this.tel = tel; + this.mob = mob; + this.instantmsg = instantmsg; + this.google = google; + this.description = description; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public String getEmail() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getSkype() { + return skype; + } + + public void setSkype(String skype) { + this.skype = skype; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getTel() { + return tel; + } + + public void setTel(String tel) { + this.tel = tel; + } + + public String getMob() { + return mob; + } + + public void setMob(String mob) { + this.mob = mob; + } + + public String getInstantmsg() { + return instantmsg; + } + + public void setInstantmsg(String instantmsg) { + this.instantmsg = instantmsg; + } + + public String getGoogle() { + return google; + } + + public void setGoogle(String google) { + this.google = google; + } + + public String getFirstName() + { + return firstName; + } + + public Company getCompany() + { + return company; + } + + public void setCompany(Company company) + { + this.company = company; + } + + public void setFirstName(String firstName) + { + this.firstName = firstName; + } + + public String getLastName() + { + return lastName; + } + + public void setLastName(String lastName) + { + this.lastName = lastName; + } + + public String getDescription() + { + return description; + } + + @Override + public String toString() + { + return "Person [" + (id != null ? "id=" + id + ", " : "") + + (enabled != null ? "enabled=" + enabled + ", " : "") + + (username != null ? "email=" + username + ", " : "") + + (firstName != null ? "firstName=" + firstName + ", " : "") + + (lastName != null ? "lastName=" + lastName + ", " : "") + + (company != null ? "company=" + company + ", " : "") + + (skype != null ? "skype=" + skype + ", " : "") + + (location != null ? "location=" + location + ", " : "") + + (tel != null ? "tel=" + tel + ", " : "") + + (mob != null ? "mob=" + mob + ", " : "") + + (instantmsg != null ? "instantmsg=" + instantmsg + ", " : "") + + (google != null ? "google=" + google + ", " : "") + + (description != null ? "description=" + description + ", " : "") + + "]"; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON(boolean fullVisibility) + { + JSONObject personJson = new JSONObject(); + personJson.put("id", getId()); + personJson.put("firstName", getFirstName()); + personJson.put("lastName", getLastName()); + if(fullVisibility) + { + personJson.put("skypeId", "skype"); + personJson.put("location", "location"); + personJson.put("telephone", "tel"); + personJson.put("mobile", "mob"); + personJson.put("instantMessageId", "instantmsg"); + personJson.put("googleId", "google"); + + personJson.put("company", company.toJSON()); + + } + return personJson; + } + + public static Person parsePerson(JSONObject jsonObject) + { + Boolean enabled = (Boolean)jsonObject.get("enabled"); + String location = (String)jsonObject.get("location"); + String instantMessageId = (String)jsonObject.get("instantMessageId"); + String googleId = (String)jsonObject.get("googleId"); + String skypeId = (String)jsonObject.get("skypeId"); + String email = (String)jsonObject.get("email"); + String telephone = (String)jsonObject.get("telephone"); + String mobile = (String)jsonObject.get("mobile"); + String userId = (String)jsonObject.get("id"); + String firstName = (String)jsonObject.get("firstName"); + String lastName = (String)jsonObject.get("lastName"); + String description = (String)jsonObject.get("description"); + + JSONObject companyJSON = (JSONObject)jsonObject.get("company"); + Company company = null; + if(companyJSON != null) + { + String organization = (String)companyJSON.get("organization"); + String address1 = (String)companyJSON.get("address1"); + String address2 = (String)companyJSON.get("address2"); + String address3 = (String)companyJSON.get("address3"); + String postcode = (String)companyJSON.get("postcode"); + String companyTelephone = (String)companyJSON.get("telephone"); + String fax = (String)companyJSON.get("fax"); + String companyEmail = (String)companyJSON.get("email"); + company = new Company(organization, address1, address2, address3, postcode, companyTelephone, fax, companyEmail); + } + Person person = new Person(userId, email, enabled, firstName, lastName, company, skypeId, location, telephone, mobile, instantMessageId, googleId, description); + return person; + } + + public Person restriced() + { + Person p = new Person(getId(), getEmail(), getEnabled(), getFirstName(), getLastName(), null, null, null, null, null, null, null, null); + return p; + } + + private static class UserContext + { + private String networkId; + private String personId; + + UserContext(String networkId, String personId) + { + super(); + this.networkId = networkId; + this.personId = personId; + } + + String getNetworkId() + { + return networkId; + } + + String getPersonId() + { + return personId; + } + } + + private static ThreadLocal userContext = new ThreadLocal(); + public static void setUserContext(String personId) + { + String networkId = Person.getNetworkId(personId); + userContext.set(new UserContext(networkId, personId)); + } + + public static void clearUserContext() + { + userContext.set(null); + } + + public static UserContext gettUserContext() + { + return userContext.get(); + } + + public static String getNetworkId(String personId) + { + int idx = personId.indexOf("@"); + return(idx == -1 ? TenantService.DEFAULT_DOMAIN : personId.substring(idx + 1)); + } + + private String getNetworkId() + { + return Person.getNetworkId(id); + } + + public boolean isVisible() + { + boolean ret = true; + + UserContext uc = gettUserContext(); + String networkId = getNetworkId(); + if(uc != null) + { + if(!networkId.equals(uc.getNetworkId())) + { + ret = false; + } + } + + return ret; + } + + @Override + public void expected(Object o) + { + assertTrue("o is an instance of " + o.getClass(), o instanceof Person); + + Person other = (Person)o; + + AssertUtil.assertEquals("userId", id, other.getId()); + AssertUtil.assertEquals("firstName", firstName, other.getFirstName()); + AssertUtil.assertEquals("lastName", lastName, other.getLastName()); + AssertUtil.assertEquals("enabled", enabled, other.getEnabled()); + + if(isVisible()) + { + AssertUtil.assertEquals("skype", skype, other.getSkype()); + AssertUtil.assertEquals("location", location, other.getLocation()); + AssertUtil.assertEquals("tel", tel, other.getTel()); + AssertUtil.assertEquals("mobile", mob, other.getMob()); + AssertUtil.assertEquals("instanceMessageId", instantmsg, other.getInstantmsg()); + AssertUtil.assertEquals("googleId", google, other.getGoogle()); + if(company != null) + { + company.expected(getCompany()); + } + } + } + + public Map getProperties() + { + final Map props = new HashMap(); + + if(firstName != null) + { + props.put(ContentModel.PROP_FIRSTNAME, firstName); + } + + if(lastName != null) + { + props.put(ContentModel.PROP_LASTNAME, lastName); + } + + if(skype != null) + { + props.put(ContentModel.PROP_SKYPE, skype); + } + + if(location != null) + { + props.put(ContentModel.PROP_LOCATION, location); + } + + if(tel != null) + { + props.put(ContentModel.PROP_TELEPHONE, tel); + } + + if(username != null) + { + props.put(ContentModel.PROP_USERNAME, username); + } + + if(mob != null) + { + props.put(ContentModel.PROP_MOBILE, mob); + } + + if(instantmsg != null) + { + props.put(ContentModel.PROP_INSTANTMSG, instantmsg); + } + + if(google != null) + { + props.put(ContentModel.PROP_GOOGLEUSERNAME, google); + } + + if(company != null) + { + if(company.getOrganization() != null) + { + props.put(ContentModel.PROP_ORGANIZATION, company.getOrganization()); + } + + if(company.getAddress1() != null) + { + props.put(ContentModel.PROP_COMPANYADDRESS1, company.getAddress1()); + } + + if(company.getAddress2() != null) + { + props.put(ContentModel.PROP_COMPANYADDRESS2, company.getAddress2()); + } + + if(company.getAddress3() != null) + { + props.put(ContentModel.PROP_COMPANYADDRESS3, company.getAddress3()); + } + + if(company.getPostcode() != null) + { + props.put(ContentModel.PROP_COMPANYPOSTCODE, company.getPostcode()); + } + + if(company.getTelephone() != null) + { + props.put(ContentModel.PROP_COMPANYTELEPHONE, company.getTelephone()); + } + + if(company.getFax() != null) + { + props.put(ContentModel.PROP_COMPANYFAX, company.getFax()); + } + + if(company.getEmail() != null) + { + props.put(ContentModel.PROP_COMPANYEMAIL, company.getEmail()); + } + } + + return props; + } + + @Override + public int compareTo(Person o) + { + int ret = Person.collator.compare(lastName, o.getLastName()); + if(ret == 0) + { + ret = Person.collator.compare(firstName, o.getFirstName()); + } + return ret; + } + + public static ListResponse parsePeople(JSONObject jsonObject) + { + List people = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + people.add(parsePerson(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + ListResponse resp = new ListResponse(paging, people); + return resp; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/PersonNetwork.java b/source/test-java/org/alfresco/rest/api/tests/client/data/PersonNetwork.java index d2bd757e0d..b83ccb60e6 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/PersonNetwork.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/PersonNetwork.java @@ -1,173 +1,173 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class PersonNetwork implements Network, Comparable, ExpectedComparison -{ - private String networkId; - private Boolean homeNetwork; - private NetworkImpl network; - - public PersonNetwork(String networkId) - { - super(); - } - - public PersonNetwork(Boolean homeNetwork, NetworkImpl network) - { - super(); - this.homeNetwork = homeNetwork; - this.network = network; - this.networkId = network.getId(); - } - - public String getId() - { - return networkId; - } - - public Boolean isHomeNetwork() - { - return homeNetwork; - } - - public NetworkImpl getNetwork() - { - return network; - } - - public static PersonNetwork parseNetworkMember(JSONObject jsonObject) - { - Boolean homeNetwork = (Boolean)jsonObject.get("homeNetwork"); - PersonNetwork networkMember = new PersonNetwork(homeNetwork, NetworkImpl.parseNetwork(jsonObject)); - return networkMember; - } - - public static ListResponse parseNetworkMembers(JSONObject jsonObject) - { - List networkMembers = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - networkMembers.add(PersonNetwork.parseNetworkMember(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - ListResponse resp = new ListResponse(paging, networkMembers); - return resp; - } - - @Override - public String toString() - { - return "NetworkMember [id=" + getId() + ", homeNetwork=" + homeNetwork - + ", network=" + network + "]"; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject networkMemberJson = new JSONObject(); - networkMemberJson.put("id", getId()); - networkMemberJson.put("homeNetwork", isHomeNetwork()); - networkMemberJson.put("network", getNetwork()); - return networkMemberJson; - } - - @Override - public int compareTo(PersonNetwork member) - { - int ret = -1 * isHomeNetwork().compareTo(member.isHomeNetwork()); - if(ret == 0) - { - ret = getId().compareTo(member.getId()); - } - return ret; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((network == null) ? 0 : network.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - PersonNetwork other = (PersonNetwork) obj; - if (network == null) { - if (other.network != null) - return false; - } else if (!network.equals(other.network)) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof PersonNetwork); - - PersonNetwork other = (PersonNetwork)o; - - AssertUtil.assertEquals("homeNetwork", homeNetwork, other.isHomeNetwork()); - if(network != null) - { - network.expected(other.getNetwork()); - } - } - - @Override - public Boolean getIsEnabled() - { - return network.getIsEnabled(); - } - - @Override - public String getCreatedAt() - { - return network.getCreatedAt(); - } - - @Override - public List getQuotas() - { - return network.getQuotas(); - } - - @Override - public String getSubscriptionLevel() - { - return network.getSubscriptionLevel(); - } - - @Override - public Boolean isPaidNetwork() - { - return network.isPaidNetwork(); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class PersonNetwork implements Network, Comparable, ExpectedComparison +{ + private String networkId; + private Boolean homeNetwork; + private NetworkImpl network; + + public PersonNetwork(String networkId) + { + super(); + } + + public PersonNetwork(Boolean homeNetwork, NetworkImpl network) + { + super(); + this.homeNetwork = homeNetwork; + this.network = network; + this.networkId = network.getId(); + } + + public String getId() + { + return networkId; + } + + public Boolean isHomeNetwork() + { + return homeNetwork; + } + + public NetworkImpl getNetwork() + { + return network; + } + + public static PersonNetwork parseNetworkMember(JSONObject jsonObject) + { + Boolean homeNetwork = (Boolean)jsonObject.get("homeNetwork"); + PersonNetwork networkMember = new PersonNetwork(homeNetwork, NetworkImpl.parseNetwork(jsonObject)); + return networkMember; + } + + public static ListResponse parseNetworkMembers(JSONObject jsonObject) + { + List networkMembers = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + networkMembers.add(PersonNetwork.parseNetworkMember(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + ListResponse resp = new ListResponse(paging, networkMembers); + return resp; + } + + @Override + public String toString() + { + return "NetworkMember [id=" + getId() + ", homeNetwork=" + homeNetwork + + ", network=" + network + "]"; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject networkMemberJson = new JSONObject(); + networkMemberJson.put("id", getId()); + networkMemberJson.put("homeNetwork", isHomeNetwork()); + networkMemberJson.put("network", getNetwork()); + return networkMemberJson; + } + + @Override + public int compareTo(PersonNetwork member) + { + int ret = -1 * isHomeNetwork().compareTo(member.isHomeNetwork()); + if(ret == 0) + { + ret = getId().compareTo(member.getId()); + } + return ret; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((network == null) ? 0 : network.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PersonNetwork other = (PersonNetwork) obj; + if (network == null) { + if (other.network != null) + return false; + } else if (!network.equals(other.network)) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof PersonNetwork); + + PersonNetwork other = (PersonNetwork)o; + + AssertUtil.assertEquals("homeNetwork", homeNetwork, other.isHomeNetwork()); + if(network != null) + { + network.expected(other.getNetwork()); + } + } + + @Override + public Boolean getIsEnabled() + { + return network.getIsEnabled(); + } + + @Override + public String getCreatedAt() + { + return network.getCreatedAt(); + } + + @Override + public List getQuotas() + { + return network.getQuotas(); + } + + @Override + public String getSubscriptionLevel() + { + return network.getSubscriptionLevel(); + } + + @Override + public Boolean isPaidNetwork() + { + return network.isPaidNetwork(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Preference.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Preference.java index 2f22e66677..aa4bfe4165 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Preference.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Preference.java @@ -1,132 +1,132 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class Preference implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = -4187479305268687836L; - - private String id; - private String value; - - public Preference(String id, String value) - { - super(); - this.id = id; - this.value = value; - } - - public String getId() - { - return id; - } - - public String getValue() - { - return value; - } - - @Override - public String toString() - { - return "Preference [id=" + id + ", value=" + value + "]"; - } - - public static Preference parsePreference(JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - String value = jsonObject.get("value").toString(); - Preference preference = new Preference(id, value); - return preference; - } - - public static ListResponse parsePreferences(JSONObject jsonObject) - { - List preferences = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - preferences.add(Preference.parsePreference(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - ListResponse resp = new ListResponse(paging, preferences); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject entry = new JSONObject(); - entry.put("id", getId()); - entry.put("value", getValue()); - return entry; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Preference other = (Preference) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - if (value == null) { - if (other.value != null) - return false; - } else if (!value.equals(other.value)) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Preference); - - Preference other = (Preference)o; - - AssertUtil.assertEquals("id", id, other.getId()); - AssertUtil.assertEquals("value", value, other.getValue()); - } - - @Override - public int compareTo(Preference o) - { - return id.compareTo(o.getId()); - } - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class Preference implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = -4187479305268687836L; + + private String id; + private String value; + + public Preference(String id, String value) + { + super(); + this.id = id; + this.value = value; + } + + public String getId() + { + return id; + } + + public String getValue() + { + return value; + } + + @Override + public String toString() + { + return "Preference [id=" + id + ", value=" + value + "]"; + } + + public static Preference parsePreference(JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + String value = jsonObject.get("value").toString(); + Preference preference = new Preference(id, value); + return preference; + } + + public static ListResponse parsePreferences(JSONObject jsonObject) + { + List preferences = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + preferences.add(Preference.parsePreference(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + ListResponse resp = new ListResponse(paging, preferences); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject entry = new JSONObject(); + entry.put("id", getId()); + entry.put("value", getValue()); + return entry; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Preference other = (Preference) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Preference); + + Preference other = (Preference)o; + + AssertUtil.assertEquals("id", id, other.getId()); + AssertUtil.assertEquals("value", value, other.getValue()); + } + + @Override + public int compareTo(Preference o) + { + return id.compareTo(o.getId()); + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Quota.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Quota.java index fc804b9779..f72062b1e5 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Quota.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Quota.java @@ -1,56 +1,56 @@ -package org.alfresco.rest.api.tests.client.data; - -import org.json.simple.JSONObject; - -public class Quota -{ - private String id; - private Object limit; - private Object quota; - - public Quota(String id, Object limit, Object quota) - { - super(); - this.id = id; - this.limit = limit; - this.quota = quota; - } - - public String getId() { - return id; - } - - public Object getLimit() { - return limit; - } - - public Object getQuota() { - return quota; - } - - public static Quota parseQuota(JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - Object limit = jsonObject.get("limit"); - Object quota = jsonObject.get("quota"); - Quota ret = new Quota(id, limit, quota); - return ret; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject quotaJson = new JSONObject(); - quotaJson.put("id", getId()); - quotaJson.put("quota", getQuota().toString()); - quotaJson.put("limit", getLimit().toString()); - return quotaJson; - } - - @Override - public String toString() - { - return "Quota [id=" + id + ", limit=" + limit + ", quota=" + quota - + "]"; - } -} +package org.alfresco.rest.api.tests.client.data; + +import org.json.simple.JSONObject; + +public class Quota +{ + private String id; + private Object limit; + private Object quota; + + public Quota(String id, Object limit, Object quota) + { + super(); + this.id = id; + this.limit = limit; + this.quota = quota; + } + + public String getId() { + return id; + } + + public Object getLimit() { + return limit; + } + + public Object getQuota() { + return quota; + } + + public static Quota parseQuota(JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + Object limit = jsonObject.get("limit"); + Object quota = jsonObject.get("quota"); + Quota ret = new Quota(id, limit, quota); + return ret; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject quotaJson = new JSONObject(); + quotaJson.put("id", getId()); + quotaJson.put("quota", getQuota().toString()); + quotaJson.put("limit", getLimit().toString()); + return quotaJson; + } + + @Override + public String toString() + { + return "Quota [id=" + id + ", limit=" + limit + ", quota=" + quota + + "]"; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Site.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Site.java index 22005e5e3c..07471ebc40 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Site.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Site.java @@ -1,19 +1,19 @@ -package org.alfresco.rest.api.tests.client.data; - -import org.json.simple.JSONObject; - -public interface Site extends JSONAble -{ - Boolean getCreated(); - String getGuid(); - String getNetworkId(); - Boolean isCreated(); - String getSiteId(); - String getTitle(); - String getDescription(); - String getVisibility(); - String getType(); - SiteRole getRole(); - void expected(Object o); - JSONObject toJSON(); -} +package org.alfresco.rest.api.tests.client.data; + +import org.json.simple.JSONObject; + +public interface Site extends JSONAble +{ + Boolean getCreated(); + String getGuid(); + String getNetworkId(); + Boolean isCreated(); + String getSiteId(); + String getTitle(); + String getDescription(); + String getVisibility(); + String getType(); + SiteRole getRole(); + void expected(Object o); + JSONObject toJSON(); +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteContainer.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteContainer.java index b3368ee637..6d781dbcab 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteContainer.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteContainer.java @@ -1,114 +1,114 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class SiteContainer implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = 535206187221924534L; - - private String siteId; - private String id; - private String folderId; - - public SiteContainer(String siteId, String folderId, String id) - { - super(); - this.siteId = siteId; - this.folderId = folderId; - this.id = id; - } - - public String getSiteId() - { - return siteId; - } - - public String getFolderId() - { - return folderId; - } - - public String getId() - { - return id; - } - - @Override - public String toString() - { - return "SiteContainer [siteId=" + siteId + ", folderId=" + folderId - + ", id=" + id + "]"; - } - - public static SiteContainer parseSiteContainer(String siteId, JSONObject json) - { - SiteContainer siteContainer = null; - - if(json != null) - { - siteContainer = new SiteContainer(siteId, (String)json.get("folderId"), (String)json.get("id")); - } - - return siteContainer; - } - - public static ListResponse parseSiteContainers(JSONObject jsonObject) - { - List siteContainers = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - siteContainers.add(SiteContainer.parseSiteContainer(null, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - - ListResponse resp = new ListResponse(paging, siteContainers); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject siteContainerJson = new JSONObject(); - siteContainerJson.put("id", id); - siteContainerJson.put("folderId", folderId); - return siteContainerJson; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof SiteContainer); - - SiteContainer other = (SiteContainer)o; - - AssertUtil.assertEquals("id", id, other.getId()); - AssertUtil.assertEquals("folderId", folderId, other.getFolderId()); - } - - @Override - public int compareTo(SiteContainer o) - { - return folderId.compareTo(o.getFolderId()); - } - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class SiteContainer implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = 535206187221924534L; + + private String siteId; + private String id; + private String folderId; + + public SiteContainer(String siteId, String folderId, String id) + { + super(); + this.siteId = siteId; + this.folderId = folderId; + this.id = id; + } + + public String getSiteId() + { + return siteId; + } + + public String getFolderId() + { + return folderId; + } + + public String getId() + { + return id; + } + + @Override + public String toString() + { + return "SiteContainer [siteId=" + siteId + ", folderId=" + folderId + + ", id=" + id + "]"; + } + + public static SiteContainer parseSiteContainer(String siteId, JSONObject json) + { + SiteContainer siteContainer = null; + + if(json != null) + { + siteContainer = new SiteContainer(siteId, (String)json.get("folderId"), (String)json.get("id")); + } + + return siteContainer; + } + + public static ListResponse parseSiteContainers(JSONObject jsonObject) + { + List siteContainers = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + siteContainers.add(SiteContainer.parseSiteContainer(null, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + + ListResponse resp = new ListResponse(paging, siteContainers); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject siteContainerJson = new JSONObject(); + siteContainerJson.put("id", id); + siteContainerJson.put("folderId", folderId); + return siteContainerJson; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof SiteContainer); + + SiteContainer other = (SiteContainer)o; + + AssertUtil.assertEquals("id", id, other.getId()); + AssertUtil.assertEquals("folderId", folderId, other.getFolderId()); + } + + @Override + public int compareTo(SiteContainer o) + { + return folderId.compareTo(o.getFolderId()); + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteFavouriteTarget.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteFavouriteTarget.java index 2a69b4c2ea..53aa9e4d38 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteFavouriteTarget.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteFavouriteTarget.java @@ -1,50 +1,50 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import org.json.simple.JSONObject; - -public class SiteFavouriteTarget implements FavouritesTarget -{ - private Site site; - - public SiteFavouriteTarget(Site site) - { - super(); - this.site = site; - } - - public Site getSite() - { - return site; - } - - @SuppressWarnings("unchecked") - @Override - public JSONObject toJSON() - { - JSONObject favouriteJson = new JSONObject(); - favouriteJson.put("site", getSite().toJSON()); - return favouriteJson; - } - - @Override - public String toString() - { - return "SiteFavouritesTarget [site=" + site + "]"; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof SiteFavouriteTarget); - - SiteFavouriteTarget other = (SiteFavouriteTarget) o; - site.expected(other.getSite()); - } - - public String getTargetGuid() - { - return site.getGuid(); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import org.json.simple.JSONObject; + +public class SiteFavouriteTarget implements FavouritesTarget +{ + private Site site; + + public SiteFavouriteTarget(Site site) + { + super(); + this.site = site; + } + + public Site getSite() + { + return site; + } + + @SuppressWarnings("unchecked") + @Override + public JSONObject toJSON() + { + JSONObject favouriteJson = new JSONObject(); + favouriteJson.put("site", getSite().toJSON()); + return favouriteJson; + } + + @Override + public String toString() + { + return "SiteFavouritesTarget [site=" + site + "]"; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof SiteFavouriteTarget); + + SiteFavouriteTarget other = (SiteFavouriteTarget) o; + site.expected(other.getSite()); + } + + public String getTargetGuid() + { + return site.getGuid(); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteImpl.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteImpl.java index 7361ab355d..c622d8eb70 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteImpl.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteImpl.java @@ -1,340 +1,340 @@ -/* - * Copyright (C) 2005-2016 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 . - */ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.alfresco.service.cmr.site.SiteInfo; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class SiteImpl implements Serializable, Site, Comparable, ExpectedComparison -{ - private static final long serialVersionUID = -3774392026234649419L; - - public static final String FIELD_SITE_ID = "siteId"; - public static final String FIELD_CREATED = "created"; - public static final String FIELD_HAS_MEMBERS = "hasMembers"; - - protected Boolean created = false; - protected String networkId; - protected String siteId; - protected String guid; - protected String title; - protected String description; - protected SiteRole role; - protected String visibility; // one of (PUBLIC,MODERATED,PRIVATE), defaults to PUBLIC - protected String type; - - public SiteImpl() - { - } - - public SiteImpl(String title, String visibility) - { - if (title == null) - { - throw new java.lang.IllegalArgumentException(); - } - - if (visibility == null) - { - throw new java.lang.IllegalArgumentException(); - } - this.title = title; - this.visibility = visibility; - } - - public SiteImpl(String networkId, String siteId, String guid) - { - if (siteId == null) - { - throw new java.lang.IllegalArgumentException(); - } - - if (guid == null) - { - throw new java.lang.IllegalArgumentException(); - } - this.networkId = networkId; - this.siteId = siteId; - this.guid = guid; - } - - public SiteImpl(SiteInfo siteInfo, SiteRole siteRole, Boolean created) - { - this.siteId = siteInfo.getShortName(); - this.description = siteInfo.getDescription(); - this.title = siteInfo.getTitle(); - this.visibility = siteInfo.getVisibility().toString(); - this.created = created; - this.guid = siteInfo.getNodeRef().getId(); - } - - public SiteImpl(String networkId, String siteId, String guid, String title, String description, - String visibility, String type, SiteRole siteRole) - { - super(); - this.networkId = networkId; - this.siteId = siteId; - this.title = title; - this.description = description; - this.visibility = visibility; - this.type = type; - this.role = siteRole; - this.guid = guid; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof SiteImpl); - - SiteImpl site = (SiteImpl)o; - - AssertUtil.assertEquals("siteId", getSiteId(), site.getSiteId()); - AssertUtil.assertEquals("guid", getGuid(), site.getGuid()); - AssertUtil.assertEquals("title", getTitle(), site.getTitle()); - AssertUtil.assertEquals("description", getDescription(), site.getDescription()); - AssertUtil.assertEquals("visibility", getVisibility(), site.getVisibility()); - AssertUtil.assertEquals("role", getRole(), site.getRole()); - } - - - public Boolean getCreated() - { - return created; - } - - public String getGuid() - { - return guid; - } - - public String getNetworkId() - { - return networkId; - } - - public Boolean isCreated() - { - return created; - } - - public void setCreated(Boolean created) - { - this.created = created; - } - - public String getSiteId() - { - return siteId; - } - - public String getTitle() - { - return title; - } - - public String getDescription() - { - return description; - } - - public String getVisibility() - { - return visibility; - } - - public String getType() - { - return type; - } - - public void setNetworkId(String networkId) - { - this.networkId = networkId; - } - - public void setSiteId(String siteId) - { - this.siteId = siteId; - } - - public void setGuid(String guid) - { - this.guid = guid; - } - - public void setTitle(String title) - { - this.title = title; - } - - public void setDescription(String description) - { - this.description = description; - } - - public void setVisibility(String visibility) - { - this.visibility = visibility; - } - - public void setType(String type) - { - this.type = type; - } - - public static Site parseSite(JSONObject jsonObject) - { - if (jsonObject == null) - { - return null; - } - - String id = (String)jsonObject.get("id"); - String guid = (String)jsonObject.get("guid"); - String title = (String)jsonObject.get("title"); - String description = (String)jsonObject.get("description"); - String visibility = (String)jsonObject.get("visibility"); - String roleStr = (String)jsonObject.get("role"); - SiteRole role = null; - if(roleStr != null) - { - role = SiteRole.valueOf(roleStr); - } - SiteImpl site = new SiteImpl(null, id, guid, title, description, visibility, "st:site", role); - return site; - } - - public static ListResponse parseSites(JSONObject jsonObject) - { - List sites = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - sites.add(parseSite(entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - - ListResponse resp = new ListResponse(paging, sites); - return resp; - } - - @Override - public SiteRole getRole() - { - return role; - } - - @Override - public String toString() - { - return "Site [created=" + created + ", networkId=" + networkId - + ", siteId=" + siteId + ", guid=" + guid + ", title=" + title - + ", description=" + description + ", role=" + role - + ", visibility=" + visibility + ", type=" + type + "]"; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject siteJson = new JSONObject(); - if (getSiteId() != null) - { - siteJson.put("id", getSiteId()); - } - if (getGuid() != null) - { - siteJson.put("guid", getGuid()); - } - if (getTitle() != null) - { - siteJson.put("title", getTitle()); - } - if (getDescription() != null) - { - siteJson.put("description", getDescription()); - } - if (getVisibility() != null) - { - siteJson.put("visibility", getVisibility()); - } - return siteJson; - } - - @Override - public int compareTo(SiteImpl site) - { - return siteId.compareTo(site.getSiteId()); - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((networkId == null) ? 0 : networkId.hashCode()); - result = prime * result + ((siteId == null) ? 0 : siteId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SiteImpl other = (SiteImpl) obj; - if (networkId == null) - { - if (other.networkId != null) - return false; - } else if (!networkId.equals(other.networkId)) - return false; - if (siteId == null) - { - if (other.siteId != null) - return false; - } else if (!siteId.equals(other.siteId)) - return false; - return true; - } -} +/* + * Copyright (C) 2005-2016 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 . + */ +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.alfresco.service.cmr.site.SiteInfo; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class SiteImpl implements Serializable, Site, Comparable, ExpectedComparison +{ + private static final long serialVersionUID = -3774392026234649419L; + + public static final String FIELD_SITE_ID = "siteId"; + public static final String FIELD_CREATED = "created"; + public static final String FIELD_HAS_MEMBERS = "hasMembers"; + + protected Boolean created = false; + protected String networkId; + protected String siteId; + protected String guid; + protected String title; + protected String description; + protected SiteRole role; + protected String visibility; // one of (PUBLIC,MODERATED,PRIVATE), defaults to PUBLIC + protected String type; + + public SiteImpl() + { + } + + public SiteImpl(String title, String visibility) + { + if (title == null) + { + throw new java.lang.IllegalArgumentException(); + } + + if (visibility == null) + { + throw new java.lang.IllegalArgumentException(); + } + this.title = title; + this.visibility = visibility; + } + + public SiteImpl(String networkId, String siteId, String guid) + { + if (siteId == null) + { + throw new java.lang.IllegalArgumentException(); + } + + if (guid == null) + { + throw new java.lang.IllegalArgumentException(); + } + this.networkId = networkId; + this.siteId = siteId; + this.guid = guid; + } + + public SiteImpl(SiteInfo siteInfo, SiteRole siteRole, Boolean created) + { + this.siteId = siteInfo.getShortName(); + this.description = siteInfo.getDescription(); + this.title = siteInfo.getTitle(); + this.visibility = siteInfo.getVisibility().toString(); + this.created = created; + this.guid = siteInfo.getNodeRef().getId(); + } + + public SiteImpl(String networkId, String siteId, String guid, String title, String description, + String visibility, String type, SiteRole siteRole) + { + super(); + this.networkId = networkId; + this.siteId = siteId; + this.title = title; + this.description = description; + this.visibility = visibility; + this.type = type; + this.role = siteRole; + this.guid = guid; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof SiteImpl); + + SiteImpl site = (SiteImpl)o; + + AssertUtil.assertEquals("siteId", getSiteId(), site.getSiteId()); + AssertUtil.assertEquals("guid", getGuid(), site.getGuid()); + AssertUtil.assertEquals("title", getTitle(), site.getTitle()); + AssertUtil.assertEquals("description", getDescription(), site.getDescription()); + AssertUtil.assertEquals("visibility", getVisibility(), site.getVisibility()); + AssertUtil.assertEquals("role", getRole(), site.getRole()); + } + + + public Boolean getCreated() + { + return created; + } + + public String getGuid() + { + return guid; + } + + public String getNetworkId() + { + return networkId; + } + + public Boolean isCreated() + { + return created; + } + + public void setCreated(Boolean created) + { + this.created = created; + } + + public String getSiteId() + { + return siteId; + } + + public String getTitle() + { + return title; + } + + public String getDescription() + { + return description; + } + + public String getVisibility() + { + return visibility; + } + + public String getType() + { + return type; + } + + public void setNetworkId(String networkId) + { + this.networkId = networkId; + } + + public void setSiteId(String siteId) + { + this.siteId = siteId; + } + + public void setGuid(String guid) + { + this.guid = guid; + } + + public void setTitle(String title) + { + this.title = title; + } + + public void setDescription(String description) + { + this.description = description; + } + + public void setVisibility(String visibility) + { + this.visibility = visibility; + } + + public void setType(String type) + { + this.type = type; + } + + public static Site parseSite(JSONObject jsonObject) + { + if (jsonObject == null) + { + return null; + } + + String id = (String)jsonObject.get("id"); + String guid = (String)jsonObject.get("guid"); + String title = (String)jsonObject.get("title"); + String description = (String)jsonObject.get("description"); + String visibility = (String)jsonObject.get("visibility"); + String roleStr = (String)jsonObject.get("role"); + SiteRole role = null; + if(roleStr != null) + { + role = SiteRole.valueOf(roleStr); + } + SiteImpl site = new SiteImpl(null, id, guid, title, description, visibility, "st:site", role); + return site; + } + + public static ListResponse parseSites(JSONObject jsonObject) + { + List sites = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + sites.add(parseSite(entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + + ListResponse resp = new ListResponse(paging, sites); + return resp; + } + + @Override + public SiteRole getRole() + { + return role; + } + + @Override + public String toString() + { + return "Site [created=" + created + ", networkId=" + networkId + + ", siteId=" + siteId + ", guid=" + guid + ", title=" + title + + ", description=" + description + ", role=" + role + + ", visibility=" + visibility + ", type=" + type + "]"; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject siteJson = new JSONObject(); + if (getSiteId() != null) + { + siteJson.put("id", getSiteId()); + } + if (getGuid() != null) + { + siteJson.put("guid", getGuid()); + } + if (getTitle() != null) + { + siteJson.put("title", getTitle()); + } + if (getDescription() != null) + { + siteJson.put("description", getDescription()); + } + if (getVisibility() != null) + { + siteJson.put("visibility", getVisibility()); + } + return siteJson; + } + + @Override + public int compareTo(SiteImpl site) + { + return siteId.compareTo(site.getSiteId()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((networkId == null) ? 0 : networkId.hashCode()); + result = prime * result + ((siteId == null) ? 0 : siteId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SiteImpl other = (SiteImpl) obj; + if (networkId == null) + { + if (other.networkId != null) + return false; + } else if (!networkId.equals(other.networkId)) + return false; + if (siteId == null) + { + if (other.siteId != null) + return false; + } else if (!siteId.equals(other.siteId)) + return false; + return true; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMember.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMember.java index 8c05d9679a..a3c9b974e7 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMember.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMember.java @@ -1,239 +1,239 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.text.Collator; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class SiteMember implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = 505331886661880389L; - - public static final String FIELD_USERNAME = "username"; - public static final String FIELD_SITE_ID = "siteId"; - public static final String FIELD_STATE = "status.state"; - - private String memberId; - private Person member; - private String siteId; - private String role; - private Status status; - - public SiteMember() - { - } - - public SiteMember(String memberId) - { - this.memberId = memberId; - } - - public SiteMember(String memberId, String role) - { - this.memberId = memberId; - this.role = role; - } - - public SiteMember(String memberId, Person member, String siteId, String role) - { - this.memberId = memberId; - this.member = member; - this.siteId = siteId; - this.role = role; - } - - public String getMemberId() - { - return memberId; - } - - public Person getMember() - { - return member; - } - - public void setMember(Person member) - { - this.member = member; - } - - public void setRole(String role) - { - this.role = role; - } - - public String getSiteId() - { - return siteId; - } - - public void setSiteId(String siteId) - { - this.siteId = siteId; - } - - public Status getStatus() - { - return status; - } - - public void setStatus(Status status) - { - this.status = status; - } - - public String getRole() - { - return role; - } - - @Override - public String toString() - { - return "SiteMember [memberId=" + memberId + ", member=" + member - + ", siteId=" + siteId + ", role=" + role + ", status=" - + status + "]"; - } - - public static SiteMember parseSiteMember(String siteId, JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - String role = (String)jsonObject.get("role"); - JSONObject personJSON = (JSONObject)jsonObject.get("person"); - Person member = Person.parsePerson(personJSON); - SiteMember siteMember = new SiteMember(id, member, siteId, role); - return siteMember; - } - - public static ListResponse parseSiteMembers(String siteId, JSONObject jsonObject) - { - List siteMembers = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - siteMembers.add(parseSiteMember(siteId, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - - ListResponse resp = new ListResponse(paging, siteMembers); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject entry = new JSONObject(); - entry.put("id", getMemberId()); - if(getRole() != null) - { - entry.put("role", getRole()); - } - - return entry; - } - - @SuppressWarnings("unchecked") - public JSONObject postJSON() - { - JSONObject entry = new JSONObject(); - entry.put("id", getMemberId()); - entry.put("role", getRole()); - - return entry; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((memberId == null) ? 0 : memberId.hashCode()); - result = prime * result + ((role == null) ? 0 : role.hashCode()); - result = prime * result + ((siteId == null) ? 0 : siteId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SiteMember other = (SiteMember) obj; - if (memberId == null) { - if (other.memberId != null) - return false; - } else if (!memberId.equals(other.memberId)) - return false; - if (role == null) { - if (other.role != null) - return false; - } else if (!role.equals(other.role)) - return false; - if (siteId == null) { - if (other.siteId != null) - return false; - } else if (!siteId.equals(other.siteId)) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof SiteMember); - - SiteMember other = (SiteMember)o; - - AssertUtil.assertEquals("memberId", memberId, other.getMemberId()); - if(member != null) - { - member.expected(other.getMember()); - } - AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); - AssertUtil.assertEquals("role", role, other.getRole()); - if(status != null) - { - status.expected(other.getStatus()); - } - } - - private Collator collator = Collator.getInstance(); - - @Override - public int compareTo(SiteMember o) - { - String firstName = member.getFirstName(); - String lastName = member.getLastName(); - int ret = collator.compare(lastName, o.getMember().getLastName()); - if(ret == 0) - { - ret = collator.compare(firstName, o.getMember().getFirstName()); - } - if(ret == 0) - { - ret = SiteRole.valueOf(role).compareTo(SiteRole.valueOf(o.getRole())); - } - return ret; - } - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.Collator; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class SiteMember implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = 505331886661880389L; + + public static final String FIELD_USERNAME = "username"; + public static final String FIELD_SITE_ID = "siteId"; + public static final String FIELD_STATE = "status.state"; + + private String memberId; + private Person member; + private String siteId; + private String role; + private Status status; + + public SiteMember() + { + } + + public SiteMember(String memberId) + { + this.memberId = memberId; + } + + public SiteMember(String memberId, String role) + { + this.memberId = memberId; + this.role = role; + } + + public SiteMember(String memberId, Person member, String siteId, String role) + { + this.memberId = memberId; + this.member = member; + this.siteId = siteId; + this.role = role; + } + + public String getMemberId() + { + return memberId; + } + + public Person getMember() + { + return member; + } + + public void setMember(Person member) + { + this.member = member; + } + + public void setRole(String role) + { + this.role = role; + } + + public String getSiteId() + { + return siteId; + } + + public void setSiteId(String siteId) + { + this.siteId = siteId; + } + + public Status getStatus() + { + return status; + } + + public void setStatus(Status status) + { + this.status = status; + } + + public String getRole() + { + return role; + } + + @Override + public String toString() + { + return "SiteMember [memberId=" + memberId + ", member=" + member + + ", siteId=" + siteId + ", role=" + role + ", status=" + + status + "]"; + } + + public static SiteMember parseSiteMember(String siteId, JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + String role = (String)jsonObject.get("role"); + JSONObject personJSON = (JSONObject)jsonObject.get("person"); + Person member = Person.parsePerson(personJSON); + SiteMember siteMember = new SiteMember(id, member, siteId, role); + return siteMember; + } + + public static ListResponse parseSiteMembers(String siteId, JSONObject jsonObject) + { + List siteMembers = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + siteMembers.add(parseSiteMember(siteId, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + + ListResponse resp = new ListResponse(paging, siteMembers); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject entry = new JSONObject(); + entry.put("id", getMemberId()); + if(getRole() != null) + { + entry.put("role", getRole()); + } + + return entry; + } + + @SuppressWarnings("unchecked") + public JSONObject postJSON() + { + JSONObject entry = new JSONObject(); + entry.put("id", getMemberId()); + entry.put("role", getRole()); + + return entry; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((memberId == null) ? 0 : memberId.hashCode()); + result = prime * result + ((role == null) ? 0 : role.hashCode()); + result = prime * result + ((siteId == null) ? 0 : siteId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SiteMember other = (SiteMember) obj; + if (memberId == null) { + if (other.memberId != null) + return false; + } else if (!memberId.equals(other.memberId)) + return false; + if (role == null) { + if (other.role != null) + return false; + } else if (!role.equals(other.role)) + return false; + if (siteId == null) { + if (other.siteId != null) + return false; + } else if (!siteId.equals(other.siteId)) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof SiteMember); + + SiteMember other = (SiteMember)o; + + AssertUtil.assertEquals("memberId", memberId, other.getMemberId()); + if(member != null) + { + member.expected(other.getMember()); + } + AssertUtil.assertEquals("siteId", siteId, other.getSiteId()); + AssertUtil.assertEquals("role", role, other.getRole()); + if(status != null) + { + status.expected(other.getStatus()); + } + } + + private Collator collator = Collator.getInstance(); + + @Override + public int compareTo(SiteMember o) + { + String firstName = member.getFirstName(); + String lastName = member.getLastName(); + int ret = collator.compare(lastName, o.getMember().getLastName()); + if(ret == 0) + { + ret = collator.compare(firstName, o.getMember().getFirstName()); + } + if(ret == 0) + { + ret = SiteRole.valueOf(role).compareTo(SiteRole.valueOf(o.getRole())); + } + return ret; + } + +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMembershipRequest.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMembershipRequest.java index 49282f66ee..291d9301e0 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMembershipRequest.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteMembershipRequest.java @@ -1,222 +1,222 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.text.Collator; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.alfresco.rest.api.tests.PublicApiDateFormat; -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class SiteMembershipRequest implements ExpectedComparison, Comparable -{ - private Collator collator = Collator.getInstance(); - - private String id; // site id - private String message; - private Date createdAt; - private Date modifiedAt; - private String title; - private Site site; - - public SiteMembershipRequest() - { - } - - public String getTitle() - { - return title; - } - - public void setTitle(String title) - { - this.title = title; - } - - public String getId() - { - return id; - } - - public void setId(String id) - { - this.id = id; - } - - public Site getSite() - { - return site; - } - - public void setSite(Site site) - { - this.site = site; - } - - public Date getCreatedAt() - { - return createdAt; - } - - public void setCreatedAt(Date createdAt) - { - this.createdAt = createdAt; - } - - public Date getModifiedAt() - { - return modifiedAt; - } - - public void setModifiedAt(Date modifiedAt) - { - this.modifiedAt = modifiedAt; - } - - public String getMessage() - { - return message; - } - - public void setMessage(String message) - { - this.message = message; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject siteMembershipRequestJson = new JSONObject(); - siteMembershipRequestJson.put("id", getId()); - siteMembershipRequestJson.put("message", getMessage()); - return siteMembershipRequestJson; - } - - public static SiteMembershipRequest parseSiteMembershipRequest(String username, JSONObject jsonObject) throws ParseException - { - String id = (String)jsonObject.get("id"); - String createdAt = (String)jsonObject.get("createdAt"); - String message = (String)jsonObject.get("message"); - String modifiedAt = (String)jsonObject.get("modifiedAt"); - JSONObject siteJSON = (JSONObject)jsonObject.get("site"); - - SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); - siteMembershipRequest.setId(id); - siteMembershipRequest.setCreatedAt(PublicApiDateFormat.getDateFormat().parse(createdAt)); - siteMembershipRequest.setMessage(message); - if(modifiedAt != null) - { - siteMembershipRequest.setModifiedAt(PublicApiDateFormat.getDateFormat().parse(modifiedAt)); - } - if(siteJSON != null) - { - Site site = SiteImpl.parseSite(siteJSON); - siteMembershipRequest.setSite(site); - } - - return siteMembershipRequest; - } - - public static ListResponse parseSiteMembershipRequests(String username, JSONObject jsonObject) throws ParseException - { - List siteMembershipRequests = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - siteMembershipRequests.add(SiteMembershipRequest.parseSiteMembershipRequest(username, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - return new ListResponse(paging, siteMembershipRequests); - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof SiteMembershipRequest); - - SiteMembershipRequest other = (SiteMembershipRequest)o; - - assertNotNull(other.getCreatedAt()); - - if(other.getModifiedAt() != null) - { - assertFalse(other.getModifiedAt().before(other.getCreatedAt())); - } - - if(modifiedAt != null) - { - // check that the modifiedAt is higher in the RHS - assertFalse(other.getModifiedAt().before(modifiedAt)); - } - - if(createdAt != null) - { - AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); - } - - AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); - // ignore case when comparing site (membership request) id - AssertUtil.assertEquals("id", id.toLowerCase(), other.getId().toLowerCase()); - AssertUtil.assertEquals("message", message, other.getMessage()); - } - - @Override - public String toString() - { - return "SiteMembershipRequest [id=" + id + ", message=" + message - + ", createdAt=" + createdAt + ", modifiedAt=" + modifiedAt - + ", title=" + title + "]"; - } - - @Override - public int compareTo(SiteMembershipRequest o) - { - int ret = collator.compare(site.getTitle(), o.getSite().getTitle()); - return ret; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SiteMembershipRequest other = (SiteMembershipRequest) obj; - if (id == null) - { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.text.Collator; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.alfresco.rest.api.tests.PublicApiDateFormat; +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class SiteMembershipRequest implements ExpectedComparison, Comparable +{ + private Collator collator = Collator.getInstance(); + + private String id; // site id + private String message; + private Date createdAt; + private Date modifiedAt; + private String title; + private Site site; + + public SiteMembershipRequest() + { + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Site getSite() + { + return site; + } + + public void setSite(Site site) + { + this.site = site; + } + + public Date getCreatedAt() + { + return createdAt; + } + + public void setCreatedAt(Date createdAt) + { + this.createdAt = createdAt; + } + + public Date getModifiedAt() + { + return modifiedAt; + } + + public void setModifiedAt(Date modifiedAt) + { + this.modifiedAt = modifiedAt; + } + + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject siteMembershipRequestJson = new JSONObject(); + siteMembershipRequestJson.put("id", getId()); + siteMembershipRequestJson.put("message", getMessage()); + return siteMembershipRequestJson; + } + + public static SiteMembershipRequest parseSiteMembershipRequest(String username, JSONObject jsonObject) throws ParseException + { + String id = (String)jsonObject.get("id"); + String createdAt = (String)jsonObject.get("createdAt"); + String message = (String)jsonObject.get("message"); + String modifiedAt = (String)jsonObject.get("modifiedAt"); + JSONObject siteJSON = (JSONObject)jsonObject.get("site"); + + SiteMembershipRequest siteMembershipRequest = new SiteMembershipRequest(); + siteMembershipRequest.setId(id); + siteMembershipRequest.setCreatedAt(PublicApiDateFormat.getDateFormat().parse(createdAt)); + siteMembershipRequest.setMessage(message); + if(modifiedAt != null) + { + siteMembershipRequest.setModifiedAt(PublicApiDateFormat.getDateFormat().parse(modifiedAt)); + } + if(siteJSON != null) + { + Site site = SiteImpl.parseSite(siteJSON); + siteMembershipRequest.setSite(site); + } + + return siteMembershipRequest; + } + + public static ListResponse parseSiteMembershipRequests(String username, JSONObject jsonObject) throws ParseException + { + List siteMembershipRequests = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + siteMembershipRequests.add(SiteMembershipRequest.parseSiteMembershipRequest(username, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + return new ListResponse(paging, siteMembershipRequests); + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof SiteMembershipRequest); + + SiteMembershipRequest other = (SiteMembershipRequest)o; + + assertNotNull(other.getCreatedAt()); + + if(other.getModifiedAt() != null) + { + assertFalse(other.getModifiedAt().before(other.getCreatedAt())); + } + + if(modifiedAt != null) + { + // check that the modifiedAt is higher in the RHS + assertFalse(other.getModifiedAt().before(modifiedAt)); + } + + if(createdAt != null) + { + AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); + } + + AssertUtil.assertEquals("createdAt", createdAt, other.getCreatedAt()); + // ignore case when comparing site (membership request) id + AssertUtil.assertEquals("id", id.toLowerCase(), other.getId().toLowerCase()); + AssertUtil.assertEquals("message", message, other.getMessage()); + } + + @Override + public String toString() + { + return "SiteMembershipRequest [id=" + id + ", message=" + message + + ", createdAt=" + createdAt + ", modifiedAt=" + modifiedAt + + ", title=" + title + "]"; + } + + @Override + public int compareTo(SiteMembershipRequest o) + { + int ret = collator.compare(site.getTitle(), o.getSite().getTitle()); + return ret; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SiteMembershipRequest other = (SiteMembershipRequest) obj; + if (id == null) + { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteRole.java b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteRole.java index 37272d4165..4e91ea6f73 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/SiteRole.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/SiteRole.java @@ -1,7 +1,7 @@ -package org.alfresco.rest.api.tests.client.data; - -public enum SiteRole -{ - // note: lexical ordering - SiteCollaborator, SiteConsumer, SiteContributor, SiteManager; -} +package org.alfresco.rest.api.tests.client.data; + +public enum SiteRole +{ + // note: lexical ordering + SiteCollaborator, SiteConsumer, SiteContributor, SiteManager; +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Status.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Status.java index c21b8aac6d..8d335c9d5f 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Status.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Status.java @@ -1,89 +1,89 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; - -public class Status implements Serializable, ExpectedComparison -{ - private static final long serialVersionUID = 7187248670785910438L; - - public static enum State - { - OK, ERROR; - }; - - private State state; - private String error; - - public Status(State state) - { - this.state = state; - } - - public Status(String error) - { - this.state = State.ERROR; - this.error = error; - } - - public static long getSerialversionuid() { - return serialVersionUID; - } - - public State getState() - { - return state; - } - - public String getError() - { - return error; - } - - @Override - public String toString() - { - return "Status [state=" + state + ", error=" + error + "]"; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((error == null) ? 0 : error.hashCode()); - result = prime * result + ((state == null) ? 0 : state.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Status other = (Status) obj; - if (error == null) { - if (other.error != null) - return false; - } else if (!error.equals(other.error)) - return false; - if (state != other.state) - return false; - return true; - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Status); - - Status other = (Status)o; - AssertUtil.assertEquals("state", state, other.getState()); - AssertUtil.assertEquals("error", error, other.getError()); - } -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; + +public class Status implements Serializable, ExpectedComparison +{ + private static final long serialVersionUID = 7187248670785910438L; + + public static enum State + { + OK, ERROR; + }; + + private State state; + private String error; + + public Status(State state) + { + this.state = state; + } + + public Status(String error) + { + this.state = State.ERROR; + this.error = error; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public State getState() + { + return state; + } + + public String getError() + { + return error; + } + + @Override + public String toString() + { + return "Status [state=" + state + ", error=" + error + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((error == null) ? 0 : error.hashCode()); + result = prime * result + ((state == null) ? 0 : state.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Status other = (Status) obj; + if (error == null) { + if (other.error != null) + return false; + } else if (!error.equals(other.error)) + return false; + if (state != other.state) + return false; + return true; + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Status); + + Status other = (Status)o; + AssertUtil.assertEquals("state", state, other.getState()); + AssertUtil.assertEquals("error", error, other.getError()); + } +} diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Tag.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Tag.java index 43b99e69c5..e67a10d18f 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/data/Tag.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Tag.java @@ -1,163 +1,163 @@ -package org.alfresco.rest.api.tests.client.data; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; -import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -public class Tag implements Serializable, ExpectedComparison, Comparable -{ - private static final long serialVersionUID = -5730063374759199632L; - - private String nodeId; - private String id; - private String tag; - - public Tag(String tag) - { - super(); - this.tag = tag; - } - - public Tag(String id, String tag) - { - super(); - this.id = id; - this.tag = tag; - } - - public Tag(String nodeId, String id, String tag) - { - super(); - this.nodeId = nodeId; - this.id = id; - this.tag = tag; - } - - public void setTag(String tag) - { - this.tag = tag; - } - - public String getNodeId() - { - return nodeId; - } - - public void setNodeId(String nodeId) - { - this.nodeId = nodeId; - } - - public void setId(String id) - { - this.id = id; - } - - public String getId() - { - return id; - } - - public String getTag() - { - return tag; - } - - @Override - public String toString() - { - return "Tag [nodeId=" + nodeId + ", id=" + id + ", tag=" + tag - + "]"; - } - - public static Tag parseTag(String nodeId, JSONObject jsonObject) - { - String id = (String)jsonObject.get("id"); - String value = (String)jsonObject.get("tag"); - Tag tag = new Tag(nodeId, id, value); - return tag; - } - - public static ListResponse parseTags(String nodeId, JSONObject jsonObject) - { - List tags = new ArrayList(); - - JSONObject jsonList = (JSONObject)jsonObject.get("list"); - assertNotNull(jsonList); - - JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); - assertNotNull(jsonEntries); - - for(int i = 0; i < jsonEntries.size(); i++) - { - JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); - JSONObject entry = (JSONObject)jsonEntry.get("entry"); - tags.add(parseTag(nodeId, entry)); - } - - ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); - ListResponse resp = new ListResponse(paging, tags); - return resp; - } - - @SuppressWarnings("unchecked") - public JSONObject toJSON() - { - JSONObject entry = new JSONObject(); -// entry.put("id", getId()); - entry.put("tag", getTag()); - return entry; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Tag other = (Tag) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - @Override - public int compareTo(Tag o) - { - return tag.compareTo(o.getTag()); - } - - @Override - public void expected(Object o) - { - assertTrue(o instanceof Tag); - - Tag other = (Tag)o; - - AssertUtil.assertEquals("id", id, other.getId()); - // case insensitive comparison - AssertUtil.assertEquals("tag", tag.toUpperCase(), other.getTag().toUpperCase()); - } - -} +package org.alfresco.rest.api.tests.client.data; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging; +import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +public class Tag implements Serializable, ExpectedComparison, Comparable +{ + private static final long serialVersionUID = -5730063374759199632L; + + private String nodeId; + private String id; + private String tag; + + public Tag(String tag) + { + super(); + this.tag = tag; + } + + public Tag(String id, String tag) + { + super(); + this.id = id; + this.tag = tag; + } + + public Tag(String nodeId, String id, String tag) + { + super(); + this.nodeId = nodeId; + this.id = id; + this.tag = tag; + } + + public void setTag(String tag) + { + this.tag = tag; + } + + public String getNodeId() + { + return nodeId; + } + + public void setNodeId(String nodeId) + { + this.nodeId = nodeId; + } + + public void setId(String id) + { + this.id = id; + } + + public String getId() + { + return id; + } + + public String getTag() + { + return tag; + } + + @Override + public String toString() + { + return "Tag [nodeId=" + nodeId + ", id=" + id + ", tag=" + tag + + "]"; + } + + public static Tag parseTag(String nodeId, JSONObject jsonObject) + { + String id = (String)jsonObject.get("id"); + String value = (String)jsonObject.get("tag"); + Tag tag = new Tag(nodeId, id, value); + return tag; + } + + public static ListResponse parseTags(String nodeId, JSONObject jsonObject) + { + List tags = new ArrayList(); + + JSONObject jsonList = (JSONObject)jsonObject.get("list"); + assertNotNull(jsonList); + + JSONArray jsonEntries = (JSONArray)jsonList.get("entries"); + assertNotNull(jsonEntries); + + for(int i = 0; i < jsonEntries.size(); i++) + { + JSONObject jsonEntry = (JSONObject)jsonEntries.get(i); + JSONObject entry = (JSONObject)jsonEntry.get("entry"); + tags.add(parseTag(nodeId, entry)); + } + + ExpectedPaging paging = ExpectedPaging.parsePagination(jsonList); + ListResponse resp = new ListResponse(paging, tags); + return resp; + } + + @SuppressWarnings("unchecked") + public JSONObject toJSON() + { + JSONObject entry = new JSONObject(); +// entry.put("id", getId()); + entry.put("tag", getTag()); + return entry; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Tag other = (Tag) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public int compareTo(Tag o) + { + return tag.compareTo(o.getTag()); + } + + @Override + public void expected(Object o) + { + assertTrue(o instanceof Tag); + + Tag other = (Tag)o; + + AssertUtil.assertEquals("id", id, other.getId()); + // case insensitive comparison + AssertUtil.assertEquals("tag", tag.toUpperCase(), other.getTag().toUpperCase()); + } + +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/CameraShyFlocket.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/CameraShyFlocket.java index 5211bfa141..edfeda4752 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/CameraShyFlocket.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/CameraShyFlocket.java @@ -1,30 +1,30 @@ -package org.alfresco.rest.framework.tests.api.mocks3; - -import org.alfresco.rest.framework.resource.content.BinaryProperty; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.codehaus.jackson.annotate.JsonIgnore; - -/** - * A small Flock that doesn't want to have a Photo. - * - * @author Gethinjames - */ -public class CameraShyFlocket extends Flocket -{ - - @Override - @JsonIgnore - public BinaryProperty getPhoto() - { - return super.getPhoto(); - } - - @Override - @JsonIgnore - public CollectionWithPagingInfo getPhotoAlbum() - { - return super.getPhotoAlbum(); - } - - -} +package org.alfresco.rest.framework.tests.api.mocks3; + +import org.alfresco.rest.framework.resource.content.BinaryProperty; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.codehaus.jackson.annotate.JsonIgnore; + +/** + * A small Flock that doesn't want to have a Photo. + * + * @author Gethinjames + */ +public class CameraShyFlocket extends Flocket +{ + + @Override + @JsonIgnore + public BinaryProperty getPhoto() + { + return super.getPhoto(); + } + + @Override + @JsonIgnore + public CollectionWithPagingInfo getPhotoAlbum() + { + return super.getPhotoAlbum(); + } + + +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flock.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flock.java index 327228fa28..39b33058bc 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flock.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flock.java @@ -1,65 +1,65 @@ -package org.alfresco.rest.framework.tests.api.mocks3; - -import java.util.List; - -import org.alfresco.rest.framework.resource.UniqueId; -import org.alfresco.rest.framework.resource.content.BinaryProperty; -import org.alfresco.rest.framework.tests.api.mocks.Sheep; -/* - * A Flock of Sheep - */ -public class Flock -{ - String name; - int quantity = 25; - List sheep; - BinaryProperty photo; - - public Flock() - { - super(); - } - - public Flock(String name, int quantity, List sheep, BinaryProperty photo) - { - super(); - this.name = name; - this.quantity = quantity; - this.sheep = sheep; - this.photo = photo; - } - - @UniqueId - public String getName() - { - return this.name; - } - public void setName(String name) - { - this.name = name; - } - public int getQuantity() - { - return this.quantity; - } - public void setQuantity(int quantity) - { - this.quantity = quantity; - } - public List getSheep() - { - return this.sheep; - } - public void setSheep(List sheep) - { - this.sheep = sheep; - } - public BinaryProperty getPhoto() - { - return this.photo; - } - public void setPhoto(BinaryProperty photo) - { - this.photo = photo; - } -} +package org.alfresco.rest.framework.tests.api.mocks3; + +import java.util.List; + +import org.alfresco.rest.framework.resource.UniqueId; +import org.alfresco.rest.framework.resource.content.BinaryProperty; +import org.alfresco.rest.framework.tests.api.mocks.Sheep; +/* + * A Flock of Sheep + */ +public class Flock +{ + String name; + int quantity = 25; + List sheep; + BinaryProperty photo; + + public Flock() + { + super(); + } + + public Flock(String name, int quantity, List sheep, BinaryProperty photo) + { + super(); + this.name = name; + this.quantity = quantity; + this.sheep = sheep; + this.photo = photo; + } + + @UniqueId + public String getName() + { + return this.name; + } + public void setName(String name) + { + this.name = name; + } + public int getQuantity() + { + return this.quantity; + } + public void setQuantity(int quantity) + { + this.quantity = quantity; + } + public List getSheep() + { + return this.sheep; + } + public void setSheep(List sheep) + { + this.sheep = sheep; + } + public BinaryProperty getPhoto() + { + return this.photo; + } + public void setPhoto(BinaryProperty photo) + { + this.photo = photo; + } +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java index 89990da100..693190111c 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java @@ -1,50 +1,50 @@ -package org.alfresco.rest.framework.tests.api.mocks3; - -import java.io.File; -import java.io.InputStream; - -import org.alfresco.rest.framework.BinaryProperties; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.content.FileBinaryResource; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.util.TempFileProvider; -import org.springframework.extensions.webscripts.Status; - -@EntityResource(name="flock",title="A resource used for testing binary properties") -public class FlockEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update -{ - - //versions/1/flock/xyz/photo PUT - @Override - @WebApiDescription(title = "Updates a photo") - @BinaryProperties("photo") - public Flock updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) - { - return null; - } - - //versions/1/flock/xyz/photo DELETE - @Override - @WebApiDescription(title = "Deletes a photo") - @BinaryProperties("photo") - public void deleteProperty(String entityId, Parameters parameters) - { - } - - //versions/1/flock/xyz/photo GET - @Override - @WebApiDescription(title = "Reads a photo as a Stream", successStatus = Status.STATUS_FOUND) - @BinaryProperties("photo") - public BinaryResource readProperty(String entityId, Parameters parameters) throws EntityNotFoundException - { - - File file = TempFileProvider.createTempFile("doesn't matter", ".txt"); - return new FileBinaryResource(file); - } - -} +package org.alfresco.rest.framework.tests.api.mocks3; + +import java.io.File; +import java.io.InputStream; + +import org.alfresco.rest.framework.BinaryProperties; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.content.FileBinaryResource; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.util.TempFileProvider; +import org.springframework.extensions.webscripts.Status; + +@EntityResource(name="flock",title="A resource used for testing binary properties") +public class FlockEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update +{ + + //versions/1/flock/xyz/photo PUT + @Override + @WebApiDescription(title = "Updates a photo") + @BinaryProperties("photo") + public Flock updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) + { + return null; + } + + //versions/1/flock/xyz/photo DELETE + @Override + @WebApiDescription(title = "Deletes a photo") + @BinaryProperties("photo") + public void deleteProperty(String entityId, Parameters parameters) + { + } + + //versions/1/flock/xyz/photo GET + @Override + @WebApiDescription(title = "Reads a photo as a Stream", successStatus = Status.STATUS_FOUND) + @BinaryProperties("photo") + public BinaryResource readProperty(String entityId, Parameters parameters) throws EntityNotFoundException + { + + File file = TempFileProvider.createTempFile("doesn't matter", ".txt"); + return new FileBinaryResource(file); + } + +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flocket.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flocket.java index 8048cdd8f2..579e12c664 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flocket.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/Flocket.java @@ -1,32 +1,32 @@ -package org.alfresco.rest.framework.tests.api.mocks3; - -import org.alfresco.rest.framework.resource.content.BinaryProperty; -import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * A small Flock - * - * @author Gethinjames - */ -public class Flocket extends Flock -{ - @JsonProperty (value="album") - CollectionWithPagingInfo photoAlbum; - - public Flocket() - { - super(); - setQuantity(6); - } - - public CollectionWithPagingInfo getPhotoAlbum() - { - return this.photoAlbum; - } - - public void setPhotoAlbum(CollectionWithPagingInfo photoAlbum) - { - this.photoAlbum = photoAlbum; - } -} +package org.alfresco.rest.framework.tests.api.mocks3; + +import org.alfresco.rest.framework.resource.content.BinaryProperty; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * A small Flock + * + * @author Gethinjames + */ +public class Flocket extends Flock +{ + @JsonProperty (value="album") + CollectionWithPagingInfo photoAlbum; + + public Flocket() + { + super(); + setQuantity(6); + } + + public CollectionWithPagingInfo getPhotoAlbum() + { + return this.photoAlbum; + } + + public void setPhotoAlbum(CollectionWithPagingInfo photoAlbum) + { + this.photoAlbum = photoAlbum; + } +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java index 4c6f8f30d1..450d44da19 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java @@ -1,41 +1,41 @@ -package org.alfresco.rest.framework.tests.api.mocks3; - -import java.io.InputStream; - -import org.alfresco.rest.framework.BinaryProperties; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.parameters.Parameters; - -@EntityResource(name="flocket",title="A resource used for testing binary properties with lost of properties") -public class FlocketEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update -{ - - @Override - @WebApiDescription(title = "Updates a flocket") - @BinaryProperties({"photo","album"}) - public Flocket updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) - { - return null; - } - - @Override - @WebApiDescription(title = "Deletes a photo") - @BinaryProperties("photo") - public void deleteProperty(String entityId, Parameters parameters) - { - } - - @Override - @WebApiDescription(title = "Reads a photo as a Stream") - @BinaryProperties({"photo","album", "madeUpProp"}) - public BinaryResource readProperty(String entityId, Parameters parameters) throws EntityNotFoundException - { - return null; - } - -} +package org.alfresco.rest.framework.tests.api.mocks3; + +import java.io.InputStream; + +import org.alfresco.rest.framework.BinaryProperties; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.parameters.Parameters; + +@EntityResource(name="flocket",title="A resource used for testing binary properties with lost of properties") +public class FlocketEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update +{ + + @Override + @WebApiDescription(title = "Updates a flocket") + @BinaryProperties({"photo","album"}) + public Flocket updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) + { + return null; + } + + @Override + @WebApiDescription(title = "Deletes a photo") + @BinaryProperties("photo") + public void deleteProperty(String entityId, Parameters parameters) + { + } + + @Override + @WebApiDescription(title = "Reads a photo as a Stream") + @BinaryProperties({"photo","album", "madeUpProp"}) + public BinaryResource readProperty(String entityId, Parameters parameters) throws EntityNotFoundException + { + return null; + } + +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/ExceptionResolverTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/ExceptionResolverTests.java index 241d8556ac..b6ccba8cca 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/ExceptionResolverTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/ExceptionResolverTests.java @@ -1,100 +1,100 @@ -package org.alfresco.rest.framework.tests.core; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.alfresco.repo.forms.FormNotFoundException; -import org.alfresco.repo.node.integrity.IntegrityException; -import org.alfresco.rest.framework.core.exceptions.ApiException; -import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; -import org.alfresco.rest.framework.core.exceptions.DeletedResourceException; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.core.exceptions.ErrorResponse; -import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException; -import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; -import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; -import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; -import org.alfresco.rest.framework.core.exceptions.StaleEntityException; -import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; -import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException; -import org.alfresco.rest.framework.tools.ApiAssistant; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import javax.servlet.http.HttpServletResponse; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "classpath:test-rest-context.xml" }) -public class ExceptionResolverTests -{ - @Autowired - ApiAssistant assistant; - - @Test - public void testWebscriptException() - { - ErrorResponse response = assistant.resolveException(new WebScriptException(null)); - assertNotNull(response); - assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR - - response = assistant.resolveException(new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed for Web Script ")); - assertNotNull(response); - assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR - } - - //04180006 Authentication failed for Web Script org/alfresco/api/ResourceWebScript.get - @Test - public void testMatchException() - { - ErrorResponse response = assistant.resolveException(new ApiException(null)); - assertNotNull(response); - assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR - - response = assistant.resolveException(new InvalidArgumentException(null)); - assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST - - response = assistant.resolveException(new InvalidQueryException(null)); - assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST - - response = assistant.resolveException(new NotFoundException(null)); - assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND - - response = assistant.resolveException(new EntityNotFoundException(null)); - assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND - - response = assistant.resolveException(new RelationshipResourceNotFoundException(null, null)); - assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND - - response = assistant.resolveException(new PermissionDeniedException(null)); - assertEquals(403, response.getStatusCode()); //default to STATUS_FORBIDDEN - - response = assistant.resolveException(new UnsupportedResourceOperationException(null)); - assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED - - response = assistant.resolveException(new DeletedResourceException(null)); - assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED - - response = assistant.resolveException(new ConstraintViolatedException(null)); - assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT - - response = assistant.resolveException(new StaleEntityException(null)); - assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT - - //Try a random exception - response = assistant.resolveException(new FormNotFoundException(null)); - assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR - - response = assistant.resolveException(new InsufficientStorageException(null)); - assertEquals(507, response.getStatusCode()); - - response = assistant.resolveException(new IntegrityException(null)); - assertEquals(422, response.getStatusCode()); - - } -} +package org.alfresco.rest.framework.tests.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.alfresco.repo.forms.FormNotFoundException; +import org.alfresco.repo.node.integrity.IntegrityException; +import org.alfresco.rest.framework.core.exceptions.ApiException; +import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; +import org.alfresco.rest.framework.core.exceptions.DeletedResourceException; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.core.exceptions.ErrorResponse; +import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.core.exceptions.NotFoundException; +import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; +import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; +import org.alfresco.rest.framework.core.exceptions.StaleEntityException; +import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; +import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException; +import org.alfresco.rest.framework.tools.ApiAssistant; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.servlet.http.HttpServletResponse; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-rest-context.xml" }) +public class ExceptionResolverTests +{ + @Autowired + ApiAssistant assistant; + + @Test + public void testWebscriptException() + { + ErrorResponse response = assistant.resolveException(new WebScriptException(null)); + assertNotNull(response); + assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR + + response = assistant.resolveException(new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed for Web Script ")); + assertNotNull(response); + assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR + } + + //04180006 Authentication failed for Web Script org/alfresco/api/ResourceWebScript.get + @Test + public void testMatchException() + { + ErrorResponse response = assistant.resolveException(new ApiException(null)); + assertNotNull(response); + assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR + + response = assistant.resolveException(new InvalidArgumentException(null)); + assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST + + response = assistant.resolveException(new InvalidQueryException(null)); + assertEquals(400, response.getStatusCode()); //default to STATUS_BAD_REQUEST + + response = assistant.resolveException(new NotFoundException(null)); + assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND + + response = assistant.resolveException(new EntityNotFoundException(null)); + assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND + + response = assistant.resolveException(new RelationshipResourceNotFoundException(null, null)); + assertEquals(404, response.getStatusCode()); //default to STATUS_NOT_FOUND + + response = assistant.resolveException(new PermissionDeniedException(null)); + assertEquals(403, response.getStatusCode()); //default to STATUS_FORBIDDEN + + response = assistant.resolveException(new UnsupportedResourceOperationException(null)); + assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED + + response = assistant.resolveException(new DeletedResourceException(null)); + assertEquals(405, response.getStatusCode()); //default to STATUS_METHOD_NOT_ALLOWED + + response = assistant.resolveException(new ConstraintViolatedException(null)); + assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT + + response = assistant.resolveException(new StaleEntityException(null)); + assertEquals(409, response.getStatusCode()); //default to STATUS_CONFLICT + + //Try a random exception + response = assistant.resolveException(new FormNotFoundException(null)); + assertEquals(500, response.getStatusCode()); //default to INTERNAL_SERVER_ERROR + + response = assistant.resolveException(new InsufficientStorageException(null)); + assertEquals(507, response.getStatusCode()); + + response = assistant.resolveException(new IntegrityException(null)); + assertEquals(422, response.getStatusCode()); + + } +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/ParamsExtender.java b/source/test-java/org/alfresco/rest/framework/tests/core/ParamsExtender.java index 08e280c467..2b17626493 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/core/ParamsExtender.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/ParamsExtender.java @@ -1,46 +1,46 @@ -package org.alfresco.rest.framework.tests.core; - -import static org.mockito.Mockito.mock; - -import java.io.InputStream; -import java.util.Map; - -import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; -import org.alfresco.rest.framework.resource.parameters.Paging; -import org.alfresco.rest.framework.resource.parameters.Params; -import org.springframework.extensions.webscripts.WebScriptRequest; - -/** - * Just extends the Params class for testing purposes - * - * @author Gethin James - */ -public class ParamsExtender extends Params -{ - - private ParamsExtender(String entityId, String relationshipId, Object passedIn, InputStream stream, String addressedProperty, RecognizedParams recognizedParams) - { - super(entityId, relationshipId, passedIn, stream, addressedProperty, recognizedParams, null, mock(WebScriptRequest.class)); - } - - public static Params valueOf(Map rFilter, String entityId) - { - return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, null, null, rFilter, null, null, null, null, false)); - } - - public static Params valueOf(boolean includeSource, String entityId) - { - return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, null, null, null, null, null, null, null, includeSource)); - } - - public static Params valueOf(Paging paging, String entityId) - { - return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, paging, null, null, null, null, null, null, false)); - } - - public static Params valueOf(Map params) - { - return new ParamsExtender(null, null, null, null, null, new Params.RecognizedParams(params, null, null, null, null, null, null, null, false)); - } - -} +package org.alfresco.rest.framework.tests.core; + +import static org.mockito.Mockito.mock; + +import java.io.InputStream; +import java.util.Map; + +import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * Just extends the Params class for testing purposes + * + * @author Gethin James + */ +public class ParamsExtender extends Params +{ + + private ParamsExtender(String entityId, String relationshipId, Object passedIn, InputStream stream, String addressedProperty, RecognizedParams recognizedParams) + { + super(entityId, relationshipId, passedIn, stream, addressedProperty, recognizedParams, null, mock(WebScriptRequest.class)); + } + + public static Params valueOf(Map rFilter, String entityId) + { + return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, null, null, rFilter, null, null, null, null, false)); + } + + public static Params valueOf(boolean includeSource, String entityId) + { + return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, null, null, null, null, null, null, null, includeSource)); + } + + public static Params valueOf(Paging paging, String entityId) + { + return new ParamsExtender(entityId, null, null, null, null, new Params.RecognizedParams(null, paging, null, null, null, null, null, null, false)); + } + + public static Params valueOf(Map params) + { + return new ParamsExtender(null, null, null, null, null, new Params.RecognizedParams(params, null, null, null, null, null, null, null, false)); + } + +}