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(url); 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 return new AmetysConcurrentUpdateSolrClient(url, getCollectionName(workspaceName), 10, 4, getLogger()); 084 } 085 086 @Override 087 public void dispose() 088 { 089 // Release the solr clients (as a Closeable). 090 IOUtils.closeQuietly(_solrReadClient); 091 for (SolrClient solrUpdateClient : _solrUpdateClients.values()) 092 { 093 IOUtils.closeQuietly(solrUpdateClient); 094 } 095 _solrReadClient = null; 096 _solrUpdateClients.clear(); 097 _solrUpdateClients = null; 098 } 099 100 @Override 101 public SolrClient getReadClient() 102 { 103 return _solrReadClient; 104 } 105 106 @Override 107 public SolrClient getUpdateClient(String workspaceName) 108 { 109 SolrClient updateClient = _solrUpdateClients.get(_nonNullWorkspaceName(workspaceName)); 110 if (updateClient == null) 111 { 112 // Perhaps the workspace was created after initializing this component, try to check if JCR workspace exist 113 try 114 { 115 if (ArrayUtils.contains(_workspaceSelector.getWorkspaces(), workspaceName)) 116 { 117 String url = Config.getInstance().getValueAsString(__SOLR_URL_CONFIG); 118 updateClient = _createUpdateClient(url, workspaceName); 119 _solrUpdateClients.put(workspaceName, updateClient); 120 } 121 } 122 catch (RepositoryException e) 123 { 124 getLogger().error("An error occurs while trying to return all JCR workspaces", e); 125 } 126 } 127 128 return updateClient; 129 } 130 131 @Override 132 public String getCollectionName() 133 { 134 return getCollectionName(_workspaceSelector.getWorkspace()); 135 } 136 137 @Override 138 public String getCollectionName(String workspaceName) 139 { 140 return _solrCorePrefix + _nonNullWorkspaceName(workspaceName); 141 } 142 143 private String _nonNullWorkspaceName(String workspaceName) 144 { 145 if (workspaceName == null) 146 { 147 getLogger().debug("Passing null workspace name. Switching to current workspace."); 148 return _workspaceSelector.getWorkspace(); 149 } 150 else 151 { 152 return workspaceName; 153 } 154 } 155}