aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/database/DataManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/database/DataManager.java')
-rw-r--r--src/main/java/org/traccar/database/DataManager.java265
1 files changed, 103 insertions, 162 deletions
diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java
index 199167419..303b8e033 100644
--- a/src/main/java/org/traccar/database/DataManager.java
+++ b/src/main/java/org/traccar/database/DataManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2022 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.
@@ -41,15 +41,20 @@ import org.traccar.model.Group;
import org.traccar.model.Maintenance;
import org.traccar.model.ManagedUser;
import org.traccar.model.Notification;
-import org.traccar.model.Order;
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.QueryExtended;
-import org.traccar.storage.QueryIgnore;
+import org.traccar.storage.Storage;
+import org.traccar.storage.StorageException;
+import org.traccar.storage.query.Columns;
+import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Limit;
+import org.traccar.storage.query.Order;
+import org.traccar.storage.query.Request;
import javax.sql.DataSource;
import java.beans.Introspector;
@@ -57,11 +62,10 @@ import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.sql.SQLException;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.LinkedList;
+import java.util.List;
public class DataManager {
@@ -81,6 +85,8 @@ public class DataManager {
return dataSource;
}
+ private final Storage storage;
+
private boolean generateQueries;
private final boolean forceLdap;
@@ -92,6 +98,8 @@ public class DataManager {
initDatabase();
initDatabaseSchema();
+
+ storage = new DatabaseStorage(dataSource);
}
private void initDatabase() throws Exception {
@@ -134,58 +142,6 @@ public class DataManager {
dataSource = new HikariDataSource(hikariConfig);
}
- public static String constructObjectQuery(String action, Class<?> clazz, boolean extended) {
- switch (action) {
- case ACTION_INSERT:
- case ACTION_UPDATE:
- StringBuilder result = new StringBuilder();
- StringBuilder fields = new StringBuilder();
- StringBuilder values = new StringBuilder();
-
- Set<Method> methods = new HashSet<>(Arrays.asList(clazz.getMethods()));
- methods.removeAll(Arrays.asList(Object.class.getMethods()));
- methods.removeAll(Arrays.asList(BaseModel.class.getMethods()));
- for (Method method : methods) {
- boolean skip;
- if (extended) {
- skip = !method.isAnnotationPresent(QueryExtended.class);
- } else {
- skip = method.isAnnotationPresent(QueryIgnore.class)
- || method.isAnnotationPresent(QueryExtended.class) && !action.equals(ACTION_INSERT);
- }
- if (!skip && method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
- String name = Introspector.decapitalize(method.getName().substring(3));
- if (action.equals(ACTION_INSERT)) {
- fields.append(name).append(", ");
- values.append(":").append(name).append(", ");
- } else {
- fields.append(name).append(" = :").append(name).append(", ");
- }
- }
- }
- fields.setLength(fields.length() - 2);
- if (action.equals(ACTION_INSERT)) {
- values.setLength(values.length() - 2);
- result.append("INSERT INTO ").append(getObjectsTableName(clazz)).append(" (");
- result.append(fields).append(") ");
- result.append("VALUES (").append(values).append(")");
- } else {
- result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET ");
- result.append(fields);
- result.append(" WHERE id = :id");
- }
- return result.toString();
- case ACTION_SELECT_ALL:
- return "SELECT * FROM " + getObjectsTableName(clazz);
- case ACTION_SELECT:
- return "SELECT * FROM " + getObjectsTableName(clazz) + " WHERE id = :id";
- case ACTION_DELETE:
- return "DELETE FROM " + getObjectsTableName(clazz) + " WHERE id = :id";
- default:
- throw new IllegalArgumentException("Unknown action");
- }
- }
-
public static String constructPermissionQuery(String action, Class<?> owner, Class<?> property) {
switch (action) {
case ACTION_SELECT_ALL:
@@ -204,39 +160,6 @@ public class DataManager {
}
}
- private String getQuery(String key) {
- String query = config.getString(key);
- if (query == null) {
- LOGGER.info("Query not provided: " + key);
- }
- return query;
- }
-
- public String getQuery(String action, Class<?> clazz) {
- return getQuery(action, clazz, false);
- }
-
- public String getQuery(String action, Class<?> clazz, boolean extended) {
- String queryName;
- if (action.equals(ACTION_SELECT_ALL)) {
- queryName = "database.select" + clazz.getSimpleName() + "s";
- } else {
- queryName = "database." + action.toLowerCase() + clazz.getSimpleName();
- if (extended) {
- queryName += "Extended";
- }
- }
- String query = config.getString(queryName);
- if (query == null) {
- if (generateQueries) {
- query = constructObjectQuery(action, clazz, extended);
- } else {
- LOGGER.info("Query not provided: " + queryName);
- }
- }
- return query;
- }
-
public String getQuery(String action, Class<?> owner, Class<?> property) {
String queryName;
switch (action) {
@@ -302,10 +225,12 @@ public class DataManager {
}
}
- public User login(String email, String password) throws SQLException {
- User user = QueryBuilder.create(dataSource, getQuery("database.loginUser"))
- .setString("email", email.trim())
- .executeQuerySingle(User.class);
+ public User login(String email, String password) throws StorageException {
+ User user = storage.getObject(User.class, new Request(
+ new Columns.Include("id", "login", "hashedPassword", "salt"),
+ new Condition.Or(
+ new Condition.Equals("email", "email", email.trim()),
+ new Condition.Equals("login", "email"))));
LdapProvider ldapProvider = Context.getLdapProvider();
if (user != null) {
if (ldapProvider != null && user.getLogin() != null && ldapProvider.login(user.getLogin(), password)
@@ -322,57 +247,75 @@ public class DataManager {
return null;
}
- public void updateDeviceStatus(Device device) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, Device.class, true))
- .setObject(device)
- .executeUpdate();
+ public void updateUserPassword(User user) throws StorageException {
+ storage.updateObject(user, new Request(
+ new Columns.Include("hashedPassword", "salt"),
+ new Condition.Equals("id", "id")));
}
- public Collection<Position> getPositions(long deviceId, Date from, Date to) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectPositions"))
- .setLong("deviceId", deviceId)
- .setDate("from", from)
- .setDate("to", to)
- .executeQuery(Position.class);
+ public void updateDeviceStatus(Device device) throws StorageException {
+ storage.updateObject(device, new Request(
+ new Columns.Include("lastUpdate"),
+ new Condition.Equals("id", "id")));
}
- public Position getPrecedingPosition(long deviceId, Date date) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectPrecedingPosition"))
- .setLong("deviceId", deviceId)
- .setDate("time", date)
- .executeQuerySingle(Position.class);
+ public Collection<Position> getPositions(long deviceId, Date from, Date to) throws StorageException {
+ return storage.getObjects(Position.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Between("fixTime", "from", from, "to", to)),
+ new Order("fixTime")));
}
- public void updateLatestPosition(Position position) throws SQLException {
- QueryBuilder.create(dataSource, getQuery("database.updateLatestPosition"))
- .setDate("now", new Date())
- .setObject(position)
- .executeUpdate();
+ public Position getPrecedingPosition(long deviceId, Date date) throws StorageException {
+ return storage.getObject(Position.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Compare("fixTime", "<=", "time", date)),
+ new Order(true, "fixTime"),
+ new Limit(1)));
}
- public Collection<Position> getLatestPositions() throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectLatestPositions"))
- .executeQuery(Position.class);
+ public void updateLatestPosition(Position position) throws StorageException {
+ Device device = new Device();
+ device.setId(position.getDeviceId());
+ device.setPositionId(position.getId());
+ storage.updateObject(device, new Request(
+ new Columns.Include("positionId"),
+ new Condition.Equals("id", "id")));
+ }
+
+ public Collection<Position> getLatestPositions() throws StorageException {
+ List<Position> positions = new LinkedList<>();
+ List<Device> devices = storage.getObjects(Device.class, new Request(new Columns.Include("positionId")));
+ for (Device device : devices) {
+ positions.addAll(storage.getObjects(Position.class, new Request(
+ new Columns.All(),
+ new Condition.Equals("id", "id", device.getPositionId()))));
+ }
+ return positions;
}
- public Server getServer() throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, Server.class))
- .executeQuerySingle(Server.class);
+ public Server getServer() throws StorageException {
+ return storage.getObject(Server.class, new Request(new Columns.All()));
}
- public Collection<Event> getEvents(long deviceId, Date from, Date to) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery("database.selectEvents"))
- .setLong("deviceId", deviceId)
- .setDate("from", from)
- .setDate("to", to)
- .executeQuery(Event.class);
+ public Collection<Event> getEvents(long deviceId, Date from, Date to) throws StorageException {
+ return storage.getObjects(Event.class, new Request(
+ new Columns.All(),
+ new Condition.And(
+ new Condition.Equals("deviceId", "deviceId", deviceId),
+ new Condition.Between("eventTime", "from", from, "to", to)),
+ new Order("eventTime")));
}
- 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 Collection<Statistics> getStatistics(Date from, Date to) throws StorageException {
+ return storage.getObjects(Statistics.class, new Request(
+ new Columns.All(),
+ new Condition.Between("captureTime", "from", from, "to", to),
+ new Order("captureTime")));
}
public static Class<?> getClassByName(String name) throws ClassNotFoundException {
@@ -400,7 +343,7 @@ public class DataManager {
case "notification":
return Notification.class;
case "order":
- return Order.class;
+ return org.traccar.model.Order.class;
default:
throw new ClassNotFoundException();
}
@@ -412,51 +355,49 @@ public class DataManager {
}
public Collection<Permission> getPermissions(Class<? extends BaseModel> owner, Class<? extends BaseModel> property)
- throws SQLException, ClassNotFoundException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property))
- .executePermissionsQuery();
+ throws StorageException, ClassNotFoundException {
+ try {
+ return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property))
+ .executePermissionsQuery();
+ } catch (SQLException e) {
+ throw new StorageException(e);
+ }
}
public void linkObject(Class<?> owner, long ownerId, Class<?> property, long propertyId, boolean link)
- throws SQLException {
+ 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);
+ }
}
- public <T extends BaseModel> T getObject(Class<T> clazz, long entityId) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT, clazz))
- .setLong("id", entityId)
- .executeQuerySingle(clazz);
+ public <T extends BaseModel> T getObject(Class<T> clazz, long entityId) throws StorageException {
+ return storage.getObject(clazz, new Request(
+ new Columns.All(),
+ new Condition.Equals("id", "id", entityId)));
}
- public <T extends BaseModel> Collection<T> getObjects(Class<T> clazz) throws SQLException {
- return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, clazz))
- .executeQuery(clazz);
+ public <T extends BaseModel> Collection<T> getObjects(Class<T> clazz) throws StorageException {
+ return storage.getObjects(clazz, new Request(new Columns.All()));
}
- public void addObject(BaseModel entity) throws SQLException {
- entity.setId(QueryBuilder.create(dataSource, getQuery(ACTION_INSERT, entity.getClass()), true)
- .setObject(entity)
- .executeUpdate());
+ public void addObject(BaseModel entity) throws StorageException {
+ entity.setId(storage.addObject(entity, new Request(new Columns.Exclude("id"))));
}
- public void updateObject(BaseModel entity) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, entity.getClass()))
- .setObject(entity)
- .executeUpdate();
- if (entity instanceof User && ((User) entity).getHashedPassword() != null) {
- QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, User.class, true))
- .setObject(entity)
- .executeUpdate();
- }
+ public void updateObject(BaseModel entity) throws StorageException {
+ storage.updateObject(entity, new Request(
+ new Columns.Exclude("id"),
+ new Condition.Equals("id", "id")));
}
- public void removeObject(Class<? extends BaseModel> clazz, long entityId) throws SQLException {
- QueryBuilder.create(dataSource, getQuery(ACTION_DELETE, clazz))
- .setLong("id", entityId)
- .executeUpdate();
+ public void removeObject(Class<? extends BaseModel> clazz, long entityId) throws StorageException {
+ storage.removeObject(clazz, new Request(new Condition.Equals("id", "id", entityId)));
}
}