aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/database
diff options
context:
space:
mode:
authorAbyss777 <abyss@fox5.ru>2017-07-25 17:33:00 +0500
committerAbyss777 <abyss@fox5.ru>2017-07-26 13:18:36 +0500
commitbbcca3d65106069018e93a69b85290c075b128db (patch)
tree63e01dbf2ffc44e05fbf02a6a7cc0cb20c943d33 /src/org/traccar/database
parent234223a179d3f5e390cf8a649158676f8c349e5c (diff)
downloadtraccar-server-bbcca3d65106069018e93a69b85290c075b128db.tar.gz
traccar-server-bbcca3d65106069018e93a69b85290c075b128db.tar.bz2
traccar-server-bbcca3d65106069018e93a69b85290c075b128db.zip
Split Drivers and Groups management
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r--src/org/traccar/database/BaseObjectManager.java124
-rw-r--r--src/org/traccar/database/DeviceManager.java342
-rw-r--r--src/org/traccar/database/ExtendedObjectManager.java20
-rw-r--r--src/org/traccar/database/GroupsManager.java104
-rw-r--r--src/org/traccar/database/ManagableObjects.java27
-rw-r--r--src/org/traccar/database/PermissionsManager.java43
-rw-r--r--src/org/traccar/database/SimpleObjectManager.java134
-rw-r--r--src/org/traccar/database/UsersManager.java6
8 files changed, 431 insertions, 369 deletions
diff --git a/src/org/traccar/database/BaseObjectManager.java b/src/org/traccar/database/BaseObjectManager.java
new file mode 100644
index 000000000..d515fc2a9
--- /dev/null
+++ b/src/org/traccar/database/BaseObjectManager.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 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.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.traccar.helper.Log;
+import org.traccar.model.BaseModel;
+
+public class BaseObjectManager {
+
+ private final DataManager dataManager;
+
+ private Map<Long, BaseModel> items;
+ private Class<? extends BaseModel> baseClass;
+
+ protected BaseObjectManager(DataManager dataManager, Class<? extends BaseModel> baseClass) {
+ this.dataManager = dataManager;
+ this.baseClass = baseClass;
+ refreshItems();
+ }
+
+ protected final DataManager getDataManager() {
+ return dataManager;
+ }
+
+ protected final Class<? extends BaseModel> getBaseClass() {
+ return baseClass;
+ }
+
+ public final BaseModel getById(long itemId) {
+ return items.get(itemId);
+ }
+
+ public void refreshItems() {
+ if (dataManager != null) {
+ try {
+ Collection<? extends BaseModel> databaseItems = dataManager.getObjects(baseClass);
+ if (items == null) {
+ items = new ConcurrentHashMap<>(databaseItems.size());
+ }
+ Set<Long> databaseItemIds = new HashSet<>();
+ for (BaseModel item : databaseItems) {
+ databaseItemIds.add(item.getId());
+ if (items.containsKey(item.getId())) {
+ updateCachedItem(item);
+ } else {
+ addNewItem(item);
+ }
+ }
+ for (Long cachedItemId : items.keySet()) {
+ if (!databaseItemIds.contains(cachedItemId)) {
+ removeCachedItem(cachedItemId);
+ }
+ }
+ } catch (SQLException error) {
+ Log.warning(error);
+ }
+ }
+ }
+
+ protected void addNewItem(BaseModel item) {
+ items.put(item.getId(), item);
+ }
+
+ public void addItem(BaseModel item) throws SQLException {
+ dataManager.addObject(item);
+ addNewItem(item);
+ }
+
+ protected void updateCachedItem(BaseModel item) {
+ items.put(item.getId(), item);
+ }
+
+ public void updateItem(BaseModel item) throws SQLException {
+ dataManager.updateObject(item);
+ updateCachedItem(item);
+ }
+
+ protected void removeCachedItem(long itemId) {
+ items.remove(itemId);
+ }
+
+ public void removeItem(long itemId) throws SQLException {
+ BaseModel item = getById(itemId);
+ if (item != null) {
+ dataManager.removeObject(baseClass, itemId);
+ removeCachedItem(itemId);
+ }
+ }
+
+ public final <T> Collection<T> getItems(Class<T> clazz, Set<Long> itemIds) {
+ Collection<T> result = new LinkedList<>();
+ for (long itemId : itemIds) {
+ result.add((T) getById(itemId));
+ }
+ return result;
+ }
+
+ public Set<Long> getAllItems() {
+ return items.keySet();
+ }
+
+}
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index 995aa8ac3..ac66f1bb8 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -19,7 +19,6 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -31,6 +30,7 @@ import org.traccar.BaseProtocol;
import org.traccar.Config;
import org.traccar.Context;
import org.traccar.helper.Log;
+import org.traccar.model.BaseModel;
import org.traccar.model.Command;
import org.traccar.model.CommandType;
import org.traccar.model.Device;
@@ -39,121 +39,42 @@ import org.traccar.model.Group;
import org.traccar.model.Position;
import org.traccar.model.Server;
-public class DeviceManager implements IdentityManager {
+public class DeviceManager extends BaseObjectManager implements IdentityManager, ManagableObjects {
public static final long DEFAULT_REFRESH_DELAY = 300;
private final Config config;
- private final DataManager dataManager;
private final long dataRefreshDelay;
private boolean lookupGroupsAttribute;
- private Map<Long, Device> devicesById;
private Map<String, Device> devicesByUniqueId;
private Map<String, Device> devicesByPhone;
private AtomicLong devicesLastUpdate = new AtomicLong();
- private Map<Long, Group> groupsById;
- private AtomicLong groupsLastUpdate = new AtomicLong();
-
private final Map<Long, Position> positions = new ConcurrentHashMap<>();
private boolean fallbackToText;
public DeviceManager(DataManager dataManager) {
- this.dataManager = dataManager;
+ super(dataManager, Device.class);
this.config = Context.getConfig();
dataRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000;
lookupGroupsAttribute = config.getBoolean("deviceManager.lookupGroupsAttribute");
fallbackToText = config.getBoolean("command.fallbackToSms");
- if (dataManager != null) {
- try {
- updateGroupCache(true);
- updateDeviceCache(true);
- for (Position position : dataManager.getLatestPositions()) {
- positions.put(position.getDeviceId(), position);
- }
- } catch (SQLException error) {
- Log.warning(error);
- }
- }
+ refreshLastPositions();
}
private void updateDeviceCache(boolean force) throws SQLException {
-
long lastUpdate = devicesLastUpdate.get();
if ((force || System.currentTimeMillis() - lastUpdate > dataRefreshDelay)
&& devicesLastUpdate.compareAndSet(lastUpdate, System.currentTimeMillis())) {
- GeofenceManager geofenceManager = Context.getGeofenceManager();
- Collection<Device> databaseDevices = dataManager.getObjects(Device.class);
- if (devicesById == null) {
- devicesById = new ConcurrentHashMap<>(databaseDevices.size());
- }
- if (devicesByUniqueId == null) {
- devicesByUniqueId = new ConcurrentHashMap<>(databaseDevices.size());
- }
- if (devicesByPhone == null) {
- devicesByPhone = new ConcurrentHashMap<>(databaseDevices.size());
- }
- Set<Long> databaseDevicesIds = new HashSet<>();
- Set<String> databaseDevicesUniqueIds = new HashSet<>();
- Set<String> databaseDevicesPhones = new HashSet<>();
- for (Device device : databaseDevices) {
- databaseDevicesIds.add(device.getId());
- databaseDevicesUniqueIds.add(device.getUniqueId());
- databaseDevicesPhones.add(device.getPhone());
- if (devicesById.containsKey(device.getId())) {
- Device cachedDevice = devicesById.get(device.getId());
- cachedDevice.setName(device.getName());
- cachedDevice.setGroupId(device.getGroupId());
- cachedDevice.setCategory(device.getCategory());
- cachedDevice.setContact(device.getContact());
- cachedDevice.setModel(device.getModel());
- cachedDevice.setAttributes(device.getAttributes());
- if (!device.getUniqueId().equals(cachedDevice.getUniqueId())) {
- devicesByUniqueId.put(device.getUniqueId(), cachedDevice);
- }
- cachedDevice.setUniqueId(device.getUniqueId());
- if (device.getPhone() != null && !device.getPhone().isEmpty()
- && !device.getPhone().equals(cachedDevice.getPhone())) {
- devicesByPhone.put(device.getPhone(), cachedDevice);
- }
- cachedDevice.setPhone(device.getPhone());
- } else {
- devicesById.put(device.getId(), device);
- devicesByUniqueId.put(device.getUniqueId(), device);
- if (device.getPhone() != null && !device.getPhone().isEmpty()) {
- devicesByPhone.put(device.getPhone(), device);
- }
- if (geofenceManager != null) {
- Position lastPosition = getLastPosition(device.getId());
- if (lastPosition != null) {
- device.setGeofenceIds(geofenceManager.getCurrentDeviceGeofences(lastPosition));
- }
- }
- }
- }
- for (Iterator<Long> iterator = devicesById.keySet().iterator(); iterator.hasNext();) {
- if (!databaseDevicesIds.contains(iterator.next())) {
- iterator.remove();
- }
- }
- for (Iterator<String> iterator = devicesByUniqueId.keySet().iterator(); iterator.hasNext();) {
- if (!databaseDevicesUniqueIds.contains(iterator.next())) {
- iterator.remove();
- }
- }
- for (Iterator<String> iterator = devicesByPhone.keySet().iterator(); iterator.hasNext();) {
- if (!databaseDevicesPhones.contains(iterator.next())) {
- iterator.remove();
- }
- }
+ refreshItems();
}
}
@Override
public Device getDeviceById(long id) {
- return devicesById.get(id);
+ return (Device) getById(id);
}
@Override
@@ -169,76 +90,129 @@ public class DeviceManager implements IdentityManager {
return devicesByPhone.get(phone);
}
+ @Override
+ public Set<Long> getAllItems() {
+ Set<Long> result = super.getAllItems();
+ if (result.isEmpty()) {
+ try {
+ updateDeviceCache(true);
+ } catch (SQLException e) {
+ Log.warning(e);
+ }
+ result = super.getAllItems();
+ }
+ return result;
+ }
+
public Collection<Device> getAllDevices() {
- boolean forceUpdate = devicesById.isEmpty();
+ return getItems(Device.class, getAllItems());
+ }
- try {
- updateDeviceCache(forceUpdate);
- } catch (SQLException e) {
- Log.warning(e);
+ @Override
+ public Set<Long> getUserItems(long userId) {
+ if (Context.getPermissionsManager() != null) {
+ return Context.getPermissionsManager().getDevicePermissions(userId);
+ } else {
+ return new HashSet<>();
}
-
- return devicesById.values();
}
- public Collection<Device> getDevices(long userId) throws SQLException {
- Collection<Device> devices = new ArrayList<>();
- for (long id : Context.getPermissionsManager().getDevicePermissions(userId)) {
- devices.add(devicesById.get(id));
+ @Override
+ public Set<Long> getManagedItems(long userId) {
+ Set<Long> result = new HashSet<>();
+ result.addAll(getUserItems(userId));
+ for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
+ result.addAll(getUserItems(managedUserId));
}
- return devices;
+ return result;
}
- public Collection<Device> getManagedDevices(long userId) throws SQLException {
- Collection<Device> devices = new HashSet<>();
- devices.addAll(getDevices(userId));
- for (long managedUserId : Context.getUsersManager().getManagedItems(userId)) {
- devices.addAll(getDevices(managedUserId));
+ private void putUniqueDeviceId(Device device) {
+ if (devicesByUniqueId == null) {
+ devicesByUniqueId = new ConcurrentHashMap<>(getAllItems().size());
}
- return devices;
+ devicesByUniqueId.put(device.getUniqueId(), device);
}
- public void addDevice(Device device) throws SQLException {
- dataManager.addObject(device);
+ private void putPhone(Device device) {
+ if (devicesByPhone == null) {
+ devicesByPhone = new ConcurrentHashMap<>(getAllItems().size());
+ }
+ devicesByPhone.put(device.getPhone(), device);
+ }
- devicesById.put(device.getId(), device);
- devicesByUniqueId.put(device.getUniqueId(), device);
+ @Override
+ protected void addNewItem(BaseModel item) {
+ Device device = (Device) item;
+ super.addNewItem(item);
+ putUniqueDeviceId(device);
if (device.getPhone() != null && !device.getPhone().isEmpty()) {
- devicesByPhone.put(device.getPhone(), device);
+ putPhone(device);
+ }
+ if (Context.getGeofenceManager() != null) {
+ Position lastPosition = getLastPosition(device.getId());
+ if (lastPosition != null) {
+ device.setGeofenceIds(Context.getGeofenceManager().getCurrentDeviceGeofences(lastPosition));
+ }
}
}
- public void updateDevice(Device device) throws SQLException {
- dataManager.updateObject(device);
+ @Override
+ protected void updateCachedItem(BaseModel item) {
+ Device device = (Device) item;
+ Device cachedDevice = (Device) getById(device.getId());
+ cachedDevice.setName(device.getName());
+ cachedDevice.setGroupId(device.getGroupId());
+ cachedDevice.setCategory(device.getCategory());
+ cachedDevice.setContact(device.getContact());
+ cachedDevice.setModel(device.getModel());
+ cachedDevice.setAttributes(device.getAttributes());
+ if (!device.getUniqueId().equals(cachedDevice.getUniqueId())) {
+ devicesByUniqueId.remove(cachedDevice.getUniqueId());
+ cachedDevice.setUniqueId(device.getUniqueId());
+ putUniqueDeviceId(cachedDevice);
+ }
+ if (device.getPhone() != null && !device.getPhone().isEmpty()
+ && !device.getPhone().equals(cachedDevice.getPhone())) {
+ devicesByPhone.remove(cachedDevice.getPhone());
+ cachedDevice.setPhone(device.getPhone());
+ putPhone(cachedDevice);
+ }
+ }
- devicesById.put(device.getId(), device);
- devicesByUniqueId.put(device.getUniqueId(), device);
- if (device.getPhone() != null && !device.getPhone().isEmpty()) {
- devicesByPhone.put(device.getPhone(), device);
+ @Override
+ protected void removeCachedItem(long deviceId) {
+ Device cachedDevice = (Device) getById(deviceId);
+ if (cachedDevice != null) {
+ String deviceUniqueId = cachedDevice.getUniqueId();
+ String phone = cachedDevice.getPhone();
+ super.removeCachedItem(deviceId);
+ devicesByUniqueId.remove(deviceUniqueId);
+ if (phone != null && !phone.isEmpty()) {
+ devicesByPhone.remove(phone);
+ }
}
+ positions.remove(deviceId);
}
public void updateDeviceStatus(Device device) throws SQLException {
- dataManager.updateDeviceStatus(device);
- if (devicesById.containsKey(device.getId())) {
- Device cachedDevice = devicesById.get(device.getId());
+ getDataManager().updateDeviceStatus(device);
+ Device cachedDevice = (Device) getById(device.getId());
+ if (cachedDevice != null) {
cachedDevice.setStatus(device.getStatus());
}
}
- public void removeDevice(long deviceId) throws SQLException {
- dataManager.removeObject(Device.class, deviceId);
-
- if (devicesById.containsKey(deviceId)) {
- String deviceUniqueId = devicesById.get(deviceId).getUniqueId();
- String phone = devicesById.get(deviceId).getPhone();
- devicesById.remove(deviceId);
- devicesByUniqueId.remove(deviceUniqueId);
- if (phone != null && !phone.isEmpty()) {
- devicesByPhone.remove(phone);
+ private void refreshLastPositions() {
+ if (getDataManager() != null) {
+ try {
+ for (Position position : getDataManager().getLatestPositions()) {
+ positions.put(position.getDeviceId(), position);
+ }
+ } catch (SQLException error) {
+ Log.warning(error);
}
}
- positions.remove(deviceId);
}
public boolean isLatestPosition(Position position) {
@@ -250,10 +224,11 @@ public class DeviceManager implements IdentityManager {
if (isLatestPosition(position)) {
- dataManager.updateLatestPosition(position);
+ getDataManager().updateLatestPosition(position);
- if (devicesById.containsKey(position.getDeviceId())) {
- devicesById.get(position.getDeviceId()).setPositionId(position.getId());
+ Device device = (Device) getById(position.getDeviceId());
+ if (device != null) {
+ device.setPositionId(position.getId());
}
positions.put(position.getDeviceId(), position);
@@ -274,7 +249,7 @@ public class DeviceManager implements IdentityManager {
List<Position> result = new LinkedList<>();
if (Context.getPermissionsManager() != null) {
- for (long deviceId : Context.getPermissionsManager().getDevicePermissions(userId)) {
+ for (long deviceId : getUserItems(userId)) {
if (positions.containsKey(deviceId)) {
result.add(positions.get(deviceId));
}
@@ -284,96 +259,6 @@ public class DeviceManager implements IdentityManager {
return result;
}
- private void updateGroupCache(boolean force) throws SQLException {
-
- long lastUpdate = groupsLastUpdate.get();
- if ((force || System.currentTimeMillis() - lastUpdate > dataRefreshDelay)
- && groupsLastUpdate.compareAndSet(lastUpdate, System.currentTimeMillis())) {
- Collection<Group> databaseGroups = dataManager.getObjects(Group.class);
- if (groupsById == null) {
- groupsById = new ConcurrentHashMap<>(databaseGroups.size());
- }
- Set<Long> databaseGroupsIds = new HashSet<>();
- for (Group group : databaseGroups) {
- databaseGroupsIds.add(group.getId());
- if (groupsById.containsKey(group.getId())) {
- Group cachedGroup = groupsById.get(group.getId());
- cachedGroup.setName(group.getName());
- cachedGroup.setGroupId(group.getGroupId());
- } else {
- groupsById.put(group.getId(), group);
- }
- }
- for (Long cachedGroupId : groupsById.keySet()) {
- if (!databaseGroupsIds.contains(cachedGroupId)) {
- groupsById.remove(cachedGroupId);
- }
- }
- databaseGroupsIds.clear();
- }
- }
-
- public Group getGroupById(long id) {
- return groupsById.get(id);
- }
-
- public Collection<Group> getAllGroups() {
- boolean forceUpdate = groupsById.isEmpty();
-
- try {
- updateGroupCache(forceUpdate);
- } catch (SQLException e) {
- Log.warning(e);
- }
-
- return groupsById.values();
- }
-
- public Collection<Group> getGroups(long userId) throws SQLException {
- Collection<Group> groups = new ArrayList<>();
- for (long id : Context.getPermissionsManager().getGroupPermissions(userId)) {
- groups.add(getGroupById(id));
- }
- return groups;
- }
-
- public Collection<Group> getManagedGroups(long userId) throws SQLException {
- Collection<Group> groups = new ArrayList<>();
- groups.addAll(getGroups(userId));
- for (long managedUserId : Context.getUsersManager().getManagedItems(userId)) {
- groups.addAll(getGroups(managedUserId));
- }
- return groups;
- }
-
- private void checkGroupCycles(Group group) {
- Set<Long> groups = new HashSet<>();
- while (group != null) {
- if (groups.contains(group.getId())) {
- throw new IllegalArgumentException("Cycle in group hierarchy");
- }
- groups.add(group.getId());
- group = groupsById.get(group.getGroupId());
- }
- }
-
- public void addGroup(Group group) throws SQLException {
- checkGroupCycles(group);
- dataManager.addObject(group);
- groupsById.put(group.getId(), group);
- }
-
- public void updateGroup(Group group) throws SQLException {
- checkGroupCycles(group);
- dataManager.updateObject(group);
- groupsById.put(group.getId(), group);
- }
-
- public void removeGroup(long groupId) throws SQLException {
- dataManager.removeObject(Group.class, groupId);
- groupsById.remove(groupId);
- }
-
public boolean lookupAttributeBoolean(
long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig) {
String result = lookupAttribute(deviceId, attributeName, lookupConfig);
@@ -426,12 +311,13 @@ public class DeviceManager implements IdentityManager {
if (result == null && lookupGroupsAttribute) {
long groupId = device.getGroupId();
while (groupId != 0) {
- if (getGroupById(groupId) != null) {
- result = getGroupById(groupId).getString(attributeName);
+ Group group = (Group) Context.getGroupsManager().getById(groupId);
+ if (group != null) {
+ result = group.getString(attributeName);
if (result != null) {
break;
}
- groupId = getGroupById(groupId).getGroupId();
+ groupId = group.getGroupId();
} else {
groupId = 0;
}
@@ -453,7 +339,7 @@ public class DeviceManager implements IdentityManager {
Position last = positions.get(deviceTotalDistance.getDeviceId());
if (last != null) {
last.getAttributes().put(Position.KEY_TOTAL_DISTANCE, deviceTotalDistance.getTotalDistance());
- dataManager.addPosition(last);
+ getDataManager().addPosition(last);
updateLatestPosition(last);
} else {
throw new IllegalArgumentException();
@@ -466,9 +352,9 @@ public class DeviceManager implements IdentityManager {
Position lastPosition = getLastPosition(deviceId);
if (lastPosition != null) {
BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
- protocol.sendTextCommand(devicesById.get(deviceId).getPhone(), command);
+ protocol.sendTextCommand(((Device) getById(deviceId)).getPhone(), command);
} else if (command.getType().equals(Command.TYPE_CUSTOM)) {
- Context.getSmppManager().sendMessageSync(devicesById.get(deviceId).getPhone(),
+ Context.getSmppManager().sendMessageSync(((Device) getById(deviceId)).getPhone(),
command.getString(Command.KEY_DATA), true);
} else {
throw new RuntimeException("Command " + command.getType() + " is not supported");
diff --git a/src/org/traccar/database/ExtendedObjectManager.java b/src/org/traccar/database/ExtendedObjectManager.java
index 2833b3bae..19c9ca5b2 100644
--- a/src/org/traccar/database/ExtendedObjectManager.java
+++ b/src/org/traccar/database/ExtendedObjectManager.java
@@ -48,10 +48,6 @@ public abstract class ExtendedObjectManager extends SimpleObjectManager {
return groupItems.get(groupId);
}
- protected final void clearGroupItems() {
- groupItems.clear();
- }
-
public final Set<Long> getDeviceItems(long deviceId) {
if (!deviceItems.containsKey(deviceId)) {
deviceItems.put(deviceId, new HashSet<Long>());
@@ -59,10 +55,6 @@ public abstract class ExtendedObjectManager extends SimpleObjectManager {
return deviceItems.get(deviceId);
}
- protected final void clearDeviceItems() {
- deviceItems.clear();
- }
-
public Set<Long> getAllDeviceItems(long deviceId) {
if (!deviceItemsWithGroups.containsKey(deviceId)) {
deviceItemsWithGroups.put(deviceId, new HashSet<Long>());
@@ -83,16 +75,15 @@ public abstract class ExtendedObjectManager extends SimpleObjectManager {
Collection<Permission> databaseGroupPermissions =
getDataManager().getPermissions(Group.class, getBaseClass());
- clearGroupItems();
+ groupItems.clear();
for (Permission groupPermission : databaseGroupPermissions) {
getGroupItems(groupPermission.getOwnerId()).add(groupPermission.getPropertyId());
}
Collection<Permission> databaseDevicePermissions =
getDataManager().getPermissions(Device.class, getBaseClass());
- Collection<Device> allDevices = Context.getDeviceManager().getAllDevices();
- clearDeviceItems();
+ deviceItems.clear();
deviceItemsWithGroups.clear();
for (Permission devicePermission : databaseDevicePermissions) {
@@ -100,12 +91,13 @@ public abstract class ExtendedObjectManager extends SimpleObjectManager {
getAllDeviceItems(devicePermission.getOwnerId()).add(devicePermission.getPropertyId());
}
- for (Device device : allDevices) {
+ for (Device device : Context.getDeviceManager().getAllDevices()) {
long groupId = device.getGroupId();
while (groupId != 0) {
getAllDeviceItems(device.getId()).addAll(getGroupItems(groupId));
- if (Context.getDeviceManager().getGroupById(groupId) != null) {
- groupId = Context.getDeviceManager().getGroupById(groupId).getGroupId();
+ Group group = (Group) Context.getGroupsManager().getById(groupId);
+ if (group != null) {
+ groupId = group.getGroupId();
} else {
groupId = 0;
}
diff --git a/src/org/traccar/database/GroupsManager.java b/src/org/traccar/database/GroupsManager.java
new file mode 100644
index 000000000..e92158fd6
--- /dev/null
+++ b/src/org/traccar/database/GroupsManager.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 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.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.traccar.Context;
+import org.traccar.helper.Log;
+import org.traccar.model.BaseModel;
+import org.traccar.model.Group;
+
+public class GroupsManager extends BaseObjectManager implements ManagableObjects {
+
+ private AtomicLong groupsLastUpdate = new AtomicLong();
+ private final long dataRefreshDelay;
+
+ public GroupsManager(DataManager dataManager) {
+ super(dataManager, Group.class);
+ dataRefreshDelay = Context.getConfig().getLong("database.refreshDelay",
+ DeviceManager.DEFAULT_REFRESH_DELAY) * 1000;
+ }
+
+ private void checkGroupCycles(BaseModel group) {
+ Set<Long> groups = new HashSet<>();
+ while (group != null) {
+ if (groups.contains(group.getId())) {
+ throw new IllegalArgumentException("Cycle in group hierarchy");
+ }
+ groups.add(group.getId());
+ group = getById(((Group) group).getGroupId());
+ }
+ }
+
+ private void updateGroupCache(boolean force) throws SQLException {
+ long lastUpdate = groupsLastUpdate.get();
+ if ((force || System.currentTimeMillis() - lastUpdate > dataRefreshDelay)
+ && groupsLastUpdate.compareAndSet(lastUpdate, System.currentTimeMillis())) {
+ refreshItems();
+ }
+ }
+
+ @Override
+ public Set<Long> getAllItems() {
+ Set<Long> result = super.getAllItems();
+ if (result.isEmpty()) {
+ try {
+ updateGroupCache(true);
+ } catch (SQLException e) {
+ Log.warning(e);
+ }
+ result = super.getAllItems();
+ }
+ return result;
+ }
+
+ @Override
+ protected void addNewItem(BaseModel item) {
+ checkGroupCycles(item);
+ super.addNewItem(item);
+ }
+
+ @Override
+ protected void updateCachedItem(BaseModel item) {
+ checkGroupCycles(item);
+ super.updateCachedItem(item);
+ }
+
+ @Override
+ public Set<Long> getUserItems(long userId) {
+ if (Context.getPermissionsManager() != null) {
+ return Context.getPermissionsManager().getGroupPermissions(userId);
+ } else {
+ return new HashSet<>();
+ }
+ }
+
+ @Override
+ public Set<Long> getManagedItems(long userId) {
+ Set<Long> result = new HashSet<>();
+ result.addAll(getUserItems(userId));
+ for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
+ result.addAll(getUserItems(managedUserId));
+ }
+ return result;
+ }
+
+}
diff --git a/src/org/traccar/database/ManagableObjects.java b/src/org/traccar/database/ManagableObjects.java
new file mode 100644
index 000000000..ec9549493
--- /dev/null
+++ b/src/org/traccar/database/ManagableObjects.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 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.util.Set;
+
+public interface ManagableObjects {
+
+ Set<Long> getUserItems(long userId);
+
+ Set<Long> getManagedItems(long userId);
+
+}
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index b38ecf9bf..54e5ed979 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -51,7 +51,7 @@ public class PermissionsManager {
this.dataManager = dataManager;
this.usersManager = usersManager;
refreshServer();
- refreshPermissions();
+ refreshDeviceAndGroupPermissions();
}
public User getUser(long userId) {
@@ -94,11 +94,12 @@ public class PermissionsManager {
}
}
- public final void refreshPermissions() {
+ public final void refreshDeviceAndGroupPermissions() {
groupPermissions.clear();
devicePermissions.clear();
try {
- GroupTree groupTree = new GroupTree(Context.getDeviceManager().getAllGroups(),
+ GroupTree groupTree = new GroupTree(Context.getGroupsManager().getItems(
+ Group.class, Context.getGroupsManager().getAllItems()),
Context.getDeviceManager().getAllDevices());
for (Permission groupPermission : dataManager.getPermissions(User.class, Group.class)) {
Set<Long> userGroupPermissions = getGroupPermissions(groupPermission.getOwnerId());
@@ -117,9 +118,9 @@ public class PermissionsManager {
}
groupDevices.clear();
- for (Group group : Context.getDeviceManager().getAllGroups()) {
- for (Device device : groupTree.getDevices(group.getId())) {
- getGroupDevices(group.getId()).add(device.getId());
+ for (long groupId : Context.getGroupsManager().getAllItems()) {
+ for (Device device : groupTree.getDevices(groupId)) {
+ getGroupDevices(groupId).add(device.getId());
}
}
@@ -159,14 +160,14 @@ public class PermissionsManager {
public void checkManager(long userId, long managedUserId) throws SecurityException {
checkManager(userId);
- if (!usersManager.getManagedItems(userId).contains(managedUserId)) {
+ if (!usersManager.getUserItems(userId).contains(managedUserId)) {
throw new SecurityException("User access denied");
}
}
public void checkUserLimit(long userId) throws SecurityException {
int userLimit = getUser(userId).getUserLimit();
- if (userLimit != -1 && usersManager.getManagedItems(userId).size() >= userLimit) {
+ if (userLimit != -1 && usersManager.getUserItems(userId).size() >= userLimit) {
throw new SecurityException("Manager user limit reached");
}
}
@@ -176,9 +177,9 @@ public class PermissionsManager {
if (deviceLimit != -1) {
int deviceCount = 0;
if (isManager(userId)) {
- deviceCount = Context.getDeviceManager().getManagedDevices(userId).size();
+ deviceCount = Context.getDeviceManager().getManagedItems(userId).size();
} else {
- deviceCount = getDevicePermissions(userId).size();
+ deviceCount = Context.getDeviceManager().getUserItems(userId).size();
}
if (deviceCount >= deviceLimit) {
throw new SecurityException("User device limit reached");
@@ -254,7 +255,7 @@ public class PermissionsManager {
public void checkGroup(long userId, long groupId) throws SecurityException {
if (!getGroupPermissions(userId).contains(groupId) && !isAdmin(userId)) {
checkManager(userId);
- for (long managedUserId : usersManager.getManagedItems(userId)) {
+ for (long managedUserId : usersManager.getUserItems(userId)) {
if (getGroupPermissions(managedUserId).contains(groupId)) {
return;
}
@@ -264,10 +265,10 @@ public class PermissionsManager {
}
public void checkDevice(long userId, long deviceId) throws SecurityException {
- if (!getDevicePermissions(userId).contains(deviceId) && !isAdmin(userId)) {
+ if (!Context.getDeviceManager().getUserItems(userId).contains(deviceId) && !isAdmin(userId)) {
checkManager(userId);
- for (long managedUserId : usersManager.getManagedItems(userId)) {
- if (getDevicePermissions(managedUserId).contains(deviceId)) {
+ for (long managedUserId : usersManager.getUserItems(userId)) {
+ if (Context.getDeviceManager().getUserItems(managedUserId).contains(deviceId)) {
return;
}
}
@@ -314,6 +315,18 @@ public class PermissionsManager {
}
}
+ public void refreshAllUsersPermissions() {
+ if (Context.getGeofenceManager() != null) {
+ Context.getGeofenceManager().refreshUserItems();
+ }
+ Context.getCalendarManager().refreshUserItems();
+ Context.getDriversManager().refreshUserItems();
+ Context.getAttributesManager().refreshUserItems();
+ if (Context.getNotificationManager() != null) {
+ Context.getNotificationManager().refresh();
+ }
+ }
+
public void refreshAllExtendedPermissions() {
if (Context.getGeofenceManager() != null) {
Context.getGeofenceManager().refreshExtendedPermissions();
@@ -326,7 +339,7 @@ public class PermissionsManager {
if (permission.getOwnerClass().equals(User.class)) {
if (permission.getPropertyClass().equals(Device.class)
|| permission.getPropertyClass().equals(Group.class)) {
- refreshPermissions();
+ refreshDeviceAndGroupPermissions();
refreshAllExtendedPermissions();
} else if (permission.getPropertyClass().equals(ManagedUser.class)) {
usersManager.refreshUserItems();
diff --git a/src/org/traccar/database/SimpleObjectManager.java b/src/org/traccar/database/SimpleObjectManager.java
index 124178a05..fa41f30b6 100644
--- a/src/org/traccar/database/SimpleObjectManager.java
+++ b/src/org/traccar/database/SimpleObjectManager.java
@@ -17,9 +17,7 @@
package org.traccar.database;
import java.sql.SQLException;
-import java.util.Collection;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -30,43 +28,15 @@ import org.traccar.model.BaseModel;
import org.traccar.model.Permission;
import org.traccar.model.User;
-public abstract class SimpleObjectManager {
+public abstract class SimpleObjectManager extends BaseObjectManager implements ManagableObjects {
- private final DataManager dataManager;
-
- private Map<Long, BaseModel> items;
- private final Map<Long, Set<Long>> userItems = new ConcurrentHashMap<>();
-
- private Class<? extends BaseModel> baseClass;
- private String baseClassIdName;
+ private Map<Long, Set<Long>> userItems;
protected SimpleObjectManager(DataManager dataManager, Class<? extends BaseModel> baseClass) {
- this.dataManager = dataManager;
- this.baseClass = baseClass;
- baseClassIdName = DataManager.makeNameId(baseClass);
- refreshItems();
- }
-
- protected final DataManager getDataManager() {
- return dataManager;
- }
-
- protected final Class<? extends BaseModel> getBaseClass() {
- return baseClass;
- }
-
- protected final String getBaseClassIdName() {
- return baseClassIdName;
- }
-
- public final BaseModel getById(long itemId) {
- return items.get(itemId);
- }
-
- protected final void clearItems() {
- items.clear();
+ super(dataManager, baseClass);
}
+ @Override
public final Set<Long> getUserItems(long userId) {
if (!userItems.containsKey(userId)) {
userItems.put(userId, new HashSet<Long>());
@@ -74,47 +44,35 @@ public abstract class SimpleObjectManager {
return userItems.get(userId);
}
- protected final void clearUserItems() {
- userItems.clear();
+ @Override
+ public Set<Long> getManagedItems(long userId) {
+ Set<Long> result = new HashSet<>();
+ result.addAll(getUserItems(userId));
+ for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
+ result.addAll(getUserItems(managedUserId));
+ }
+ return result;
}
public final boolean checkItemPermission(long userId, long itemId) {
return getUserItems(userId).contains(itemId);
}
+ @Override
public void refreshItems() {
- if (dataManager != null) {
- try {
- Collection<? extends BaseModel> databaseItems = dataManager.getObjects(baseClass);
- if (items == null) {
- items = new ConcurrentHashMap<>(databaseItems.size());
- }
- Set<Long> databaseItemIds = new HashSet<>();
- for (BaseModel item : databaseItems) {
- databaseItemIds.add(item.getId());
- if (items.containsKey(item.getId())) {
- updateCachedItem(item);
- } else {
- addNewItem(item);
- }
- }
- for (Long cachedItemId : items.keySet()) {
- if (!databaseItemIds.contains(cachedItemId)) {
- removeCachedItem(cachedItemId);
- }
- }
- } catch (SQLException error) {
- Log.warning(error);
- }
- }
+ super.refreshItems();
refreshUserItems();
}
public final void refreshUserItems() {
- if (dataManager != null) {
+ if (getDataManager() != null) {
try {
- clearUserItems();
- for (Permission permission : dataManager.getPermissions(User.class, baseClass)) {
+ if (userItems != null) {
+ userItems.clear();
+ } else {
+ userItems = new ConcurrentHashMap<>();
+ }
+ for (Permission permission : getDataManager().getPermissions(User.class, getBaseClass())) {
getUserItems(permission.getOwnerId()).add(permission.getPropertyId());
}
} catch (SQLException | ClassNotFoundException error) {
@@ -123,56 +81,10 @@ public abstract class SimpleObjectManager {
}
}
- protected void addNewItem(BaseModel item) {
- items.put(item.getId(), item);
- }
-
- public void addItem(BaseModel item) throws SQLException {
- dataManager.addObject(item);
- addNewItem(item);
- }
-
- protected void updateCachedItem(BaseModel item) {
- items.put(item.getId(), item);
- }
-
- public void updateItem(BaseModel item) throws SQLException {
- dataManager.updateObject(item);
- updateCachedItem(item);
- }
-
- protected void removeCachedItem(long itemId) {
- items.remove(itemId);
- }
-
+ @Override
public void removeItem(long itemId) throws SQLException {
- BaseModel item = getById(itemId);
- if (item != null) {
- dataManager.removeObject(baseClass, itemId);
- removeCachedItem(itemId);
- }
+ super.removeItem(itemId);
refreshUserItems();
}
- public final <T> Collection<T> getItems(Class<T> clazz, Set<Long> itemIds) {
- Collection<T> result = new LinkedList<>();
- for (long itemId : itemIds) {
- result.add((T) getById(itemId));
- }
- return result;
- }
-
- public final Set<Long> getAllItems() {
- return items.keySet();
- }
-
- public Set<Long> getManagedItems(long userId) {
- Set<Long> result = new HashSet<>();
- result.addAll(getUserItems(userId));
- for (long managedUserId : Context.getUsersManager().getManagedItems(userId)) {
- result.addAll(getUserItems(managedUserId));
- }
- return result;
- }
-
}
diff --git a/src/org/traccar/database/UsersManager.java b/src/org/traccar/database/UsersManager.java
index 3c9c8b280..cb4ea623f 100644
--- a/src/org/traccar/database/UsersManager.java
+++ b/src/org/traccar/database/UsersManager.java
@@ -16,6 +16,7 @@
*/
package org.traccar.database;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -73,7 +74,10 @@ public class UsersManager extends SimpleObjectManager {
@Override
public Set<Long> getManagedItems(long userId) {
- return getUserItems(userId);
+ Set<Long> result = new HashSet<>();
+ result.addAll(getUserItems(userId));
+ result.add(userId);
+ return result;
}
public User getUserByToken(String token) {