From 41fe4ca770875842f4d17531506c4bc74dc90501 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Fri, 10 Jun 2016 16:02:06 +0500 Subject: Geofences --- src/org/traccar/database/ConnectionManager.java | 3 +- src/org/traccar/database/DataManager.java | 92 +++++++++++ src/org/traccar/database/GeofenceManager.java | 191 +++++++++++++++++++++++ src/org/traccar/database/PermissionsManager.java | 7 + 4 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 src/org/traccar/database/GeofenceManager.java (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java index ec5903548..6e47dfad3 100644 --- a/src/org/traccar/database/ConnectionManager.java +++ b/src/org/traccar/database/ConnectionManager.java @@ -155,7 +155,8 @@ public class ConnectionManager { Log.warning(error); } for (long userId : Context.getPermissionsManager().getDeviceUsers(deviceId)) { - if (listeners.containsKey(userId)) { + if (listeners.containsKey(userId) && (event.getGeofenceId() == 0 + || Context.getGeofenceManager().checkGeofence(userId, event.getGeofenceId()))) { for (UpdateListener listener : listeners.get(userId)) { listener.onUpdateEvent(event, position); } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 67b7d1e55..86c930c0b 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -48,11 +48,15 @@ import org.traccar.helper.Log; import org.traccar.model.Device; import org.traccar.model.DevicePermission; import org.traccar.model.Event; +import org.traccar.model.Geofence; import org.traccar.model.Group; +import org.traccar.model.GroupGeofence; import org.traccar.model.GroupPermission; import org.traccar.model.Position; import org.traccar.model.Server; import org.traccar.model.User; +import org.traccar.model.UserDeviceGeofence; +import org.traccar.model.GeofencePermission; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @@ -368,6 +372,7 @@ public class DataManager implements IdentityManager { Device cachedDevice = getDeviceById(device.getId()); cachedDevice.setStatus(device.getStatus()); cachedDevice.setMotion(device.getMotion()); + cachedDevice.setGeofenceId(device.getGeofenceId()); } public void removeDevice(long deviceId) throws SQLException { @@ -524,4 +529,91 @@ public class DataManager implements IdentityManager { return getEvents(deviceId, type, new Date(), to); } + public Collection 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) + .executeUpdate()); + } + + public void updateGeofence(Geofence geofence) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.updateGeofence")) + .setObject(geofence) + .executeUpdate(); + } + + public void removeGeofence(long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.deleteGeofence")) + .setLong("id", geofenceId) + .executeUpdate(); + } + + public Collection getGeofencePermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGeofencePermissions")) + .executeQuery(GeofencePermission.class); + } + + public void linkGeofence(long userId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkGeofence")) + .setLong("userId", userId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } + + public void unlinkGeofence(long userId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkGeofence")) + .setLong("userId", userId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } + + public Collection getGroupGeofences() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupGeofences")) + .executeQuery(GroupGeofence.class); + } + + public void linkGroupGeofence(long groupId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkGroupGeofence")) + .setLong("groupId", groupId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } + + public void unlinkGroupGeofence(long groupId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkGroupGeofence")) + .setLong("groupId", groupId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } + + public Collection getUserDeviceGeofences() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectUserDeviceGeofences")) + .executeQuery(UserDeviceGeofence.class); + } + + public void linkUserDeviceGeofence(long userId, long deviceId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkUserDeviceGeofence")) + .setLong("userId", userId) + .setLong("deviceId", deviceId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } + + public void unlinkUserDeviceGeofence(long userId, long deviceId, long geofenceId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkUserDeviceGeofence")) + .setLong("userId", userId) + .setLong("deviceId", deviceId) + .setLong("geofenceId", geofenceId) + .executeUpdate(); + } } diff --git a/src/org/traccar/database/GeofenceManager.java b/src/org/traccar/database/GeofenceManager.java new file mode 100644 index 000000000..64afc876c --- /dev/null +++ b/src/org/traccar/database/GeofenceManager.java @@ -0,0 +1,191 @@ +package org.traccar.database; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.traccar.helper.Log; +import org.traccar.model.Device; +import org.traccar.model.Geofence; +import org.traccar.model.GroupGeofence; +import org.traccar.model.UserDeviceGeofence; +import org.traccar.model.GeofencePermission; + +public class GeofenceManager { + + private final DataManager dataManager; + + private final Map geofences = new HashMap<>(); + private final Map> userGeofences = new HashMap<>(); + private final Map> groupGeofences = new HashMap<>(); + + private final Map> deviceGeofences = new HashMap<>(); + private final Map>> userDeviceGeofences = new HashMap<>(); + + private final ReadWriteLock deviceGeofencesLock = new ReentrantReadWriteLock(); + private final ReadWriteLock geofencesLock = new ReentrantReadWriteLock(); + private final ReadWriteLock groupGeofencesLock = new ReentrantReadWriteLock(); + + public GeofenceManager(DataManager dataManager) { + this.dataManager = dataManager; + refresh(); + } + + public Set getUserGeofencesIds(long userId) { + if (!userGeofences.containsKey(userId)) { + userGeofences.put(userId, new HashSet()); + } + return userGeofences.get(userId); + } + + private Set getGroupGeofences(long groupId) { + if (!groupGeofences.containsKey(groupId)) { + groupGeofences.put(groupId, new HashSet()); + } + return groupGeofences.get(groupId); + } + + public Set getAllDeviceGeofences(long deviceId) { + deviceGeofencesLock.readLock().lock(); + try { + return getDeviceGeofences(deviceGeofences, deviceId); + } finally { + deviceGeofencesLock.readLock().unlock(); + } + + } + + public Set getUserDeviceGeofences(long userId, long deviceId) { + deviceGeofencesLock.readLock().lock(); + try { + return getUserDeviceGeofencesUnlocked(userId, deviceId); + } finally { + deviceGeofencesLock.readLock().unlock(); + } + } + + private Set getDeviceGeofences(Map> deviceGeofences, long deviceId) { + if (!deviceGeofences.containsKey(deviceId)) { + deviceGeofences.put(deviceId, new HashSet()); + } + return deviceGeofences.get(deviceId); + } + + private Set getUserDeviceGeofencesUnlocked(long userId, long deviceId) { + if (!userDeviceGeofences.containsKey(userId)) { + userDeviceGeofences.put(userId, new HashMap>()); + } + return getDeviceGeofences(userDeviceGeofences.get(userId), deviceId); + } + + public final void refresh() { + if (dataManager != null) { + try { + geofencesLock.writeLock().lock(); + groupGeofencesLock.writeLock().lock(); + deviceGeofencesLock.writeLock().lock(); + try { + geofences.clear(); + for (Geofence geofence : dataManager.getGeofences()) { + geofences.put(geofence.getId(), geofence); + } + + userGeofences.clear(); + for (GeofencePermission geofencePermission : dataManager.getGeofencePermissions()) { + getUserGeofencesIds(geofencePermission.getUserId()).add(geofencePermission.getGeofenceId()); + } + + groupGeofences.clear(); + for (GroupGeofence groupGeofence : dataManager.getGroupGeofences()) { + getGroupGeofences(groupGeofence.getGroupId()).add(groupGeofence.getGeofenceId()); + } + + deviceGeofences.clear(); + + for (Map.Entry>> deviceGeofence : userDeviceGeofences.entrySet()) { + deviceGeofence.getValue().clear(); + } + userDeviceGeofences.clear(); + + for (UserDeviceGeofence userDeviceGeofence : dataManager.getUserDeviceGeofences()) { + getDeviceGeofences(deviceGeofences, userDeviceGeofence.getDeviceId()) + .add(userDeviceGeofence.getGeofenceId()); + getUserDeviceGeofencesUnlocked(userDeviceGeofence.getUserId(), userDeviceGeofence.getDeviceId()) + .add(userDeviceGeofence.getGeofenceId()); + } + for (Device device : dataManager.getAllDevices()) { + long groupId = device.getGroupId(); + while (groupId != 0) { + getDeviceGeofences(deviceGeofences, device.getId()).addAll(getGroupGeofences(groupId)); + groupId = dataManager.getGroupById(groupId).getGroupId(); + } + } + + } finally { + geofencesLock.writeLock().unlock(); + groupGeofencesLock.writeLock().unlock(); + deviceGeofencesLock.writeLock().unlock(); + } + + } catch (SQLException error) { + Log.warning(error); + } + } + } + + public final Collection getAllGeofences() { + geofencesLock.readLock().lock(); + try { + return geofences.values(); + } finally { + geofencesLock.readLock().unlock(); + } + } + + public final Collection getUserGeofences(long userId) { + geofencesLock.readLock().lock(); + try { + Collection result = new LinkedList<>(); + for (Long geofenceId : getUserGeofencesIds(userId)) { + result.add(getGeofence(geofenceId)); + } + return result; + } finally { + geofencesLock.readLock().unlock(); + } + } + + public final Geofence getGeofence(Long geofenceId) { + geofencesLock.readLock().lock(); + try { + return geofences.get(geofenceId); + } finally { + geofencesLock.readLock().unlock(); + } + } + + public final void updateGeofence(Geofence geofence) { + geofencesLock.writeLock().lock(); + try { + geofences.put(geofence.getId(), geofence); + } finally { + geofencesLock.writeLock().unlock(); + } + try { + dataManager.updateGeofence(geofence); + } catch (SQLException error) { + Log.warning(error); + } + } + + public boolean checkGeofence(long userId, long geofenceId) { + return getUserGeofencesIds(userId).contains(geofenceId); + } + +} diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 08d44b382..96a6488ef 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -15,6 +15,7 @@ */ package org.traccar.database; +import org.traccar.Context; import org.traccar.helper.Log; import org.traccar.model.Device; import org.traccar.model.DevicePermission; @@ -145,4 +146,10 @@ public class PermissionsManager { } } + public void checkGeofence(long userId, long geofenceId) throws SecurityException { + if (!Context.getGeofenceManager().checkGeofence(userId, geofenceId) && !isAdmin(userId)) { + throw new SecurityException("Geofence access denied"); + } + } + } -- cgit v1.2.3