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.search.solr; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import javax.jcr.RepositoryException; 022 023import org.apache.avalon.framework.activity.Disposable; 024import org.apache.avalon.framework.activity.Initializable; 025import org.apache.avalon.framework.component.Component; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.commons.io.IOUtils; 030import org.apache.commons.lang3.ArrayUtils; 031import org.apache.solr.client.solrj.SolrClient; 032import org.apache.solr.client.solrj.impl.HttpSolrClient; 033 034import org.ametys.plugins.repository.provider.WorkspaceSelector; 035import org.ametys.runtime.config.Config; 036import org.ametys.runtime.plugin.component.AbstractLogEnabled; 037 038/** 039 * Component acting as a single entry point to get access to Solr clients. 040 */ 041public class DefaultSolrClientProvider extends AbstractLogEnabled implements SolrClientProvider, Component, Serviceable, Initializable, Disposable 042{ 043 private static final String __SOLR_URL_CONFIG = "cms.solr.core.url"; 044 private static final String __SOLR_CORE_PREFIX_CONFIG = "cms.solr.core.prefix"; 045 046 /** The workspace selector. */ 047 protected WorkspaceSelector _workspaceSelector; 048 049 /** The Solr read client. */ 050 protected SolrClient _solrReadClient; 051 052 /** The Solr "default" update clients, per workspace */ 053 protected Map<String, SolrClient> _solrDefaultUpdateClients; 054 055 /** The Solr "no auto commit" update clients, per workspace */ 056 protected Map<String, SolrClient> _solrNoAutoCommitUpdateClients; 057 058 /** The solr core prefix. */ 059 protected String _solrCorePrefix; 060 061 @Override 062 public void service(ServiceManager serviceManager) throws ServiceException 063 { 064 _workspaceSelector = (WorkspaceSelector) serviceManager.lookup(WorkspaceSelector.ROLE); 065 } 066 067 @Override 068 public void initialize() throws Exception 069 { 070 String url = Config.getInstance().getValue(__SOLR_URL_CONFIG); 071 _solrCorePrefix = Config.getInstance().getValue(__SOLR_CORE_PREFIX_CONFIG); 072 073 _solrReadClient = new HttpSolrClient.Builder(url).build(); 074 075 String[] workspaces = _workspaceSelector.getWorkspaces(); 076 _solrDefaultUpdateClients = new HashMap<>(); 077 _solrNoAutoCommitUpdateClients = new HashMap<>(); 078 for (String workspaceName : workspaces) 079 { 080 _solrDefaultUpdateClients.put(workspaceName, _createDefaultUpdateClient(url, workspaceName)); 081 _solrNoAutoCommitUpdateClients.put(workspaceName, _createNoAutoCommitUpdateClient(url, workspaceName)); 082 } 083 } 084 085 private SolrClient _createDefaultUpdateClient(String url, String workspaceName) 086 { 087 AbstractAmetysConcurrentUpdateClient updateClient = new DefaultUpdateClient(url, getCollectionName(workspaceName), 10, 4, getLogger()); 088 updateClient.setPollQueueTime(10); 089 return updateClient; 090 } 091 092 private SolrClient _createNoAutoCommitUpdateClient(String url, String workspaceName) 093 { 094 AbstractAmetysConcurrentUpdateClient updateClient = new NoAutoCommitUpdateClient(url, getCollectionName(workspaceName), 10, 4, getLogger()); 095 updateClient.setPollQueueTime(10); 096 return updateClient; 097 } 098 099 @SuppressWarnings("deprecation") 100 @Override 101 public void dispose() 102 { 103 // Release the solr clients (as a Closeable). 104 IOUtils.closeQuietly(_solrReadClient); 105 _solrReadClient = null; 106 107 for (SolrClient solrDefaultUpdateClient : _solrDefaultUpdateClients.values()) 108 { 109 IOUtils.closeQuietly(solrDefaultUpdateClient); 110 } 111 _solrDefaultUpdateClients.clear(); 112 _solrDefaultUpdateClients = null; 113 114 for (SolrClient solrNoAutoCommitUpdateClient : _solrNoAutoCommitUpdateClients.values()) 115 { 116 IOUtils.closeQuietly(solrNoAutoCommitUpdateClient); 117 } 118 _solrNoAutoCommitUpdateClients.clear(); 119 _solrNoAutoCommitUpdateClients = null; 120 } 121 122 @Override 123 public SolrClient getReadClient() 124 { 125 return _solrReadClient; 126 } 127 128 @Override 129 public SolrClient getUpdateClient(String workspaceName, boolean autoCommit) 130 { 131 Map<String, SolrClient> updateClients = autoCommit ? _solrDefaultUpdateClients : _solrNoAutoCommitUpdateClients; 132 133 SolrClient updateClient = updateClients.get(_nonNullWorkspaceName(workspaceName)); 134 if (updateClient == null) 135 { 136 // Perhaps the workspace was created after initializing this component, try to check if JCR workspace exist 137 try 138 { 139 if (ArrayUtils.contains(_workspaceSelector.getWorkspaces(), workspaceName)) 140 { 141 String url = Config.getInstance().getValue(__SOLR_URL_CONFIG); 142 updateClient = autoCommit ? _createDefaultUpdateClient(url, workspaceName) : _createNoAutoCommitUpdateClient(url, workspaceName); 143 updateClients.put(workspaceName, updateClient); 144 } 145 } 146 catch (RepositoryException e) 147 { 148 getLogger().error("An error occurs while trying to return all JCR workspaces", e); 149 } 150 } 151 152 return updateClient; 153 } 154 155 @Override 156 public String getCollectionName() 157 { 158 return getCollectionName(_workspaceSelector.getWorkspace()); 159 } 160 161 @Override 162 public String getCollectionName(String workspaceName) 163 { 164 return _solrCorePrefix + _nonNullWorkspaceName(workspaceName); 165 } 166 167 private String _nonNullWorkspaceName(String workspaceName) 168 { 169 if (workspaceName == null) 170 { 171 getLogger().debug("Passing null workspace name. Switching to current workspace."); 172 return _workspaceSelector.getWorkspace(); 173 } 174 else 175 { 176 return workspaceName; 177 } 178 } 179}