/** | |
* | |
*/ | |
package org.eclipse.smila.solr.admin; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.net.MalformedURLException; | |
import java.text.MessageFormat; | |
import java.util.List; | |
import java.util.Map; | |
import javax.servlet.http.HttpServletResponse; | |
import javax.xml.stream.XMLStreamException; | |
import org.apache.commons.collections.CollectionUtils; | |
import org.apache.commons.lang.ArrayUtils; | |
import org.apache.commons.lang.BooleanUtils; | |
import org.apache.commons.lang.NotImplementedException; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.commons.lang.exception.ExceptionUtils; | |
import org.apache.solr.client.solrj.SolrServerException; | |
import org.eclipse.jetty.http.MimeTypes; | |
import org.eclipse.smila.datamodel.Any; | |
import org.eclipse.smila.datamodel.Record; | |
import org.eclipse.smila.datamodel.impl.DefaultDataFactoryImpl; | |
import org.eclipse.smila.datamodel.util.AnyUtil; | |
import org.eclipse.smila.datamodel.xml.XmlSerializationUtils; | |
import org.eclipse.smila.http.server.HttpExchange; | |
import org.eclipse.smila.http.server.util.ARequestHandler; | |
import org.eclipse.smila.http.server.util.UnsupportedMethodException; | |
import org.eclipse.smila.processing.parameters.MissingParameterException; | |
import org.eclipse.smila.solr.Activator; | |
/** | |
* @author pwissel | |
* | |
*/ | |
public class SolrAdministrationHandler extends ARequestHandler { | |
/** | |
* @see org.eclipse.smila.http.server.HttpHandler#handle(org.eclipse.smila.http.server.HttpExchange) | |
*/ | |
@Override | |
public void handle(HttpExchange exchange) throws IOException { | |
try { | |
final String method = exchange.getRequestMethod(); | |
Any result = null; | |
if (StringUtils.equalsIgnoreCase("GET", method)) { | |
result = doGet(exchange); | |
} else if (StringUtils.equalsIgnoreCase("POST", method)) { | |
result = doPost(exchange); | |
} else { | |
final String msg = | |
String.format("HttpMethod must be GET . HttpMethod '%s' is unsupported by SolrAdministrationHandler", | |
method); | |
throw new UnsupportedMethodException(msg); | |
} | |
sendResponse(exchange, result); | |
} catch (Exception exception) { | |
sendError(exchange, exception); | |
} | |
} | |
private Any doGet(HttpExchange exchange) throws Exception { | |
final GetCommand command = getGetCommand(exchange.getRequestURI()); | |
final SolrAdministration administration = getSolrAdministration(); | |
final Map<String, String[]> parameter = exchange.getParameterMap(); | |
Any response = null; | |
switch (command) { | |
case CORENAMES: | |
final List<String> coreNames = administration.getCoreNames(); | |
response = AnyUtil.objectToAny(coreNames); | |
break; | |
case FIELDNAMES: | |
final String core = getParameter(SolrAdministration.CORE, parameter); | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
final List<String> fieldNames = administration.getFieldNames(core); | |
response = AnyUtil.objectToAny(fieldNames); | |
break; | |
default: | |
throw new NotImplementedException("Command: " + command); | |
} | |
return response; | |
} | |
private Any doPost(HttpExchange exchange) throws MissingParameterException, SolrAdministrationException, | |
SolrServerException, IOException { | |
final PostCommand command = getPostCommand(exchange.getRequestURI()); | |
final SolrAdministration administration = getSolrAdministration(); | |
final Map<String, String[]> parameter = exchange.getParameterMap(); | |
final String core = getParameter(SolrAdministration.CORE, parameter); | |
final String other = getParameter(SolrAdministration.OTHER, parameter); | |
Any response = null; | |
switch (command) { | |
case STATUS: | |
if (core != null) { | |
response = administration.status(core); | |
break; | |
} | |
response = administration.status(); | |
break; | |
case CREATE: | |
final String name = getParameter(SolrAdministration.NAME, parameter); | |
assertRequiredParameterNotNull(name, SolrAdministration.NAME); | |
final String instanceDir = getParameter(SolrAdministration.INSTANCE_DIR, parameter); | |
assertRequiredParameterNotNull(instanceDir, SolrAdministration.INSTANCE_DIR); | |
response = administration.create(name, instanceDir, parameter); | |
break; | |
case RELOAD: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
response = administration.reload(core); | |
break; | |
case RENAME: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
assertRequiredParameterNotNull(other, SolrAdministration.OTHER); | |
response = administration.rename(core, other); | |
break; | |
case SWAP: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
assertRequiredParameterNotNull(other, SolrAdministration.OTHER); | |
response = administration.swap(core, other); | |
break; | |
case UNLOAD: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
final String deleteIndexString = getParameter(SolrAdministration.DELETE_INDEX, parameter); | |
final boolean deleteIndex = BooleanUtils.toBoolean(deleteIndexString); | |
response = administration.unload(core, deleteIndex); | |
break; | |
case LOAD: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
response = administration.load(core); | |
break; | |
case MERGE: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
final String[] sourceCore = parameter.get(SolrAdministration.SRC_CORE); | |
assertRequiredParametersNotNull(sourceCore, SolrAdministration.SRC_CORE); | |
response = administration.mergeIndexes(core, sourceCore); | |
break; | |
case CLEARCORECACHE: | |
if (core != null) { | |
administration.clearCoreCache(core); | |
break; | |
} | |
administration.clearCoreCaches(); | |
break; | |
case OPTIMIZE: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
response = administration.optimize(core); | |
break; | |
case PING: | |
assertRequiredParameterNotNull(core, SolrAdministration.CORE); | |
response = administration.ping(core); | |
break; | |
default: | |
throw new NotImplementedException("Command: " + command); | |
} | |
return response; | |
} | |
private GetCommand getGetCommand(String requestUri) throws MalformedURLException { | |
final List<String> dynamicUriParts = getDynamicUriParts(requestUri); | |
final String command = CollectionUtils.isEmpty(dynamicUriParts) ? null : dynamicUriParts.get(0); | |
if (StringUtils.isBlank(command)) { | |
throw new MalformedURLException("RequestUri must contain command."); | |
} | |
try { | |
return GetCommand.valueOf(command.toUpperCase()); | |
} catch (Exception exception) { | |
final String allowed = StringUtils.join(GetCommand.values(), " "); | |
final String msg = | |
MessageFormat.format("Invalid get command: {0}. Valid commands are: {1}", command, allowed); | |
throw new IllegalArgumentException(msg, exception); | |
} | |
} | |
private PostCommand getPostCommand(final String requestUri) throws MalformedURLException { | |
final List<String> dynamicUriParts = getDynamicUriParts(requestUri); | |
final String command = CollectionUtils.isEmpty(dynamicUriParts) ? null : dynamicUriParts.get(0); | |
if (StringUtils.isBlank(command)) { | |
throw new MalformedURLException("RequestUri must contain command."); | |
} | |
try { | |
return PostCommand.valueOf(command.toUpperCase()); | |
} catch (Exception exception) { | |
final String allowed = StringUtils.join(PostCommand.values(), " "); | |
final String msg = | |
MessageFormat.format("Invalid post command: {0}. Valid commands are: {1}.", command, allowed); | |
throw new IllegalArgumentException(msg, exception); | |
} | |
} | |
private void assertRequiredParameterNotNull(String parameter, String name) throws MissingParameterException { | |
if (parameter == null) { | |
final String msg = MessageFormat.format("Required paramter {0} must not be null", name); | |
throw new MissingParameterException(msg); | |
} | |
} | |
private void assertRequiredParametersNotNull(String[] parameters, String name) throws MissingParameterException { | |
if (ArrayUtils.isEmpty(parameters)) { | |
final String msg = MessageFormat.format("Required paramter array {0} must not be null", name); | |
throw new MissingParameterException(msg); | |
} | |
} | |
private String getParameter(String name, Map<String, String[]> parameter) { | |
final String[] values = parameter.get(name); | |
if (ArrayUtils.isEmpty(values)) { | |
return null; | |
} | |
return values[0]; | |
} | |
private void sendResponse(HttpExchange exchange, Any result) throws IOException { | |
final OutputStream responseStream = exchange.getResponseStream(); | |
final Record record = new DefaultDataFactoryImpl().createRecord(); | |
record.getMetadata().put("administration", result); | |
final String xml = XmlSerializationUtils.serialize2string(record); | |
responseStream.write(xml.getBytes("UTF-8")); | |
// Didn't work for whatever reason. | |
// XmlSerializationUtils.serialize2stream(record, responseStream); | |
exchange.setResponseHeader("Content-Type", MimeTypes.TEXT_XML_UTF_8); | |
exchange.setResponseStatus(HttpServletResponse.SC_OK); | |
responseStream.flush(); | |
} | |
/** | |
* Send an error response. | |
* | |
* @param exchange | |
* the {@link HttpExchange}. | |
* @param exception | |
* the {@link Throwable} to send. | |
* @throws IOException | |
* if {@link HttpExchange#getResponseStream()} or {@link OutputStream#write(byte[])} or | |
* {@link OutputStream#flush()} throws {@link IOException}. | |
* @throws XMLStreamException | |
*/ | |
private void sendError(HttpExchange exchange, Throwable exception) throws IOException { | |
final String fullStackTrace = ExceptionUtils.getFullStackTrace(exception); | |
final OutputStream errorStream = exchange.getResponseStream(); | |
errorStream.write(fullStackTrace.getBytes()); | |
exchange.setResponseHeader("Content-Type", "text"); | |
if (exception instanceof UnsupportedMethodException || exception instanceof MissingParameterException) { | |
exchange.setResponseStatus(HttpServletResponse.SC_BAD_REQUEST); | |
} else { | |
exchange.setResponseStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | |
} | |
errorStream.flush(); | |
} | |
enum PostCommand { | |
STATUS, CREATE, RELOAD, RENAME, SWAP, UNLOAD, LOAD, MERGE, OPTIMIZE, PING, CLEARCORECACHE; | |
} | |
enum GetCommand { | |
CORENAMES, FIELDNAMES; | |
} | |
private SolrAdministration getSolrAdministration() { | |
return Activator.getInstance().getSolrManager().getSolrAdministration(); | |
} | |
} |