diff --git a/common/src/main/java/org/fao/geonet/exceptions/GNException.java b/common/src/main/java/org/fao/geonet/exceptions/GNException.java new file mode 100644 index 00000000000..cedd2239e43 --- /dev/null +++ b/common/src/main/java/org/fao/geonet/exceptions/GNException.java @@ -0,0 +1,34 @@ +//============================================================================= +//=== Copyright (C) 2001-2023 Food and Agriculture Organization of the +//=== United Nations (FAO-UN), United Nations World Food Programme (WFP) +//=== and United Nations Environment Programme (UNEP) +//=== +//=== This program is free software; you can redistribute it and/or modify +//=== it under the terms of the GNU General Public License as published by +//=== the Free Software Foundation; either version 2 of the License, or (at +//=== your option) any later version. +//=== +//=== This program 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 +//=== General Public License for more details. +//=== +//=== You should have received a copy of the GNU General Public License +//=== along with this program; if not, write to the Free Software +//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +//=== +//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, +//=== Rome - Italy. email: geonetwork@osgeo.org +//============================================================================== +package org.fao.geonet.exceptions; + +public class GNException extends RuntimeException { + + public GNException(String msg) { + super(msg); + } + + public GNException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/core/src/main/java/org/fao/geonet/kernel/datamanager/base/BaseMetadataManager.java b/core/src/main/java/org/fao/geonet/kernel/datamanager/base/BaseMetadataManager.java index b5af7069a50..ac6165935c1 100644 --- a/core/src/main/java/org/fao/geonet/kernel/datamanager/base/BaseMetadataManager.java +++ b/core/src/main/java/org/fao/geonet/kernel/datamanager/base/BaseMetadataManager.java @@ -23,6 +23,7 @@ package org.fao.geonet.kernel.datamanager.base; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; @@ -39,6 +40,7 @@ import org.fao.geonet.constants.Geonet; import org.fao.geonet.constants.Params; import org.fao.geonet.domain.*; +import org.fao.geonet.exceptions.GNException; import org.fao.geonet.exceptions.UnAuthorizedException; import org.fao.geonet.kernel.*; import org.fao.geonet.kernel.datamanager.*; @@ -139,6 +141,10 @@ public class BaseMetadataManager implements IMetadataManager { @Autowired private ApplicationContext _applicationContext; + + @VisibleForTesting + public int maxMdsReferencingSubTemplate = 10000; + @PersistenceContext private EntityManager _entityManager; @@ -1317,7 +1323,10 @@ boolean hasReferencingMetadata(ServiceContext context, AbstractMetadata metadata private void indexMdsReferencingSubTemplate(ServiceContext context, AbstractMetadata subTemplate) throws Exception { StringBuilder query = new StringBuilder(String.format("xlink:*%s*", subTemplate.getUuid())); - SearchResponse response = this.searchManager.query(query.toString(), null, 0, 10000); + SearchResponse response = this.searchManager.query(query.toString(), null, 0, maxMdsReferencingSubTemplate); + if (response.getHits().getTotalHits().value > maxMdsReferencingSubTemplate) { + throw new GNException("Not implemented"); + } ArrayList<String> toIndex = new ArrayList<>(); response.getHits().forEach(consumer -> { String consumerUuid = consumer.getId(); diff --git a/core/src/test/java/org/fao/geonet/kernel/LocalXLinksUpdateDeleteTest.java b/core/src/test/java/org/fao/geonet/kernel/LocalXLinksUpdateDeleteTest.java index 8682fae3570..cf63907de4f 100644 --- a/core/src/test/java/org/fao/geonet/kernel/LocalXLinksUpdateDeleteTest.java +++ b/core/src/test/java/org/fao/geonet/kernel/LocalXLinksUpdateDeleteTest.java @@ -6,8 +6,9 @@ import org.elasticsearch.action.search.SearchResponse; import org.fao.geonet.AbstractCoreIntegrationTest; import org.fao.geonet.domain.AbstractMetadata; -import org.fao.geonet.kernel.datamanager.IMetadataManager; +import org.fao.geonet.exceptions.GNException; import org.fao.geonet.kernel.datamanager.base.BaseMetadataIndexer; +import org.fao.geonet.kernel.datamanager.base.BaseMetadataManager; import org.fao.geonet.kernel.search.EsSearchManager; import org.fao.geonet.kernel.search.IndexingMode; import org.fao.geonet.kernel.setting.SettingManager; @@ -33,13 +34,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.when; public class LocalXLinksUpdateDeleteTest extends AbstractIntegrationTestWithMockedSingletons { @Autowired - private IMetadataManager metadataManager; + private BaseMetadataManager metadataManager; @Autowired private SettingManager settingManager; @@ -60,29 +63,29 @@ public void setUp() throws Exception { @Test public void updateHasToRegisterReferrersForIndexation() throws Exception { - URL contactResource = AbstractCoreIntegrationTest.class.getResource("kernel/babarContact.xml"); - Element contactElement = Xml.loadStream(contactResource.openStream()); - AbstractMetadata contactMetadata = insertContact(contactElement); - AbstractMetadata vicinityMapMetadata = insertVicinityMap(contactMetadata); - assertEquals(1, countMetadataUsing(vicinityMapMetadata.getUuid(), "babar").getHits().getHits().length); - assertEquals(0, countMetadataUsing(vicinityMapMetadata.getUuid(), "momo").getHits().getHits().length); + Mockito.reset(metadataIndexer); - Xml.selectElement(contactElement, "gmd:individualName/gco:CharacterString", Arrays.asList(GMD, GCO)).setText("momo"); - metadataManager.updateMetadata(serviceContext, - Integer.toString(contactMetadata.getId()), - contactElement, - false, - false, - null, - null, - false, - IndexingMode.full); + AbstractMetadata vicinityMapMetadata = updateASubtemplateUsedByOneMetadata(); ArgumentCaptor<List> toIndexCaptor = ArgumentCaptor.forClass(List.class); Mockito.verify(metadataIndexer).batchIndexInThreadPool(Mockito.anyObject(), toIndexCaptor.capture()); assertTrue(toIndexCaptor.getValue().contains(Integer.toString(vicinityMapMetadata.getId()))); } + @Test + public void exceedMaxMdsReferencingSubTemplateThrowsException() { + Mockito.reset(metadataIndexer); + try { + metadataManager.maxMdsReferencingSubTemplate = 0; + + assertThrows(GNException.class, () -> updateASubtemplateUsedByOneMetadata()); + + Mockito.verify(metadataIndexer, never()).batchIndexInThreadPool(Mockito.anyObject(), Mockito.anyList()); + } finally { + metadataManager.maxMdsReferencingSubTemplate = 10000; + } + } + private SearchResponse countMetadataUsing(String mdUuid, String contactForResourceIndividual) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); @@ -155,6 +158,27 @@ private AbstractMetadata insertContact(Element contactElement) throws Exception return contactMetadata; } + private AbstractMetadata updateASubtemplateUsedByOneMetadata() throws Exception { + URL contactResource = AbstractCoreIntegrationTest.class.getResource("kernel/babarContact.xml"); + Element contactElement = Xml.loadStream(contactResource.openStream()); + AbstractMetadata contactMetadata = insertContact(contactElement); + AbstractMetadata vicinityMapMetadata = insertVicinityMap(contactMetadata); + assertEquals(1, countMetadataUsing(vicinityMapMetadata.getUuid(), "babar").getHits().getHits().length); + assertEquals(0, countMetadataUsing(vicinityMapMetadata.getUuid(), "momo").getHits().getHits().length); + + Xml.selectElement(contactElement, "gmd:individualName/gco:CharacterString", Arrays.asList(GMD, GCO)).setText("momo"); + metadataManager.updateMetadata(serviceContext, + Integer.toString(contactMetadata.getId()), + contactElement, + false, + false, + null, + null, + false, + IndexingMode.full); + return vicinityMapMetadata; + } + static public class SpyFactory { @Autowired BaseMetadataIndexer baseMetadataIndexer;