diff options
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r-- | src/org/traccar/database/ActiveDevice.java | 2 | ||||
-rw-r--r-- | src/org/traccar/database/AliasesManager.java | 113 | ||||
-rw-r--r-- | src/org/traccar/database/ConnectionManager.java | 22 | ||||
-rw-r--r-- | src/org/traccar/database/DataManager.java | 64 | ||||
-rw-r--r-- | src/org/traccar/database/DeviceManager.java | 14 | ||||
-rw-r--r-- | src/org/traccar/database/GeofenceManager.java | 2 | ||||
-rw-r--r-- | src/org/traccar/database/GroupTree.java | 2 | ||||
-rw-r--r-- | src/org/traccar/database/IdentityManager.java | 2 | ||||
-rw-r--r-- | src/org/traccar/database/NotificationManager.java | 7 | ||||
-rw-r--r-- | src/org/traccar/database/PermissionsManager.java | 66 | ||||
-rw-r--r-- | src/org/traccar/database/QueryBuilder.java | 2 | ||||
-rw-r--r-- | src/org/traccar/database/StatisticsManager.java | 88 |
12 files changed, 335 insertions, 49 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 new file mode 100644 index 000000000..4f4f09731 --- /dev/null +++ b/src/org/traccar/database/AliasesManager.java @@ -0,0 +1,113 @@ +/* + * 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. + * 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 java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.traccar.Context; +import org.traccar.helper.Log; +import org.traccar.model.AttributeAlias; + +public class AliasesManager { + + private final DataManager dataManager; + + private final Map<Long, Set<AttributeAlias>> deviceAliases = new ConcurrentHashMap<>(); + private final Map<Long, AttributeAlias> aliasesById = new ConcurrentHashMap<>(); + + public AliasesManager(DataManager dataManager) { + this.dataManager = dataManager; + if (dataManager != null) { + try { + for (AttributeAlias attributeAlias : dataManager.getAttributeAliases()) { + getAttributeAliases(attributeAlias.getDeviceId()) + .add(attributeAlias); + aliasesById.put(attributeAlias.getId(), attributeAlias); + } + } catch (SQLException error) { + Log.warning(error); + } + } + } + + public Set<AttributeAlias> getAttributeAliases(long deviceId) { + if (!deviceAliases.containsKey(deviceId)) { + deviceAliases.put(deviceId, new HashSet<AttributeAlias>()); + } + return deviceAliases.get(deviceId); + } + + public void removeDevice(long deviceId) { + for (AttributeAlias attributeAlias : getAttributeAliases(deviceId)) { + aliasesById.remove(attributeAlias.getId()); + } + deviceAliases.remove(deviceId); + } + + public void addAttributeAlias(AttributeAlias attributeAlias) throws SQLException { + dataManager.addAttributeAlias(attributeAlias); + aliasesById.put(attributeAlias.getId(), attributeAlias); + getAttributeAliases(attributeAlias.getDeviceId()).add(attributeAlias); + } + + public void updateAttributeAlias(AttributeAlias attributeAlias) throws SQLException { + dataManager.updateAttributeAlias(attributeAlias); + AttributeAlias cachedAlias = aliasesById.get(attributeAlias.getId()); + if (cachedAlias.getDeviceId() != attributeAlias.getDeviceId()) { + getAttributeAliases(cachedAlias.getDeviceId()).remove(cachedAlias); + cachedAlias.setDeviceId(attributeAlias.getDeviceId()); + getAttributeAliases(cachedAlias.getDeviceId()).add(cachedAlias); + } + cachedAlias.setAttribute(attributeAlias.getAttribute()); + cachedAlias.setAlias(attributeAlias.getAlias()); + } + + public void removeArrtibuteAlias(long attributeAliasId) throws SQLException { + dataManager.removeAttributeAlias(attributeAliasId); + AttributeAlias cachedAlias = aliasesById.get(attributeAliasId); + getAttributeAliases(cachedAlias.getDeviceId()).remove(cachedAlias); + aliasesById.remove(attributeAliasId); + } + + public AttributeAlias getAttributeAlias(long deviceId, String attribute) { + for (AttributeAlias alias : getAttributeAliases(deviceId)) { + if (alias.getAttribute().equals(attribute)) { + return alias; + } + } + return null; + } + + public Collection<AttributeAlias> getAllAttributeAliases(long userId) { + Collection<AttributeAlias> userDevicesAliases = new ArrayList<>(); + for (long deviceId : Context.getPermissionsManager().getDevicePermissions(userId)) { + userDevicesAliases.addAll(getAttributeAliases(deviceId)); + } + return userDevicesAliases; + } + + public AttributeAlias getAttributeAlias(long id) { + return aliasesById.get(id); + } + +} 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 abc48f063..afa8b1677 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; @@ -37,6 +36,7 @@ import liquibase.resource.ResourceAccessor; import org.traccar.Config; import org.traccar.helper.Log; +import org.traccar.model.AttributeAlias; import org.traccar.model.Device; import org.traccar.model.DevicePermission; import org.traccar.model.Event; @@ -47,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; @@ -158,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) @@ -336,33 +331,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) @@ -460,4 +441,41 @@ public class DataManager { .setLong("id", notification.getId()) .executeUpdate(); } + + public Collection<AttributeAlias> getAttributeAliases() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectAttributeAliases")) + .executeQuery(AttributeAlias.class); + } + + public void addAttributeAlias(AttributeAlias attributeAlias) throws SQLException { + attributeAlias.setId(QueryBuilder.create(dataSource, getQuery("database.insertAttributeAlias"), true) + .setObject(attributeAlias) + .executeUpdate()); + } + + public void updateAttributeAlias(AttributeAlias attributeAlias) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.updateAttributeAlias")) + .setObject(attributeAlias) + .executeUpdate(); + } + + public void removeAttributeAlias(long attributeAliasId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.deleteAttributeAlias")) + .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..5681602fe 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; @@ -428,4 +429,15 @@ public class DeviceManager implements IdentityManager { } 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..7e79e289f 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. @@ -74,7 +74,6 @@ public class NotificationManager { } public void updateEvents(Collection<Event> events, Position position) { - for (Event event : events) { updateEvent(event, position); } @@ -176,9 +175,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 +192,5 @@ public class NotificationManager { } return notifications; } + } 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); + } + } + +} |