Java tutorial
/** * Logspace * Copyright (c) 2015 Indoqa Software Design und Beratung GmbH. All rights reserved. * This program and the accompanying materials are made available under the terms of * the Eclipse Public License Version 1.0, which accompanies this distribution and * is available at http://www.eclipse.org/legal/epl-v10.html. */ package io.logspace.hq.solr; import static com.indoqa.lang.util.StringUtils.escapeSolr; import static com.indoqa.lang.util.TimeUtils.formatSolrDate; import static java.util.Calendar.*; import static java.util.concurrent.TimeUnit.*; import static org.apache.solr.common.params.CommonParams.SORT; import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_PARAM; import static org.apache.solr.common.params.ShardParams._ROUTE_; import java.io.*; import java.text.MessageFormat; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.AutoCloseInputStream; import org.apache.commons.lang3.StringUtils; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.StreamingResponseCallback; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.InputStreamResponseParser; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.FacetField.Count; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.cloud.Slice; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.response.JSONResponseWriter; import org.apache.solr.response.SolrQueryResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import com.indoqa.lang.util.TimeTracker; import com.indoqa.lang.util.TimeUtils; import com.indoqa.solr.facet.api.*; import io.logspace.agent.api.event.Event; import io.logspace.agent.api.event.EventProperty; import io.logspace.agent.api.json.EventPage; import io.logspace.agent.api.order.Aggregate; import io.logspace.agent.api.order.PropertyDescription; import io.logspace.agent.api.order.PropertyType; import io.logspace.hq.core.api.capabilities.CapabilitiesService; import io.logspace.hq.core.api.event.EventService; import io.logspace.hq.core.api.event.NativeQueryResult; import io.logspace.hq.core.api.event.StoredEvent; import io.logspace.hq.rest.api.DataRetrievalException; import io.logspace.hq.rest.api.EventStoreException; import io.logspace.hq.rest.api.agentactivity.AgentActivities; import io.logspace.hq.rest.api.agentactivity.AgentActivity; import io.logspace.hq.rest.api.event.*; import io.logspace.hq.rest.api.suggestion.AgentDescription; import io.logspace.hq.rest.api.suggestion.Suggestion; import io.logspace.hq.rest.api.suggestion.SuggestionInput; import io.logspace.hq.rest.api.timeseries.InvalidTimeSeriesDefinitionException; import io.logspace.hq.rest.api.timeseries.TimeSeriesDefinition; import io.logspace.hq.rest.api.timeseries.TimeWindow; @Named public class SolrEventService implements EventService { private static final String ALL_DOCS_QUERY = "*:*"; private static final String SORT_CRON_ASC = "timestamp ASC, id ASC"; private static final String SORT_CRON_DESC = "timestamp DESC, id ASC"; private static final long AGENT_DESCRIPTION_REFRESH_INTERVAL = 60000L; private static final long SLICE_UPDATE_INTERVAL = 1000L; private static final String VALUE_FACET_NAME = "val"; private static final String AGGREGATION_FACET_NAME = "agg"; private static final String COUNT_FACET_NAME = "count"; private static final String FIELD_ID = "id"; private static final String FIELD_SPACE = "space"; private static final String FIELD_SYSTEM = "system"; private static final String FIELD_AGENT_ID = "agent_id"; private static final String FIELD_GLOBAL_AGENT_ID = "global_agent_id"; private static final String FIELD_TYPE = "type"; private static final String FIELD_MARKER = "marker"; private static final String FIELD_GLOBAL_ID = "global_id"; private static final String FIELD_PARENT_ID = "parent_id"; private static final String FIELD_TIMESTAMP = "timestamp"; private static final String FIELD_PROPERTY_ID = "property_id"; private static final String FIELD_TOKENIZED_SEARCH_FIELD = "tokenized_search_field"; private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Inject @Qualifier("logspace-solr-client") private SolrClient solrClient; @Inject private CapabilitiesService capabilitiesService; @Value("${logspace.solr.fallback-shard}") private String fallbackShard; private boolean isCloud; private Map<String, Slice> activeSlicesMap; private long nextSliceUpdate; private final Map<String, AgentDescription> cachedAgentDescriptions = new ConcurrentHashMap<>(); private final JSONResponseWriter jsonResponseWriter = new JSONResponseWriter(); @Override public NativeQueryResult executeNativeQuery(Map<String, String[]> parameters) { SolrParams params = this.createSolrParams(parameters); try { QueryRequest request = new QueryRequest(params, METHOD.POST); request.setResponseParser(new InputStreamResponseParser("json")); QueryResponse response = request.process(this.solrClient); InputStream inputStream = (InputStream) response.getResponse().get("stream"); if (inputStream != null) { return new SolrNativeQueryResult(inputStream); } return new SolrNativeQueryResult(this.serializeResponse(params, response)); } catch (SolrException | SolrServerException | IOException e) { throw new DataRetrievalException( "Could not execute direct query with parameters " + parameters.toString() + ".", e); } } @SuppressWarnings("unchecked") @Override public AgentActivities getAgentActivities(int start, int count, int durationSeconds, int steps, String sort) { SolrQuery solrQuery = new SolrQuery(ALL_DOCS_QUERY); solrQuery.setRows(0); Date endDate = new Date(); Date startDate = new Date(endDate.getTime() - SECONDS.toMillis(durationSeconds)); solrQuery.addFilterQuery(this.getTimestampRangeQuery(startDate, endDate)); TermsFacet agentFacet = new TermsFacet(FIELD_GLOBAL_AGENT_ID, FIELD_GLOBAL_AGENT_ID); agentFacet.setOffset(start); agentFacet.setLimit(count); agentFacet.setMincount(0); agentFacet.setNumBuckets(true); agentFacet.setSort(sort); agentFacet.addSubFacet(new RangeFacet(FIELD_TIMESTAMP, FIELD_TIMESTAMP, startDate, endDate, GapUnit.SECONDS, durationSeconds / steps)); solrQuery.set("json.facet", FacetList.toJsonString(agentFacet)); try { AgentActivities result = new AgentActivities(); QueryResponse response = this.solrClient.query(solrQuery, METHOD.POST); Buckets agentBuckets = Buckets.fromResponse(response, FIELD_GLOBAL_AGENT_ID); result.setOffset(start); result.setTotalCount(agentBuckets.getNumBuckets()); int maxHistoryValue = 0; for (NamedList<Object> eachAgentBucket : agentBuckets) { AgentActivity agentActivity = new AgentActivity(); agentActivity.setGlobalAgentId((String) eachAgentBucket.get(VALUE_FACET_NAME)); agentActivity.setEventCount(Buckets.getInt(eachAgentBucket, COUNT_FACET_NAME)); int[] history = new int[steps]; Buckets historyBuckets = Buckets .fromFacet((NamedList<Object>) eachAgentBucket.get(FIELD_TIMESTAMP)); for (int i = 0; i < Math.min(historyBuckets.getBucketCount(), history.length); i++) { NamedList<Object> historyBucket = historyBuckets.getBucket(i); int historyValue = Buckets.getInt(historyBucket, COUNT_FACET_NAME); history[i] = historyValue; maxHistoryValue = Math.max(maxHistoryValue, historyValue); } agentActivity.setHistory(history); result.add(agentActivity); } result.setMaxHistoryValue(maxHistoryValue); return result; } catch (SolrException | SolrServerException | IOException e) { throw new DataRetrievalException("Could not retrieve Agent activities.", e); } } @Override public Suggestion getSuggestion(SuggestionInput input) { TimeTracker timeTracker = new TimeTracker(); SolrQuery solrQuery = new SolrQuery(ALL_DOCS_QUERY); solrQuery.setRows(0); if (!StringUtils.isBlank(input.getText())) { solrQuery.addFilterQuery(FIELD_TOKENIZED_SEARCH_FIELD + ":" + escapeSolr(input.getText()) + "*"); } this.addFilterQuery(solrQuery, FIELD_PROPERTY_ID, input.getPropertyId()); this.addFilterQuery(solrQuery, FIELD_SPACE, input.getSpaceId()); this.addFilterQuery(solrQuery, FIELD_SYSTEM, input.getSystemId()); solrQuery.setFacetMinCount(1); solrQuery.addFacetField(FIELD_GLOBAL_AGENT_ID); try { Suggestion result = new Suggestion(); QueryResponse response = this.solrClient.query(solrQuery); FacetField globalAgentIdFacetField = response.getFacetField(FIELD_GLOBAL_AGENT_ID); for (Count eachValue : globalAgentIdFacetField.getValues()) { String globalAgentId = eachValue.getName(); result.addAgentDescription(this.getAgentDescription(globalAgentId)); } result.setExecutionTime(timeTracker.getElapsed(MILLISECONDS)); return result; } catch (SolrException | SolrServerException | IOException e) { throw new DataRetrievalException("Failed to create suggestions", e); } } @Override public Object[] getTimeSeries(TimeSeriesDefinition dataDefinition) { SolrQuery solrQuery = new SolrQuery(ALL_DOCS_QUERY); solrQuery.setRows(0); solrQuery.addFilterQuery(FIELD_GLOBAL_AGENT_ID + ":" + escapeSolr(dataDefinition.getGlobalAgentId())); solrQuery.addFilterQuery(this.getTimestampRangeQuery(dataDefinition.getTimeWindow())); solrQuery.addFilterQuery(dataDefinition.getPropertyId() + ":*"); solrQuery.set("json.facet", this.createTimeSeriesFacets(dataDefinition)); try { QueryResponse response = this.solrClient.query(solrQuery, METHOD.POST); List<Object> values = new ArrayList<Object>(); Buckets buckets = Buckets.fromResponse(response, FIELD_TIMESTAMP); for (NamedList<Object> eachBucket : buckets) { if (dataDefinition.getAggregate() == Aggregate.count) { values.add(eachBucket.get(COUNT_FACET_NAME)); } else { values.add(eachBucket.get(AGGREGATION_FACET_NAME)); } } return values.toArray(); } catch (SolrException | SolrServerException | IOException e) { throw new DataRetrievalException("Could not retrieve data.", e); } } @PostConstruct public void initialize() { this.isCloud = this.solrClient instanceof CloudSolrClient; if (this.isCloud) { ((CloudSolrClient) this.solrClient).connect(); } new Timer(true).schedule(new RefreshAgentDescriptionCacheTask(), AGENT_DESCRIPTION_REFRESH_INTERVAL, AGENT_DESCRIPTION_REFRESH_INTERVAL); } @Override public EventPage retrieve(EventFilter eventFilter, int count, String cursorMark) { return this.retrieve(eventFilter, count, cursorMark, SORT_CRON_ASC); } @Override public EventPage retrieveReversed(EventFilter eventFilter, int count, String cursorMark) { return this.retrieve(eventFilter, count, cursorMark, SORT_CRON_DESC); } @Override public void store(Collection<? extends Event> events, String space) { if (events == null || events.isEmpty()) { return; } String system = events.stream().findFirst().get().getSystem(); this.logger.debug("Storing {} event(s) for space '{}' from system {}", events.size(), space, system); try { Collection<SolrInputDocument> inputDocuments = this.createInputDocuments(events, space); this.solrClient.add(inputDocuments); this.logger.info("Successfully stored {} event(s) for space '{}' from system {}", events.size(), space, system); } catch (SolrServerException | IOException e) { String message = "Failed to store " + events.size() + " events."; this.logger.error(message, e); throw EventStoreException.storeFailed(message, e); } } @Override public void stream(EventFilter eventFilter, int count, int offset, EventStreamer eventStreamer) { SolrQuery solrQuery = new SolrQuery(ALL_DOCS_QUERY); solrQuery.setStart(offset); solrQuery.setRows(count); solrQuery.set(SORT, SORT_CRON_ASC); for (EventFilterElement eachElement : eventFilter) { solrQuery.addFilterQuery(this.createFilterQuery(eachElement)); } try { this.solrClient.queryAndStreamResponse(solrQuery, new EventStreamCallback(eventStreamer)); } catch (SolrServerException | IOException e) { String message = "Failed to stream events."; this.logger.error(message, e); throw EventStoreException.retrieveFailed(message, e); } } protected void refreshAgentDescriptionCache() { for (String eachGlobalAgentId : this.cachedAgentDescriptions.keySet()) { try { this.cachedAgentDescriptions.put(eachGlobalAgentId, this.loadAgentDescription(eachGlobalAgentId)); } catch (Exception e) { this.cachedAgentDescriptions.remove(eachGlobalAgentId); } } } private void addFilterQuery(SolrQuery solrQuery, String fieldName, String value) { if (StringUtils.isBlank(value)) { return; } solrQuery.addFilterQuery(fieldName + ":" + escapeSolr(value)); } private void addProperties(SolrInputDocument document, Iterable<? extends EventProperty<?>> properties, String prefix) { for (EventProperty<?> eachProperty : properties) { String propertyId = prefix + eachProperty.getKey(); document.addField(propertyId, eachProperty.getValue()); document.addField(FIELD_PROPERTY_ID, propertyId); } } private void appendSolrValue(StringBuilder stringBuilder, Object value) { if (value == null) { stringBuilder.append('*'); return; } if (value instanceof Date) { stringBuilder.append(TimeUtils.formatSolrDate((Date) value)); } String result = String.valueOf(value); if (StringUtils.isBlank(result)) { stringBuilder.append('*'); return; } stringBuilder.append('"'); stringBuilder.append(result); stringBuilder.append('"'); } private Event createEvent(SolrDocument solrDocument) { StoredEvent result = new StoredEvent(); result.setId(this.getString(solrDocument, FIELD_ID)); result.setSystem(this.getString(solrDocument, FIELD_SYSTEM)); result.setAgentId(this.getString(solrDocument, FIELD_AGENT_ID)); result.setType(this.getString(solrDocument, FIELD_TYPE)); result.setMarker(this.getString(solrDocument, FIELD_MARKER)); result.setTimestamp(this.getDate(solrDocument, FIELD_TIMESTAMP)); result.setParentEventId(this.getString(solrDocument, FIELD_PARENT_ID)); result.setGlobalEventId(this.getString(solrDocument, FIELD_GLOBAL_ID)); for (Entry<String, Object> eachField : solrDocument) { String fieldName = eachField.getKey(); if (fieldName.startsWith("boolean_property_")) { result.addProperties(fieldName.substring("boolean_property_".length()), eachField.getValue()); } if (fieldName.startsWith("date_property_")) { result.addProperties(fieldName.substring("date_property_".length()), eachField.getValue()); } if (fieldName.startsWith("double_property_")) { result.addProperties(fieldName.substring("double_property_".length()), eachField.getValue()); } if (fieldName.startsWith("float_property_")) { result.addProperties(fieldName.substring("float_property_".length()), eachField.getValue()); } if (fieldName.startsWith("integer_property_")) { result.addProperties(fieldName.substring("integer_property_".length()), eachField.getValue()); } if (fieldName.startsWith("long_property_")) { result.addProperties(fieldName.substring("long_property_".length()), eachField.getValue()); } if (fieldName.startsWith("string_property_")) { result.addProperties(fieldName.substring("string_property_".length()), eachField.getValue()); } } return result; } private String createFilterQuery(EventFilterElement eventFilterElement) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(eventFilterElement.getProperty()); stringBuilder.append(':'); if (eventFilterElement instanceof EqualsEventFilterElement) { EqualsEventFilterElement equalsEventFilterElement = (EqualsEventFilterElement) eventFilterElement; this.appendSolrValue(stringBuilder, equalsEventFilterElement.getValue()); } if (eventFilterElement instanceof RangeEventFilterElement) { RangeEventFilterElement rangeEventFilterElement = (RangeEventFilterElement) eventFilterElement; stringBuilder.append('['); this.appendSolrValue(stringBuilder, rangeEventFilterElement.getFrom()); stringBuilder.append(" TO "); this.appendSolrValue(stringBuilder, rangeEventFilterElement.getTo()); stringBuilder.append(']'); } if (eventFilterElement instanceof MultiValueEventFilterElement) { MultiValueEventFilterElement multiValueEventFilterElement = (MultiValueEventFilterElement) eventFilterElement; stringBuilder.append('('); for (Iterator<String> iterator = multiValueEventFilterElement.getValues().iterator(); iterator .hasNext();) { this.appendSolrValue(stringBuilder, iterator.next()); if (iterator.hasNext()) { stringBuilder.append(' '); stringBuilder.append(multiValueEventFilterElement.getOperator()); stringBuilder.append(' '); } } stringBuilder.append(')'); } return stringBuilder.toString(); } private SolrInputDocument createInputDocument(Event event, String space) { SolrInputDocument result = new SolrInputDocument(); result.addField(FIELD_ID, event.getId()); result.addField(FIELD_GLOBAL_AGENT_ID, this.capabilitiesService.getGlobalAgentId(space, event.getSystem(), event.getAgentId())); result.addField(FIELD_SPACE, space); result.addField(FIELD_SYSTEM, event.getSystem()); result.addField(FIELD_AGENT_ID, event.getAgentId()); result.addField(FIELD_TYPE, event.getType()); result.addField(FIELD_MARKER, event.getMarker()); result.addField(FIELD_TIMESTAMP, event.getTimestamp()); result.addField(FIELD_PARENT_ID, event.getParentEventId()); result.addField(FIELD_GLOBAL_ID, event.getGlobalEventId()); this.addProperties(result, event.getBooleanProperties(), "boolean_property_"); this.addProperties(result, event.getDateProperties(), "date_property_"); this.addProperties(result, event.getDoubleProperties(), "double_property_"); this.addProperties(result, event.getFloatProperties(), "float_property_"); this.addProperties(result, event.getIntegerProperties(), "integer_property_"); this.addProperties(result, event.getLongProperties(), "long_property_"); this.addProperties(result, event.getStringProperties(), "string_property_"); if (this.isCloud) { result.setField(_ROUTE_, this.getTargetShard(event.getTimestamp())); } return result; } private Collection<SolrInputDocument> createInputDocuments(Collection<? extends Event> events, String space) { Collection<SolrInputDocument> result = new ArrayList<SolrInputDocument>(); for (Event eachEvent : events) { result.add(this.createInputDocument(eachEvent, space)); } return result; } private PropertyDescription createPropertyDescription(String propertyId) { if (propertyId == null) { return null; } Pattern propertyIdPattern = Pattern.compile("(\\w+)_property_(.*?)"); Matcher matcher = propertyIdPattern.matcher(propertyId); if (!matcher.matches()) { return null; } PropertyDescription result = new PropertyDescription(); result.setId(propertyId); result.setPropertyType(PropertyType.get(matcher.group(1))); result.setName(matcher.group(2)); return result; } private SolrParams createSolrParams(Map<String, String[]> parameters) { ModifiableSolrParams result = new ModifiableSolrParams(); for (Entry<String, String[]> eachEntry : parameters.entrySet()) { result.add(eachEntry.getKey(), eachEntry.getValue()); } return result; } private String createTimeSeriesFacets(TimeSeriesDefinition dataDefinition) { PropertyDescription propertyDescription = this.createPropertyDescription(dataDefinition.getPropertyId()); if (!propertyDescription.getPropertyType().isAllowed(dataDefinition.getAggregate())) { throw InvalidTimeSeriesDefinitionException.illegalAggregate(propertyDescription.getPropertyType(), dataDefinition.getAggregate()); } Date startDate = dataDefinition.getTimeWindow().getStart(); Date endDate = dataDefinition.getTimeWindow().getEnd(); int gap = dataDefinition.getTimeWindow().getGap(); RangeFacet rangeFacet = new RangeFacet(FIELD_TIMESTAMP, FIELD_TIMESTAMP, startDate, endDate, GapUnit.SECONDS, gap); if (dataDefinition.getAggregate() != Aggregate.count) { rangeFacet.addSubFacet(new StatisticFacet(AGGREGATION_FACET_NAME, dataDefinition.getFacetFunction())); } return FacetList.toJsonString(rangeFacet); } private AgentDescription getAgentDescription(String globalAgentId) throws SolrServerException, IOException { AgentDescription agentDescription = this.capabilitiesService.getAgentDescription(globalAgentId); if (agentDescription == null || agentDescription.getPropertyDescriptions() == null || agentDescription.getPropertyDescriptions().isEmpty()) { agentDescription = this.cachedAgentDescriptions.get(globalAgentId); } if (agentDescription == null) { agentDescription = this.loadAgentDescription(globalAgentId); this.cachedAgentDescriptions.put(globalAgentId, agentDescription); } return agentDescription; } private Date getDate(SolrDocument solrDocument, String fieldName) { return (Date) solrDocument.getFieldValue(fieldName); } private String getFirstFacetValue(QueryResponse response, String fieldName) { FacetField facetField = response.getFacetField(fieldName); if (facetField == null) { return null; } List<Count> values = facetField.getValues(); if (values == null || values.isEmpty()) { return null; } return values.get(0).getName(); } private String getString(SolrDocument solrDocument, String fieldName) { return (String) solrDocument.getFieldValue(fieldName); } private String getTargetShard(Date timestamp) { if (!this.isCloud) { return null; } CloudSolrClient cloudSolrClient = (CloudSolrClient) this.solrClient; if (System.currentTimeMillis() > this.nextSliceUpdate) { this.nextSliceUpdate = System.currentTimeMillis() + SLICE_UPDATE_INTERVAL; this.activeSlicesMap = cloudSolrClient.getZkStateReader().getClusterState() .getActiveSlicesMap(cloudSolrClient.getDefaultCollection()); } Calendar calendar = Calendar.getInstance(); calendar.setTime(timestamp); String sliceName = MessageFormat.format("{0,number,0000}-{1,number,00}", calendar.get(YEAR), calendar.get(MONTH) + 1); if (this.activeSlicesMap.containsKey(sliceName)) { return sliceName; } return this.fallbackShard; } private String getTimestampRangeQuery(Date start, Date end) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(FIELD_TIMESTAMP); stringBuilder.append(":["); stringBuilder.append(formatSolrDate(start)); stringBuilder.append(" TO "); stringBuilder.append(formatSolrDate(end)); stringBuilder.append("}"); return stringBuilder.toString(); } private String getTimestampRangeQuery(TimeWindow timeWindow) { return this.getTimestampRangeQuery(timeWindow.getStart(), timeWindow.getEnd()); } private AgentDescription loadAgentDescription(String globalAgentId) throws SolrServerException, IOException { SolrQuery query = new SolrQuery(ALL_DOCS_QUERY); query.setRows(0); query.setFilterQueries(FIELD_GLOBAL_AGENT_ID + ":\"" + globalAgentId + "\""); query.setFacetMinCount(1); query.addFacetField(FIELD_SPACE, FIELD_SYSTEM, FIELD_PROPERTY_ID); QueryResponse response = this.solrClient.query(query); AgentDescription result = new AgentDescription(); result.setGlobalId(globalAgentId); result.setName(this.capabilitiesService.getAgentId(globalAgentId)); result.setSpace(this.getFirstFacetValue(response, FIELD_SPACE)); result.setSystem(this.getFirstFacetValue(response, FIELD_SYSTEM)); List<PropertyDescription> propertyDescriptions = new ArrayList<>(); FacetField facetField = response.getFacetField(FIELD_PROPERTY_ID); for (Count eachValue : facetField.getValues()) { propertyDescriptions.add(this.createPropertyDescription(eachValue.getName())); } Collections.sort(propertyDescriptions); result.setPropertyDescriptions(propertyDescriptions); return result; } private EventPage retrieve(EventFilter eventFilter, int count, String cursorMark, String sort) { SolrQuery solrQuery = new SolrQuery(ALL_DOCS_QUERY); solrQuery.setRows(count); solrQuery.set(CURSOR_MARK_PARAM, cursorMark); solrQuery.set(SORT, sort); for (EventFilterElement eachElement : eventFilter) { solrQuery.addFilterQuery(this.createFilterQuery(eachElement)); } try { EventPage result = new EventPage(); QueryResponse response = this.solrClient.query(solrQuery); for (SolrDocument eachSolrDocument : response.getResults()) { result.addEvent(this.createEvent(eachSolrDocument)); } result.setNextCursorMark(response.getNextCursorMark()); result.setTotalCount(response.getResults().getNumFound()); return result; } catch (SolrServerException | IOException | SolrException e) { String message = "Failed to retrieve events."; this.logger.error(message, e); throw EventStoreException.retrieveFailed(message, e); } } private InputStream serializeResponse(SolrParams params, QueryResponse response) throws IOException { LocalSolrQueryRequest solrQueryRequest = new LocalSolrQueryRequest(null, params); SolrQueryResponse solrQueryResponse = new SolrQueryResponse(); solrQueryResponse.setAllValues(response.getResponse()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8"); this.jsonResponseWriter.write(writer, solrQueryRequest, solrQueryResponse); writer.flush(); return new ByteArrayInputStream(baos.toByteArray()); } protected class RefreshAgentDescriptionCacheTask extends TimerTask { @Override public void run() { SolrEventService.this.refreshAgentDescriptionCache(); } } private final class EventStreamCallback extends StreamingResponseCallback { private final EventStreamer eventStreamer; public EventStreamCallback(EventStreamer eventStreamer) { this.eventStreamer = eventStreamer; } @Override public void streamDocListInfo(long numFound, long start, Float maxScore) { // do nothing } @Override public void streamSolrDocument(SolrDocument solrDocument) { try { this.eventStreamer.streamEvent(SolrEventService.this.createEvent(solrDocument)); } catch (IOException e) { throw EventStoreException.retrieveFailed("Failed to stream events.", e); } } } private static class SolrNativeQueryResult implements NativeQueryResult { private final InputStream inputStream; public SolrNativeQueryResult(InputStream inputStream) { super(); this.inputStream = new AutoCloseInputStream(inputStream); } @Override public String getContentType() { return "application/json;charset=UTF-8"; } @Override public void writeTo(OutputStream outputStream) throws IOException { IOUtils.copy(this.inputStream, outputStream); } } }