// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.apidb.v0_6.impl; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; import org.openstreetmap.osmosis.apidb.common.DatabaseContext; import org.openstreetmap.osmosis.core.OsmosisRuntimeException; import org.openstreetmap.osmosis.core.database.ReleasableStatementContainer; import org.openstreetmap.osmosis.core.domain.v0_6.OsmUser; import org.openstreetmap.osmosis.core.lifecycle.Closeable; /** * Creates or loads the details of the Osmosis user in the database. * * @author Brett Henderson */ public class UserManager implements Closeable { private static final String SELECT_SQL_USER_EXISTS = "SELECT Count(id) AS userCount FROM users WHERE id = ?"; private static final String INSERT_SQL_USER = "INSERT INTO users (id, email, pass_crypt," + " creation_time, display_name, data_public, description, home_lat, home_lon, home_zoom," + " nearby, pass_salt) VALUES (?, ?, '00000000000000000000000000000000', NOW(), ?, ?," + " ?, 0, 0, 3, 50, '00000000')"; private static final String UPDATE_SQL_USER = "UPDATE users SET display_name = ? WHERE id = ?"; private final DatabaseContext dbCtx; private final Set<Integer> updatedUsers; private final ReleasableStatementContainer statementContainer; private PreparedStatement statementInsert; private PreparedStatement statementExists; private PreparedStatement statementUpdate; /** * Creates a new instance. * * @param dbCtx The database context to use for all database access. */ public UserManager(DatabaseContext dbCtx) { this.dbCtx = dbCtx; updatedUsers = new HashSet<Integer>(); statementContainer = new ReleasableStatementContainer(); } /** * Checks if the specified user exists in the database. * * @param user The user to check for. * @return True if the user exists, false otherwise. */ private boolean doesUserExistInDb(OsmUser user) { if (statementExists == null) { statementExists = statementContainer.add(dbCtx.prepareStatementForStreaming(SELECT_SQL_USER_EXISTS)); } try { statementExists.setInt(1, user.getId()); try (ResultSet resultSet = statementExists.executeQuery()) { resultSet.next(); return resultSet.getInt("userCount") != 0; } } catch (SQLException e) { throw new OsmosisRuntimeException("Unable to check if user with id " + user.getId() + " exists in the database.", e); } } /** * Inserts the specified user into the database. * * @param user The user to be inserted. */ private void insertUser(OsmUser user) { int prmIndex; String userName; boolean dataPublic; if (statementInsert == null) { statementInsert = statementContainer.add(dbCtx.prepareStatement(INSERT_SQL_USER)); } if (OsmUser.NONE.equals(user)) { userName = "Osmosis Anonymous"; dataPublic = false; } else { userName = user.getName(); dataPublic = true; } try { prmIndex = 1; statementInsert.setInt(prmIndex++, user.getId()); statementInsert.setString(prmIndex++, "osmosis_user_" + user.getId() + "@example.com"); statementInsert.setString(prmIndex++, userName); statementInsert.setBoolean(prmIndex++, dataPublic); statementInsert.setString(prmIndex++, userName); statementInsert.executeUpdate(); } catch (SQLException e) { throw new OsmosisRuntimeException("Unable to insert user with id " + user.getId() + " into the database.", e); } } /** * Updates the specified user in the database. * * @param user The user to be updated. */ private void updateUser(OsmUser user) { int prmIndex; if (statementUpdate == null) { statementUpdate = statementContainer.add(dbCtx.prepareStatement(UPDATE_SQL_USER)); } try { String userName; if (OsmUser.NONE.equals(user)) { userName = "Osmosis Anonymous"; } else { userName = user.getName(); } prmIndex = 1; statementUpdate.setString(prmIndex++, userName); statementUpdate.setInt(prmIndex++, user.getId()); statementUpdate.executeUpdate(); } catch (SQLException e) { throw new OsmosisRuntimeException("Unable to update user with id " + user.getId() + " in the database.", e); } } /** * Adds the user to the database or updates the name of the existing database entry if one * already exists with the same id. * * @param user The user to be created or updated. */ public void addOrUpdateUser(OsmUser user) { if (!updatedUsers.contains(user.getId())) { if (doesUserExistInDb(user)) { updateUser(user); } else { insertUser(user); } updatedUsers.add(user.getId()); } } /** * {@inheritDoc} */ @Override public void close() { statementContainer.close(); } }