/*
* Copyright 2011-2014 Proofpoint, Inc.
*
* 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 com.proofpoint.event.collector;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.proofpoint.event.collector.EventCollectorStats.ProcessType;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.proofpoint.event.collector.EventCollectorStats.EventStatus.UNSUPPORTED;
import static com.proofpoint.event.collector.EventCollectorStats.EventStatus.VALID;
import static com.proofpoint.event.collector.EventCollectorStats.ProcessType.DISTRIBUTE;
import static com.proofpoint.event.collector.EventCollectorStats.ProcessType.WRITE;
import static com.proofpoint.event.collector.EventResource.EventProcessor.DISTRIBUTOR;
import static com.proofpoint.event.collector.EventResource.EventProcessor.WRITER;
@Path("/v2/event")
public class EventResource
{
private final Set<EventWriter> writers;
private final Set<String> acceptedEventTypes;
private final EventCollectorStats eventCollectorStats;
@Inject
public EventResource(Set<EventWriter> writers, ServerConfig config, EventCollectorStats eventCollectorStats)
{
this.eventCollectorStats = checkNotNull(eventCollectorStats, "eventCollectorStats is null");
this.writers = checkNotNull(writers, "writers are null");
this.acceptedEventTypes = ImmutableSet.copyOf(checkNotNull(config, "config is null").getAcceptedEventTypes());
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response write(List<Event> events)
throws IOException
{
return processEvents(WRITER, events, WRITE);
}
@POST
@Path("/distribute")
@Consumes(MediaType.APPLICATION_JSON)
public Response distribute(List<Event> events)
throws IOException
{
return processEvents(DISTRIBUTOR, events, DISTRIBUTE);
}
private Response processEvents(EventProcessor processor, List<Event> events, ProcessType processType)
throws IOException
{
Set<String> badEvents = Sets.newHashSet();
for (Event event : events) {
if (acceptedEventType(event.getType())) {
for (EventWriter writer : writers) {
processor.process(writer, event);
}
eventCollectorStats.inboundEvents(event.getType(), VALID, processType).add(1);
}
else {
badEvents.add(event.getType());
eventCollectorStats.inboundEvents(event.getType(), UNSUPPORTED, processType).add(1);
}
}
if (!badEvents.isEmpty()) {
String errorMessage = "Unsupported event type(s): " + Joiner.on(", ").join(badEvents);
return Response.status(Status.BAD_REQUEST).entity(errorMessage).build();
}
return Response.status(Response.Status.ACCEPTED).build();
}
private boolean acceptedEventType(String type)
{
return acceptedEventTypes.isEmpty() || acceptedEventTypes.contains(type);
}
public enum EventProcessor
{
WRITER
{
@Override
void process(EventWriter writer, Event event)
throws IOException
{
writer.write(event);
}
},
DISTRIBUTOR
{
@Override
void process(EventWriter writer, Event event)
throws IOException
{
writer.distribute(event);
}
};
abstract void process(EventWriter writer, Event event)
throws IOException;
}
}