diff --git a/config/alfresco/subsystems/Search/solr/solr-search-context.xml b/config/alfresco/subsystems/Search/solr/solr-search-context.xml index dc82848a2a..b6c54bdf2d 100644 --- a/config/alfresco/subsystems/Search/solr/solr-search-context.xml +++ b/config/alfresco/subsystems/Search/solr/solr-search-context.xml @@ -40,6 +40,9 @@ + + + @@ -164,9 +167,6 @@ - - - diff --git a/source/java/org/alfresco/cmis/search/CmisFunctionEvaluationContext.java b/source/java/org/alfresco/cmis/search/CmisFunctionEvaluationContext.java index ec61ad212c..762631f274 100644 --- a/source/java/org/alfresco/cmis/search/CmisFunctionEvaluationContext.java +++ b/source/java/org/alfresco/cmis/search/CmisFunctionEvaluationContext.java @@ -93,6 +93,7 @@ public class CmisFunctionEvaluationContext implements FunctionEvaluationContext EXPOSED_FIELDS.add(AbstractLuceneQueryParser.FIELD_PRIMARYASSOCTYPEQNAME); EXPOSED_FIELDS.add(AbstractLuceneQueryParser.FIELD_DBID); EXPOSED_FIELDS.add(AbstractLuceneQueryParser.FIELD_TAG); + EXPOSED_FIELDS.add(AbstractLuceneQueryParser.FIELD_TENANT); EXPOSED_FIELDS.add(AbstractLuceneQueryParser.FIELD_ANCESTOR); diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java index 9642d70cc5..f883779269 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2011 Alfresco Software Limited. * * This file is part of Alfresco * @@ -23,9 +23,7 @@ import org.alfresco.repo.search.IndexerException; import org.alfresco.repo.search.QueryRegisterComponent; import org.alfresco.repo.search.SearcherException; import org.alfresco.repo.search.impl.NoActionIndexer; -import org.alfresco.repo.search.impl.lucene.ADMLuceneSearcherImpl; import org.alfresco.repo.search.impl.lucene.AbstractIndexerAndSearcher; -import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; @@ -43,7 +41,6 @@ public class SolrIndexerAndSearcherFactory extends AbstractIndexerAndSearcher private NamespacePrefixResolver namespacePrefixResolver; private NodeService nodeService; private QueryRegisterComponent queryRegister; - private TenantService tenantService; private String baseUrl; public DictionaryService getDictionaryService() @@ -86,16 +83,6 @@ public class SolrIndexerAndSearcherFactory extends AbstractIndexerAndSearcher this.queryRegister = queryRegister; } - public TenantService getTenantService() - { - return tenantService; - } - - public void setTenantService(TenantService tenantService) - { - this.tenantService = tenantService; - } - public String getBaseUrl() { return baseUrl; @@ -121,15 +108,12 @@ public class SolrIndexerAndSearcherFactory extends AbstractIndexerAndSearcher @Override public SearchService getSearcher(StoreRef storeRef, boolean searchDelta) throws SearcherException { - //storeRef = tenantService.getName(storeRef); - SolrSearchService searchService = new SolrSearchService(); searchService.setDictionaryService(dictionaryService); searchService.setNamespacePrefixResolver(namespacePrefixResolver); searchService.setNodeService(nodeService); searchService.setQueryLanguages(getQueryLanguages()); searchService.setQueryRegister(queryRegister); - searchService.setTenantService(tenantService); return searchService; } diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java index 326275476a..7a209b736f 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2011 Alfresco Software Limited. * * This file is part of Alfresco * @@ -30,15 +30,14 @@ import javax.servlet.http.HttpServletResponse; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.httpclient.HttpClientFactory; -import org.alfresco.model.ContentModel; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException; import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet; +import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters.FieldFacet; import org.alfresco.service.cmr.search.SearchParameters.FieldFacetMethod; @@ -76,6 +75,8 @@ public class SolrQueryHTTPClient private NodeService nodeService; private PermissionService permissionService; + + private TenantService tenantService; private Map languageMappings; @@ -121,6 +122,11 @@ public class SolrQueryHTTPClient { this.permissionService = permissionService; } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } public void setLanguageMappings(Map languageMappings) { @@ -136,11 +142,6 @@ public class SolrQueryHTTPClient { try { -// Simple demo -// FieldFacet ff = new FieldFacet("@"+ContentModel.PROP_NAME); -// ff.setLimit(2); -// searchParameters.addFieldFacet(ff); - URLCodec encoder = new URLCodec(); StringBuilder url = new StringBuilder(); url.append(baseUrl); @@ -216,25 +217,9 @@ public class SolrQueryHTTPClient } url.append(sortBuffer); - // Authorities go over in body - - StringBuilder authQuery = new StringBuilder(); - for (String authority : permissionService.getAuthorisations()) - { - if (authQuery.length() > 0) - { - authQuery.append(" "); - } - authQuery.append("|AUTHORITY:\"").append(authority).append("\""); - } - - // url.append("&fq="); - // encoder = new URLCodec(); - // url.append(encoder.encode(authQuery.toString(), "UTF-8")); - url.append("&fq=").append(encoder.encode("{!afts}AUTHORITY_FILTER_FROM_JSON", "UTF-8")); - - // facets would go on url? + + url.append("&fq=").append(encoder.encode("{!afts}TENANT_FILTER_FROM_JSON", "UTF-8")); if(searchParameters.getFieldFacets().size() > 0) { @@ -275,9 +260,20 @@ public class SolrQueryHTTPClient JSONObject body = new JSONObject(); body.put("query", searchParameters.getQuery()); - // body.put("defaultField", searchParameters.getDefaultFieldName()); - body.put("filter", authQuery); + + // Authorities go over as is - and tenant mangling and query building takes place on the SOLR side + + JSONArray authorities = new JSONArray(); + for (String authority : permissionService.getAuthorisations()) + { + authorities.put(authority); + } + body.put("authorities", authorities); + + JSONArray tenants = new JSONArray(); + tenants.put(tenantService.getCurrentUserDomain()); + body.put("tenants", tenants); JSONArray locales = new JSONArray(); for (Locale currentLocale : searchParameters.getLocales()) diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java b/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java index e33b4a4143..709e3303fb 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2011 Alfresco Software Limited. * * This file is part of Alfresco * @@ -34,7 +34,6 @@ import org.alfresco.repo.search.impl.NodeSearcher; import org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.repo.search.impl.lucene.QueryParameterisationException; -import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; @@ -46,8 +45,8 @@ import org.alfresco.service.cmr.search.QueryParameter; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.search.SearchParameters.Operator; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO9075; @@ -58,11 +57,8 @@ import org.alfresco.util.SearchLanguageConversion; */ public class SolrSearchService implements SearchService { - private NodeService nodeService; - private TenantService tenantService; - private NamespacePrefixResolver namespacePrefixResolver; private DictionaryService dictionaryService; @@ -81,16 +77,6 @@ public class SolrSearchService implements SearchService this.nodeService = nodeService; } - public TenantService getTenantService() - { - return tenantService; - } - - public void setTenantService(TenantService tenantService) - { - this.tenantService = tenantService; - } - public NamespacePrefixResolver getNamespacePrefixResolver() { return namespacePrefixResolver; @@ -150,8 +136,6 @@ public class SolrSearchService implements SearchService @Override public ResultSet query(StoreRef store, String language, String query, QueryParameterDefinition[] queryParameterDefinitions) { - store = tenantService.getName(store); - SearchParameters sp = new SearchParameters(); sp.addStore(store); sp.setLanguage(language); @@ -164,10 +148,10 @@ public class SolrSearchService implements SearchService } } sp.excludeDataInTheCurrentTransaction(true); - + return query(sp); } - + /* * (non-Javadoc) * @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.repository.StoreRef, @@ -337,10 +321,7 @@ public class SolrSearchService implements SearchService { throw new IllegalStateException("Only one store can be searched at present"); } - - ArrayList stores = searchParameters.getStores(); - stores.set(0, tenantService.getName(searchParameters.getStores().get(0))); - + String parameterisedQueryString; if (searchParameters.getQueryParameterDefinitions().size() > 0) { diff --git a/source/java/org/alfresco/repo/solr/AclReaders.java b/source/java/org/alfresco/repo/solr/AclReaders.java index 41bd96c15f..93cd721040 100644 --- a/source/java/org/alfresco/repo/solr/AclReaders.java +++ b/source/java/org/alfresco/repo/solr/AclReaders.java @@ -20,6 +20,8 @@ package org.alfresco.repo.solr; import java.util.Set; +import org.alfresco.repo.tenant.TenantService; + /** * Bean for SOLR ACL readers. * @@ -31,11 +33,12 @@ public class AclReaders private Long aclId; private Set readers; private long aclChangeSetId; + private String tenantDomain = TenantService.DEFAULT_DOMAIN; @Override public String toString() { - return "AclReaders [aclId=" + aclId + ", readers=" + readers + ", aclChangeSetId=" + aclChangeSetId + "]"; + return "AclReaders [aclId=" + aclId + ", readers=" + readers + ", aclChangeSetId=" + aclChangeSetId + ", tenantDomain=" + tenantDomain + "]"; } public Long getAclId() { @@ -61,5 +64,12 @@ public class AclReaders { this.aclChangeSetId = aclChangeSetId; } - + public String getTenantDomain() + { + return tenantDomain; + } + public void setTenantDomain(String tenantDomain) + { + this.tenantDomain = tenantDomain; + } } diff --git a/source/java/org/alfresco/repo/solr/NodeMetaData.java b/source/java/org/alfresco/repo/solr/NodeMetaData.java index c9d61017ae..8cedb17822 100644 --- a/source/java/org/alfresco/repo/solr/NodeMetaData.java +++ b/source/java/org/alfresco/repo/solr/NodeMetaData.java @@ -23,7 +23,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.zip.CRC32; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; @@ -50,6 +49,7 @@ public class NodeMetaData private Long parentAssocsCrc; private List childIds; private Long txnId; + private String tenantDomain; public String getOwner() { @@ -156,6 +156,13 @@ public class NodeMetaData public void setTxnId(Long txnId) { this.txnId = txnId; - } - + } + public String getTenantDomain() + { + return tenantDomain; + } + public void setTenantDomain(String tenantDomain) + { + this.tenantDomain = tenantDomain; + } } diff --git a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java index 8bc4bd604e..9ff793fcf4 100644 --- a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java +++ b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java @@ -39,6 +39,7 @@ import org.alfresco.repo.domain.node.NodeDAO.ChildAssocRefQueryCallback; import org.alfresco.repo.domain.permissions.AclDAO; import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.domain.solr.SOLRDAO; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -185,6 +186,8 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent * This is an N+1 query that should, in theory, make use of cached ACL readers data. */ + Map aclChangeSetTenant = new HashMap(aclIds.size()); + List aclsReaders = new ArrayList(aclIds.size() * 10); for (Long aclId : aclIds) { @@ -192,10 +195,30 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent AclReaders readers = new AclReaders(); readers.setAclId(aclId); readers.setReaders(readersSet); - readers.setAclChangeSetId(aclDAO.getAccessControlList(aclId).getProperties().getAclChangeSetId()); + + Long aclChangeSetId = aclDAO.getAccessControlList(aclId).getProperties().getAclChangeSetId(); + readers.setAclChangeSetId(aclChangeSetId); + + if (AuthenticationUtil.isMtEnabled()) + { + // MT - for now, derive the tenant for acl (via acl change set) + String tenantDomain = aclChangeSetTenant.get(aclChangeSetId); + if (tenantDomain == null) + { + tenantDomain = getTenant(aclId, aclChangeSetId); + if (tenantDomain == null) + { + // skip this acl ! + continue; + } + aclChangeSetTenant.put(aclChangeSetId, tenantDomain); + } + readers.setTenantDomain(tenantDomain); + } + aclsReaders.add(readers); } - + return aclsReaders; } else @@ -203,7 +226,51 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent return Collections.emptyList(); } } - + + private String getTenant(long aclId, long aclChangeSetId) + { + String tenantDomain = getAclTenant(aclId); + if (tenantDomain == null) + { + List aclChangeSetIds = new ArrayList(1); + aclChangeSetIds.add(aclChangeSetId); + + List acls = solrDAO.getAcls(aclChangeSetIds, null, 1024); + for (Acl acl : acls) + { + tenantDomain = getAclTenant(acl.getId()); + if (tenantDomain != null) + { + break; + } + } + + if (tenantDomain == null) + { + // tenant not found - log warning ? + tenantDomain = null; // temp - for debug breakpoint only + } + } + return tenantDomain; + } + + private String getAclTenant(long aclId) + { + List nodeIds = aclDAO.getADMNodesByAcl(aclId, 1); + if (nodeIds.size() == 0) + { + return null; + } + + Pair nodePair = nodeDAO.getNodePair(nodeIds.get(0)); + if (nodePair == null) + { + return null; + } + + return tenantService.getDomain(nodePair.getSecond().getStoreRef().getIdentifier()); + } + @Override public List getTransactions(Long minTxnId, Long fromCommitTime, int maxResults) { @@ -519,12 +586,16 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent nodeMetaData.setPaths(paths); } - + + NodeRef nodeRef = pair.getSecond(); + if(includeNodeRef) { - nodeMetaData.setNodeRef(pair.getSecond()); + nodeMetaData.setNodeRef(tenantService.getBaseName(nodeRef, true)); } - + + nodeMetaData.setTenantDomain(tenantService.getDomain(nodeRef.getStoreRef().getIdentifier())); + if(includeChildAssociations) { final List childAssocs = new ArrayList(100); @@ -546,7 +617,7 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent public boolean handle(Pair childAssocPair, Pair parentNodePair, Pair childNodePair) { - childAssocs.add(childAssocPair.getSecond()); + childAssocs.add(tenantService.getBaseName(childAssocPair.getSecond(), true)); return true; } @@ -612,7 +683,7 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent public boolean handle(Pair childAssocPair, Pair parentNodePair, Pair childNodePair) { - parentAssocs.add(childAssocPair.getSecond()); + parentAssocs.add(tenantService.getBaseName(childAssocPair.getSecond(), true)); return true; } diff --git a/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java index fe3bf5b3e5..5a3e039476 100644 --- a/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java +++ b/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java @@ -277,10 +277,17 @@ public class MultiTServiceImpl implements TenantService * @see org.alfresco.repo.tenant.TenantService#getBaseName(org.alfresco.service.cmr.repository.NodeRef) */ public NodeRef getBaseName(NodeRef nodeRef) - { + { + return getBaseName(nodeRef, false); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantService#getBaseName(org.alfresco.service.cmr.repository.NodeRef, boolean) + */ + public NodeRef getBaseName(NodeRef nodeRef, boolean forceForNonTenant) + { if (nodeRef == null) { return null; } - - return new NodeRef(nodeRef.getStoreRef().getProtocol(), getBaseName(nodeRef.getStoreRef().getIdentifier()), nodeRef.getId()); + return new NodeRef(nodeRef.getStoreRef().getProtocol(), getBaseName(nodeRef.getStoreRef().getIdentifier(), forceForNonTenant), nodeRef.getId()); } /* (non-Javadoc) @@ -298,13 +305,21 @@ public class MultiTServiceImpl implements TenantService */ public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef) { + return getBaseName(childAssocRef, false); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantService#getBaseName(org.alfresco.service.cmr.repository.ChildAssociationRef, boolean) + */ + public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef, boolean forceForNonTenant) + { if (childAssocRef == null) { return null; } return new ChildAssociationRef( childAssocRef.getTypeQName(), - getBaseName(childAssocRef.getParentRef()), + getBaseName(childAssocRef.getParentRef(), forceForNonTenant), childAssocRef.getQName(), - getBaseName(childAssocRef.getChildRef()), + getBaseName(childAssocRef.getChildRef(), forceForNonTenant), childAssocRef.isPrimary(), childAssocRef.getNthSibling()); }