/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.monitor; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; import org.geoserver.monitor.Query.Comparison; import org.geoserver.monitor.Query.SortOrder; import org.geoserver.ows.util.OwsUtils; public class MemoryMonitorDAO implements MonitorDAO { public static final String NAME = "memory"; Queue<RequestData> live = new ConcurrentLinkedQueue<RequestData>(); Queue<RequestData> history = new ConcurrentLinkedQueue<RequestData>(); AtomicLong REQUEST_ID_GEN = new AtomicLong(1); @Override public String getName() { return NAME; } @Override public void init(MonitorConfig config) { } public RequestData init(RequestData data) { data.setId(REQUEST_ID_GEN.getAndIncrement()); return data; } public void add(RequestData data) { live.add(data); } public void update(RequestData data) { } public void save(RequestData data) { live.remove(data); history.add(data); if (history.size() > 100) { history.poll(); } } public RequestData getRequest(long id) { for (RequestData r : getRequests()) { if (r.getId() == id) { return r; } } return null; } public List<RequestData> getRequests() { List<RequestData> requests = new LinkedList(); requests.addAll(live); requests.addAll(history); return requests; } public List<RequestData> getRequests(Query q) { List<RequestData> requests = getRequests(); List<Predicate> predicates = new ArrayList(); if (q.getFilter() != null) { Filter f = q.getFilter(); predicates.add(new PropertyCompare(f.getLeft(), f.getType(), f.getRight())); } if (q.getFromDate() != null || q.getToDate() != null) { predicates.add(new DateRange(q.getFromDate(), q.getToDate())); } int i = 1, count = 0; O: for (Iterator<RequestData> it = requests.iterator(); it.hasNext();) { RequestData r = it.next(); for (Predicate p : predicates) { if (!p.matches(r)) { it.remove(); continue O; } } if (q.getOffset() != null && q.getOffset() >= i++) { it.remove(); continue; } if (q.getCount() != null && q.getCount() <= count) { it.remove(); continue; } count++; } if (q.getSortBy() != null) { Collections.sort(requests, new Sorter(q.getSortBy(), q.getSortOrder())); } else if (q.getFromDate() != null || q.getToDate() != null) { Collections.sort(requests, new Sorter("startTime", SortOrder.DESC)); } return requests; } public void getRequests(Query query, RequestDataVisitor visitor) { for (RequestData r : getRequests(query)) { visitor.visit(r); } } public long getCount(Query query) { return getRequests(query).size(); } public Iterator<RequestData> getIterator(Query query) { return getRequests(query).iterator(); } public ResourceData getLayer(String name) { // TODO Auto-generated method stub return null; } public List<ResourceData> getLayers() { // TODO Auto-generated method stub return null; } public List<ResourceData> getLayers(Query query) { // TODO Auto-generated method stub return null; } public void getLayers(Query query, MonitorVisitor<ResourceData> visitor) { // TODO Auto-generated method stub } public List<RequestData> getOwsRequests() { return null; } public java.util.List<RequestData> getOwsRequests(String service, String operation, String version) { return null; }; public void clear() { live.clear(); history.clear(); } public void dispose() { live.clear(); history.clear(); REQUEST_ID_GEN = new AtomicLong(1); } static interface Predicate { boolean matches(RequestData data); } static class DateRange implements Predicate { Date from; Date to; DateRange(Date from, Date to) { this.from = from; this.to = to; } public boolean matches(RequestData data) { Date time = data.getStartTime(); if (time == null) { return false; } if (from != null) { if (time.before(from)) { return false; } } if (to != null) { if (time.after(to)) { return false; } } return true; } } static class PropertyCompare implements Predicate{ Object left, right; Comparison compare; public PropertyCompare(Object left, Comparison compare, Object right) { this.left = left; this.right = right; this.compare = compare; } public boolean matches(RequestData data) { String property = null; Object value = null; if (left instanceof String && OwsUtils.has(data, (String)left)) { property = (String) left; value = right; } else if (right instanceof String && OwsUtils.has(data, (String)right)) { property = (String) right; value = left; } if (property == null) { throw new IllegalArgumentException("Could not find property"); } Object o = OwsUtils.get(data, property); if (o == null) { return value == null && compare == Comparison.EQ; } if (compare == Comparison.IN) { if (!(value instanceof List)) { throw new UnsupportedOperationException( "IN comparison only supported against list values"); } return ((List)value).contains(o); } if (compare == Comparison.EQ) { return o.equals(value); } if (compare == Comparison.NEQ) { return !o.equals(value); } if (o instanceof Comparable) { int c = ((Comparable)o).compareTo(value); switch(compare) { case LT: return c < 0; case LTE: return c <= 0; case GT: return c > 0; case GTE: return c >= 0; } return false; } else { throw new UnsupportedOperationException("Values of type "+value.getClass().getName() + " only support equality and non-equality comparison."); } } } static class Sorter implements Comparator<RequestData> { String property; SortOrder order; Sorter(String property, SortOrder order) { this.property = property; this.order = order; } public int compare(RequestData r1, RequestData r2) { int c = compareInternal(r1, r2); return order == SortOrder.ASC ? c : -1 * c; } public int compareInternal(RequestData r1, RequestData r2) { Object o1 = OwsUtils.get(r1, property); Object o2 = OwsUtils.get(r2, property); if (o1 == null && o2 != null) { return 1; } if (o1 != null && o2 == null) { return -1; } if (o1 == null && o2 == null) { return 0; } if (o1 instanceof Comparable) { return ((Comparable)o1).compareTo(o2); } return o1.toString().compareTo(o2.toString()); } } }