aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/config/Keys.java7
-rw-r--r--src/main/java/org/traccar/database/DataManager.java141
-rw-r--r--src/main/java/org/traccar/model/Permission.java95
-rw-r--r--src/main/java/org/traccar/storage/DatabaseStorage.java50
-rw-r--r--src/main/java/org/traccar/storage/MemoryStorage.java16
-rw-r--r--src/main/java/org/traccar/storage/QueryBuilder.java2
-rw-r--r--src/main/java/org/traccar/storage/Storage.java8
7 files changed, 164 insertions, 155 deletions
diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java
index cb3bd4de8..ccfe4bee7 100644
--- a/src/main/java/org/traccar/config/Keys.java
+++ b/src/main/java/org/traccar/config/Keys.java
@@ -343,13 +343,6 @@ public final class Keys {
Collections.singletonList(KeyType.GLOBAL));
/**
- * Automatically generate SQL database queries when possible.
- */
- public static final ConfigKey<Boolean> DATABASE_GENERATE_QUERIES = new ConfigKey<>(
- "database.generateQueries",
- Collections.singletonList(KeyType.GLOBAL));
-
- /**
* Database connection pool size. Default value is defined by the HikariCP library.
*/
public static final ConfigKey<Integer> DATABASE_MAX_POOL_SIZE = new ConfigKey<>(
diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java
index 303b8e033..178cbbc57 100644
--- a/src/main/java/org/traccar/database/DataManager.java
+++ b/src/main/java/org/traccar/database/DataManager.java
@@ -24,30 +24,18 @@ import liquibase.database.DatabaseFactory;
import liquibase.exception.LiquibaseException;
import liquibase.resource.FileSystemResourceAccessor;
import liquibase.resource.ResourceAccessor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.traccar.Context;
import org.traccar.config.Config;
import org.traccar.config.Keys;
-import org.traccar.model.Attribute;
import org.traccar.model.BaseModel;
-import org.traccar.model.Calendar;
-import org.traccar.model.Command;
import org.traccar.model.Device;
-import org.traccar.model.Driver;
import org.traccar.model.Event;
-import org.traccar.model.Geofence;
-import org.traccar.model.Group;
-import org.traccar.model.Maintenance;
-import org.traccar.model.ManagedUser;
-import org.traccar.model.Notification;
import org.traccar.model.Permission;
import org.traccar.model.Position;
import org.traccar.model.Server;
import org.traccar.model.Statistics;
import org.traccar.model.User;
import org.traccar.storage.DatabaseStorage;
-import org.traccar.storage.QueryBuilder;
import org.traccar.storage.Storage;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
@@ -57,11 +45,9 @@ import org.traccar.storage.query.Order;
import org.traccar.storage.query.Request;
import javax.sql.DataSource;
-import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
-import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
@@ -69,14 +55,6 @@ import java.util.List;
public class DataManager {
- private static final Logger LOGGER = LoggerFactory.getLogger(DataManager.class);
-
- public static final String ACTION_SELECT_ALL = "selectAll";
- public static final String ACTION_SELECT = "select";
- public static final String ACTION_INSERT = "insert";
- public static final String ACTION_UPDATE = "update";
- public static final String ACTION_DELETE = "delete";
-
private final Config config;
private DataSource dataSource;
@@ -87,8 +65,6 @@ public class DataManager {
private final Storage storage;
- private boolean generateQueries;
-
private final boolean forceLdap;
public DataManager(Config config) throws Exception {
@@ -137,72 +113,9 @@ public class DataManager {
hikariConfig.setMaximumPoolSize(maxPoolSize);
}
- generateQueries = config.getBoolean(Keys.DATABASE_GENERATE_QUERIES);
-
dataSource = new HikariDataSource(hikariConfig);
}
- public static String constructPermissionQuery(String action, Class<?> owner, Class<?> property) {
- switch (action) {
- case ACTION_SELECT_ALL:
- return "SELECT " + makeNameId(owner) + ", " + makeNameId(property) + " FROM "
- + getPermissionsTableName(owner, property);
- case ACTION_INSERT:
- return "INSERT INTO " + getPermissionsTableName(owner, property)
- + " (" + makeNameId(owner) + ", " + makeNameId(property) + ") VALUES (:"
- + makeNameId(owner) + ", :" + makeNameId(property) + ")";
- case ACTION_DELETE:
- return "DELETE FROM " + getPermissionsTableName(owner, property)
- + " WHERE " + makeNameId(owner) + " = :" + makeNameId(owner)
- + " AND " + makeNameId(property) + " = :" + makeNameId(property);
- default:
- throw new IllegalArgumentException("Unknown action");
- }
- }
-
- public String getQuery(String action, Class<?> owner, Class<?> property) {
- String queryName;
- switch (action) {
- case ACTION_SELECT_ALL:
- queryName = "database.select" + owner.getSimpleName() + property.getSimpleName() + "s";
- break;
- case ACTION_INSERT:
- queryName = "database.link" + owner.getSimpleName() + property.getSimpleName();
- break;
- default:
- queryName = "database.unlink" + owner.getSimpleName() + property.getSimpleName();
- break;
- }
- String query = config.getString(queryName);
- if (query == null) {
- if (generateQueries) {
- query = constructPermissionQuery(
- action, owner, property.equals(User.class) ? ManagedUser.class : property);
- } else {
- LOGGER.info("Query not provided: " + queryName);
- }
- }
- return query;
- }
-
- private static String getPermissionsTableName(Class<?> owner, Class<?> property) {
- String propertyName = property.getSimpleName();
- if (propertyName.equals("ManagedUser")) {
- propertyName = "User";
- }
- return "tc_" + Introspector.decapitalize(owner.getSimpleName())
- + "_" + Introspector.decapitalize(propertyName);
- }
-
- private static String getObjectsTableName(Class<?> clazz) {
- String result = "tc_" + Introspector.decapitalize(clazz.getSimpleName());
- // Add "s" ending if object name is not plural already
- if (!result.endsWith("s")) {
- result += "s";
- }
- return result;
- }
-
private void initDatabaseSchema() throws LiquibaseException {
if (config.hasKey(Keys.DATABASE_CHANGELOG)) {
@@ -318,61 +231,17 @@ public class DataManager {
new Order("captureTime")));
}
- public static Class<?> getClassByName(String name) throws ClassNotFoundException {
- switch (name.toLowerCase().replace("id", "")) {
- case "device":
- return Device.class;
- case "group":
- return Group.class;
- case "user":
- return User.class;
- case "manageduser":
- return ManagedUser.class;
- case "geofence":
- return Geofence.class;
- case "driver":
- return Driver.class;
- case "attribute":
- return Attribute.class;
- case "calendar":
- return Calendar.class;
- case "command":
- return Command.class;
- case "maintenance":
- return Maintenance.class;
- case "notification":
- return Notification.class;
- case "order":
- return org.traccar.model.Order.class;
- default:
- throw new ClassNotFoundException();
- }
- }
-
- private static String makeNameId(Class<?> clazz) {
- String name = clazz.getSimpleName();
- return Introspector.decapitalize(name) + (!name.contains("Id") ? "Id" : "");
- }
-
public Collection<Permission> getPermissions(Class<? extends BaseModel> owner, Class<? extends BaseModel> property)
throws StorageException, ClassNotFoundException {
- try {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property))
- .executePermissionsQuery();
- } catch (SQLException e) {
- throw new StorageException(e);
- }
+ return storage.getPermissions(owner, property);
}
public void linkObject(Class<?> owner, long ownerId, Class<?> property, long propertyId, boolean link)
throws StorageException {
- try {
- QueryBuilder.create(dataSource, getQuery(link ? ACTION_INSERT : ACTION_DELETE, owner, property))
- .setLong(makeNameId(owner), ownerId)
- .setLong(makeNameId(property), propertyId)
- .executeUpdate();
- } catch (SQLException e) {
- throw new StorageException(e);
+ if (link) {
+ storage.addPermission(new Permission(owner, ownerId, property, propertyId));
+ } else {
+ storage.removePermission(new Permission(owner, ownerId, property, propertyId));
}
}
diff --git a/src/main/java/org/traccar/model/Permission.java b/src/main/java/org/traccar/model/Permission.java
index 6475a4582..ad0176b39 100644
--- a/src/main/java/org/traccar/model/Permission.java
+++ b/src/main/java/org/traccar/model/Permission.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,42 +16,115 @@
*/
package org.traccar.model;
-import java.util.Iterator;
+import java.beans.Introspector;
+import java.io.IOException;
+import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.TreeMap;
-import org.traccar.database.DataManager;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.traccar.helper.ClassScanner;
+import org.traccar.storage.QueryIgnore;
public class Permission {
+ private static final Map<String, Class<?>> CLASSES = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ static {
+ try {
+ for (Class<?> clazz : ClassScanner.findSubclasses(BaseModel.class)) {
+ CLASSES.put(clazz.getSimpleName(), clazz);
+ }
+ } catch (IOException | ReflectiveOperationException | URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final LinkedHashMap<String, Long> data;
+
private final Class<?> ownerClass;
private final long ownerId;
private final Class<?> propertyClass;
private final long propertyId;
- public Permission(LinkedHashMap<String, Long> permissionMap) throws ClassNotFoundException {
- Iterator<Map.Entry<String, Long>> iterator = permissionMap.entrySet().iterator();
- String owner = iterator.next().getKey();
- ownerClass = DataManager.getClassByName(owner);
- String property = iterator.next().getKey();
- propertyClass = DataManager.getClassByName(property);
- ownerId = permissionMap.get(owner);
- propertyId = permissionMap.get(property);
+ public Permission(LinkedHashMap<String, Long> data) {
+ this.data = data;
+ var iterator = data.entrySet().iterator();
+ var owner = iterator.next();
+ ownerClass = CLASSES.get(owner.getKey().substring(0, owner.getKey().length() - 2));
+ ownerId = owner.getValue();
+ var property = iterator.next();
+ propertyClass = CLASSES.get(property.getKey().substring(0, property.getKey().length() - 2));
+ propertyId = property.getValue();
}
+ public Permission(Class<?> ownerClass, long ownerId, Class<?> propertyClass, long propertyId) {
+ this.ownerClass = ownerClass;
+ this.ownerId = ownerId;
+ this.propertyClass = propertyClass;
+ this.propertyId = propertyId;
+ data = new LinkedHashMap<>();
+ data.put(getKey(ownerClass), ownerId);
+ data.put(getKey(propertyClass), propertyId);
+ }
+
+ private static String getKey(Class<?> clazz) {
+ return Introspector.decapitalize(clazz.getSimpleName()) + "Id";
+ }
+
+ public static String getStorageName(Class<?> ownerClass, Class<?> propertyClass) {
+ String ownerName = ownerClass.getSimpleName();
+ String propertyName = propertyClass.getSimpleName();
+ String managedPrefix = "Managed";
+ if (propertyName.startsWith(managedPrefix)) {
+ propertyName = propertyName.substring(managedPrefix.length());
+ }
+ return "tc_" + Introspector.decapitalize(ownerName) + "_" + Introspector.decapitalize(propertyName);
+ }
+
+ @QueryIgnore
+ @JsonIgnore
+ public String getStorageName() {
+ return getStorageName(ownerClass, propertyClass);
+ }
+
+ @QueryIgnore
+ @JsonAnyGetter
+ public Map<String, Long> get() {
+ return data;
+ }
+
+ @QueryIgnore
+ @JsonAnySetter
+ public void set(String key, Long value) {
+ data.put(key, value);
+ }
+
+ @QueryIgnore
+ @JsonIgnore
public Class<?> getOwnerClass() {
return ownerClass;
}
+ @QueryIgnore
+ @JsonIgnore
public long getOwnerId() {
return ownerId;
}
+ @QueryIgnore
+ @JsonIgnore
public Class<?> getPropertyClass() {
return propertyClass;
}
+ @QueryIgnore
+ @JsonIgnore
public long getPropertyId() {
return propertyId;
}
+
}
diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java
index 2c893ebbc..d73dc7b25 100644
--- a/src/main/java/org/traccar/storage/DatabaseStorage.java
+++ b/src/main/java/org/traccar/storage/DatabaseStorage.java
@@ -1,5 +1,6 @@
package org.traccar.storage;
+import org.traccar.model.Permission;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Limit;
@@ -29,6 +30,7 @@ public class DatabaseStorage extends Storage {
query.append(" FROM ").append(getTableName(clazz));
query.append(formatCondition(request.getCondition()));
query.append(formatOrder(request.getOrder()));
+ query.append(formatLimit(request.getLimit()));
try {
QueryBuilder builder = QueryBuilder.create(dataSource, query.toString());
for (Map.Entry<String, Object> variable : getConditionVariables(request.getCondition()).entrySet()) {
@@ -93,6 +95,54 @@ public class DatabaseStorage extends Storage {
}
}
+ @Override
+ public List<Permission> getPermissions(Class<?> ownerClass, Class<?> propertyClass) throws StorageException {
+ StringBuilder query = new StringBuilder("SELECT * FROM ");
+ query.append(Permission.getStorageName(ownerClass, propertyClass));
+ try {
+ QueryBuilder builder = QueryBuilder.create(dataSource, query.toString());
+ return builder.executePermissionsQuery();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
+ }
+
+ @Override
+ public void addPermission(Permission permission) throws StorageException {
+ StringBuilder query = new StringBuilder("INSERT INTO ");
+ query.append(permission.getStorageName());
+ query.append(" VALUES (");
+ query.append(permission.get().keySet().stream().map(key -> ':' + key).collect(Collectors.joining(", ")));
+ query.append(")");
+ try {
+ QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true);
+ for (var entry : permission.get().entrySet()) {
+ builder.setLong(entry.getKey(), entry.getValue());
+ }
+ builder.executeUpdate();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
+ }
+
+ @Override
+ public void removePermission(Permission permission) throws StorageException {
+ StringBuilder query = new StringBuilder("DELETE FROM ");
+ query.append(permission.getStorageName());
+ query.append(" WHERE ");
+ query.append(permission
+ .get().keySet().stream().map(key -> key + " = :" + key).collect(Collectors.joining(" AND ")));
+ try {
+ QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true);
+ for (var entry : permission.get().entrySet()) {
+ builder.setLong(entry.getKey(), entry.getValue());
+ }
+ builder.executeUpdate();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
+ }
+
private String getTableName(Class<?> clazz) throws StorageException {
StorageName storageName = clazz.getAnnotation(StorageName.class);
if (storageName == null) {
diff --git a/src/main/java/org/traccar/storage/MemoryStorage.java b/src/main/java/org/traccar/storage/MemoryStorage.java
index 0ebd3b87e..0a2e5a81f 100644
--- a/src/main/java/org/traccar/storage/MemoryStorage.java
+++ b/src/main/java/org/traccar/storage/MemoryStorage.java
@@ -1,5 +1,6 @@
package org.traccar.storage;
+import org.traccar.model.Permission;
import org.traccar.storage.query.Request;
import java.util.List;
@@ -24,4 +25,19 @@ public class MemoryStorage extends Storage {
public void removeObject(Class<?> clazz, Request request) throws StorageException {
}
+ @Override
+ public List<Permission> getPermissions(Class<?> ownerClass, Class<?> propertyClass) throws StorageException {
+ return null;
+ }
+
+ @Override
+ public void addPermission(Permission permission) throws StorageException {
+
+ }
+
+ @Override
+ public void removePermission(Permission permission) throws StorageException {
+
+ }
+
}
diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java
index edaacb74d..da8002f0b 100644
--- a/src/main/java/org/traccar/storage/QueryBuilder.java
+++ b/src/main/java/org/traccar/storage/QueryBuilder.java
@@ -472,7 +472,7 @@ public final class QueryBuilder {
return 0;
}
- public List<Permission> executePermissionsQuery() throws SQLException, ClassNotFoundException {
+ public List<Permission> executePermissionsQuery() throws SQLException {
List<Permission> result = new LinkedList<>();
if (query != null) {
try {
diff --git a/src/main/java/org/traccar/storage/Storage.java b/src/main/java/org/traccar/storage/Storage.java
index 3726fbf50..22c48cae0 100644
--- a/src/main/java/org/traccar/storage/Storage.java
+++ b/src/main/java/org/traccar/storage/Storage.java
@@ -1,5 +1,6 @@
package org.traccar.storage;
+import org.traccar.model.Permission;
import org.traccar.storage.query.Request;
import java.util.List;
@@ -14,6 +15,13 @@ public abstract class Storage {
public abstract void removeObject(Class<?> clazz, Request request) throws StorageException;
+ public abstract List<Permission> getPermissions(
+ Class<?> ownerClass, Class<?> propertyClass) throws StorageException;
+
+ public abstract void addPermission(Permission permission) throws StorageException;
+
+ public abstract void removePermission(Permission permission) throws StorageException;
+
public <T> T getObject(Class<T> clazz, Request request) throws StorageException {
var objects = getObjects(clazz, request);
return objects.isEmpty() ? null : objects.get(0);