From c5e430ec0c3b11d3f2c99b8ae813524f101489e0 Mon Sep 17 00:00:00 2001 From: Jesse Eichar Date: Tue, 29 Jul 2014 16:40:06 +0200 Subject: [PATCH 1/5] Reduce database queries of DataManager.buildMetadataInfo for many metadata. LuceneSearcher calls DataManager.buildMetadataInfo for each search result. The buildMetadata makes several database queries for each call. This change modifies buildMetadataInfo so that it takes several metadata ids and builds the info for all of the objects with only a few queries. Tests indicate that it takes the same time for 1 metadata but 14x faster for 20 metadata and 30x faster for 40 metadata. --- .../org/fao/geonet/kernel/AccessManager.java | 102 ++++++--- .../org/fao/geonet/kernel/DataManager.java | 209 ++++++++++++------ .../geonet/kernel/search/LuceneSearcher.java | 42 ++-- .../kernel/DataManagerIntegrationTest.java | 58 ++++- .../repository/MetadataRepositoryCustom.java | 11 +- .../repository/MetadataRepositoryImpl.java | 38 +++- .../specification/OperationAllowedSpecs.java | 31 ++- .../repository/MetadataRepositoryTest.java | 41 +++- .../OperationAllowedSpecsTest.java | 23 +- web/src/main/webapp/WEB-INF/config-lucene.xml | 4 +- 10 files changed, 426 insertions(+), 133 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/kernel/AccessManager.java b/core/src/main/java/org/fao/geonet/kernel/AccessManager.java index a28a44d7567..4d5f5c2d527 100644 --- a/core/src/main/java/org/fao/geonet/kernel/AccessManager.java +++ b/core/src/main/java/org/fao/geonet/kernel/AccessManager.java @@ -23,23 +23,44 @@ package org.fao.geonet.kernel; -import static org.fao.geonet.repository.specification.OperationAllowedSpecs.*; -import static org.springframework.data.jpa.domain.Specifications.where; -import java.util.*; - import jeeves.server.UserSession; import jeeves.server.context.ServiceContext; - -import org.fao.geonet.domain.*; +import org.fao.geonet.domain.Group; +import org.fao.geonet.domain.HarvesterSetting; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataSourceInfo; +import org.fao.geonet.domain.Operation; +import org.fao.geonet.domain.OperationAllowed; import org.fao.geonet.domain.Pair; -import org.fao.geonet.repository.*; +import org.fao.geonet.domain.Profile; +import org.fao.geonet.domain.ReservedGroup; +import org.fao.geonet.domain.ReservedOperation; +import org.fao.geonet.domain.User; +import org.fao.geonet.domain.UserGroup; +import org.fao.geonet.domain.User_; +import org.fao.geonet.repository.GroupRepository; +import org.fao.geonet.repository.HarvesterSettingRepository; +import org.fao.geonet.repository.MetadataRepository; +import org.fao.geonet.repository.OperationAllowedRepository; +import org.fao.geonet.repository.OperationRepository; +import org.fao.geonet.repository.SortUtils; +import org.fao.geonet.repository.UserGroupRepository; +import org.fao.geonet.repository.UserRepository; import org.fao.geonet.repository.specification.UserGroupSpecs; import org.jdom.Element; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specifications; -import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +import static org.fao.geonet.repository.specification.OperationAllowedSpecs.hasMetadataId; +import static org.fao.geonet.repository.specification.OperationAllowedSpecs.hasOperation; +import static org.springframework.data.jpa.domain.Specifications.where; /** * Handles the access to a metadata depending on the metadata/group. @@ -270,42 +291,63 @@ public boolean canEdit(final ServiceContext context, final String id) throws Exc * @throws Exception */ public boolean isOwner(final ServiceContext context, final String id) throws Exception { - UserSession us = context.getUserSession(); - if (!us.isAuthenticated()) { - return false; - } //--- retrieve metadata info Metadata info = _metadataRepository.findOne(id); - if (info == null) - return false; + if (info == null) + return false; + final MetadataSourceInfo sourceInfo = info.getSourceInfo(); + return isOwner(context, sourceInfo); + } - //--- check if the user is an administrator + /** + * Return true if the current user is: + * + * + * Note: old GeoNetwork was also restricting editing on harvested + * record. This is not restricted on the server side anymore. + * If a record is harvested it could be edited by default + * but the client application may restrict this condition. + * + * @param sourceInfo The metadata source/owner information + */ + public boolean isOwner(ServiceContext context, MetadataSourceInfo sourceInfo) throws Exception { + + UserSession us = context.getUserSession(); + if (!us.isAuthenticated()) { + return false; + } + + //--- check if the user is an administrator final Profile profile = us.getProfile(); if (profile == Profile.Administrator) return true; - //--- check if the user is the metadata owner - // - if (us.getUserIdAsInt() == info.getSourceInfo().getOwner()) + //--- check if the user is the metadata owner + // + if (us.getUserIdAsInt() == sourceInfo.getOwner()) return true; - //--- check if the user is a reviewer or useradmin - if (profile != Profile.Reviewer && profile != Profile.UserAdmin) - return false; + //--- check if the user is a reviewer or useradmin + if (profile != Profile.Reviewer && profile != Profile.UserAdmin) + return false; - //--- if there is no group owner then the reviewer cannot review and the useradmin cannot administer - final Integer groupOwner = info.getSourceInfo().getGroupOwner(); + //--- if there is no group owner then the reviewer cannot review and the useradmin cannot administer + final Integer groupOwner = sourceInfo.getGroupOwner(); if (groupOwner == null) { return false; } - for (Integer userGroup : getReviewerGroups(us)) { - if (userGroup == groupOwner.intValue()) - return true; - } - return false; - } + for (Integer userGroup : getReviewerGroups(us)) { + if (userGroup == groupOwner.intValue()) + return true; + } + return false; + } /** * TODO javadoc. diff --git a/core/src/main/java/org/fao/geonet/kernel/DataManager.java b/core/src/main/java/org/fao/geonet/kernel/DataManager.java index 097fd7b6808..877ec1f9567 100644 --- a/core/src/main/java/org/fao/geonet/kernel/DataManager.java +++ b/core/src/main/java/org/fao/geonet/kernel/DataManager.java @@ -27,51 +27,100 @@ package org.fao.geonet.kernel; -import static org.fao.geonet.kernel.schema.MetadataSchema.SCHEMATRON_DIR; -import static org.fao.geonet.repository.specification.MetadataSpecs.hasMetadataUuid; - import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; - +import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; import jeeves.TransactionAspect; import jeeves.TransactionTask; -import org.eclipse.jetty.util.ConcurrentHashSet; -import org.fao.geonet.exceptions.JeevesException; -import org.fao.geonet.exceptions.ServiceNotAllowedEx; -import org.fao.geonet.exceptions.XSDValidationErrorEx; - import jeeves.server.UserSession; import jeeves.server.context.ServiceContext; - -import org.fao.geonet.repository.specification.*; -import org.fao.geonet.repository.statistic.PathSpec; -import org.fao.geonet.utils.Log; -import org.fao.geonet.utils.Xml; -import org.fao.geonet.utils.Xml.ErrorHandler; - import jeeves.xlink.Processor; - import org.apache.commons.lang.StringUtils; +import org.eclipse.jetty.util.ConcurrentHashSet; import org.fao.geonet.GeonetContext; import org.fao.geonet.constants.Edit; import org.fao.geonet.constants.Geonet; import org.fao.geonet.constants.Geonet.Namespaces; import org.fao.geonet.constants.Params; -import org.fao.geonet.domain.*; +import org.fao.geonet.domain.Constants; +import org.fao.geonet.domain.Group; +import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataCategory; +import org.fao.geonet.domain.MetadataDataInfo; +import org.fao.geonet.domain.MetadataDataInfo_; +import org.fao.geonet.domain.MetadataFileUpload; +import org.fao.geonet.domain.MetadataFileUpload_; +import org.fao.geonet.domain.MetadataHarvestInfo; +import org.fao.geonet.domain.MetadataRatingByIp; +import org.fao.geonet.domain.MetadataRatingByIpId; +import org.fao.geonet.domain.MetadataSourceInfo; +import org.fao.geonet.domain.MetadataStatus; +import org.fao.geonet.domain.MetadataStatusId; +import org.fao.geonet.domain.MetadataStatusId_; +import org.fao.geonet.domain.MetadataStatus_; +import org.fao.geonet.domain.MetadataType; +import org.fao.geonet.domain.MetadataValidation; +import org.fao.geonet.domain.MetadataValidationId; +import org.fao.geonet.domain.MetadataValidationStatus; +import org.fao.geonet.domain.Metadata_; +import org.fao.geonet.domain.OperationAllowed; +import org.fao.geonet.domain.OperationAllowedId; +import org.fao.geonet.domain.OperationAllowedId_; +import org.fao.geonet.domain.Pair; +import org.fao.geonet.domain.Profile; +import org.fao.geonet.domain.ReservedGroup; +import org.fao.geonet.domain.ReservedOperation; +import org.fao.geonet.domain.Schematron; +import org.fao.geonet.domain.SchematronCriteria; +import org.fao.geonet.domain.SchematronCriteriaGroup; +import org.fao.geonet.domain.SchematronRequirement; +import org.fao.geonet.domain.User; +import org.fao.geonet.domain.UserGroup; +import org.fao.geonet.domain.UserGroupId; +import org.fao.geonet.exceptions.JeevesException; import org.fao.geonet.exceptions.NoSchemaMatchesException; import org.fao.geonet.exceptions.SchemaMatchConflictException; import org.fao.geonet.exceptions.SchematronValidationErrorEx; +import org.fao.geonet.exceptions.ServiceNotAllowedEx; +import org.fao.geonet.exceptions.XSDValidationErrorEx; import org.fao.geonet.kernel.schema.MetadataSchema; import org.fao.geonet.kernel.search.SearchManager; -import org.fao.geonet.domain.Pair; import org.fao.geonet.kernel.setting.SettingManager; import org.fao.geonet.lib.Lib; import org.fao.geonet.notifier.MetadataNotifierManager; -import org.fao.geonet.repository.*; +import org.fao.geonet.repository.GroupRepository; +import org.fao.geonet.repository.MetadataCategoryRepository; +import org.fao.geonet.repository.MetadataFileUploadRepository; +import org.fao.geonet.repository.MetadataRatingByIpRepository; +import org.fao.geonet.repository.MetadataRepository; +import org.fao.geonet.repository.MetadataStatusRepository; +import org.fao.geonet.repository.MetadataValidationRepository; +import org.fao.geonet.repository.OperationAllowedRepository; +import org.fao.geonet.repository.SchematronCriteriaGroupRepository; +import org.fao.geonet.repository.SchematronRepository; +import org.fao.geonet.repository.SortUtils; +import org.fao.geonet.repository.StatusValueRepository; +import org.fao.geonet.repository.Updater; +import org.fao.geonet.repository.UserGroupRepository; +import org.fao.geonet.repository.UserRepository; +import org.fao.geonet.repository.specification.MetadataFileUploadSpecs; +import org.fao.geonet.repository.specification.MetadataSpecs; +import org.fao.geonet.repository.specification.MetadataStatusSpecs; +import org.fao.geonet.repository.specification.OperationAllowedSpecs; +import org.fao.geonet.repository.specification.UserGroupSpecs; +import org.fao.geonet.repository.specification.UserSpecs; +import org.fao.geonet.repository.statistic.PathSpec; import org.fao.geonet.util.ThreadUtils; +import org.fao.geonet.utils.Log; +import org.fao.geonet.utils.Xml; +import org.fao.geonet.utils.Xml.ErrorHandler; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; @@ -89,18 +138,12 @@ import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.interceptor.TransactionAspectSupport; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.Root; - import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -113,6 +156,17 @@ import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Root; + +import static org.fao.geonet.kernel.schema.MetadataSchema.SCHEMATRON_DIR; +import static org.fao.geonet.repository.specification.MetadataSpecs.hasMetadataUuid; +import static org.springframework.data.jpa.domain.Specifications.where; /** * Handles all operations on metadata (select,insert,update,delete etc...). @@ -2540,7 +2594,7 @@ public Optional getOperationAllowedToAdd(final ServiceContext // Reserved groups if (ReservedGroup.isReserved(grpId)) { - Specification hasUserIdAndProfile = Specifications.where(UserGroupSpecs.hasProfile(Profile.Reviewer)) + Specification hasUserIdAndProfile = where(UserGroupSpecs.hasProfile(Profile.Reviewer)) .and(UserGroupSpecs.hasUserId(userId)); List groupIds = userGroupRepo.findGroupIds(hasUserIdAndProfile); @@ -2660,7 +2714,7 @@ public boolean isUserMetadataStatus(int userId) throws Exception { } public boolean existsUser(ServiceContext context, int id) throws Exception { - return context.getBean(UserRepository.class).count(Specifications.where(UserSpecs.hasUserId(id))) > 0; + return context.getBean(UserRepository.class).count(where(UserSpecs.hasUserId(id))) > 0; } //-------------------------------------------------------------------------- @@ -3078,7 +3132,9 @@ private Element buildInfoElem(ServiceContext context, String id, String version) addElement(info, Edit.Info.Elem.VERSION, version); } - buildPrivilegesMetadataInfo(context, id, info); + Map map = Maps.newHashMap(); + map.put(id, info); + buildPrivilegesMetadataInfo(context, map); // add owner name User user = _applicationContext.getBean(UserRepository.class).findOne(owner); @@ -3142,50 +3198,77 @@ private Element buildInfoElem(ServiceContext context, String id, String version) } /** - * Add privileges information about the metadata record + * Add privileges information about metadata record * which depends on context and usually could not be stored in db * or Lucene index because depending on the current user * or current client IP address. * * @param context - * @param id The metadata id - * @param info The element to add the info into + * @param mdIdToInfoMap a map from the metadata Id -> the info element to which the privilege information should be added. * @throws Exception */ - public void buildPrivilegesMetadataInfo(ServiceContext context, String id, - Element info) throws Exception { - if (accessMan.canEdit(context, id)) - addElement(info, Edit.Info.Elem.EDIT, "true"); + public void buildPrivilegesMetadataInfo(ServiceContext context, Map mdIdToInfoMap) throws Exception { + Collection metadataIds = Collections2.transform(mdIdToInfoMap.keySet(), new Function() { + @Nullable + @Override + public Integer apply(String input) { + return Integer.valueOf(input); + } + }); + Specification operationAllowedSpec = OperationAllowedSpecs.hasMetadataIdIn(metadataIds); - if (accessMan.isOwner(context, id)) { - addElement(info, Edit.Info.Elem.OWNER, "true"); - } + final Collection allUserGroups = accessMan.getUserGroups(context.getUserSession(), context.getIpAddress(), false); + final SetMultimap operationsPerMetadata = loadOperationsAllowed(context, where(operationAllowedSpec).and(OperationAllowedSpecs.hasGroupIdIn(allUserGroups))); + final Set visibleToAll = loadOperationsAllowed(context, where(operationAllowedSpec).and(OperationAllowedSpecs.isPublic(ReservedOperation.view))).keySet(); + final Set downloadableByGuest = loadOperationsAllowed(context, where(operationAllowedSpec).and(OperationAllowedSpecs.hasGroupId(ReservedGroup.guest.getId())).and(OperationAllowedSpecs.hasOperation(ReservedOperation.download))).keySet(); + final Map allSourceInfo = _metadataRepository.findAllSourceInfo(MetadataSpecs.hasMetadataIdIn(metadataIds)); - if (accessMan.isVisibleToAll(id)) { - addElement(info, Edit.Info.Elem.IS_PUBLISHED_TO_ALL, "true"); - } else { - addElement(info, Edit.Info.Elem.IS_PUBLISHED_TO_ALL, "false"); - } + for (Map.Entry entry : mdIdToInfoMap.entrySet()) { + Element infoEl = entry.getValue(); + final Integer mdId = Integer.valueOf(entry.getKey()); + MetadataSourceInfo sourceInfo = allSourceInfo.get(mdId); + Set operations = operationsPerMetadata.get(mdId); + if (operations == null) { + operations = Collections.emptySet(); + } - Set operations = accessMan.getAllOperations(context, id, context.getIpAddress()); - Set hsOper = accessMan.getOperationNames(context, id, context.getIpAddress(), operations); + boolean isOwner = accessMan.isOwner(context, sourceInfo); - addElement(info, Edit.Info.Elem.VIEW, String.valueOf(hsOper.contains(ReservedOperation.view.name()))); - addElement(info, Edit.Info.Elem.NOTIFY, String.valueOf(hsOper.contains(ReservedOperation.notify.name()))); - addElement(info, Edit.Info.Elem.DOWNLOAD, String.valueOf(hsOper.contains(ReservedOperation.download.name()))); - addElement(info, Edit.Info.Elem.DYNAMIC, String.valueOf(hsOper.contains(ReservedOperation.dynamic.name()))); - addElement(info, Edit.Info.Elem.FEATURED, String.valueOf(hsOper.contains(ReservedOperation.featured.name()))); + if (isOwner) { + operations = Sets.newHashSet(Arrays.asList(ReservedOperation.values())); + } - if (!hsOper.contains(ReservedOperation.download.name())) { - ApplicationContext appContext = context.getApplicationContext(); - int groupId = ReservedGroup.guest.getId(); - int metadataId = Integer.parseInt(id); - int operationId = ReservedOperation.download.getId(); - OperationAllowed opAllowed = appContext.getBean(OperationAllowedRepository.class).findOneById_GroupIdAndId_MetadataIdAndId_OperationId(groupId, metadataId, operationId); - boolean canDownload = opAllowed != null; - addElement(info, Edit.Info.Elem.GUEST_DOWNLOAD, String.valueOf(canDownload)); + if (isOwner || operations.contains(ReservedOperation.editing) { + addElement(infoEl, Edit.Info.Elem.EDIT, "true"); + } + + if (isOwner) { + addElement(infoEl, Edit.Info.Elem.OWNER, "true"); + } + + addElement(infoEl, Edit.Info.Elem.IS_PUBLISHED_TO_ALL, visibleToAll.contains(mdId)); + addElement(infoEl, ReservedOperation.view.name(), operations.contains(ReservedOperation.view)); + addElement(infoEl, ReservedOperation.notify.name(), operations.contains(ReservedOperation.notify)); + addElement(infoEl, ReservedOperation.download.name(), operations.contains(ReservedOperation.download)); + addElement(infoEl, ReservedOperation.dynamic.name(), operations.contains(ReservedOperation.dynamic)); + addElement(infoEl, ReservedOperation.featured.name(), operations.contains(ReservedOperation.featured)); + + if (!operations.contains(ReservedOperation.download)) { + addElement(infoEl, Edit.Info.Elem.GUEST_DOWNLOAD, downloadableByGuest.contains(mdId)); + } } + } + private SetMultimap loadOperationsAllowed(ServiceContext context, Specification + operationAllowedSpec) { + final OperationAllowedRepository operationAllowedRepo= context.getBean(OperationAllowedRepository.class); + List operationsAllowed = operationAllowedRepo.findAll(operationAllowedSpec); + SetMultimap operationsPerMetadata = HashMultimap.create(); + for (OperationAllowed allowed : operationsAllowed) { + final OperationAllowedId id = allowed.getId(); + operationsPerMetadata.put(id.getMetadataId(), ReservedOperation.lookup(id.getOperationId())); + } + return operationsPerMetadata; } /** @@ -3194,8 +3277,8 @@ public void buildPrivilegesMetadataInfo(ServiceContext context, String id, * @param name * @param value */ - private static void addElement(Element root, String name, String value) { - root.addContent(new Element(name).setText(value)); + private static void addElement(Element root, String name, Object value) { + root.addContent(new Element(name).setText(value.toString())); } diff --git a/core/src/main/java/org/fao/geonet/kernel/search/LuceneSearcher.java b/core/src/main/java/org/fao/geonet/kernel/search/LuceneSearcher.java index 578cb54ce8e..1b458c54cb1 100644 --- a/core/src/main/java/org/fao/geonet/kernel/search/LuceneSearcher.java +++ b/core/src/main/java/org/fao/geonet/kernel/search/LuceneSearcher.java @@ -23,19 +23,13 @@ package org.fao.geonet.kernel.search; +import com.google.common.collect.Maps; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.WKTReader; import jeeves.constants.Jeeves; import jeeves.server.ServiceConfig; import jeeves.server.UserSession; import jeeves.server.context.ServiceContext; -import org.fao.geonet.domain.ISODate; -import org.fao.geonet.domain.Metadata; -import org.fao.geonet.domain.Profile; -import org.fao.geonet.exceptions.BadParameterEx; -import org.fao.geonet.utils.Log; -import org.fao.geonet.Util; -import org.fao.geonet.utils.Xml; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.lucene.analysis.TokenStream; @@ -76,11 +70,20 @@ import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.TopFieldCollector; import org.fao.geonet.GeonetContext; +import org.fao.geonet.Util; import org.fao.geonet.constants.Edit; import org.fao.geonet.constants.Geonet; +import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.Pair; +import org.fao.geonet.domain.Profile; +import org.fao.geonet.domain.ReservedOperation; +import org.fao.geonet.exceptions.BadParameterEx; import org.fao.geonet.exceptions.UnAuthorizedException; import org.fao.geonet.kernel.AccessManager; import org.fao.geonet.kernel.DataManager; +import org.fao.geonet.kernel.region.Region; +import org.fao.geonet.kernel.region.RegionsDAO; import org.fao.geonet.kernel.search.LuceneConfig.Facet; import org.fao.geonet.kernel.search.LuceneConfig.FacetConfig; import org.fao.geonet.kernel.search.LuceneConfig.LuceneConfigNumericField; @@ -88,18 +91,15 @@ import org.fao.geonet.kernel.search.index.GeonetworkMultiReader; import org.fao.geonet.kernel.search.log.SearcherLogger; import org.fao.geonet.kernel.search.lucenequeries.DateRangeQuery; -import org.fao.geonet.domain.Pair; import org.fao.geonet.kernel.search.spatial.SpatialFilter; import org.fao.geonet.kernel.setting.SettingInfo; import org.fao.geonet.languages.LanguageDetector; -import org.fao.geonet.kernel.region.Region; -import org.fao.geonet.kernel.region.RegionsDAO; +import org.fao.geonet.utils.Log; +import org.fao.geonet.utils.Xml; import org.jdom.Content; import org.jdom.Element; import org.jdom.JDOMException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.Constructor; @@ -119,6 +119,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * search metadata locally using lucene. @@ -321,7 +323,9 @@ else if ("index".equals(sFast)) { md = LuceneSearcher.getMetadataFromIndex(doc, id, true, _language.presentationLanguage, _luceneConfig.getMultilingualSortFields(), _luceneConfig.getDumpFields()); // Retrieve dynamic properties according to context (eg. editable) - gc.getBean(DataManager.class).buildPrivilegesMetadataInfo(srvContext, id, md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE)); + Map map = Maps.newHashMap(); + map.put(id, md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE)); + gc.getBean(DataManager.class).buildPrivilegesMetadataInfo(srvContext, map); } else if (srvContext != null) { boolean forEditing = false, withValidationErrors = false, keepXlinkAttributes = false; @@ -1477,8 +1481,8 @@ private static Element getMetadataFromIndexForPdf(UserSession us, Set u Element info = md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE); if ( us.getProfile() == Profile.Administrator) { - info.addContent(new Element(Edit.Info.Elem.DOWNLOAD).setText("true")); - info.addContent(new Element(Edit.Info.Elem.DYNAMIC).setText("true")); + info.addContent(new Element(ReservedOperation.download.name()).setText("true")); + info.addContent(new Element(ReservedOperation.dynamic.name()).setText("true")); } else { // Owner @@ -1497,8 +1501,8 @@ private static Element getMetadataFromIndexForPdf(UserSession us, Set u } if (isOwner) { - info.addContent(new Element(Edit.Info.Elem.DOWNLOAD).setText("true")); - info.addContent(new Element(Edit.Info.Elem.DYNAMIC).setText("true")); + info.addContent(new Element(ReservedOperation.download.name()).setText("true")); + info.addContent(new Element(ReservedOperation.dynamic.name()).setText("true")); } else { // Download @@ -1506,7 +1510,7 @@ private static Element getMetadataFromIndexForPdf(UserSession us, Set u for (IndexableField f : values) { if (f != null) { if (userGroups.contains(Integer.parseInt(f.stringValue()))) { - info.addContent(new Element(Edit.Info.Elem.DOWNLOAD).setText("true")); + info.addContent(new Element(ReservedOperation.download.name()).setText("true")); break; } } @@ -1517,7 +1521,7 @@ private static Element getMetadataFromIndexForPdf(UserSession us, Set u for (IndexableField f : values) { if (f != null) { if (userGroups.contains(Integer.parseInt(f.stringValue()))) { - info.addContent(new Element(Edit.Info.Elem.DYNAMIC).setText("true")); + info.addContent(new Element(ReservedOperation.dynamic.name()).setText("true")); break; } } diff --git a/core/src/test/java/org/fao/geonet/kernel/DataManagerIntegrationTest.java b/core/src/test/java/org/fao/geonet/kernel/DataManagerIntegrationTest.java index 677a9af425b..ee9733c85fd 100644 --- a/core/src/test/java/org/fao/geonet/kernel/DataManagerIntegrationTest.java +++ b/core/src/test/java/org/fao/geonet/kernel/DataManagerIntegrationTest.java @@ -1,28 +1,45 @@ package org.fao.geonet.kernel; -import static org.junit.Assert.*; -import static org.springframework.data.jpa.domain.Specifications.where; - import com.google.common.base.Optional; +import com.google.common.collect.Maps; import jeeves.server.UserSession; import jeeves.server.context.ServiceContext; import org.fao.geonet.AbstractCoreIntegrationTest; +import org.fao.geonet.constants.Geonet; import org.fao.geonet.constants.Params; -import org.fao.geonet.domain.*; +import org.fao.geonet.domain.Group; +import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataCategory; +import org.fao.geonet.domain.MetadataStatus; +import org.fao.geonet.domain.MetadataType; +import org.fao.geonet.domain.ReservedGroup; +import org.fao.geonet.domain.Source; +import org.fao.geonet.domain.User; import org.fao.geonet.kernel.search.IndexAndTaxonomy; import org.fao.geonet.kernel.search.SearchManager; -import org.fao.geonet.repository.*; +import org.fao.geonet.repository.GroupRepository; +import org.fao.geonet.repository.MetadataCategoryRepository; +import org.fao.geonet.repository.MetadataRepository; +import org.fao.geonet.repository.SourceRepository; +import org.fao.geonet.repository.Updater; import org.fao.geonet.repository.specification.MetadataSpecs; import org.fao.geonet.utils.Xml; import org.jdom.Element; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.domain.Specifications; -import javax.annotation.Nonnull; import java.io.ByteArrayInputStream; +import java.util.Map; import java.util.UUID; +import javax.annotation.Nonnull; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.data.jpa.domain.Specifications.where; /** * Tests for the DataManager. @@ -55,6 +72,33 @@ public void testDeleteMetadata() throws Exception { assertEquals(count, _metadataRepository.count()); } + @Test + public void testBuildPrivilegesMetadataInfo() throws Exception { + final ServiceContext serviceContext = createServiceContext(); + loginAsAdmin(serviceContext); + final UserSession userSession = serviceContext.getUserSession(); + + final String mdId1 = _dataManager.insertMetadata(serviceContext, "iso19139", new Element("MD_Metadata"), "uuid", + userSession.getUserIdAsInt(), + "" + ReservedGroup.all.getId(), "sourceid", "n", "doctype", null, new ISODate().getDateAndTime(), new ISODate().getDateAndTime(), + false, false); + + + Element info = new Element("info", Geonet.Namespaces.GEONET); + Map map = Maps.newHashMap(); + map.put(mdId1, info); + info.removeContent(); + _dataManager.buildPrivilegesMetadataInfo(serviceContext, map); + assertEqualsText("true", info, "edit"); + assertEqualsText("true", info, "owner"); + assertEqualsText("true", info, "isPublishedToAll"); + assertEqualsText("true", info, "view"); + assertEqualsText("true", info, "notify"); + assertEqualsText("true", info, "download"); + assertEqualsText("true", info, "dynamic"); + assertEqualsText("true", info, "featured"); + } + @Test public void testCreateMetadataWithTemplateMetadata() throws Exception { final ServiceContext serviceContext = createServiceContext(); diff --git a/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryCustom.java b/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryCustom.java index db3ee81785d..11220edbb15 100644 --- a/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryCustom.java +++ b/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryCustom.java @@ -2,6 +2,7 @@ import org.fao.geonet.domain.ISODate; import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataSourceInfo; import org.fao.geonet.domain.Pair; import org.fao.geonet.repository.reports.MetadataReportsQueries; import org.fao.geonet.repository.statistic.MetadataStatisticsQueries; @@ -9,9 +10,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; +import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.List; /** * Custom (Non spring-data) Query methods for {@link Metadata} entities. @@ -81,4 +83,11 @@ public interface MetadataRepositoryCustom { @Nullable Metadata findOneOldestByChangeDate(); + /** + * Load the source info objects for all the metadata selected by the spec. + * + * @param spec the specification identifying the metadata of interest + * @return a map of metadataId -> SourceInfo + */ + Map findAllSourceInfo(Specification spec); } diff --git a/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryImpl.java b/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryImpl.java index 7b0635a4d99..27b62f38355 100644 --- a/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryImpl.java +++ b/domain/src/main/java/org/fao/geonet/repository/MetadataRepositoryImpl.java @@ -1,6 +1,12 @@ package org.fao.geonet.repository; -import org.fao.geonet.domain.*; +import com.google.common.collect.Maps; +import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataDataInfo_; +import org.fao.geonet.domain.MetadataSourceInfo; +import org.fao.geonet.domain.Metadata_; +import org.fao.geonet.domain.Pair; import org.fao.geonet.repository.reports.MetadataReportsQueries; import org.fao.geonet.repository.statistic.MetadataStatisticsQueries; import org.springframework.data.domain.Page; @@ -9,15 +15,20 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Tuple; import javax.persistence.TypedQuery; -import javax.persistence.criteria.*; -import java.util.ArrayList; -import java.util.List; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Root; /** * Implementation for all {@link Metadata} queries that cannot be automatically generated by Spring-data. @@ -104,4 +115,23 @@ public Metadata findOneOldestByChangeDate() { return _entityManager.createQuery(query).setMaxResults(1).getSingleResult(); } + @Override + public Map findAllSourceInfo(Specification spec) { + CriteriaBuilder cb = _entityManager.getCriteriaBuilder(); + CriteriaQuery cbQuery = cb.createQuery(Object[].class); + Root root = cbQuery.from(Metadata.class); + cbQuery.select(cb.array(root.get(Metadata_.id), root.get(Metadata_.sourceInfo))); + + cbQuery.where(spec.toPredicate(root, cbQuery, cb)); + Map results = Maps.newHashMap(); + final List resultList = _entityManager.createQuery(cbQuery).getResultList(); + for (Object[] objects : resultList) { + final Integer metadataId = (Integer) objects[0]; + final MetadataSourceInfo sourceInfo = (MetadataSourceInfo) objects[1]; + results.put(metadataId, sourceInfo); + } + + return results; + } + } diff --git a/domain/src/main/java/org/fao/geonet/repository/specification/OperationAllowedSpecs.java b/domain/src/main/java/org/fao/geonet/repository/specification/OperationAllowedSpecs.java index 964cba740c5..5a4fb6e2e19 100644 --- a/domain/src/main/java/org/fao/geonet/repository/specification/OperationAllowedSpecs.java +++ b/domain/src/main/java/org/fao/geonet/repository/specification/OperationAllowedSpecs.java @@ -3,6 +3,7 @@ import org.fao.geonet.domain.*; import org.springframework.data.jpa.domain.Specification; +import java.util.Collection; import javax.persistence.criteria.*; public final class OperationAllowedSpecs { @@ -47,8 +48,7 @@ public static Specification hasGroupId(final int groupId) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { Path mdIdAttributePath = root.get(OperationAllowed_.id).get(OperationAllowedId_.groupId); - Predicate mdIdEqualPredicate = cb.equal(mdIdAttributePath, cb.literal(groupId)); - return mdIdEqualPredicate; + return cb.equal(mdIdAttributePath, cb.literal(groupId)); } }; } @@ -98,4 +98,31 @@ public Predicate toPredicate(Root root, CriteriaQuery query } }; } + + /** + * A specification that selects all the operations allowed for all the metadata. + * @param metadataIds the ids of all the metadata + */ + public static Specification hasMetadataIdIn(final Collection metadataIds) { + return new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return root.get(OperationAllowed_.id).get(OperationAllowedId_.metadataId).in(metadataIds); + } + }; + } + + /** + * A specification that selects all the operations allowed for all the groups provided. + * @param groupIds the ids of all the groups + */ + public static Specification hasGroupIdIn(final Collection groupIds) { + return new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return root.get(OperationAllowed_.id).get(OperationAllowedId_.groupId).in(groupIds); + } + }; + } + } diff --git a/domain/src/test/java/org/fao/geonet/repository/MetadataRepositoryTest.java b/domain/src/test/java/org/fao/geonet/repository/MetadataRepositoryTest.java index af5f38d32c1..21dfc50f1f5 100644 --- a/domain/src/test/java/org/fao/geonet/repository/MetadataRepositoryTest.java +++ b/domain/src/test/java/org/fao/geonet/repository/MetadataRepositoryTest.java @@ -1,6 +1,11 @@ package org.fao.geonet.repository; -import org.fao.geonet.domain.*; +import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.Metadata; +import org.fao.geonet.domain.MetadataDataInfo_; +import org.fao.geonet.domain.MetadataSourceInfo; +import org.fao.geonet.domain.Metadata_; +import org.fao.geonet.domain.Pair; import org.fao.geonet.repository.specification.MetadataSpecs; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -8,13 +13,22 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +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; public class MetadataRepositoryTest extends AbstractSpringDataTest { @@ -169,6 +183,25 @@ public void testFindAllIdsAndChangeDates() throws Exception { assertEquals(metadata3.getDataInfo().getChangeDate(), secondPage.getContent().get(2).two()); } + @Test + public void testFindAllSourceInfo() throws Exception { + Metadata metadata = _repo.save(newMetadata()); + Metadata metadata2 = _repo.save(newMetadata()); + Metadata metadata3 = _repo.save(newMetadata()); + + final Specification spec = MetadataSpecs.hasMetadataIdIn(Arrays.asList(metadata.getId(), metadata3.getId())); + final Map allSourceInfo = _repo.findAllSourceInfo(Specifications.where(spec)); + + assertEquals(2, allSourceInfo.size()); + assertTrue(allSourceInfo.containsKey(metadata.getId())); + assertFalse(allSourceInfo.containsKey(metadata2.getId())); + assertTrue(allSourceInfo.containsKey(metadata3.getId())); + + assertNotNull(allSourceInfo.get(metadata.getId())); + assertNull(allSourceInfo.get(metadata2.getId())); + assertNotNull(allSourceInfo.get(metadata3.getId())); + } + private Metadata updateChangeDate(Metadata metadata, String date) { metadata.getDataInfo().setChangeDate(new ISODate(date)); return metadata; diff --git a/domain/src/test/java/org/fao/geonet/repository/specification/OperationAllowedSpecsTest.java b/domain/src/test/java/org/fao/geonet/repository/specification/OperationAllowedSpecsTest.java index 807b44a810b..23454a6797a 100644 --- a/domain/src/test/java/org/fao/geonet/repository/specification/OperationAllowedSpecsTest.java +++ b/domain/src/test/java/org/fao/geonet/repository/specification/OperationAllowedSpecsTest.java @@ -1,13 +1,18 @@ package org.fao.geonet.repository.specification; import com.google.common.base.Optional; -import org.fao.geonet.domain.*; +import org.fao.geonet.domain.OperationAllowed; +import org.fao.geonet.domain.OperationAllowedId_; +import org.fao.geonet.domain.OperationAllowed_; +import org.fao.geonet.domain.ReservedGroup; +import org.fao.geonet.domain.ReservedOperation; import org.fao.geonet.repository.AbstractOperationsAllowedTest; import org.fao.geonet.repository.SortUtils; import org.junit.Test; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; +import java.util.Arrays; import java.util.List; import static org.fao.geonet.repository.SpringDataTestSupport.setId; @@ -43,6 +48,22 @@ public void testHasMetadataId() { assertEquals(_md1.getId(), found.get(2).getId().getMetadataId()); } + @Test + public void testHasMetadataIdIn() { + Specification hasMetadataId = OperationAllowedSpecs.hasMetadataIdIn(Arrays.asList(_md1.getId(), _md2.getId())); + List found = _opAllowRepo.findAll(hasMetadataId, new Sort(operationIdPath(), metadataIdPath())); + + assertEquals(found.size(), 4); + } + + @Test + public void testHasGroupIdIn() { + Specification hasGroupIdIn = OperationAllowedSpecs.hasGroupIdIn(Arrays.asList(_intranetGroup.getId())); + List found = _opAllowRepo.findAll(hasGroupIdIn, new Sort(operationIdPath(), metadataIdPath())); + + assertEquals(found.size(), 3); + } + @Test public void testIsPublic() throws Exception { int viewOpId = ReservedOperation.view.getId(); diff --git a/web/src/main/webapp/WEB-INF/config-lucene.xml b/web/src/main/webapp/WEB-INF/config-lucene.xml index 9606e4f4ef9..be9ad7454c9 100644 --- a/web/src/main/webapp/WEB-INF/config-lucene.xml +++ b/web/src/main/webapp/WEB-INF/config-lucene.xml @@ -15,10 +15,10 @@ 36 - 30000 + 1000 - false + true org.tuckey @@ -196,6 +191,10 @@ org.slf4j slf4j-log4j12 + + org.slf4j + slf4j-api + jaxen jaxen diff --git a/core/src/main/java/org/fao/geonet/kernel/DataManager.java b/core/src/main/java/org/fao/geonet/kernel/DataManager.java index fa12afa3f9f..2a6930cbe27 100644 --- a/core/src/main/java/org/fao/geonet/kernel/DataManager.java +++ b/core/src/main/java/org/fao/geonet/kernel/DataManager.java @@ -133,7 +133,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.domain.Specifications; import org.springframework.transaction.NoTransactionException; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.interceptor.TransactionAspectSupport; @@ -3278,7 +3277,7 @@ private SetMultimap loadOperationsAllowed(ServiceCon * @param value */ private static void addElement(Element root, String name, Object value) { - root.addContent(new Element(name).setText(value.toString())); + root.addContent(new Element(name).setText(value == null ? "" : value.toString())); } diff --git a/domain/pom.xml b/domain/pom.xml index 4d96bdeb839..211d85ecad7 100644 --- a/domain/pom.xml +++ b/domain/pom.xml @@ -44,6 +44,10 @@ org.hibernate hibernate-entitymanager + + org.hibernate + hibernate-ehcache + org.springframework spring-context diff --git a/domain/src/main/java/org/fao/geonet/domain/StatusValue.java b/domain/src/main/java/org/fao/geonet/domain/StatusValue.java index c5ce0257607..12f85cde782 100644 --- a/domain/src/main/java/org/fao/geonet/domain/StatusValue.java +++ b/domain/src/main/java/org/fao/geonet/domain/StatusValue.java @@ -13,6 +13,7 @@ @Entity @Access(AccessType.PROPERTY) @Table(name = "StatusValues") +@Cacheable @EntityListeners(StatusValueEntityListenerManager.class) @SequenceGenerator(name=StatusValue.ID_SEQ_NAME, initialValue=100, allocationSize=1) public class StatusValue extends Localized { diff --git a/domain/src/main/java/org/fao/geonet/repository/statistic/SearchRequestRepositoryImpl.java b/domain/src/main/java/org/fao/geonet/repository/statistic/SearchRequestRepositoryImpl.java index 755998b51be..d35d1bef586 100644 --- a/domain/src/main/java/org/fao/geonet/repository/statistic/SearchRequestRepositoryImpl.java +++ b/domain/src/main/java/org/fao/geonet/repository/statistic/SearchRequestRepositoryImpl.java @@ -3,6 +3,7 @@ import com.google.common.base.Function; import com.google.common.collect.Lists; import org.fao.geonet.domain.ISODate; +import org.fao.geonet.domain.ISODate_; import org.fao.geonet.domain.Pair; import org.fao.geonet.domain.ReservedOperation; import org.fao.geonet.domain.statistic.SearchRequest; @@ -10,14 +11,22 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; +import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Tuple; -import javax.persistence.criteria.*; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CompoundSelection; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; import javax.persistence.metamodel.SingularAttribute; -import java.util.List; /** * Implementation for the custom search methods of {@link org.fao.geonet.repository.statistic.SearchRequestParamRepositoryCustom}. @@ -67,7 +76,7 @@ List> getRequestDateToRequestCountBetween(@Nonnull final T date final Root requestRoot = cbQuery.from(SearchRequest.class); final Path requestDate = requestRoot.get(SearchRequest_.requestDate); - final Expression requestDateByType = cb.substring(requestDate.as(String.class), 1, dateInterval.getSubstringEnd()); + final Expression requestDateByType = cb.substring(requestDate.get(ISODate_.dateAndTime), 1, dateInterval.getSubstringEnd()); Predicate whereClause = cb.and(cb.lessThanOrEqualTo(requestDate, to), cb.greaterThanOrEqualTo(requestDate, from)); if (spec != null) { @@ -79,7 +88,8 @@ List> getRequestDateToRequestCountBetween(@Nonnull final T date .groupBy(requestDateByType) .orderBy(cb.desc(requestDateByType)); - List stats = _EntityManager.createQuery(cbQuery).getResultList(); + final TypedQuery query = _EntityManager.createQuery(cbQuery); + List stats = query.getResultList(); return Lists.transform(stats, new Function>() { @Nullable diff --git a/domain/src/main/resources/META-INF/persistence.xml b/domain/src/main/resources/META-INF/persistence.xml index 52ff4e4a36a..b750f943024 100644 --- a/domain/src/main/resources/META-INF/persistence.xml +++ b/domain/src/main/resources/META-INF/persistence.xml @@ -1,5 +1,8 @@ - + + ENABLE_SELECTIVE + + \ No newline at end of file diff --git a/domain/src/main/resources/config-spring-geonetwork.xml b/domain/src/main/resources/config-spring-geonetwork.xml index a715f062f5c..7e12c24744b 100644 --- a/domain/src/main/resources/config-spring-geonetwork.xml +++ b/domain/src/main/resources/config-spring-geonetwork.xml @@ -2,9 +2,11 @@ @@ -19,16 +21,7 @@ - - - - - - - - - - + diff --git a/domain/src/test/resources/domain-repository-test-context.xml b/domain/src/test/resources/domain-repository-test-context.xml index c3352960510..d3efaf2b328 100644 --- a/domain/src/test/resources/domain-repository-test-context.xml +++ b/domain/src/test/resources/domain-repository-test-context.xml @@ -1,8 +1,10 @@ @@ -34,4 +36,19 @@ + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 7406a49bd8c..1b26ea2ae59 100644 --- a/pom.xml +++ b/pom.xml @@ -361,11 +361,6 @@ - - net.sf.ehcache - ehcache-core - 2.5.3 - org.tuckey @@ -534,6 +529,11 @@ batik-ext 1.6 + + org.slf4j + slf4j-api + 1.7.5 + org.slf4j slf4j-log4j12 @@ -966,8 +966,13 @@ org.hibernate hibernate-entitymanager - 4.3.0.Beta5 + 4.3.6.Final + + org.hibernate + hibernate-ehcache + 4.3.6.Final + org.springframework.data spring-data-jpa diff --git a/web/pom.xml b/web/pom.xml index 034c00748b0..355ac7ff91c 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -32,12 +32,6 @@ org.slf4j slf4j-log4j12 - - - net.sf.ehcache - ehcache-core - - org.tuckey diff --git a/web/src/main/webapp/WEB-INF/classes/log4j.xml b/web/src/main/webapp/WEB-INF/classes/log4j.xml index 56cbd2c81f3..c17ed3f73cf 100644 --- a/web/src/main/webapp/WEB-INF/classes/log4j.xml +++ b/web/src/main/webapp/WEB-INF/classes/log4j.xml @@ -183,7 +183,7 @@ - + diff --git a/web/src/main/webapp/WEB-INF/config-spring-geonetwork.xml b/web/src/main/webapp/WEB-INF/config-spring-geonetwork.xml index 3adb0d009e5..ac50c644fcb 100644 --- a/web/src/main/webapp/WEB-INF/config-spring-geonetwork.xml +++ b/web/src/main/webapp/WEB-INF/config-spring-geonetwork.xml @@ -57,4 +57,20 @@ spa tur + + + + + + + + + + + + + + + + From a1a61d7c64d7dc60eb1ad2ebe8ba48a1dff3417f Mon Sep 17 00:00:00 2001 From: Jesse Eichar Date: Wed, 30 Jul 2014 16:24:29 +0200 Subject: [PATCH 4/5] allow tests to use hibernate caching --- .../src/test/resources/domain-repository-test-context.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/domain/src/test/resources/domain-repository-test-context.xml b/domain/src/test/resources/domain-repository-test-context.xml index d3efaf2b328..ffab4ab38eb 100644 --- a/domain/src/test/resources/domain-repository-test-context.xml +++ b/domain/src/test/resources/domain-repository-test-context.xml @@ -43,9 +43,9 @@ - - - + + + From 1b27140dbb1e65a387d20441c2e36d99c36ff5b6 Mon Sep 17 00:00:00 2001 From: Jesse Eichar Date: Wed, 30 Jul 2014 16:51:11 +0200 Subject: [PATCH 5/5] Languages cached. Disable sql logging by default --- .../org/fao/geonet/domain/IsoLanguage.java | 18 +++++++++++++++++- .../java/org/fao/geonet/domain/Language.java | 1 + web/src/main/webapp/WEB-INF/classes/log4j.xml | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/domain/src/main/java/org/fao/geonet/domain/IsoLanguage.java b/domain/src/main/java/org/fao/geonet/domain/IsoLanguage.java index a472acd4ab0..8cbd6462d3f 100644 --- a/domain/src/main/java/org/fao/geonet/domain/IsoLanguage.java +++ b/domain/src/main/java/org/fao/geonet/domain/IsoLanguage.java @@ -2,8 +2,23 @@ import org.fao.geonet.entitylistener.IsoLanguageEntityListenerManager; -import javax.persistence.*; import java.util.Map; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Cacheable; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapKeyColumn; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; /** * An entity representing the bi-directional mapping between the different iso language codes (de -> ger) and translations of the @@ -16,6 +31,7 @@ @Access(AccessType.PROPERTY) @Table(name = "IsoLanguages") @EntityListeners(IsoLanguageEntityListenerManager.class) +@Cacheable @SequenceGenerator(name=IsoLanguage.ID_SEQ_NAME, initialValue=10000, allocationSize=1) public class IsoLanguage extends Localized { static final String ID_SEQ_NAME = "iso_language_id_seq"; diff --git a/domain/src/main/java/org/fao/geonet/domain/Language.java b/domain/src/main/java/org/fao/geonet/domain/Language.java index 8b944837620..2c564f24290 100644 --- a/domain/src/main/java/org/fao/geonet/domain/Language.java +++ b/domain/src/main/java/org/fao/geonet/domain/Language.java @@ -17,6 +17,7 @@ @Entity @Access(AccessType.PROPERTY) @Table(name = "Languages") +@Cacheable @EntityListeners(LanguageEntityListenerManager.class) public class Language extends GeonetEntity { String _id; diff --git a/web/src/main/webapp/WEB-INF/classes/log4j.xml b/web/src/main/webapp/WEB-INF/classes/log4j.xml index c17ed3f73cf..06478f49cf5 100644 --- a/web/src/main/webapp/WEB-INF/classes/log4j.xml +++ b/web/src/main/webapp/WEB-INF/classes/log4j.xml @@ -68,7 +68,7 @@ - +