Package org.springframework.data.solr.server.support

Source Code of org.springframework.data.solr.server.support.SolrServerUtils

/*
* Copyright 2012 - 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.solr.server.support;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.client.solrj.impl.LBHttpSolrServer;
import org.apache.solr.core.CoreContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.solr.VersionUtil;
import org.springframework.data.solr.core.mapping.SolrDocument;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

/**
* @author Christoph Strobl
*/
public class SolrServerUtils {

  private static final Logger logger = LoggerFactory.getLogger(SolrServerUtils.class);
  private static final String SLASH = "/";

  private SolrServerUtils() {}

  /**
   * Resolve solr core/collection name for given type.
   *
   * @param type
   * @return empty string if {@link SolrDocument} not present or {@link SolrDocument#solrCoreName()} is blank.
   * @since 1.1
   */
  public static String resolveSolrCoreName(Class<?> type) {
    SolrDocument annotation = AnnotationUtils.findAnnotation(type, SolrDocument.class);
    if (annotation != null && StringUtils.isNotBlank(annotation.solrCoreName())) {
      return annotation.solrCoreName();
    }
    return "";
  }

  public static <T extends SolrServer> T clone(T solrServer) {
    return clone(solrServer, null);
  }

  /**
   * Create a clone of given {@link SolrServer} and modify baseUrl of clone to point to the given core.
   *
   * @param solrServer Non null reference {@link SolrServer} to copy properties from.
   * @param core Name of solr core to point to.
   * @return
   * @throws BeanInstantiationException if creating instance failed
   */
  @SuppressWarnings("unchecked")
  public static <T extends SolrServer> T clone(T solrServer, String core) {
    Assert.notNull(solrServer);
    String shortName = getSolrServerTypeName(solrServer);
    if (shortName.equals("SolrServer")) { // cannot create instance of interface,
      return solrServer;
    }

    SolrServer clone = null;
    if (shortName.equals("HttpSolrServer") || shortName.equals("CommonsHttpSolrServer")) {
      clone = cloneHttpSolrServer(solrServer, core);
    } else if (shortName.equals("LBHttpSolrServer")) {
      clone = cloneLBHttpSolrServer(solrServer, core);
    } else if (shortName.equals("CloudSolrServer")) {
      clone = cloneCloudSolrServer(solrServer, core);
    } else if (shortName.equals("EmbeddedSolrServer")) {
      clone = cloneEmbeddedSolrServer(solrServer, core);
    }

    if (clone == null) {
      throw new BeanInstantiationException(solrServer.getClass(), "Cannot create instace of " + shortName + ".");
    }

    copyProperties(solrServer, clone);
    return (T) clone;
  }

  /**
   * Append core to given baseUrl
   *
   * @param baseUrl
   * @param core
   * @return
   */
  public static String appendCoreToBaseUrl(String baseUrl, String core) {
    Assert.notNull(baseUrl);

    if (!org.springframework.util.StringUtils.hasText(core)) {
      return baseUrl;
    }
    String url = baseUrl;
    if (!StringUtils.endsWith(baseUrl, SLASH)) {
      url = url + SLASH;
    }
    url = url + core;
    return url;
  }

  private static String getSolrServerTypeName(SolrServer solrServer) {
    Class<?> solrServerType = ClassUtils.isCglibProxy(solrServer) ? ClassUtils.getUserClass(solrServer) : solrServer
        .getClass();
    String shortName = ClassUtils.getShortName(solrServerType);
    return shortName;
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  private static SolrServer cloneEmbeddedSolrServer(SolrServer solrServer, String core) {

    CoreContainer coreContainer = ((EmbeddedSolrServer) solrServer).getCoreContainer();
    try {
      Constructor constructor = ClassUtils.getConstructorIfAvailable(solrServer.getClass(), CoreContainer.class,
          String.class);
      return (SolrServer) BeanUtils.instantiateClass(constructor, coreContainer, core);
    } catch (Exception e) {
      throw new BeanInstantiationException(solrServer.getClass(), "Cannot create instace of " + solrServer.getClass()
          + ".", e);
    }
  }

  private static SolrServer cloneHttpSolrServer(SolrServer solrServer, String core) {
    if (solrServer == null) {
      return null;
    }

    Method baseUrlGetterMethod = ClassUtils.getMethodIfAvailable(solrServer.getClass(), "getBaseURL");
    if (baseUrlGetterMethod == null) {
      return null;
    }

    String baseUrl = (String) ReflectionUtils.invokeMethod(baseUrlGetterMethod, solrServer);
    String url = appendCoreToBaseUrl(baseUrl, core);

    try {

      HttpClient clientToUse = readAndCloneHttpClient(solrServer);

      if (clientToUse != null) {
        Constructor<? extends SolrServer> constructor = (Constructor<? extends SolrServer>) ClassUtils
            .getConstructorIfAvailable(solrServer.getClass(), String.class, HttpClient.class);
        if (constructor != null) {
          return (SolrServer) BeanUtils.instantiateClass(constructor, url, clientToUse);
        }
      }

      Constructor<? extends SolrServer> constructor = (Constructor<? extends SolrServer>) ClassUtils
          .getConstructorIfAvailable(solrServer.getClass(), String.class);
      return (SolrServer) BeanUtils.instantiateClass(constructor, url);
    } catch (Exception e) {
      throw new BeanInstantiationException(solrServer.getClass(), "Cannot create instace of " + solrServer.getClass()
          + ". ", e);
    }
  }

  private static LBHttpSolrServer cloneLBHttpSolrServer(SolrServer solrServer, String core) {
    if (solrServer == null) {
      return null;
    }

    LBHttpSolrServer clone = null;
    try {
      if (VersionUtil.isSolr3XAvailable()) {
        clone = cloneSolr3LBHttpServer(solrServer, core);
      } else if (VersionUtil.isSolr4XAvailable()) {
        clone = cloneSolr4LBHttpServer(solrServer, core);
      }
    } catch (Exception e) {
      throw new BeanInstantiationException(solrServer.getClass(), "Cannot create instace of " + solrServer.getClass()
          + ". ", e);
    }
    Object o = readField(solrServer, "interval");
    if (o != null) {
      clone.setAliveCheckInterval(Integer.valueOf(o.toString()).intValue());
    }
    return clone;
  }

  private static SolrServer cloneCloudSolrServer(SolrServer solrServer, String core) {
    if (VersionUtil.isSolr3XAvailable() || solrServer == null) {
      return null;
    }

    CloudSolrServer cloudServer = (CloudSolrServer) solrServer;
    String zkHost = readField(solrServer, "zkHost");

    Constructor<? extends SolrServer> constructor = (Constructor<? extends SolrServer>) ClassUtils
        .getConstructorIfAvailable(solrServer.getClass(), String.class, LBHttpSolrServer.class);

    CloudSolrServer clone = (CloudSolrServer) BeanUtils.instantiateClass(constructor, zkHost,
        cloneLBHttpSolrServer(cloudServer.getLbServer(), core));

    if (org.springframework.util.StringUtils.hasText(core)) {
      clone.setDefaultCollection(core);
    }
    return clone;
  }

  private static LBHttpSolrServer cloneSolr3LBHttpServer(SolrServer solrServer, String core)
      throws MalformedURLException {
    CopyOnWriteArrayList<?> list = readField(solrServer, "aliveServers");

    String[] servers = new String[list.size()];
    for (int i = 0; i < list.size(); i++) {
      servers[i] = appendCoreToBaseUrl(list.get(i).toString(), core);
    }
    return new LBHttpSolrServer(servers);
  }

  private static LBHttpSolrServer cloneSolr4LBHttpServer(SolrServer solrServer, String core)
      throws MalformedURLException, InstantiationException, IllegalAccessException, IllegalArgumentException,
      InvocationTargetException {
    Map<String, ?> map = readField(solrServer, "aliveServers");

    String[] servers = new String[map.size()];
    int i = 0;
    for (String key : map.keySet()) {
      servers[i] = appendCoreToBaseUrl(key, core);
      i++;
    }

    Boolean isInternalCient = readField(solrServer, "clientIsInternal");

    if (isInternalCient != null && !isInternalCient) {
      HttpClient clientToUse = readAndCloneHttpClient(solrServer);
      return new LBHttpSolrServer(clientToUse, servers);
    }
    return new LBHttpSolrServer(servers);
  }

  private static HttpClient readAndCloneHttpClient(SolrServer solrServer) throws InstantiationException,
      IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    HttpClient sourceClient = readField(solrServer, "httpClient");
    return cloneHttpClient(sourceClient);
  }

  private static HttpClient cloneHttpClient(HttpClient sourceClient) throws InstantiationException,
      IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    if (sourceClient == null) {
      return null;
    }

    Class<?> clientType = ClassUtils.getUserClass(sourceClient);
    Constructor<?> constructor = ClassUtils.getConstructorIfAvailable(clientType, HttpParams.class);
    if (constructor != null) {

      HttpClient targetClient = (HttpClient) constructor.newInstance(sourceClient.getParams());
      BeanUtils.copyProperties(sourceClient, targetClient);
      return targetClient;
    } else {
      return new DefaultHttpClient(sourceClient.getParams());
    }

  }

  @SuppressWarnings("unchecked")
  private static <T> T readField(SolrServer solrServer, String fieldName) {
    Field field = ReflectionUtils.findField(solrServer.getClass(), fieldName);
    if (field == null) {
      return null;
    }
    ReflectionUtils.makeAccessible(field);
    return (T) ReflectionUtils.getField(field, solrServer);
  }

  /**
   * Solr property names do not match the getters/setters used for them. Check on any write method, try to find the
   * according property and set the value for it. Will ignore all other, and nested properties
   *
   * @param source
   * @param target
   */
  private static void copyProperties(SolrServer source, SolrServer target) {
    BeanWrapperImpl wrapperImpl = new BeanWrapperImpl(source);
    for (PropertyDescriptor pd : wrapperImpl.getPropertyDescriptors()) {
      Method writer = pd.getWriteMethod();
      if (writer != null) {
        try {
          Field property = ReflectionUtils.findField(source.getClass(), pd.getName());
          if (property != null) {
            ReflectionUtils.makeAccessible(property);
            Object o = ReflectionUtils.getField(property, source);
            if (o != null) {
              writer.invoke(target, o);
            }
          }
        } catch (Exception e) {
          logger.warn("Could not copy property value for: " + pd.getName(), e);
        }
      }
    }
  }

}
TOP

Related Classes of org.springframework.data.solr.server.support.SolrServerUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.