/*
* Licensed to the Ted Dunning under one or more contributor license
* agreements. See the NOTICE file that may be
* distributed with this work for additional information
* regarding copyright ownership. Ted Dunning licenses this file
* to you 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.mapr.anomaly;
import com.google.common.base.Preconditions;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents an event from a log.
*/
public class Event implements Comparable<Event> {
private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
private static final Pattern format = Pattern.compile("\\[(.*)] /(.+)[\\?&]user=(.*) (.*)\\.(.*)\\.(.*)\\.(.*)");
private final int uid;
private final long time;
private final int ip;
private final String op;
public Event(int uid, long time, int ip, String op) {
Preconditions.checkNotNull(op);
this.uid = uid;
this.time = time;
this.ip = ip;
this.op = op;
}
public static Event read(BufferedReader in) throws IOException {
in.mark(1000);
String line = in.readLine();
if (line == null) {
return null;
}
try {
Matcher m = format.matcher(line);
if (m.matches()) {
int i = 1;
Date d = df.parse(m.group(i++));
String op = m.group(i++);
int uid = Integer.parseInt(m.group(i++), 16);
int ip = Integer.parseInt(m.group(i++)) << 24;
ip += Integer.parseInt(m.group(i++)) << 16;
ip += Integer.parseInt(m.group(i++)) << 8;
ip += Integer.parseInt(m.group(i));
return new Event(uid, d.getTime(), ip, op);
} else {
in.reset();
return null;
}
} catch (ParseException e) {
in.reset();
return null;
} catch (NumberFormatException e) {
in.reset();
return null;
}
}
public int getIp() {
return ip;
}
public long getTime() {
return time;
}
public int getUid() {
return uid;
}
public String getOp() {
return op;
}
@Override
public int compareTo(Event o) {
int r = Integer.compare(uid, o.uid);
if (r != 0) {
return r;
}
r = Long.compare(time, o.time);
if (r != 0) {
return r;
}
r = Integer.compare(ip, o.ip);
return r;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Event)) return false;
Event event = (Event) o;
if (ip != event.ip) return false;
if (time != event.time) return false;
if (uid != event.uid) return false;
return op.equals(event.op);
}
@Override
public int hashCode() {
int result = uid;
result = 31 * result + (int) (time ^ (time >>> 32));
result = 31 * result + ip;
result = 31 * result + op.hashCode();
return result;
}
public static class EventFormatException extends Throwable {
@SuppressWarnings("unused")
public EventFormatException(String line) {
super(String.format("Invalid event format found: \"%s\"", line));
}
}
}