ACS-2151 Get StorageProps endpoint (#807)

* ACS-2151: Initial code for get StorageProps endpoint.

* ACS-2151: Get StorageProps enhancements - proper namespace resolver, unit tests and javadoc + @Experimental annotation.

* ACS-2151: Reverting unnecessary POM changes.

* ACS-2151: Initial code for get StorageProps endpoint.

* ACS-2151: Reverting unnecessary POM changes.

* ACS-2151: Fix after code review.

* ACS-2151: Initial code for get StorageProps endpoint.

* ACS-2151: Reverting unnecessary POM changes.
This commit is contained in:
mpichura
2021-12-01 13:19:51 +01:00
committed by GitHub
parent 9fefc17eef
commit fb37f18e57
6 changed files with 401 additions and 1 deletions

View File

@@ -0,0 +1,51 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api;
import org.alfresco.rest.api.model.ContentStorageInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
/**
* Storage information for content API.
* Note: Currently marked as experimental and subject to change.
*
* @author mpichura
*/
@Experimental
public interface ContentStorageInformation
{
/**
* Note: Currently marked as experimental and subject to change.
* @param nodeId Identifier of the node
* @param contentPropName Qualified name of content property (e.g. 'cm_content')
* @param parameters {@link Parameters} object to get the parameters passed into the request
* @return {@link ContentStorageInfo} object consisting of qualified name of content property and a map of storage properties
*/
@Experimental
ContentStorageInfo getStorageInfo(String nodeId, String contentPropName, Parameters parameters);
}

View File

@@ -0,0 +1,83 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import org.alfresco.rest.api.ContentStorageInformation;
import org.alfresco.rest.api.model.ContentStorageInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import java.util.Map;
/**
* Default implementation for {@link ContentStorageInformation}
* Note: Currently marked as experimental and subject to change.
*
* @author mpichura
*/
@Experimental
public class ContentStorageInformationImpl implements ContentStorageInformation
{
public static final char PREFIX_SEPARATOR = '_';
private final ContentService contentService;
private final NamespaceService namespaceService;
public ContentStorageInformationImpl(ContentService contentService, NamespaceService namespaceService)
{
this.contentService = contentService;
this.namespaceService = namespaceService;
}
/**
* {@inheritDoc}
*/
@Override
@Experimental
public ContentStorageInfo getStorageInfo(String nodeId, String contentPropName, Parameters parameters)
{
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
final QName propQName = getQName(contentPropName);
final Map<String, String> storageProperties = contentService.getStorageProperties(nodeRef, propQName);
final ContentStorageInfo storageInfo = new ContentStorageInfo();
storageInfo.setId(propQName.toPrefixString(namespaceService));
storageInfo.setStorageProperties(storageProperties);
return storageInfo;
}
private QName getQName(final String contentPropName)
{
final String properContentPropName = contentPropName.replace(PREFIX_SEPARATOR, QName.NAMESPACE_PREFIX);
return QName.resolveToQName(namespaceService, properContentPropName);
}
}

View File

@@ -0,0 +1,71 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model;
import java.util.HashMap;
import java.util.Map;
/**
* Representation of storage information for content.
*
* @author mpichura
*/
public class ContentStorageInfo
{
/**
* Qualified name of content property
*/
private String id;
/**
* Key-value (String-String) collection representing storage properties of given content
*/
private Map<String, String> storageProperties;
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public Map<String, String> getStorageProperties()
{
if (storageProperties == null) {
storageProperties = new HashMap<>();
}
return storageProperties;
}
public void setStorageProperties(Map<String, String> storageProperties)
{
this.storageProperties = storageProperties;
}
}

View File

@@ -0,0 +1,75 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.nodes;
import org.alfresco.rest.api.ContentStorageInformation;
import org.alfresco.rest.api.model.ContentStorageInfo;
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.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
import javax.servlet.http.HttpServletResponse;
/**
* Node storage information.
* Note: Currently marked as experimental and subject to change.
*
* @author mpichura
*/
@Experimental
@RelationshipResource(name = "storage-info", entityResource = NodesEntityResource.class, title = "Node's content storage information")
public class NodeStorageInfoRelation implements RelationshipResourceAction.ReadById<ContentStorageInfo>, InitializingBean
{
private final ContentStorageInformation storageInformation;
public NodeStorageInfoRelation(ContentStorageInformation storageInformation)
{
this.storageInformation = storageInformation;
}
@WebApiDescription(title = "Get storage properties",
description = "Retrieves storage properties for given node's content",
successStatus = HttpServletResponse.SC_OK)
@Override
public ContentStorageInfo readById(String entityResourceId, String id, Parameters parameters)
throws RelationshipResourceNotFoundException
{
return storageInformation.getStorageInfo(entityResourceId, id, parameters);
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "storageInformation", storageInformation);
}
}

View File

@@ -606,6 +606,26 @@
</list>
</property>
</bean>
<bean id="contentStorageInformation" class="org.alfresco.rest.api.impl.ContentStorageInformationImpl">
<constructor-arg name="contentService" ref="ContentService"/>
<constructor-arg name="namespaceService" ref="NamespaceService"/>
</bean>
<bean id="ContentStorageInformation" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.ContentStorageInformation</value>
</property>
<property name="target">
<ref bean="contentStorageInformation" />
</property>
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean id="deletedNodes" class="org.alfresco.rest.api.impl.DeletedNodesImpl">
<property name="nodes" ref="Nodes" />
<property name="nodeService" ref="NodeService" />
@@ -977,7 +997,11 @@
<property name="behaviourFilter" ref="policyBehaviourFilter"/>
<property name="directAccessUrlHelper" ref="directAccessUrlHelper" />
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeStorageInfoRelation">
<constructor-arg name="storageInformation" ref="ContentStorageInformation" />
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeSecondaryChildrenRelation" parent="baseNodeRelation"/>
<bean class="org.alfresco.rest.api.nodes.NodeParentsRelation" parent="baseNodeRelation"/>

View File

@@ -0,0 +1,96 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import org.alfresco.rest.api.model.ContentStorageInfo;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.NamespaceService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@RunWith(MockitoJUnitRunner.class)
public class ContentStorageInformationImplTest
{
@Mock
private ContentService contentService;
@Mock
private NamespaceService namespaceService;
@InjectMocks
private ContentStorageInformationImpl objectUnderTest;
@Test
public void shouldReturnStorageInfoResponseWithNonEmptyStorageProps()
{
final String nodeId = "dummy-node-id";
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
final String contentPropName = "cm:content";
final Map<String, String> storageProps = Map.of("x-amz-storage-class", "INTELLIGENT_TIERING", "x-alf-archived", "false");
Mockito.when(contentService.getStorageProperties(Mockito.eq(nodeRef), Mockito.any())).thenReturn(storageProps);
Mockito.when(namespaceService.getNamespaceURI(NamespaceService.CONTENT_MODEL_PREFIX))
.thenReturn(NamespaceService.CONTENT_MODEL_1_0_URI);
Mockito.when(namespaceService.getPrefixes(NamespaceService.CONTENT_MODEL_1_0_URI))
.thenReturn(List.of(NamespaceService.CONTENT_MODEL_PREFIX));
final ContentStorageInfo storageInfo = objectUnderTest.getStorageInfo(nodeId, contentPropName, null);
Assert.assertEquals(storageProps, storageInfo.getStorageProperties());
Assert.assertEquals(storageInfo.getId(), contentPropName);
}
@Test
public void shouldReturnStorageInfoResponseWithEmptyStorageProps()
{
final String nodeId = "dummy-node-id";
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
final String contentPropName = "cm:content";
Mockito.when(contentService.getStorageProperties(Mockito.eq(nodeRef), Mockito.any())).thenCallRealMethod();
Mockito.when(namespaceService.getNamespaceURI(NamespaceService.CONTENT_MODEL_PREFIX))
.thenReturn(NamespaceService.CONTENT_MODEL_1_0_URI);
Mockito.when(namespaceService.getPrefixes(NamespaceService.CONTENT_MODEL_1_0_URI))
.thenReturn(List.of(NamespaceService.CONTENT_MODEL_PREFIX));
final ContentStorageInfo storageInfo = objectUnderTest.getStorageInfo(nodeId, contentPropName, null);
Assert.assertEquals(Collections.emptyMap(), storageInfo.getStorageProperties());
Assert.assertEquals(storageInfo.getId(), contentPropName);
}
}