/**
*
*/
package com.sdyc.ndcls2.solr;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
import org.xml.sax.SAXException;
/**
*
*
* 该类是一个静态工厂方法.属于单利模式,在多线程环境下各个线程安全是安全的.
*
* Solr的CoreContainer在初始化的时候默认需要solr.solr.home的System.Property信息,
* 所以你需要在得到 {@link #getInstance()}前显式的指定一个solr.solr.home.
* 或者使用 {@link #getInstance(String)} 初始化,当使用 {@link #getInstance(String)}
* 进行初始化时,如果已经在System.getProperties()中加入solr.solr.home,
* Factory会优先使用solr.solr.home信息进行初始化,
* 并把solrHome覆盖为solr.solr.home的值
*
*
* 初始化该类时,Solr配置中的所有Core并不会立即发生初始化(defaultCore除外).
*
*
* defaultCore在初始化时有一个复杂的过程,具体有以下几种情况:
* 1.当在Solr配置文件中的solr.xml文件中没有配置defaultCoreName节点信息.
* 那么在Factory中你有必要指定一个defaultCoreName(并且defaultCoreName必须满足一些规定).
* 则默认的defaultCore是以defaultCoreName为Core的SolrServer.
* 2.当在Solr配置文件中的solr.xml文件中已经配置了defaultCoreName.
* 那么即时你手动的设置Factory的defaultCoreName也是无效的.
* 也就是说,defaultCoreName永远会以Solr中的配置为优先的原则.
*
*
*
*
* 传入的coreName必须是一个有效的Java 标示符名称.在内部的实现使用了Map字典,
* 这个字典的Key是所有Solr Core内有效的coreName,因此你必须保证字典中的所有key满足Java
* 标示符的命名规则.在这里传入null, "", OR " "都是不允许的.
*
*
*
*
*
* 在没有特别指定的情况下,任何需要传入参数的方法,当传入null值时,
* 会发生NullPointException异常.
*
* @author ZhenQin
*
* @since 2.0
*
*/
public final class SolrServerFactory {
/**
* Solr.home
*/
private static String solrHome = null;
/**
* 默认的defaultCoreName,该参数默认是defaultCoreName = ""
*/
private static String defaultCoreName = "";
/**
* 初始化的solrCoreContainer
*
*/
private static CoreContainer solrCoreContainer = null;
/**
* 默认的defaultSolrServer
*
*/
private static SolrServer defaultSolrServer = null;
/**
*
* 保存这的SolrServer,对应多个solrServer的时候,保存的SolrServer
*
*/
private final Map solrServerCache = new HashMap();
/**
* 锁
*/
private java.util.concurrent.locks.ReentrantLock lock = new java.util.concurrent.locks.ReentrantLock();
/**
* 日志
*/
private static Log log = LogFactory.getLog(SolrServerFactory.class);
/**
*
* 静态工厂方法,单例模式.SolrServerFactory只能有一个对象实例
*
*/
private static SolrServerFactory instance = null;
/**
* 私有化构造方法
*/
private SolrServerFactory() {
initBuild();
}
/**
* 初始化时的Build,该方法只能被初始化的时候执行一次
*
*/
private void initBuild() {
try {
setSolrCoreContainer(new CoreContainer.Initializer().initialize());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
}
String defaultCoreName = SolrServerFactory.getSolrCoreContainer().getDefaultCoreName();
if(defaultCoreName == null){
if(validate(SolrServerFactory.getDefaultCoreName())){
setDefaultSolrServer(new EmbeddedSolrServer(SolrServerFactory.getSolrCoreContainer(),
SolrServerFactory.getDefaultCoreName()));
}
}
if(defaultCoreName.equals("")){
setDefaultCoreName(defaultCoreName);
setDefaultSolrServer(new EmbeddedSolrServer(SolrServerFactory.getSolrCoreContainer(),
SolrServerFactory.getDefaultCoreName()));
} else if(defaultCoreName.trim().length() > 0){
setDefaultCoreName(defaultCoreName);
setDefaultSolrServer(new EmbeddedSolrServer(SolrServerFactory.getSolrCoreContainer(),
SolrServerFactory.getDefaultCoreName()));
}
lock.lock();
try {
if(StringUtils.isNotBlank(getDefaultCoreName())){
this.solrServerCache.put(getDefaultCoreName(), getDefaultSolrServer());
}
} finally {
lock.unlock();
}
}
/**
*
* 通过静态工厂方法获得类的实例
* @throws java.lang.RuntimeException 当没有查找到System.getProperty("solr.solr.home")的参数时,
* 发生该异常.如果需要显式的传入SolrHome,请使用:{@link #getInstance(String)}
* @return 返回SolrServerFactory唯一实例
*/
public static SolrServerFactory getInstance() {
if(instance != null){
return instance;
}
synchronized (SolrServerFactory.class) {
if(instance == null) {
String solrHome = System.getProperty("solr.solr.home");
if(StringUtils.isNotBlank(solrHome)){
SolrServerFactory.solrHome = solrHome;
instance = new SolrServerFactory();
} else if(StringUtils.isNotBlank(SolrServerFactory.solrHome)) {
System.setProperty("solr.solr.home", SolrServerFactory.solrHome);
instance = new SolrServerFactory();
} else {
throw new RuntimeException("not fount System.getProperty(\"solr.solr.home\") attr.");
}
}
}
return instance;
}
/**
*
* 通过静态工厂方法获得类的实例
*
* @return 返回SolrServerFactory唯一实例
*/
public static SolrServerFactory getInstance(String solrHome) {
if(StringUtils.isNotBlank(solrHome)){
SolrServerFactory.solrHome = solrHome;
return getInstance();
}
throw new RuntimeException("solrHome is an invalid ${solr.solr.home}.");
}
/**
* @return
* @see org.apache.solr.core.CoreContainer#getSolrHome()
*/
public String getSolrHome() {
return solrCoreContainer.getSolrHome();
}
/**
*
* @see org.apache.solr.core.CoreContainer#persist()
*/
public void persist() {
solrCoreContainer.persist();
}
/**
* @param core
* @param returnPrev
* @return
* @see org.apache.solr.core.CoreContainer#register(org.apache.solr.core.SolrCore, boolean)
*/
public SolrCore register(SolrCore core, boolean returnPrev) {
return solrCoreContainer.register(core, returnPrev);
}
/**
* @param name
* @param core
* @param returnPrevNotClosed
* @return
* @see org.apache.solr.core.CoreContainer#register(java.lang.String, org.apache.solr.core.SolrCore, boolean)
*/
public SolrCore register(String name, SolrCore core,
boolean returnPrevNotClosed) {
return solrCoreContainer.register(name, core,
returnPrevNotClosed);
}
/**
*
* @see org.apache.solr.core.CoreContainer#shutdown()
*/
public void shutdown() {
solrCoreContainer.shutdown();
}
/**
* @return the defaultSolrCoreContainer
*/
public static CoreContainer getSolrCoreContainer(){
if(SolrServerFactory.solrCoreContainer == null){
SolrServerFactory.getInstance();
}
return SolrServerFactory.solrCoreContainer;
}
/**
*
* 返回一个SolrCore对象,这个对象可以允许使用Lucene原生API进行编程.
* @param coreName Solr的一个coreName,
* 这个coreName需要 {@link #validate(String)}验证通过.否则返回null
* @return the Solr Lucene API
*/
public SolrCore getSolrCore(String coreName){
if(validate(coreName)){
return SolrServerFactory.solrCoreContainer.getCore(coreName);
}
return null;
}
/**
*
* @param solrCoreContainer the defaultSolrCoreContainer to set
*/
protected void setSolrCoreContainer(CoreContainer solrCoreContainer) {
SolrServerFactory.solrCoreContainer = solrCoreContainer;
}
/**
*
* 取得默认的SolrServer对象.
* 注意:
* 返回的SolrServer有可能是null值,这取决着你是否在Solr的solr.xml
* 是否配置了defaultCoreName信息或者显式的设置Factory的defaultCoreName信息.
*
* @return 返回Solr的SolrServer
*/
public static SolrServer getDefaultSolrServer(){
if(SolrServerFactory.solrCoreContainer == null){
SolrServerFactory.getInstance();
}
return SolrServerFactory.defaultSolrServer;
}
/**
* 检验一个CoreName是否是Solr核心配置所支持的
*
* @param coreName Solr core,具体见${solr.solr.home}/solr.xml中的cor.name属性
*
* @return 返回是否是合法的Solr coreName.
*/
public static boolean validate(String coreName) {
return coreName.equals(defaultCoreName) ? true : SolrServerFactory.getSolrCoreContainer().getCoreNames().contains(coreName);
}
/**
*
* 根据名称取得一个SolrServer.
* 传入的coreName必须是一个有效的Java 标示符名称.在内部的实现使用了Map字典,
* 这个字典的Key是所有Solr Core内有效的coreName,因此你必须保证字典中的所有key满足Java
* 标示符的命名规则.在这里传入null, "", OR " "都是不允许的.
*
*
*
* 注意:
* SolrServerFactory在初始化的时候并不会自动注册每一个SolrCore(除了defaultSolrCore).
* 具体见:{@link com.sdyc.ndcls2.solr.SolrServerFactory}
*
*
* @param coreName 这个coreName需要 {@link #validate(String)}验证通过.否则返回null
* @return 返回SolrServer,当coreName不满足必要的条件则返回null
*/
public SolrServer getSolrServer(String coreName){
if(StringUtils.isNotBlank(coreName) && validate(coreName)){
SolrServer tmpSolrServer = solrServerCache.get(coreName);
if(tmpSolrServer == null){
lock.lock();
try {
tmpSolrServer = new EmbeddedSolrServer(getSolrCoreContainer(), coreName);
solrServerCache.put(coreName, tmpSolrServer);
} catch(Exception e){
log.error(e);
} finally {
lock.unlock();
}
}
return tmpSolrServer;
}
return null;
}
/**
* @param defaultSolrServer the defaultSolrServer to set
*/
protected void setDefaultSolrServer(SolrServer defaultSolrServer) {
SolrServerFactory.defaultSolrServer = defaultSolrServer;
}
/**
* @param defaultCoreName the defaultCoreName to set
*/
public static void setDefaultCoreName(String defaultCoreName) {
SolrServerFactory.defaultCoreName = defaultCoreName;
}
/**
* @return the defaultCoreName
*/
public static String getDefaultCoreName() {
return defaultCoreName;
}
}