001/* 002 * Copyright 2015 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.indexing.solr; 017 018import java.io.IOException; 019import java.util.Set; 020 021import javax.jcr.Repository; 022import javax.jcr.RepositoryException; 023import javax.jcr.Session; 024 025import org.apache.avalon.framework.component.Component; 026import org.apache.avalon.framework.context.Context; 027import org.apache.avalon.framework.context.ContextException; 028import org.apache.avalon.framework.context.Contextualizable; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032import org.apache.cocoon.components.ContextHelper; 033import org.apache.cocoon.environment.Request; 034import org.apache.solr.client.solrj.SolrServerException; 035 036import org.ametys.cms.content.indexing.solr.SolrIndexer; 037import org.ametys.cms.indexing.IndexingException; 038import org.ametys.cms.indexing.WorkspaceIndexer; 039import org.ametys.cms.repository.RequestAttributeWorkspaceSelector; 040import org.ametys.core.ui.Callable; 041import org.ametys.plugins.repository.provider.AbstractRepository; 042import org.ametys.plugins.repository.provider.WorkspaceSelector; 043import org.ametys.runtime.plugin.component.AbstractLogEnabled; 044 045/** 046 * Component indexing a workspace in a Solr server. 047 */ 048public class SolrWorkspaceIndexer extends AbstractLogEnabled implements WorkspaceIndexer, Component, Serviceable, Contextualizable 049{ 050 /** The repository. */ 051 protected Repository _repository; 052 053 /** The solr indexer. */ 054 protected SolrIndexer _solrIndexer; 055 056 /** The workspace selector. */ 057 protected WorkspaceSelector _workspaceSelector; 058 059 /** Additional documents provider extension point. */ 060 protected DocumentProviderExtensionPoint _docProviderEP; 061 062 /** The component context. */ 063 protected Context _context; 064 065 @Override 066 public void service(ServiceManager manager) throws ServiceException 067 { 068 _repository = (Repository) manager.lookup(AbstractRepository.ROLE); 069 _solrIndexer = (SolrIndexer) manager.lookup(SolrIndexer.ROLE); 070 _workspaceSelector = (WorkspaceSelector) manager.lookup(WorkspaceSelector.ROLE); 071 _docProviderEP = (DocumentProviderExtensionPoint) manager.lookup(DocumentProviderExtensionPoint.ROLE); 072 } 073 074 @Override 075 public void contextualize(Context context) throws ContextException 076 { 077 _context = context; 078 } 079 080 @Override 081 @Callable 082 public void indexAllWorkspaces() throws IndexingException 083 { 084 try 085 { 086 // Get all the workspaces and reindex them. 087 Session session = _repository.login(); 088 String[] workspaceNames = session.getWorkspace().getAccessibleWorkspaceNames(); 089 090 for (String workspaceName : workspaceNames) 091 { 092 index(workspaceName); 093 } 094 } 095 catch (RepositoryException e) 096 { 097 getLogger().error("Error while indexing the workspaces.", e); 098 throw new IndexingException("Error while indexing the workspaces.", e); 099 } 100 } 101 102 @Override 103 public void index(String workspaceName) throws IndexingException 104 { 105 try 106 { 107 // Create the core corresponding to the workspace if it doesn't exist. 108 ensureCoreExists(workspaceName); 109 110 _solrIndexer.sendSchema(); 111 112 getLogger().info("Start indexing workspace {}...", workspaceName); 113 114 _forceWorkspaceAndDoIndex(workspaceName); 115 116 getLogger().info("Successfully indexed workspace {}", workspaceName); 117 } 118 catch (IOException | SolrServerException e) 119 { 120 getLogger().error("Error while sending schema.", e); 121 throw new IndexingException("Error while sending schema.", e); 122 } 123 } 124 125 private void _forceWorkspaceAndDoIndex(String workspaceName) throws IndexingException 126 { 127 Request request = ContextHelper.getRequest(_context); 128 129 // Retrieve the current workspace. 130 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 131 132 try 133 { 134 // Force the workspace. 135 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, workspaceName); 136 doIndex(workspaceName); 137 } 138 finally 139 { 140 // Restore context 141 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 142 } 143 144 } 145 146 /** 147 * Index the given workspace. 148 * @param workspaceName The workspace name. 149 * @throws IndexingException If an error occurs indexing the workspace. 150 */ 151 protected void doIndex(String workspaceName) throws IndexingException 152 { 153 try 154 { 155 // First, unindex all documents. 156 _solrIndexer.unindexAllDocuments(workspaceName, false); 157 158 // Index all contents. 159 _solrIndexer.indexAllContents(workspaceName, false); 160 161 // Index all resources. 162 _solrIndexer.indexAllResources(workspaceName, false); 163 164 // Eventually index additional documents. 165 indexAdditionalDocuments(workspaceName); 166 167 // Commit changes 168 _solrIndexer.commit(workspaceName); 169 // When done indexing, optimize. 170 _solrIndexer.optimize(workspaceName); 171 } 172 catch (Exception e) 173 { 174 getLogger().error("Error indexing the workspace '" + workspaceName + "'.", e); 175 throw new IndexingException("Error indexing the workspace '" + workspaceName + "'.", e); 176 } 177 } 178 179 /** 180 * Index additional documents provided by the extensions. 181 * @param workspaceName The workspace name. 182 * @throws IndexingException If an error occurs while indexing. 183 */ 184 protected void indexAdditionalDocuments(String workspaceName) throws IndexingException 185 { 186 for (String id : _docProviderEP.getExtensionsIds()) 187 { 188 DocumentProvider docProvider = _docProviderEP.getExtension(id); 189 docProvider.indexDocuments(workspaceName); 190 } 191 } 192 193 /** 194 * Create the given core if it doesn't exist. 195 * @param coreName The core name. 196 * @throws IOException If an I/O error occurs. 197 * @throws SolrServerException If a solr error occurs. 198 */ 199 protected void ensureCoreExists(String coreName) throws IOException, SolrServerException 200 { 201 Set<String> coreNames = _solrIndexer.getCoreNames(); 202 if (!coreNames.contains(coreName)) 203 { 204 _solrIndexer.createCore(coreName); 205 } 206 } 207 208}