diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index bc21b1d21b..4d3b6227ea 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -861,6 +861,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/templates/publicapi/org/alfresco/api/DiscoveryApiWebscript.get.desc.xml b/config/alfresco/templates/publicapi/org/alfresco/api/DiscoveryApiWebscript.get.desc.xml
new file mode 100644
index 0000000000..bcadf83ba9
--- /dev/null
+++ b/config/alfresco/templates/publicapi/org/alfresco/api/DiscoveryApiWebscript.get.desc.xml
@@ -0,0 +1,10 @@
+
+
+ Handles GET for the Discovery api
+ Returns repository information
+ /discovery
+ user
+ required
+ argument
+ public_api
+
\ No newline at end of file
diff --git a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java
index 35b6c5adfd..c264769ce7 100644
--- a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java
+++ b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRequest.java
@@ -1,28 +1,28 @@
-/*
- * #%L
- * Alfresco Remote API
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * 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 .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
package org.alfresco.rest.api;
import javax.servlet.http.HttpServletRequest;
@@ -35,42 +35,49 @@ 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);
- }
+ public static final String NETWORKS_PATH = "networks";
+ public static final String NETWORK_PATH = "network";
- @Override
+ 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;
+ // no tenant - "index" request
+ tenant = TenantUtil.DEFAULT_TENANT;
pathInfo = NETWORKS_PATH;
}
+ else if (realPathInfo.equals("/discovery"))
+ {
+ // The '/discovery' API is special and doesn't need network info, however,
+ // we set the tenant to default, to satisfy PublicApiTenantAuthentication logic.
+ tenant = TenantUtil.DEFAULT_TENANT;
+ pathInfo = realPathInfo;
+ }
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;
+ // 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
- {
+ }
+ else
+ {
int idx = realPathInfo.indexOf('/', 1);
- // remove tenant
- tenant = realPathInfo.substring(1, idx == -1 ? realPathInfo.length() : idx);
- pathInfo = realPathInfo.substring(tenant.length() + 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 667fbc5eb0..8df1321ea1 100644
--- a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java
+++ b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java
@@ -1,28 +1,28 @@
-/*
- * #%L
- * Alfresco Remote API
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * 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 .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
package org.alfresco.rest.api;
import java.io.IOException;
@@ -44,12 +44,12 @@ public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServl
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);
+ 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()
@@ -81,27 +81,27 @@ public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServl
// 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;
+ // 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;
- }
- }
+ if(!pathInfo.substring(0, 6).toLowerCase().equals("/cmis/") && !pathInfo.equals("/discovery"))
+ {
+ // 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)
*/
@@ -110,13 +110,13 @@ public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServl
{
// try
// {
- // make the request input stream a BufferedInputStream so that the first x bytes can be reused.
+ // 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;
+ // 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)
// {
diff --git a/source/java/org/alfresco/rest/api/discovery/DiscoveryApiWebscript.java b/source/java/org/alfresco/rest/api/discovery/DiscoveryApiWebscript.java
new file mode 100644
index 0000000000..e9b0921e95
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/discovery/DiscoveryApiWebscript.java
@@ -0,0 +1,168 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
+package org.alfresco.rest.api.discovery;
+
+import org.alfresco.rest.api.model.DiscoveryDetails;
+import org.alfresco.rest.api.model.ModulePackage;
+import org.alfresco.rest.api.model.RepositoryInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.LicenseInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.StatusInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.VersionInfo;
+import org.alfresco.rest.framework.jacksonextensions.JacksonHelper;
+import org.alfresco.rest.framework.tools.ApiAssistant;
+import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
+import org.alfresco.rest.framework.tools.ResponseWriter;
+import org.alfresco.service.cmr.admin.RepoAdminService;
+import org.alfresco.service.cmr.audit.AuditService;
+import org.alfresco.service.cmr.module.ModuleDetails;
+import org.alfresco.service.cmr.module.ModuleService;
+import org.alfresco.service.cmr.quickshare.QuickShareService;
+import org.alfresco.service.descriptor.Descriptor;
+import org.alfresco.service.descriptor.DescriptorService;
+import org.alfresco.util.PropertyCheck;
+import org.json.simple.JSONObject;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.extensions.webscripts.AbstractWebScript;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Jamal Kaabi-Mofrad
+ */
+public class DiscoveryApiWebscript extends AbstractWebScript implements RecognizedParamsExtractor, ResponseWriter, InitializingBean
+{
+ private DescriptorService descriptorService;
+ private RepoAdminService repoAdminService;
+ private AuditService auditService;
+ private QuickShareService quickShareService;
+ private ModuleService moduleService;
+ private ApiAssistant assistant;
+
+ public void setDescriptorService(DescriptorService descriptorService)
+ {
+ this.descriptorService = descriptorService;
+ }
+
+ public void setRepoAdminService(RepoAdminService repoAdminService)
+ {
+ this.repoAdminService = repoAdminService;
+ }
+
+ public void setAuditService(AuditService auditService)
+ {
+ this.auditService = auditService;
+ }
+
+ public void setQuickShareService(QuickShareService quickShareService)
+ {
+ this.quickShareService = quickShareService;
+ }
+
+ public void setModuleService(ModuleService moduleService)
+ {
+ this.moduleService = moduleService;
+ }
+
+ public void setAssistant(ApiAssistant assistant)
+ {
+ this.assistant = assistant;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ PropertyCheck.mandatory(this, "descriptorService", descriptorService);
+ PropertyCheck.mandatory(this, "repoAdminService", repoAdminService);
+ PropertyCheck.mandatory(this, "auditService", auditService);
+ PropertyCheck.mandatory(this, "quickShareService", quickShareService);
+ PropertyCheck.mandatory(this, "moduleService", moduleService);
+ PropertyCheck.mandatory(this, "assistant", assistant);
+ }
+
+ @Override
+ public void execute(WebScriptRequest webScriptRequest, WebScriptResponse webScriptResponse) throws IOException
+ {
+ try
+ {
+ DiscoveryDetails discoveryDetails = new DiscoveryDetails(getRepositoryInfo());
+ // Write response
+ setResponse(webScriptResponse, DEFAULT_SUCCESS);
+ renderJsonResponse(webScriptResponse, discoveryDetails, assistant.getJsonHelper());
+ }
+ catch (Exception exception)
+ {
+ renderException(exception, webScriptResponse, assistant);
+ }
+ }
+
+ protected RepositoryInfo getRepositoryInfo()
+ {
+ LicenseInfo licenseInfo = null;
+ if(descriptorService.getLicenseDescriptor() != null)
+ {
+ licenseInfo = new LicenseInfo(descriptorService.getLicenseDescriptor());
+ }
+ Descriptor serverDescriptor = descriptorService.getServerDescriptor();
+ return new RepositoryInfo()
+ .setEdition(serverDescriptor.getEdition())
+ .setVersion(new VersionInfo(serverDescriptor))
+ .setLicense(licenseInfo)
+ .setModules(getModules())
+ .setStatus(new StatusInfo()
+ .setReadOnly(repoAdminService.getUsage().isReadOnly())
+ .setAuditEnabled(auditService.isAuditEnabled())
+ .setQuickShareEnabled(quickShareService.isQuickShareEnabled()));
+ }
+
+ private List getModules()
+ {
+ List details = moduleService.getAllModules();
+ if (details.isEmpty())
+ {
+ return null;
+ }
+ List packages = new ArrayList<>(details.size());
+ for (ModuleDetails detail : details)
+ {
+ packages.add(ModulePackage.fromModuleDetails(detail));
+ }
+ return packages;
+ }
+
+ @Override
+ public void renderJsonResponse(final WebScriptResponse res, final Object toSerialize, final JacksonHelper jsonHelper) throws IOException
+ {
+ jsonHelper.withWriter(res.getOutputStream(), (generator, objectMapper) -> {
+ JSONObject obj = new JSONObject();
+ obj.put("entry", toSerialize);
+ objectMapper.writeValue(generator, obj);
+ });
+ }
+}
diff --git a/source/java/org/alfresco/rest/api/model/DiscoveryDetails.java b/source/java/org/alfresco/rest/api/model/DiscoveryDetails.java
new file mode 100644
index 0000000000..e88b8f872c
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/model/DiscoveryDetails.java
@@ -0,0 +1,65 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
+package org.alfresco.rest.api.model;
+
+/**
+ * Representation of the discovery information
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+public class DiscoveryDetails
+{
+ private RepositoryInfo repository;
+
+ public DiscoveryDetails()
+ {
+ }
+
+ public DiscoveryDetails(RepositoryInfo repository)
+ {
+ this.repository = repository;
+ }
+
+ public RepositoryInfo getRepository()
+ {
+ return repository;
+ }
+
+ public DiscoveryDetails setRepository(RepositoryInfo repository)
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DiscoveryDetails [repository=").append(repository)
+ .append(']');
+ return sb.toString();
+ }
+}
diff --git a/source/java/org/alfresco/rest/api/model/RepositoryInfo.java b/source/java/org/alfresco/rest/api/model/RepositoryInfo.java
new file mode 100644
index 0000000000..fe5408ef33
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/model/RepositoryInfo.java
@@ -0,0 +1,455 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
+package org.alfresco.rest.api.model;
+
+import org.alfresco.service.descriptor.Descriptor;
+import org.alfresco.service.license.LicenseDescriptor;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Representation of the repository information.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+public class RepositoryInfo
+{
+ private String edition;
+ private VersionInfo version;
+ private LicenseInfo license;
+ private StatusInfo status;
+ private List modules;
+
+ public String getEdition()
+ {
+ return edition;
+ }
+
+ public RepositoryInfo setEdition(String edition)
+ {
+ this.edition = edition;
+ return this;
+ }
+
+ public VersionInfo getVersion()
+ {
+ return version;
+ }
+
+ public RepositoryInfo setVersion(VersionInfo version)
+ {
+ this.version = version;
+ return this;
+ }
+
+ public LicenseInfo getLicense()
+ {
+ return license;
+ }
+
+ public RepositoryInfo setLicense(LicenseInfo license)
+ {
+ this.license = license;
+ return this;
+ }
+
+ public StatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public RepositoryInfo setStatus(StatusInfo status)
+ {
+ this.status = status;
+ return this;
+ }
+
+ public List getModules()
+ {
+ return modules;
+ }
+
+ public RepositoryInfo setModules(List modules)
+ {
+ this.modules = modules;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(450);
+ sb.append("RepositoryInfo [edition=").append(edition)
+ .append(", version=").append(version)
+ .append(", license=").append(license)
+ .append(", status=").append(status)
+ .append(", modules=").append(modules)
+ .append(']');
+ return sb.toString();
+ }
+
+ /**
+ * Representation of the repository version information.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+ public static class VersionInfo
+ {
+ private static final Pattern HOTFIX_PATTERN = Pattern.compile("^[0-9]+$");
+ private String major;
+ private String minor;
+ private String patch;
+ private String hotfix;
+ private int schema;
+ private String label;
+ private String display;
+
+ // Default constructor required for test purposes
+ public VersionInfo()
+ {
+ }
+
+ public VersionInfo(Descriptor descriptor)
+ {
+ this.major = descriptor.getVersionMajor();
+ this.minor = descriptor.getVersionMinor();
+ this.patch = descriptor.getVersionRevision();
+ this.hotfix = getHotfix(descriptor.getVersionLabel());
+ this.schema = descriptor.getSchema();
+ this.label = descriptor.getVersionBuild();
+ this.display = getVersionDisplay();
+ }
+
+ public String getMajor()
+ {
+ return major;
+ }
+
+ public String getMinor()
+ {
+ return minor;
+ }
+
+ public String getPatch()
+ {
+ return patch;
+ }
+
+ public String getHotfix()
+ {
+ return hotfix;
+ }
+
+ public int getSchema()
+ {
+ return schema;
+ }
+
+ public String getLabel()
+ {
+ return label;
+ }
+
+ public String getDisplay()
+ {
+ return display;
+ }
+
+ private String getHotfix(String versionLabel)
+ {
+ /*
+ * if the label starts with a dot, then digit(s), or just digit(s), we return the number only.
+ * for anything else zero will be returned.
+ */
+ if (StringUtils.isNotEmpty(versionLabel))
+ {
+ if (versionLabel.startsWith("."))
+ {
+ versionLabel = versionLabel.substring(1);
+ }
+ Matcher matcher = HOTFIX_PATTERN.matcher(versionLabel);
+ if (matcher.find())
+ {
+ return versionLabel;
+ }
+ }
+ return Integer.toString(0);
+ }
+
+ private String getVersionDisplay()
+ {
+ StringBuilder version = new StringBuilder(major);
+ version.append('.')
+ .append(minor)
+ .append('.')
+ .append(patch)
+ .append('.')
+ .append(getHotfix());
+
+ if (StringUtils.isNotEmpty(label))
+ {
+ version.append(" (").append(label).append(") ");
+ }
+ version.append("schema ").append(schema);
+
+ // Display example: "5.2.0.1 (r123456-b0) schema 10001"
+ return version.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(250);
+ sb.append("VersionInfo [major=").append(major)
+ .append(", minor=").append(minor)
+ .append(", patch=").append(patch)
+ .append(", hotfix=").append(hotfix)
+ .append(", schema=").append(schema)
+ .append(", label=").append(label)
+ .append(", display=").append(display)
+ .append(']');
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Representation of the license information.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+ public static class LicenseInfo
+ {
+ private Date issuedAt;
+ private Date expiresAt;
+ private Integer remainingDays;
+ private String holder;
+ private String mode;
+ private LicenseEntitlement entitlements;
+
+ // Default constructor required for test purposes
+ public LicenseInfo()
+ {
+ }
+
+ public LicenseInfo(LicenseDescriptor licenseDescriptor)
+ {
+ this.issuedAt = licenseDescriptor.getIssued();
+ this.expiresAt = licenseDescriptor.getValidUntil();
+ this.remainingDays = licenseDescriptor.getRemainingDays();
+ this.holder = licenseDescriptor.getHolderOrganisation();
+ this.mode = licenseDescriptor.getLicenseMode().name();
+ this.entitlements = new LicenseEntitlement()
+ .setMaxDocs(licenseDescriptor.getMaxDocs())
+ .setMaxUsers(licenseDescriptor.getMaxUsers())
+ .setClusterEnabled(licenseDescriptor.isClusterEnabled())
+ .setCryptodocEnabled(licenseDescriptor.isCryptodocEnabled());
+ }
+
+ public Date getIssuedAt()
+ {
+ return issuedAt;
+ }
+
+ public Date getExpiresAt()
+ {
+ return expiresAt;
+ }
+
+ public Integer getRemainingDays()
+ {
+ return remainingDays;
+ }
+
+ public String getHolder()
+ {
+ return holder;
+ }
+
+ public String getMode()
+ {
+ return mode;
+ }
+
+ public LicenseEntitlement getEntitlements()
+ {
+ return entitlements;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(250);
+ sb.append("LicenseInfo [issuedAt=").append(issuedAt)
+ .append(", expiresAt=").append(expiresAt)
+ .append(", remainingDays=").append(remainingDays)
+ .append(", holder=").append(holder)
+ .append(", mode=").append(mode)
+ .append(", entitlements=").append(entitlements)
+ .append(']');
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Representation of the license's entitlement.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+ public static class LicenseEntitlement
+ {
+ private Long maxUsers;
+ private Long maxDocs;
+ private boolean isClusterEnabled;
+ private boolean isCryptodocEnabled;
+
+ public LicenseEntitlement()
+ {
+ }
+
+ public Long getMaxUsers()
+ {
+ return maxUsers;
+ }
+
+ public LicenseEntitlement setMaxUsers(Long maxUsers)
+ {
+ this.maxUsers = maxUsers;
+ return this;
+ }
+
+ public Long getMaxDocs()
+ {
+ return maxDocs;
+ }
+
+ public LicenseEntitlement setMaxDocs(Long maxDocs)
+ {
+ this.maxDocs = maxDocs;
+ return this;
+ }
+
+ public boolean getIsClusterEnabled()
+ {
+ return isClusterEnabled;
+ }
+
+ public LicenseEntitlement setClusterEnabled(boolean clusterEnabled)
+ {
+ isClusterEnabled = clusterEnabled;
+ return this;
+ }
+
+ public boolean getIsCryptodocEnabled()
+ {
+ return isCryptodocEnabled;
+ }
+
+ public LicenseEntitlement setCryptodocEnabled(boolean cryptodocEnabled)
+ {
+ isCryptodocEnabled = cryptodocEnabled;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(100);
+ sb.append("LicenseEntitlement [maxUsers=").append(maxUsers)
+ .append(", maxDocs=").append(maxDocs)
+ .append(", isClusterEnabled=").append(isClusterEnabled)
+ .append(", isCryptodocEnabled=").append(isCryptodocEnabled)
+ .append(']');
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Representation of the repository status information.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+ public static class StatusInfo
+ {
+ private boolean isReadOnly;
+ private boolean isAuditEnabled;
+ private boolean isQuickShareEnabled;
+
+ public StatusInfo()
+ {
+ }
+
+ public boolean getIsReadOnly()
+ {
+ return isReadOnly;
+ }
+
+ public StatusInfo setReadOnly(boolean readOnly)
+ {
+ isReadOnly = readOnly;
+ return this;
+ }
+
+ public boolean getIsAuditEnabled()
+ {
+ return isAuditEnabled;
+ }
+
+ public StatusInfo setAuditEnabled(boolean auditEnabled)
+ {
+ isAuditEnabled = auditEnabled;
+ return this;
+ }
+
+ public boolean getIsQuickShareEnabled()
+ {
+ return isQuickShareEnabled;
+ }
+
+ public StatusInfo setQuickShareEnabled(boolean quickShareEnabled)
+ {
+ isQuickShareEnabled = quickShareEnabled;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder(250);
+ sb.append("StatusInfo [isReadOnly=").append(isReadOnly)
+ .append(", isAuditEnabled=").append(isAuditEnabled)
+ .append(", isQuickShareEnabled=").append(isQuickShareEnabled)
+ .append(']');
+ return sb.toString();
+ }
+ }
+}
diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
index e53a160432..991920a3d3 100644
--- a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
@@ -328,6 +328,14 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return getSingle(url, entityId, null, expectedStatus);
}
+ public HttpResponse get(String url, Map params, int expectedStatus) throws IOException
+ {
+ HttpResponse response = publicApiClient.get(url, params);
+ checkStatus(expectedStatus, response.getStatusCode());
+
+ return response;
+ }
+
protected HttpResponse getSingle(String url, String entityId, Map params, int expectedStatus) throws Exception
{
HttpResponse response = publicApiClient.get(getScope(), url, entityId, null, null, params);
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 8e474ced25..5e65a23704 100644
--- a/source/test-java/org/alfresco/rest/api/tests/ApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/ApiTest.java
@@ -57,6 +57,7 @@ import org.junit.runners.Suite;
AuthenticationsTest.class,
ModulePackagesApiTest.class,
WherePredicateApiTest.class,
+ DiscoveryApiTest.class,
TestSites.class,
TestNodeComments.class,
TestFavouriteSites.class,
diff --git a/source/test-java/org/alfresco/rest/api/tests/DiscoveryApiTest.java b/source/test-java/org/alfresco/rest/api/tests/DiscoveryApiTest.java
new file mode 100644
index 0000000000..db6770039d
--- /dev/null
+++ b/source/test-java/org/alfresco/rest/api/tests/DiscoveryApiTest.java
@@ -0,0 +1,315 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * 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 .
+ * #L%
+ */
+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.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.alfresco.rest.AbstractSingleNetworkSiteTest;
+import org.alfresco.rest.api.discovery.DiscoveryApiWebscript;
+import org.alfresco.rest.api.model.DiscoveryDetails;
+import org.alfresco.rest.api.model.ModulePackage;
+import org.alfresco.rest.api.model.RepositoryInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.LicenseEntitlement;
+import org.alfresco.rest.api.model.RepositoryInfo.LicenseInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.StatusInfo;
+import org.alfresco.rest.api.model.RepositoryInfo.VersionInfo;
+import org.alfresco.rest.api.tests.client.HttpResponse;
+import org.alfresco.rest.api.tests.util.RestApiUtil;
+import org.alfresco.service.cmr.admin.RepoUsage.LicenseMode;
+import org.alfresco.service.descriptor.Descriptor;
+import org.alfresco.service.descriptor.DescriptorService;
+import org.alfresco.service.license.LicenseDescriptor;
+import org.joda.time.DateTime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * V1 REST API tests for retrieving detailed repository information.
+ *
+ * - {@literal :/alfresco/api/discovery}
+ *
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+public class DiscoveryApiTest extends AbstractSingleNetworkSiteTest
+{
+
+ private static final DateTime NOW = DateTime.now();
+
+ @Mock
+ private DescriptorService descriptorServiceMock;
+ @Mock
+ private Descriptor serverDescriptor;
+ @Mock
+ private LicenseDescriptor licenseDescriptorMock;
+
+ private Date licenseIssuedAt;
+ private Date licenseExpiresAt;
+
+ @Before
+ public void setup() throws Exception
+ {
+ super.setup();
+
+ this.licenseIssuedAt = NOW.toDate();
+ this.licenseExpiresAt = NOW.plusDays(5).toDate();
+
+ // Mock the required descriptors
+ this.descriptorServiceMock = mock(DescriptorService.class);
+ this.serverDescriptor = mock(Descriptor.class);
+ this.licenseDescriptorMock = mock(LicenseDescriptor.class);
+
+ when(descriptorServiceMock.getServerDescriptor()).thenReturn(serverDescriptor);
+ when(serverDescriptor.getEdition()).thenReturn("Enterprise");
+ when(serverDescriptor.getVersionMajor()).thenReturn("5");
+ when(serverDescriptor.getVersionMinor()).thenReturn("2");
+ when(serverDescriptor.getVersionRevision()).thenReturn("1");
+ when(serverDescriptor.getVersionLabel()).thenReturn(".3");
+ when(serverDescriptor.getVersionBuild()).thenReturn("r123456-b0");
+ when(serverDescriptor.getSchema()).thenReturn(10051);
+
+ when(descriptorServiceMock.getLicenseDescriptor()).thenReturn(licenseDescriptorMock);
+ when(licenseDescriptorMock.getIssued()).thenReturn(this.licenseIssuedAt);
+ when(licenseDescriptorMock.getValidUntil()).thenReturn(this.licenseExpiresAt);
+ when(licenseDescriptorMock.getRemainingDays()).thenReturn(5);
+ when(licenseDescriptorMock.getLicenseMode()).thenReturn(LicenseMode.ENTERPRISE);
+ when(licenseDescriptorMock.getHolderOrganisation()).thenReturn("Alfresco Dev Test");
+ when(licenseDescriptorMock.getMaxUsers()).thenReturn(20L);
+ when(licenseDescriptorMock.getMaxDocs()).thenReturn(1000L);
+ when(licenseDescriptorMock.isClusterEnabled()).thenReturn(true);
+
+ // Override the descriptor service
+ DiscoveryApiWebscript discoveryApiWebscript = applicationContext
+ .getBean("webscript.org.alfresco.api.DiscoveryApiWebscript.get", DiscoveryApiWebscript.class);
+ discoveryApiWebscript.setDescriptorService(descriptorServiceMock);
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ /**
+ * Tests get discovery.
+ * GET:
+ * {@literal :/alfresco/api/discovery}
+ */
+ @Test
+ public void testGetDiscovery() throws Exception
+ {
+ setRequestContext(null, user1, "wrongPassword");
+ get("discovery", null, 401);
+
+ setRequestContext(null, user1, null);
+ HttpResponse response = get("discovery", null, 200);
+
+ DiscoveryDetails discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ RepositoryInfo repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+ assertEquals("Enterprise", repositoryInfo.getEdition());
+
+ // Check version info
+ VersionInfo versionInfo = repositoryInfo.getVersion();
+ assertNotNull(versionInfo);
+ assertEquals("5", versionInfo.getMajor());
+ assertEquals("2", versionInfo.getMinor());
+ assertEquals("1", versionInfo.getPatch());
+ assertEquals("3", versionInfo.getHotfix());
+ assertEquals("r123456-b0", versionInfo.getLabel());
+ assertEquals(10051, versionInfo.getSchema());
+ assertEquals("5.2.1.3 (r123456-b0) schema 10051", versionInfo.getDisplay());
+
+ // Check license info
+ LicenseInfo licenseInfo = repositoryInfo.getLicense();
+ assertNotNull(licenseInfo);
+ assertEquals(LicenseMode.ENTERPRISE.name(), licenseInfo.getMode());
+ assertEquals(licenseIssuedAt.toString(), licenseInfo.getIssuedAt().toString());
+ assertEquals(licenseExpiresAt.toString(), licenseInfo.getExpiresAt().toString());
+ assertEquals(Integer.valueOf(5), licenseInfo.getRemainingDays());
+ assertEquals("Alfresco Dev Test", licenseInfo.getHolder());
+ LicenseEntitlement entitlements = licenseInfo.getEntitlements();
+ assertNotNull(entitlements);
+ assertNotNull(entitlements.getMaxUsers());
+ assertEquals(20L, entitlements.getMaxUsers().longValue());
+ assertNotNull(entitlements.getMaxDocs());
+ assertEquals(1000L, entitlements.getMaxDocs().longValue());
+ assertTrue(entitlements.getIsClusterEnabled());
+ assertFalse(entitlements.getIsCryptodocEnabled());
+
+ // Check status
+ StatusInfo statusInfo = repositoryInfo.getStatus();
+ assertNotNull(statusInfo);
+ assertFalse(statusInfo.getIsReadOnly());
+ assertTrue(statusInfo.getIsAuditEnabled());
+ assertTrue(statusInfo.getIsQuickShareEnabled());
+
+ // Check modules
+ List modulePackageList = repositoryInfo.getModules();
+ assertNotNull(modulePackageList);
+ }
+
+ /**
+ * Tests get discovery.
+ * GET:
+ * {@literal :/alfresco/api/discovery}
+ */
+ @Test
+ public void testGetDiscovery_hotfixValue() throws Exception
+ {
+ /*
+ * The agreement was that if the hotfix value (versionLabel) does not follow the standard
+ * of "dot then digits" or just "digits", the API should return zero.
+ */
+
+ when(serverDescriptor.getVersionLabel()).thenReturn("4");
+ setRequestContext(null, user1, null);
+ HttpResponse response = get("discovery", null, 200);
+
+ DiscoveryDetails discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ RepositoryInfo repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+ assertEquals("Enterprise", repositoryInfo.getEdition());
+
+ // Check version info
+ VersionInfo versionInfo = repositoryInfo.getVersion();
+ assertNotNull(versionInfo);
+ assertEquals("5", versionInfo.getMajor());
+ assertEquals("2", versionInfo.getMinor());
+ assertEquals("1", versionInfo.getPatch());
+ assertEquals("4", versionInfo.getHotfix());
+ assertEquals("r123456-b0", versionInfo.getLabel());
+ assertEquals(10051, versionInfo.getSchema());
+ assertEquals("5.2.1.4 (r123456-b0) schema 10051", versionInfo.getDisplay());
+
+ when(serverDescriptor.getVersionLabel()).thenReturn("d");
+ response = get("discovery", null, 200);
+
+ discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+ // Check version info
+ versionInfo = repositoryInfo.getVersion();
+ assertNotNull(versionInfo);
+ assertEquals("5", versionInfo.getMajor());
+ assertEquals("2", versionInfo.getMinor());
+ assertEquals("1", versionInfo.getPatch());
+ assertEquals("0", versionInfo.getHotfix());
+ assertEquals("r123456-b0", versionInfo.getLabel());
+ assertEquals(10051, versionInfo.getSchema());
+ assertEquals("5.2.1.0 (r123456-b0) schema 10051", versionInfo.getDisplay());
+
+ when(serverDescriptor.getVersionLabel()).thenReturn("39.4");
+ response = get("discovery", null, 200);
+
+ discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+ // Check version info
+ versionInfo = repositoryInfo.getVersion();
+ assertNotNull(versionInfo);
+ assertEquals("5", versionInfo.getMajor());
+ assertEquals("2", versionInfo.getMinor());
+ assertEquals("1", versionInfo.getPatch());
+ assertEquals("0", versionInfo.getHotfix());
+ assertEquals("r123456-b0", versionInfo.getLabel());
+ assertEquals(10051, versionInfo.getSchema());
+ assertEquals("5.2.1.0 (r123456-b0) schema 10051", versionInfo.getDisplay());
+ }
+
+ /**
+ * Tests get discovery.
+ * GET:
+ * {@literal :/alfresco/api/discovery}
+ */
+ @Test
+ public void testGetDiscovery_licenseEntitlement() throws Exception
+ {
+ // Override maxUsers
+ when(licenseDescriptorMock.getMaxUsers()).thenReturn(null);
+
+ setRequestContext(null, user1, null);
+ HttpResponse response = get("discovery", null, 200);
+
+ DiscoveryDetails discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ RepositoryInfo repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+ assertEquals("Enterprise", repositoryInfo.getEdition());
+
+ // Check license info
+ LicenseInfo licenseInfo = repositoryInfo.getLicense();
+ assertNotNull(licenseInfo);
+ assertEquals(LicenseMode.ENTERPRISE.name(), licenseInfo.getMode());
+ assertEquals(licenseIssuedAt.toString(), licenseInfo.getIssuedAt().toString());
+ assertEquals(licenseExpiresAt.toString(), licenseInfo.getExpiresAt().toString());
+ assertEquals(Integer.valueOf(5), licenseInfo.getRemainingDays());
+ assertEquals("Alfresco Dev Test", licenseInfo.getHolder());
+ LicenseEntitlement entitlements = licenseInfo.getEntitlements();
+ assertNotNull(entitlements);
+ assertNull(entitlements.getMaxUsers());
+ assertEquals(1000L, entitlements.getMaxDocs().longValue());
+ assertTrue(entitlements.getIsClusterEnabled());
+ assertFalse(entitlements.getIsCryptodocEnabled());
+
+ // Override entitlements
+ when(licenseDescriptorMock.getMaxDocs()).thenReturn(null);
+ when(licenseDescriptorMock.isClusterEnabled()).thenReturn(false);
+ when(licenseDescriptorMock.isCryptodocEnabled()).thenReturn(true);
+
+ response = get("discovery", null, 200);
+
+ discoveryDetails = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), DiscoveryDetails.class);
+ assertNotNull(discoveryDetails);
+ repositoryInfo = discoveryDetails.getRepository();
+ assertNotNull(repositoryInfo);
+
+ // Check license info
+ licenseInfo = repositoryInfo.getLicense();
+ assertNotNull(licenseInfo);
+ entitlements = licenseInfo.getEntitlements();
+ assertNotNull(entitlements);
+ assertNull(entitlements.getMaxUsers());
+ assertNull(entitlements.getMaxDocs());
+ assertFalse(entitlements.getIsClusterEnabled());
+ assertTrue(entitlements.getIsCryptodocEnabled());
+ }
+}
+