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 update clients, per workspace */ 053 protected Map<String, SolrClient> _solrUpdateClients; 054 055 /** The solr core prefix. */ 056 protected String _solrCorePrefix; 057 058 @Override 059 public void service(ServiceManager serviceManager) throws ServiceException 060 { 061 _workspaceSelector = (WorkspaceSelector) serviceManager.lookup(WorkspaceSelector.ROLE); 062 } 063 064 @Override 065 public void initialize() throws Exception 066 { 067 String url = Config.getInstance().getValueAsString(__SOLR_URL_CONFIG); 068 _solrCorePrefix = Config.getInstance().getValueAsString(__SOLR_CORE_PREFIX_CONFIG); 069 070 _solrReadClient = new HttpSolrClient.Builder(url).build(); 071 if (_solrUpdateClients == null) 072 { 073 _solrUpdateClients = new HashMap<>(); 074 for (String workspaceName : _workspaceSelector.getWorkspaces()) 075 { 076 _solrUpdateClients.put(workspaceName, _createUpdateClient(url, workspaceName)); 077 } 078 } 079 } 080 081 private SolrClient _createUpdateClient(String url, String workspaceName) 082 { 083 AmetysConcurrentUpdateSolrClient updateClient = new AmetysConcurrentUpdateSolrClient(url, getCollectionName(workspaceName), 10, 4, getLogger()); 084 updateClient.setPollQueueTime(10); 085 return updateClient; 086 } 087 088 @Override 089 public void dispose() 090 { 091 // Release the solr clients (as a Closeable). 092 IOUtils.closeQuietly(_solrReadClient); 093 for (SolrClient solrUpdateClient : _solrUpdateClients.values()) 094 { 095 IOUtils.closeQuietly(solrUpdateClient); 096 } 097 _solrReadClient = null; 098 _solrUpdateClients.clear(); 099 _solrUpdateClients = null; 100 } 101 102 @Override 103 public SolrClient getReadClient() 104 { 105 return _solrReadClient; 106 } 107 108 @Override 109 public SolrClient getUpdateClient(String workspaceName) 110 { 111 SolrClient updateClient = _solrUpdateClients.get(_nonNullWorkspaceName(workspaceName)); 112 if (updateClient == null) 113 { 114 // Perhaps the workspace was created after initializing this component, try to check if JCR workspace exist 115 try 116 { 117 if (ArrayUtils.contains(_workspaceSelector.getWorkspaces(), workspaceName)) 118 { 119 String url = Config.getInstance().getValueAsString(__SOLR_URL_CONFIG); 120 updateClient = _createUpdateClient(url, workspaceName); 121 _solrUpdateClients.put(workspaceName, updateClient); 122 } 123 } 124 catch (RepositoryException e) 125 { 126 getLogger().error("An error occurs while trying to return all JCR workspaces", e); 127 } 128 } 129 130 return updateClient; 131 } 132 133 @Override 134 public String getCollectionName() 135 { 136 return getCollectionName(_workspaceSelector.getWorkspace()); 137 } 138 139 @Override 140 public String getCollectionName(String workspaceName) 141 { 142 return _solrCorePrefix + _nonNullWorkspaceName(workspaceName); 143 } 144 145 private String _nonNullWorkspaceName(String workspaceName) 146 { 147 if (workspaceName == null) 148 { 149 getLogger().debug("Passing null workspace name. Switching to current workspace."); 150 return _workspaceSelector.getWorkspace(); 151 } 152 else 153 { 154 return workspaceName; 155 } 156 } 157}