aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/database
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r--src/org/traccar/database/ActiveDevice.java2
-rw-r--r--src/org/traccar/database/AliasesManager.java4
-rw-r--r--src/org/traccar/database/ConnectionManager.java22
-rw-r--r--src/org/traccar/database/DataManager.java46
-rw-r--r--src/org/traccar/database/DeviceManager.java94
-rw-r--r--src/org/traccar/database/GeofenceManager.java2
-rw-r--r--src/org/traccar/database/GroupTree.java2
-rw-r--r--src/org/traccar/database/IdentityManager.java2
-rw-r--r--src/org/traccar/database/NotificationManager.java32
-rw-r--r--src/org/traccar/database/PermissionsManager.java66
-rw-r--r--src/org/traccar/database/QueryBuilder.java2
-rw-r--r--src/org/traccar/database/StatisticsManager.java88
12 files changed, 247 insertions, 115 deletions
diff --git a/src/org/traccar/database/ActiveDevice.java b/src/org/traccar/database/ActiveDevice.java
index 3f2510af1..6109bc517 100644
--- a/src/org/traccar/database/ActiveDevice.java
+++ b/src/org/traccar/database/ActiveDevice.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/AliasesManager.java b/src/org/traccar/database/AliasesManager.java
index 6c09e8731..4f4f09731 100644
--- a/src/org/traccar/database/AliasesManager.java
+++ b/src/org/traccar/database/AliasesManager.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
- * Copyright 2016 Andrey Kunitsyn (abyss@fox5.ru)
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java
index 46ccab81e..bc44c31ae 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/org/traccar/database/ConnectionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ public class ConnectionManager {
private static final long DEFAULT_TIMEOUT = 600;
private final long deviceTimeout;
+ private final boolean enableStatusEvents;
private final Map<Long, ActiveDevice> activeDevices = new HashMap<>();
private final Map<Long, Set<UpdateListener>> listeners = new HashMap<>();
@@ -47,6 +48,7 @@ public class ConnectionManager {
public ConnectionManager() {
deviceTimeout = Context.getConfig().getLong("status.timeout", DEFAULT_TIMEOUT) * 1000;
+ enableStatusEvents = Context.getConfig().getBoolean("event.statusHandler");
}
public void addActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
@@ -73,11 +75,20 @@ public class ConnectionManager {
return;
}
- if (!status.equals(device.getStatus())) {
- Event event = new Event(Event.TYPE_DEVICE_OFFLINE, deviceId);
- if (status.equals(Device.STATUS_ONLINE)) {
- event.setType(Event.TYPE_DEVICE_ONLINE);
+ if (enableStatusEvents && !status.equals(device.getStatus())) {
+ String eventType;
+ switch (status) {
+ case Device.STATUS_ONLINE:
+ eventType = Event.TYPE_DEVICE_ONLINE;
+ break;
+ case Device.STATUS_UNKNOWN:
+ eventType = Event.TYPE_DEVICE_UNKNOWN;
+ break;
+ default:
+ eventType = Event.TYPE_DEVICE_OFFLINE;
+ break;
}
+ Event event = new Event(eventType, deviceId);
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().updateEvent(event, null);
}
@@ -89,7 +100,6 @@ public class ConnectionManager {
timeout.cancel();
}
-
if (time != null) {
device.setLastUpdate(time);
}
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index 02adb0455..8be53ad7b 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2012 - 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.SQLException;
-import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@@ -48,6 +47,7 @@ import org.traccar.model.GroupPermission;
import org.traccar.model.Notification;
import org.traccar.model.Position;
import org.traccar.model.Server;
+import org.traccar.model.Statistics;
import org.traccar.model.User;
import org.traccar.model.DeviceGeofence;
import org.traccar.model.GeofencePermission;
@@ -159,12 +159,6 @@ public class DataManager {
.executeQuery(User.class);
}
- public User getUser(long userId) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectUser"))
- .setLong("id", userId)
- .executeQuerySingle(User.class);
- }
-
public void addUser(User user) throws SQLException {
user.setId(QueryBuilder.create(dataSource, getQuery("database.insertUser"), true)
.setObject(user)
@@ -286,6 +280,12 @@ public class DataManager {
.executeQuery(Position.class);
}
+ public Position getPosition(long positionId) throws SQLException {
+ return QueryBuilder.create(dataSource, getQuery("database.selectPosition"))
+ .setLong("id", positionId)
+ .executeQuerySingle(Position.class);
+ }
+
public void addPosition(Position position) throws SQLException {
position.setId(QueryBuilder.create(dataSource, getQuery("database.insertPosition"), true)
.setDate("now", new Date())
@@ -337,33 +337,19 @@ public class DataManager {
.executeUpdate());
}
- public Collection<Event> getEvents(long deviceId, String type, Date from, Date to) throws SQLException {
+ public Collection<Event> getEvents(long deviceId, Date from, Date to) throws SQLException {
return QueryBuilder.create(dataSource, getQuery("database.selectEvents"))
.setLong("deviceId", deviceId)
- .setString("type", type)
.setDate("from", from)
.setDate("to", to)
.executeQuery(Event.class);
}
- public Collection<Event> getLastEvents(long deviceId, String type, int interval) throws SQLException {
- Calendar calendar = Calendar.getInstance();
- calendar.add(Calendar.SECOND, -interval);
- Date from = calendar.getTime();
- return getEvents(deviceId, type, from, new Date());
- }
-
public Collection<Geofence> getGeofences() throws SQLException {
return QueryBuilder.create(dataSource, getQuery("database.selectGeofencesAll"))
.executeQuery(Geofence.class);
}
- public Geofence getGeofence(long geofenceId) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectGeofences"))
- .setLong("id", geofenceId)
- .executeQuerySingle(Geofence.class);
- }
-
public void addGeofence(Geofence geofence) throws SQLException {
geofence.setId(QueryBuilder.create(dataSource, getQuery("database.insertGeofence"), true)
.setObject(geofence)
@@ -484,4 +470,18 @@ public class DataManager {
.setLong("id", attributeAliasId)
.executeUpdate();
}
+
+ public Collection<Statistics> getStatistics(Date from, Date to) throws SQLException {
+ return QueryBuilder.create(dataSource, getQuery("database.selectStatistics"))
+ .setDate("from", from)
+ .setDate("to", to)
+ .executeQuery(Statistics.class);
+ }
+
+ public void addStatistics(Statistics statistics) throws SQLException {
+ statistics.setId(QueryBuilder.create(dataSource, getQuery("database.insertStatistics"), true)
+ .setObject(statistics)
+ .executeUpdate());
+ }
+
}
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index f32c7edd2..c70e67231 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import org.traccar.Config;
import org.traccar.Context;
import org.traccar.helper.Log;
import org.traccar.model.Device;
+import org.traccar.model.DeviceTotalDistance;
import org.traccar.model.Group;
import org.traccar.model.Position;
import org.traccar.model.Server;
@@ -316,98 +317,60 @@ public class DeviceManager implements IdentityManager {
groupsById.remove(groupId);
}
- public boolean lookupServerBoolean(long deviceId, String attributeName, boolean defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, true);
+ public boolean lookupAttributeBoolean(
+ long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig) {
+ String result = lookupAttribute(deviceId, attributeName, lookupConfig);
if (result != null) {
return Boolean.parseBoolean(result);
}
return defaultValue;
}
- public String lookupServerString(long deviceId, String attributeName, String defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, true);
+ public String lookupAttributeString(
+ long deviceId, String attributeName, String defaultValue, boolean lookupConfig) {
+ String result = lookupAttribute(deviceId, attributeName, lookupConfig);
if (result != null) {
return result;
}
return defaultValue;
}
- public int lookupServerInteger(long deviceId, String attributeName, int defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, true);
+ public int lookupAttributeInteger(long deviceId, String attributeName, int defaultValue, boolean lookupConfig) {
+ String result = lookupAttribute(deviceId, attributeName, lookupConfig);
if (result != null) {
return Integer.parseInt(result);
}
return defaultValue;
}
- public long lookupServerLong(long deviceId, String attributeName, long defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, true);
+ public long lookupAttributeLong(
+ long deviceId, String attributeName, long defaultValue, boolean lookupConfig) {
+ String result = lookupAttribute(deviceId, attributeName, lookupConfig);
if (result != null) {
return Long.parseLong(result);
}
return defaultValue;
}
- public double lookupServerDouble(long deviceId, String attributeName, double defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, true);
+ public double lookupAttributeDouble(
+ long deviceId, String attributeName, double defaultValue, boolean lookupConfig) {
+ String result = lookupAttribute(deviceId, attributeName, lookupConfig);
if (result != null) {
return Double.parseDouble(result);
}
return defaultValue;
}
- public boolean lookupConfigBoolean(long deviceId, String attributeName, boolean defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, false);
- if (result != null) {
- return Boolean.parseBoolean(result);
- }
- return defaultValue;
- }
-
- public String lookupConfigString(long deviceId, String attributeName, String defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, false);
- if (result != null) {
- return result;
- }
- return defaultValue;
- }
-
- public int lookupConfigInteger(long deviceId, String attributeName, int defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, false);
- if (result != null) {
- return Integer.parseInt(result);
- }
- return defaultValue;
- }
-
- public long lookupConfigLong(long deviceId, String attributeName, long defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, false);
- if (result != null) {
- return Long.parseLong(result);
- }
- return defaultValue;
- }
-
- public double lookupConfigDouble(long deviceId, String attributeName, double defaultValue) {
- String result = lookupAttribute(deviceId, attributeName, false);
- if (result != null) {
- return Double.parseDouble(result);
- }
- return defaultValue;
- }
-
- private String lookupAttribute(long deviceId, String attributeName, boolean lookupServer) {
+ private String lookupAttribute(long deviceId, String attributeName, boolean lookupConfig) {
String result = null;
Device device = getDeviceById(deviceId);
if (device != null) {
- if (device.getAttributes().containsKey(attributeName)) {
- result = (String) device.getAttributes().get(attributeName);
- }
+ result = device.getString(attributeName);
if (result == null && lookupGroupsAttribute) {
long groupId = device.getGroupId();
while (groupId != 0) {
if (getGroupById(groupId) != null) {
- result = (String) getGroupById(groupId).getAttributes().get(attributeName);
+ result = getGroupById(groupId).getString(attributeName);
if (result != null) {
break;
}
@@ -418,14 +381,25 @@ public class DeviceManager implements IdentityManager {
}
}
if (result == null) {
- if (lookupServer) {
- Server server = Context.getPermissionsManager().getServer();
- result = (String) server.getAttributes().get(attributeName);
- } else {
+ if (lookupConfig) {
result = Context.getConfig().getString(attributeName);
+ } else {
+ Server server = Context.getPermissionsManager().getServer();
+ result = server.getString(attributeName);
}
}
}
return result;
}
+
+ public void resetTotalDistance(DeviceTotalDistance deviceTotalDistance) throws SQLException {
+ Position last = positions.get(deviceTotalDistance.getDeviceId());
+ if (last != null) {
+ last.getAttributes().put(Position.KEY_TOTAL_DISTANCE, deviceTotalDistance.getTotalDistance());
+ dataManager.addPosition(last);
+ updateLatestPosition(last);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
}
diff --git a/src/org/traccar/database/GeofenceManager.java b/src/org/traccar/database/GeofenceManager.java
index 74dff70f4..e2e0c12d4 100644
--- a/src/org/traccar/database/GeofenceManager.java
+++ b/src/org/traccar/database/GeofenceManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/GroupTree.java b/src/org/traccar/database/GroupTree.java
index 9062e7aa8..8798f55bc 100644
--- a/src/org/traccar/database/GroupTree.java
+++ b/src/org/traccar/database/GroupTree.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/IdentityManager.java b/src/org/traccar/database/IdentityManager.java
index 8507d1f2e..db8e9c1c7 100644
--- a/src/org/traccar/database/IdentityManager.java
+++ b/src/org/traccar/database/IdentityManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/NotificationManager.java b/src/org/traccar/database/NotificationManager.java
index 779f42483..ee804f5cd 100644
--- a/src/org/traccar/database/NotificationManager.java
+++ b/src/org/traccar/database/NotificationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,10 +59,10 @@ public class NotificationManager {
&& Context.getGeofenceManager().checkGeofence(userId, event.getGeofenceId())) {
Notification notification = getUserNotificationByType(userId, event.getType());
if (notification != null) {
- if (notification.getAttributes().containsKey("web")) {
+ if (notification.getWeb()) {
Context.getConnectionManager().updateEvent(userId, event, position);
}
- if (notification.getAttributes().containsKey("mail")) {
+ if (notification.getMail()) {
NotificationMail.sendMailAsync(userId, event, position);
}
}
@@ -74,7 +74,6 @@ public class NotificationManager {
}
public void updateEvents(Collection<Event> events, Position position) {
-
for (Event event : events) {
updateEvent(event, position);
}
@@ -131,8 +130,9 @@ public class NotificationManager {
public void updateNotification(Notification notification) {
Notification cachedNotification = getUserNotificationByType(notification.getUserId(), notification.getType());
if (cachedNotification != null) {
- if (!cachedNotification.getAttributes().equals(notification.getAttributes())) {
- if (notification.getAttributes().isEmpty()) {
+ if (cachedNotification.getWeb() != notification.getWeb()
+ || cachedNotification.getMail() != notification.getMail()) {
+ if (!notification.getWeb() && !notification.getMail()) {
try {
dataManager.removeNotification(cachedNotification);
} catch (SQLException error) {
@@ -147,6 +147,8 @@ public class NotificationManager {
} else {
notificationsLock.writeLock().lock();
try {
+ cachedNotification.setWeb(notification.getWeb());
+ cachedNotification.setMail(notification.getMail());
cachedNotification.setAttributes(notification.getAttributes());
} finally {
notificationsLock.writeLock().unlock();
@@ -160,7 +162,7 @@ public class NotificationManager {
} else {
notification.setId(cachedNotification.getId());
}
- } else if (!notification.getAttributes().isEmpty()) {
+ } else if (notification.getWeb() || notification.getMail()) {
try {
dataManager.addNotification(notification);
} catch (SQLException error) {
@@ -176,9 +178,8 @@ public class NotificationManager {
}
public Set<Notification> getAllNotifications() {
-
Set<Notification> notifications = new HashSet<>();
- long id = 0;
+ long id = 1;
Field[] fields = Event.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getName().startsWith("TYPE_")) {
@@ -194,4 +195,17 @@ public class NotificationManager {
}
return notifications;
}
+
+ public Collection<Notification> getAllUserNotifications(long userId) {
+ Map<String, Notification> notifications = new HashMap<>();
+ for (Notification notification : getAllNotifications()) {
+ notification.setUserId(userId);
+ notifications.put(notification.getType(), notification);
+ }
+ for (Notification notification : getUserNotifications(userId)) {
+ notifications.put(notification.getType(), notification);
+ }
+ return notifications.values();
+ }
+
}
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index f5fed978a..078a5f935 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -39,6 +40,7 @@ public class PermissionsManager {
private volatile Server server;
private final Map<Long, User> users = new ConcurrentHashMap<>();
+ private final Map<String, Long> usersTokens = new HashMap<>();
private final Map<Long, Set<Long>> groupPermissions = new HashMap<>();
private final Map<Long, Set<Long>> devicePermissions = new HashMap<>();
@@ -81,10 +83,14 @@ public class PermissionsManager {
public final void refreshUsers() {
users.clear();
+ usersTokens.clear();
try {
server = dataManager.getServer();
for (User user : dataManager.getUsers()) {
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
}
} catch (SQLException error) {
Log.warning(error);
@@ -140,6 +146,37 @@ public class PermissionsManager {
}
}
+ public boolean isReadonly(long userId) {
+ return users.containsKey(userId) && users.get(userId).getReadonly();
+ }
+
+ public void checkReadonly(long userId) throws SecurityException {
+ if (!isAdmin(userId) && (server.getReadonly() || isReadonly(userId))) {
+ throw new SecurityException("Account is readonly");
+ }
+ }
+
+ public void checkUserEnabled(long userId) throws SecurityException {
+ User user = getUser(userId);
+ if (user.getDisabled()) {
+ throw new SecurityException("Account is disabled");
+ }
+ if (user.getExpirationTime() != null && System.currentTimeMillis() > user.getExpirationTime().getTime()) {
+ throw new SecurityException("Account has expired");
+ }
+ }
+
+ public void checkUserUpdate(long userId, User before, User after) throws SecurityException {
+ if (before.getAdmin() != after.getAdmin()
+ || before.getReadonly() != after.getReadonly()
+ || before.getDisabled() != after.getDisabled()
+ || before.getDeviceLimit() != after.getDeviceLimit()
+ || !Objects.equals(before.getExpirationTime(), after.getExpirationTime())
+ || !Objects.equals(before.getToken(), after.getToken())) {
+ checkAdmin(userId);
+ }
+ }
+
public void checkUser(long userId, long otherUserId) throws SecurityException {
if (userId != otherUserId) {
checkAdmin(userId);
@@ -164,12 +201,6 @@ public class PermissionsManager {
}
}
- public void checkReadonly(long userId) {
- if (server.getReadonly() && !isAdmin(userId)) {
- throw new SecurityException("Readonly user");
- }
- }
-
public void checkGeofence(long userId, long geofenceId) throws SecurityException {
if (!Context.getGeofenceManager().checkGeofence(userId, geofenceId) && !isAdmin(userId)) {
throw new SecurityException("Geofence access denied");
@@ -196,28 +227,43 @@ public class PermissionsManager {
public void addUser(User user) throws SQLException {
dataManager.addUser(user);
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
refreshPermissions();
}
public void updateUser(User user) throws SQLException {
dataManager.updateUser(user);
+ User old = users.get(user.getId());
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
+ if (old.getToken() != null && !old.getToken().equals(user.getToken())) {
+ usersTokens.remove(old.getToken());
+ }
refreshPermissions();
}
public void removeUser(long userId) throws SQLException {
dataManager.removeUser(userId);
+ usersTokens.remove(users.get(userId).getToken());
users.remove(userId);
refreshPermissions();
}
public User login(String email, String password) throws SQLException {
User user = dataManager.login(email, password);
- if (user != null && users.get(user.getId()) != null) {
+ if (user != null) {
+ checkUserEnabled(user.getId());
return users.get(user.getId());
- } else {
- return null;
}
+ return null;
+ }
+
+ public User getUserByToken(String token) {
+ return users.get(usersTokens.get(token));
}
}
diff --git a/src/org/traccar/database/QueryBuilder.java b/src/org/traccar/database/QueryBuilder.java
index 1a83daab9..50d689a2a 100644
--- a/src/org/traccar/database/QueryBuilder.java
+++ b/src/org/traccar/database/QueryBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2015 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/org/traccar/database/StatisticsManager.java b/src/org/traccar/database/StatisticsManager.java
new file mode 100644
index 000000000..5b0aa5f41
--- /dev/null
+++ b/src/org/traccar/database/StatisticsManager.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ *
+ * 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 org.traccar.database;
+
+import org.traccar.Context;
+import org.traccar.helper.Log;
+import org.traccar.model.Statistics;
+
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+public class StatisticsManager {
+
+ private static final int SPLIT_MODE = Calendar.DAY_OF_MONTH;
+
+ private int lastUpdate = Calendar.getInstance().get(SPLIT_MODE);
+
+ private Set<Long> users = new HashSet<>();
+ private Set<Long> devices = new HashSet<>();
+
+ private int requests;
+ private int messagesReceived;
+ private int messagesStored;
+
+ private void checkSplit() {
+ int currentUpdate = Calendar.getInstance().get(SPLIT_MODE);
+ if (lastUpdate != currentUpdate) {
+ Statistics statistics = new Statistics();
+ statistics.setCaptureTime(new Date());
+ statistics.setActiveUsers(users.size());
+ statistics.setActiveDevices(devices.size());
+ statistics.setRequests(requests);
+ statistics.setMessagesReceived(messagesReceived);
+ statistics.setMessagesStored(messagesStored);
+
+ try {
+ Context.getDataManager().addStatistics(statistics);
+ } catch (SQLException e) {
+ Log.warning(e);
+ }
+
+ users.clear();
+ devices.clear();
+ requests = 0;
+ messagesReceived = 0;
+ messagesStored = 0;
+ lastUpdate = currentUpdate;
+ }
+ }
+
+ public synchronized void registerRequest(long userId) {
+ checkSplit();
+ requests += 1;
+ if (userId != 0) {
+ users.add(userId);
+ }
+ }
+
+ public synchronized void registerMessageReceived() {
+ checkSplit();
+ messagesReceived += 1;
+ }
+
+ public synchronized void registerMessageStored(long deviceId) {
+ checkSplit();
+ messagesStored += 1;
+ if (deviceId != 0) {
+ devices.add(deviceId);
+ }
+ }
+
+}