|
|
@@ -0,0 +1,403 @@
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+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;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * 该类是一个静态工厂方法.属于单利模式,在多线程环境下各个线程安全是安全的.<br><br>
|
|
|
+ *
|
|
|
+ * 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的值<br><br>
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * 初始化该类时,Solr配置中的所有Core并不会立即发生初始化(defaultCore除外).
|
|
|
+ *
|
|
|
+ * <br><br>
|
|
|
+ * defaultCore在初始化时有一个复杂的过程,具体有以下几种情况:<br>
|
|
|
+ * 1.当在Solr配置文件中的solr.xml文件中没有配置defaultCoreName节点信息.
|
|
|
+ * 那么在Factory中你有必要指定一个defaultCoreName(并且defaultCoreName必须满足一些规定).
|
|
|
+ * 则默认的defaultCore是以defaultCoreName为Core的SolrServer.<br>
|
|
|
+ * 2.当在Solr配置文件中的solr.xml文件中已经配置了defaultCoreName.
|
|
|
+ * 那么即时你手动的设置Factory的defaultCoreName也是无效的.
|
|
|
+ * 也就是说,defaultCoreName永远会以Solr中的配置为优先的原则.<br><br>
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * 传入的coreName必须是一个有效的Java 标示符名称.在内部的实现使用了Map字典,
|
|
|
+ * 这个字典的Key是所有Solr Core内有效的coreName,因此你必须保证字典中的所有key满足Java
|
|
|
+ * 标示符的命名规则.在这里传入null, "", OR " "都是不允许的.
|
|
|
+ *
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * 在没有特别指定的情况下,任何需要传入参数的方法,当传入null值时,
|
|
|
+ * 会发生NullPointException异常.
|
|
|
+ * </p>
|
|
|
+ * @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<String, SolrServer> solrServerCache = new HashMap<String, SolrServer>();
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 锁
|
|
|
+ */
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * <p>
|
|
|
+ * 取得默认的SolrServer对象.<br><br>
|
|
|
+ * <b>注意:</b><br>
|
|
|
+ * 返回的SolrServer有可能是null值,这取决着你是否在Solr的solr.xml
|
|
|
+ * 是否配置了defaultCoreName信息或者显式的设置Factory的defaultCoreName信息.
|
|
|
+ * </p>
|
|
|
+ * @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);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * <p>
|
|
|
+ * 根据名称取得一个SolrServer.<br>
|
|
|
+ * 传入的coreName必须是一个有效的Java 标示符名称.在内部的实现使用了Map字典,
|
|
|
+ * 这个字典的Key是所有Solr Core内有效的coreName,因此你必须保证字典中的所有key满足Java
|
|
|
+ * 标示符的命名规则.在这里传入null, "", OR " "都是不允许的.
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * <b>注意:</b><br>
|
|
|
+ * SolrServerFactory在初始化的时候并不会自动注册每一个SolrCore(除了defaultSolrCore).
|
|
|
+ * 具体见:{@link com.sdyc.ndcls2.solr.SolrServerFactory}
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @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;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|