Unverified 提交 6c004246 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1211 from katzyn/misc

Assorted minor changes
...@@ -33,7 +33,7 @@ Change Log ...@@ -33,7 +33,7 @@ Change Log
</li> </li>
<li>PR #1176: Magic value replacement with constant <li>PR #1176: Magic value replacement with constant
</li> </li>
<li>PR #1171: Introduce last commited value into a VersionedValue <li>PR #1171: Introduce last committed value into a VersionedValue
</li> </li>
<li>PR #1175: tighten test conditions - do not ignore any exceptions <li>PR #1175: tighten test conditions - do not ignore any exceptions
</li> </li>
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=Serializer cannot be changed because there is a data table: {0} 90141=Serializer cannot be changed because there is a data table: {0}
90142=Step size must not be zero 90142=Step size must not be zero
90143=Row {1} not found in primary index {0} 90143=Row {1} not found in primary index {0}
90144=Authenticator not enabled on database {0}
HY000=General error: {0} HY000=General error: {0}
HY004=Unknown data type: {0} HY004=Unknown data type: {0}
HYC00=Feature not supported: {0} HYC00=Feature not supported: {0}
......
...@@ -9,8 +9,8 @@ import org.h2.security.auth.AuthenticationInfo; ...@@ -9,8 +9,8 @@ import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.Configurable; import org.h2.security.auth.Configurable;
/** /**
* A class that implement this interface can be used to validate * A class that implement this interface can be used to validate credentials
* credentials provided by client. * provided by client.
* <p> * <p>
* <b>This feature is experimental and subject to change</b> * <b>This feature is experimental and subject to change</b>
* </p> * </p>
...@@ -18,10 +18,14 @@ import org.h2.security.auth.Configurable; ...@@ -18,10 +18,14 @@ import org.h2.security.auth.Configurable;
public interface CredentialsValidator extends Configurable { public interface CredentialsValidator extends Configurable {
/** /**
* Validate user credential * Validate user credential.
* @param authenticationInfo = authentication info *
* @param authenticationInfo
* = authentication info
* @return true if credentials are valid, otherwise false * @return true if credentials are valid, otherwise false
* @throws Exception any exception occurred (invalid credentials or internal issue) prevent user login * @throws Exception
* any exception occurred (invalid credentials or internal
* issue) prevent user login
*/ */
boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception; boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception;
......
...@@ -6,15 +6,14 @@ ...@@ -6,15 +6,14 @@
package org.h2.api; package org.h2.api;
import java.util.Collection; import java.util.Collection;
import java.util.Set;
import org.h2.security.auth.AuthenticationException; import org.h2.security.auth.AuthenticationException;
import org.h2.security.auth.AuthenticationInfo; import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.Configurable; import org.h2.security.auth.Configurable;
/** /**
* A class that implement this interface can be used during * A class that implement this interface can be used during authentication to
* authentication to map external users to database roles. * map external users to database roles.
* <p> * <p>
* <b>This feature is experimental and subject to change</b> * <b>This feature is experimental and subject to change</b>
* </p> * </p>
...@@ -22,10 +21,13 @@ import org.h2.security.auth.Configurable; ...@@ -22,10 +21,13 @@ import org.h2.security.auth.Configurable;
public interface UserToRolesMapper extends Configurable { public interface UserToRolesMapper extends Configurable {
/** /**
* Map user identified by authentication info to a set of granted roles * Map user identified by authentication info to a set of granted roles.
*
* @param authenticationInfo * @param authenticationInfo
* authentication information
* @return list of roles to be assigned to the user temporary * @return list of roles to be assigned to the user temporary
* @throws AuthenticationException * @throws AuthenticationException
* on authentication exception
*/ */
Collection<String> mapUserToRoles(AuthenticationInfo authenticationInfo) throws AuthenticationException; Collection<String> mapUserToRoles(AuthenticationInfo authenticationInfo) throws AuthenticationException;
} }
...@@ -321,7 +321,7 @@ public abstract class Command implements CommandInterface { ...@@ -321,7 +321,7 @@ public abstract class Command implements CommandInterface {
if (start != 0 && TimeUnit.NANOSECONDS.toMillis(now - start) > session.getLockTimeout()) { if (start != 0 && TimeUnit.NANOSECONDS.toMillis(now - start) > session.getLockTimeout()) {
throw DbException.get(ErrorCode.LOCK_TIMEOUT_1, e); throw DbException.get(ErrorCode.LOCK_TIMEOUT_1, e);
} }
// Only in PageStore mode we need to sleep here to avoid buzy wait loop // Only in PageStore mode we need to sleep here to avoid busy wait loop
Database database = session.getDatabase(); Database database = session.getDatabase();
if (database.getMvStore() == null) { if (database.getMvStore() == null) {
int sleep = 1 + MathUtils.randomInt(10); int sleep = 1 + MathUtils.randomInt(10);
......
...@@ -548,9 +548,10 @@ public class Set extends Prepared { ...@@ -548,9 +548,10 @@ public class Set extends Prepared {
} }
addOrUpdateSetting(name,expression.getValue(session).getString(),0); addOrUpdateSetting(name,expression.getValue(session).getString(),0);
} catch (Exception e) { } catch (Exception e) {
//Errors during start are ignored to allow to open the database // Errors during start are ignored to allow to open the database
if (database.isStarting()) { if (database.isStarting()) {
database.getTrace(Trace.DATABASE).error(e, "{0}: failed to set authenticator during database start ",expression.toString()); database.getTrace(Trace.DATABASE).error(e,
"{0}: failed to set authenticator during database start ", expression.toString());
} else { } else {
throw DbException.convert(e); throw DbException.convert(e);
} }
......
...@@ -664,6 +664,9 @@ public class ConnectionInfo implements Cloneable { ...@@ -664,6 +664,9 @@ public class ConnectionInfo implements Cloneable {
return url; return url;
} }
/**
* Clear authentication properties.
*/
public void cleanAuthenticationInfo() { public void cleanAuthenticationInfo() {
removeProperty("AUTHREALM", false); removeProperty("AUTHREALM", false);
removeProperty("AUTHZPWD", false); removeProperty("AUTHZPWD", false);
......
...@@ -2989,7 +2989,7 @@ public class Database implements DataHandler { ...@@ -2989,7 +2989,7 @@ public class Database implements DataHandler {
public void setAuthenticator(Authenticator authenticator) { public void setAuthenticator(Authenticator authenticator) {
if (authenticator!=null) { if (authenticator!=null) {
authenticator.init(this); authenticator.init(this);
}; }
this.authenticator=authenticator; this.authenticator=authenticator;
} }
} }
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.engine; package org.h2.engine;
import org.h2.security.auth.AuthenticationInfo; import org.h2.security.auth.AuthenticationInfo;
...@@ -6,16 +11,24 @@ import org.h2.util.MathUtils; ...@@ -6,16 +11,24 @@ import org.h2.util.MathUtils;
public class UserBuilder { public class UserBuilder {
/** /**
* build the database user starting from authentication informations * Build the database user starting from authentication informations.
* @param authenticationInfo = authentication info *
* @param database = target database * @param authenticationInfo
* @param persistent = true if the user will be persisted in the database * authentication info
* @param database
* target database
* @param persistent
* true if the user will be persisted in the database
* @return user bean * @return user bean
*/ */
public static User buildUser(AuthenticationInfo authenticationInfo, Database database, boolean persistent) { public static User buildUser(AuthenticationInfo authenticationInfo, Database database, boolean persistent) {
User user = new User(database, persistent ? database.allocateObjectId() : -1, authenticationInfo.getFullyQualifiedName(), false); User user = new User(database, persistent ? database.allocateObjectId() : -1,
//In case of external authentication fill the password hash with random data authenticationInfo.getFullyQualifiedName(), false);
user.setUserPasswordHash( authenticationInfo.getRealm()==null ? authenticationInfo.getConnectionInfo().getUserPasswordHash(): MathUtils.secureRandomBytes(64)); // In case of external authentication fill the password hash with random
// data
user.setUserPasswordHash(
authenticationInfo.getRealm() == null ? authenticationInfo.getConnectionInfo().getUserPasswordHash()
: MathUtils.secureRandomBytes(64));
user.setTemporary(!persistent); user.setTemporary(!persistent);
return user; return user;
} }
......
...@@ -11,7 +11,6 @@ import org.h2.schema.Sequence; ...@@ -11,7 +11,6 @@ import org.h2.schema.Sequence;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
/** /**
...@@ -27,9 +26,9 @@ public class SequenceValue extends Expression { ...@@ -27,9 +26,9 @@ public class SequenceValue extends Expression {
@Override @Override
public Value getValue(Session session) { public Value getValue(Session session) {
long value = sequence.getNext(session); ValueLong value = ValueLong.get(sequence.getNext(session));
session.setLastIdentity(ValueLong.get(value)); session.setLastIdentity(value);
return ValueLong.get(value); return value;
} }
@Override @Override
...@@ -59,12 +58,12 @@ public class SequenceValue extends Expression { ...@@ -59,12 +58,12 @@ public class SequenceValue extends Expression {
@Override @Override
public long getPrecision() { public long getPrecision() {
return ValueInt.PRECISION; return ValueLong.PRECISION;
} }
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return ValueInt.DISPLAY_SIZE; return ValueLong.DISPLAY_SIZE;
} }
@Override @Override
......
...@@ -40,11 +40,10 @@ import org.h2.command.CommandInterface; ...@@ -40,11 +40,10 @@ import org.h2.command.CommandInterface;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.SessionInterface; import org.h2.engine.SessionInterface;
import org.h2.engine.SessionRemote; import org.h2.engine.SessionRemote;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.Session;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.TraceObject; import org.h2.message.TraceObject;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
......
...@@ -114,6 +114,7 @@ public class DatabaseInfo implements DatabaseInfoMBean { ...@@ -114,6 +114,7 @@ public class DatabaseInfo implements DatabaseInfoMBean {
return database.isMultiThreaded(); return database.isMultiThreaded();
} }
@Deprecated
@Override @Override
public boolean isMvcc() { public boolean isMvcc() {
return database.isMVStore(); return database.isMVStore();
......
...@@ -53,6 +53,7 @@ public interface DatabaseInfoMBean { ...@@ -53,6 +53,7 @@ public interface DatabaseInfoMBean {
* *
* @return true if MVCC is enabled, false otherwise * @return true if MVCC is enabled, false otherwise
*/ */
@Deprecated
boolean isMvcc(); boolean isMvcc();
/** /**
......
...@@ -2568,7 +2568,7 @@ public class MVStore { ...@@ -2568,7 +2568,7 @@ public class MVStore {
String oldName = getMapName(id); String oldName = getMapName(id);
if (oldName != null && !oldName.equals(newName)) { if (oldName != null && !oldName.equals(newName)) {
String idHexStr = Integer.toHexString(id); String idHexStr = Integer.toHexString(id);
// we need to cope whith the case of previously unfinished rename // we need to cope with the case of previously unfinished rename
String existingIdHexStr = meta.get("name." + newName); String existingIdHexStr = meta.get("name." + newName);
DataUtils.checkArgument( DataUtils.checkArgument(
existingIdHexStr == null || existingIdHexStr.equals(idHexStr), existingIdHexStr == null || existingIdHexStr.equals(idHexStr),
......
...@@ -119,7 +119,7 @@ public class MVTable extends TableBase { ...@@ -119,7 +119,7 @@ public class MVTable extends TableBase {
*/ */
private final ArrayDeque<Session> waitingSessions = new ArrayDeque<>(); private final ArrayDeque<Session> waitingSessions = new ArrayDeque<>();
private final Trace traceLock; private final Trace traceLock;
private final AtomicInteger changesUnitlAnalyze; private final AtomicInteger changesUntilAnalyze;
private int nextAnalyze; private int nextAnalyze;
private final boolean containsLargeObject; private final boolean containsLargeObject;
private Column rowIdColumn; private Column rowIdColumn;
...@@ -130,7 +130,7 @@ public class MVTable extends TableBase { ...@@ -130,7 +130,7 @@ public class MVTable extends TableBase {
public MVTable(CreateTableData data, MVTableEngine.Store store) { public MVTable(CreateTableData data, MVTableEngine.Store store) {
super(data); super(data);
nextAnalyze = database.getSettings().analyzeAuto; nextAnalyze = database.getSettings().analyzeAuto;
changesUnitlAnalyze = nextAnalyze <= 0 ? null : new AtomicInteger(nextAnalyze); changesUntilAnalyze = nextAnalyze <= 0 ? null : new AtomicInteger(nextAnalyze);
this.store = store; this.store = store;
this.transactionStore = store.getTransactionStore(); this.transactionStore = store.getTransactionStore();
this.isHidden = data.isHidden; this.isHidden = data.isHidden;
...@@ -714,8 +714,8 @@ public class MVTable extends TableBase { ...@@ -714,8 +714,8 @@ public class MVTable extends TableBase {
Index index = indexes.get(i); Index index = indexes.get(i);
index.truncate(session); index.truncate(session);
} }
if (changesUnitlAnalyze != null) { if (changesUntilAnalyze != null) {
changesUnitlAnalyze.set(nextAnalyze); changesUntilAnalyze.set(nextAnalyze);
} }
} }
...@@ -745,12 +745,12 @@ public class MVTable extends TableBase { ...@@ -745,12 +745,12 @@ public class MVTable extends TableBase {
} }
private void analyzeIfRequired(Session session) { private void analyzeIfRequired(Session session) {
if (changesUnitlAnalyze != null) { if (changesUntilAnalyze != null) {
if (changesUnitlAnalyze.decrementAndGet() == 0) { if (changesUntilAnalyze.decrementAndGet() == 0) {
if (nextAnalyze <= Integer.MAX_VALUE / 2) { if (nextAnalyze <= Integer.MAX_VALUE / 2) {
nextAnalyze *= 2; nextAnalyze *= 2;
} }
changesUnitlAnalyze.set(nextAnalyze); changesUntilAnalyze.set(nextAnalyze);
session.markTableForAnalyze(this); session.markTableForAnalyze(this);
} }
} }
......
...@@ -149,7 +149,7 @@ public class MVTableEngine implements TableEngine { ...@@ -149,7 +149,7 @@ public class MVTableEngine implements TableEngine {
* @param builder the builder * @param builder the builder
* @param encrypted whether the store is encrypted * @param encrypted whether the store is encrypted
*/ */
private void open(Database db, MVStore.Builder builder, boolean encrypted) { void open(Database db, MVStore.Builder builder, boolean encrypted) {
this.encrypted = encrypted; this.encrypted = encrypted;
try { try {
this.store = builder.open(); this.store = builder.open();
......
...@@ -28,7 +28,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -28,7 +28,7 @@ final class CommitDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
assert decision == null; assert decision == null;
if (existingValue == null || if (existingValue == null ||
// map entry was treated as already committed, and then // map entry was treated as already committed, and then
// it has been removed by another transaction (commited and closed by now ) // it has been removed by another transaction (committed and closed by now)
existingValue.getOperationId() != undoKey) { existingValue.getOperationId() != undoKey) {
// this is not a final undo log entry for this key, // this is not a final undo log entry for this key,
// or map entry was treated as already committed and then // or map entry was treated as already committed and then
......
...@@ -30,8 +30,8 @@ final class RollbackDecisionMaker extends MVMap.DecisionMaker<Object[]> { ...@@ -30,8 +30,8 @@ final class RollbackDecisionMaker extends MVMap.DecisionMaker<Object[]> {
@Override @Override
public MVMap.Decision decide(Object[] existingValue, Object[] providedValue) { public MVMap.Decision decide(Object[] existingValue, Object[] providedValue) {
assert decision == null; assert decision == null;
// normaly existingValue will always be there except of db initialization // normally existingValue will always be there except of db initialization
// where some undo log enty was captured on disk but actual map entry was not // where some undo log entry was captured on disk but actual map entry was not
if (existingValue != null ) { if (existingValue != null ) {
VersionedValue valueToRestore = (VersionedValue) existingValue[2]; VersionedValue valueToRestore = (VersionedValue) existingValue[2];
long operationId; long operationId;
......
...@@ -475,14 +475,19 @@ public class Transaction { ...@@ -475,14 +475,19 @@ public class Transaction {
public boolean waitFor(Transaction toWaitFor) { public boolean waitFor(Transaction toWaitFor) {
if (isDeadlocked(toWaitFor)) { if (isDeadlocked(toWaitFor)) {
StringBuilder details = new StringBuilder(String.format("Transaction %d has been chosen as a deadlock victim. Details:%n", transactionId)); StringBuilder details = new StringBuilder(
for(Transaction tx = toWaitFor, nextTx; (nextTx = tx.blockingTransaction) != null; tx = nextTx) { String.format("Transaction %d has been chosen as a deadlock victim. Details:%n", transactionId));
details.append(String.format("Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n", for (Transaction tx = toWaitFor, nextTx; (nextTx = tx.blockingTransaction) != null; tx = nextTx) {
details.append(String.format(
"Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n",
tx.transactionId, tx.blockingMap.getName(), tx.blockingKey, tx.blockingTransaction)); tx.transactionId, tx.blockingMap.getName(), tx.blockingKey, tx.blockingTransaction));
if (nextTx == this) { if (nextTx == this) {
details.append(String.format("Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n", details.append(String.format(
"Transaction %d attempts to update map <%s> entry with key <%s>"
+ " modified by transaction %s%n",
transactionId, blockingMap.getName(), blockingKey, toWaitFor)); transactionId, blockingMap.getName(), blockingKey, toWaitFor));
throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK, details.toString()); throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK,
details.toString());
} }
} }
} }
......
...@@ -109,7 +109,7 @@ public class TransactionMap<K, V> { ...@@ -109,7 +109,7 @@ public class TransactionMap<K, V> {
// Entries describing removals from the map by this transaction and all transactions, // Entries describing removals from the map by this transaction and all transactions,
// which are committed but not closed yet, // which are committed but not closed yet,
// and antries about additions to the map by other uncommitted transactions were counted, // and entries about additions to the map by other uncommitted transactions were counted,
// but they should not contribute into total count. // but they should not contribute into total count.
if (2 * undoLogSize > size) { if (2 * undoLogSize > size) {
// the undo log is larger than half of the map - scan the entries of the map directly // the undo log is larger than half of the map - scan the entries of the map directly
...@@ -130,7 +130,8 @@ public class TransactionMap<K, V> { ...@@ -130,7 +130,8 @@ public class TransactionMap<K, V> {
} }
} }
} else { } else {
// The undo logs are much smaller than the map - scan all undo logs, and then lookup relevant map entry. // The undo logs are much smaller than the map - scan all undo logs,
// and then lookup relevant map entry.
for (MVMap.RootReference undoLogRootReference : undoLogRootReferences) { for (MVMap.RootReference undoLogRootReference : undoLogRootReferences) {
if (undoLogRootReference != null) { if (undoLogRootReference != null) {
Cursor<Long, Object[]> cursor = new Cursor<>(undoLogRootReference.root, null); Cursor<Long, Object[]> cursor = new Cursor<>(undoLogRootReference.root, null);
...@@ -139,12 +140,15 @@ public class TransactionMap<K, V> { ...@@ -139,12 +140,15 @@ public class TransactionMap<K, V> {
Object op[] = cursor.getValue(); Object op[] = cursor.getValue();
if ((int) op[0] == map.getId()) { if ((int) op[0] == map.getId()) {
VersionedValue currentValue = map.get(mapRootPage, op[1]); VersionedValue currentValue = map.get(mapRootPage, op[1]);
// If map entry is not there, then we never counted it, in the first place, so skip it. // If map entry is not there, then we never counted
// This is possible when undo entry exists because it belongs // it, in the first place, so skip it.
// to a committed but not yet closed transaction, // This is possible when undo entry exists because
// and it was later deleted by some other already committed and closed transaction. // it belongs to a committed but not yet closed
// transaction, and it was later deleted by some
// other already committed and closed transaction.
if (currentValue != null) { if (currentValue != null) {
// only the last undo entry for any given map key should be considered // only the last undo entry for any given map
// key should be considered
long operationId = cursor.getKey(); long operationId = cursor.getKey();
if (currentValue.getOperationId() == operationId) { if (currentValue.getOperationId() == operationId) {
int txId = TransactionStore.getTransactionId(operationId); int txId = TransactionStore.getTransactionId(operationId);
...@@ -204,7 +208,8 @@ public class TransactionMap<K, V> { ...@@ -204,7 +208,8 @@ public class TransactionMap<K, V> {
*/ */
public V putIfAbsent(K key, V value) { public V putIfAbsent(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null"); DataUtils.checkArgument(value != null, "The value may not be null");
TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value, transaction); TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value,
transaction);
return set(key, decisionMaker); return set(key, decisionMaker);
} }
...@@ -275,8 +280,10 @@ public class TransactionMap<K, V> { ...@@ -275,8 +280,10 @@ public class TransactionMap<K, V> {
} while (blockingTransaction.sequenceNum > sequenceNumWhenStarted || transaction.waitFor(blockingTransaction)); } while (blockingTransaction.sequenceNum > sequenceNumWhenStarted || transaction.waitFor(blockingTransaction));
throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTION_LOCKED, throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTION_LOCKED,
"Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4} within allocated time interval {5} ms.", "Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4}"
map.getName(), key, result, blockingTransaction.transactionId, transaction.transactionId, transaction.timeoutMillis); + " within allocated time interval {5} ms.",
map.getName(), key, result, blockingTransaction.transactionId, transaction.transactionId,
transaction.timeoutMillis);
} }
/** /**
...@@ -319,7 +326,8 @@ public class TransactionMap<K, V> { ...@@ -319,7 +326,8 @@ public class TransactionMap<K, V> {
*/ */
public boolean trySet(K key, V value) { public boolean trySet(K key, V value) {
try { try {
// TODO: effective transaction.timeoutMillis should be set to 0 here and restored before return // TODO: effective transaction.timeoutMillis should be set to 0 here
// and restored before return
// TODO: eliminate exception usage as part of normal control flaw // TODO: eliminate exception usage as part of normal control flaw
set(key, value); set(key, value);
return true; return true;
......
...@@ -89,7 +89,7 @@ public class TransactionStore { ...@@ -89,7 +89,7 @@ public class TransactionStore {
private final AtomicReferenceArray<Transaction> transactions = private final AtomicReferenceArray<Transaction> transactions =
new AtomicReferenceArray<>(MAX_OPEN_TRANSACTIONS + 1); new AtomicReferenceArray<>(MAX_OPEN_TRANSACTIONS + 1);
private static final String UNDO_LOG_NAME_PEFIX = "undoLog"; private static final String UNDO_LOG_NAME_PREFIX = "undoLog";
private static final char UNDO_LOG_COMMITTED = '-'; // must come before open in lexicographical order private static final char UNDO_LOG_COMMITTED = '-'; // must come before open in lexicographical order
private static final char UNDO_LOG_OPEN = '.'; private static final char UNDO_LOG_OPEN = '.';
...@@ -101,7 +101,7 @@ public class TransactionStore { ...@@ -101,7 +101,7 @@ public class TransactionStore {
public static String getUndoLogName(boolean committed, int transactionId) { public static String getUndoLogName(boolean committed, int transactionId) {
return UNDO_LOG_NAME_PEFIX + return UNDO_LOG_NAME_PREFIX +
(committed ? UNDO_LOG_COMMITTED : UNDO_LOG_OPEN) + (committed ? UNDO_LOG_COMMITTED : UNDO_LOG_OPEN) +
(transactionId > 0 ? String.valueOf(transactionId) : ""); (transactionId > 0 ? String.valueOf(transactionId) : "");
} }
...@@ -120,7 +120,7 @@ public class TransactionStore { ...@@ -120,7 +120,7 @@ public class TransactionStore {
* *
* @param store the store * @param store the store
* @param dataType the data type for map keys and values * @param dataType the data type for map keys and values
* @param timeoutMillis lock aquisition timeout in milliseconds, 0 means no wait * @param timeoutMillis lock acquisition timeout in milliseconds, 0 means no wait
*/ */
public TransactionStore(MVStore store, DataType dataType, int timeoutMillis) { public TransactionStore(MVStore store, DataType dataType, int timeoutMillis) {
this.store = store; this.store = store;
...@@ -143,10 +143,10 @@ public class TransactionStore { ...@@ -143,10 +143,10 @@ public class TransactionStore {
public void init() { public void init() {
if (!init) { if (!init) {
for (String mapName : store.getMapNames()) { for (String mapName : store.getMapNames()) {
if (mapName.startsWith(UNDO_LOG_NAME_PEFIX)) { if (mapName.startsWith(UNDO_LOG_NAME_PREFIX)) {
boolean committed = mapName.charAt(UNDO_LOG_NAME_PEFIX.length()) == UNDO_LOG_COMMITTED; boolean committed = mapName.charAt(UNDO_LOG_NAME_PREFIX.length()) == UNDO_LOG_COMMITTED;
if (store.hasData(mapName) || committed) { if (store.hasData(mapName) || committed) {
int transactionId = Integer.parseInt(mapName.substring(UNDO_LOG_NAME_PEFIX.length() + 1)); int transactionId = Integer.parseInt(mapName.substring(UNDO_LOG_NAME_PREFIX.length() + 1));
VersionedBitSet openTxBitSet = openTransactions.get(); VersionedBitSet openTxBitSet = openTransactions.get();
if (!openTxBitSet.get(transactionId)) { if (!openTxBitSet.get(transactionId)) {
Object[] data = preparedTransactions.get(transactionId); Object[] data = preparedTransactions.get(transactionId);
...@@ -168,7 +168,8 @@ public class TransactionStore { ...@@ -168,7 +168,8 @@ public class TransactionStore {
assert committed || lastUndoKey != null; assert committed || lastUndoKey != null;
assert committed || getTransactionId(lastUndoKey) == transactionId; assert committed || getTransactionId(lastUndoKey) == transactionId;
long logId = lastUndoKey == null ? 0 : getLogId(lastUndoKey) + 1; long logId = lastUndoKey == null ? 0 : getLogId(lastUndoKey) + 1;
registerTransaction(transactionId, status, name, logId, timeoutMillis, 0, RollbackListener.NONE); registerTransaction(transactionId, status, name, logId, timeoutMillis, 0,
RollbackListener.NONE);
} }
} }
} }
......
...@@ -49,10 +49,11 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue ...@@ -49,10 +49,11 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
logIt(existingValue.value == null ? null : VersionedValue.getInstance(existingValue.value)); logIt(existingValue.value == null ? null : VersionedValue.getInstance(existingValue.value));
decision = MVMap.Decision.PUT; decision = MVMap.Decision.PUT;
} else if(fetchTransaction(blockingId) == null) { } else if(fetchTransaction(blockingId) == null) {
// condition above means transaction has been committed/rplled back and closed by now // condition above means transaction has been committed/rolled back and closed by now
decision = MVMap.Decision.REPEAT; decision = MVMap.Decision.REPEAT;
} else { } else {
// this entry comes from a different transaction, and this transaction is not committed yet // this entry comes from a different transaction, and this
// transaction is not committed yet
// should wait on blockingTransaction that was determined earlier // should wait on blockingTransaction that was determined earlier
decision = MVMap.Decision.ABORT; decision = MVMap.Decision.ABORT;
} }
......
...@@ -11,8 +11,9 @@ import java.util.BitSet; ...@@ -11,8 +11,9 @@ import java.util.BitSet;
* Class VersionedBitSet extends standard BitSet to add a version field. * Class VersionedBitSet extends standard BitSet to add a version field.
* This will allow bit set and version to be changed atomically. * This will allow bit set and version to be changed atomically.
*/ */
final class VersionedBitSet extends BitSet final class VersionedBitSet extends BitSet {
{ private static final long serialVersionUID = 1L;
private long version; private long version;
public VersionedBitSet() {} public VersionedBitSet() {}
......
...@@ -35,7 +35,7 @@ public class VersionedValue { ...@@ -35,7 +35,7 @@ public class VersionedValue {
return new Uncommitted(operationId, value, committedValue); return new Uncommitted(operationId, value, committedValue);
} }
private VersionedValue(Object value) { VersionedValue(Object value) {
this.value = value; this.value = value;
} }
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=#Serializer cannot be changed because there is a data table: {0} 90141=#Serializer cannot be changed because there is a data table: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Obecná chyba: {0} HY000=Obecná chyba: {0}
HY004=Neznámý datový typ: {0} HY004=Neznámý datový typ: {0}
HYC00=Vlastnost není podporována: {0} HYC00=Vlastnost není podporována: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=Serialisierer kann nicht geändert werden wenn eine Daten-Tabelle existiert: {0} 90141=Serialisierer kann nicht geändert werden wenn eine Daten-Tabelle existiert: {0}
90142=Schrittgrösse darf nicht 0 sein 90142=Schrittgrösse darf nicht 0 sein
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Allgemeiner Fehler: {0} HY000=Allgemeiner Fehler: {0}
HY004=Unbekannter Datentyp: {0} HY004=Unbekannter Datentyp: {0}
HYC00=Dieses Feature wird nicht unterstützt: {0} HYC00=Dieses Feature wird nicht unterstützt: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=#Serializer cannot be changed because there is a data table: {0} 90141=#Serializer cannot be changed because there is a data table: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Error General : {0} HY000=Error General : {0}
HY004=Tipo de dato desconocido : {0} HY004=Tipo de dato desconocido : {0}
HYC00=Caracteristica no soportada: {0} HYC00=Caracteristica no soportada: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=Le sérialiseur ne peut être changé parce que il y a des données dans la table: {0} 90141=Le sérialiseur ne peut être changé parce que il y a des données dans la table: {0}
90142=La taille de l'étape ne doit pas être de 0 90142=La taille de l'étape ne doit pas être de 0
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Erreur générale: {0} HY000=Erreur générale: {0}
HY004=Type de données inconnu: {0} HY004=Type de données inconnu: {0}
HYC00=Fonctionnalité non supportée: {0} HYC00=Fonctionnalité non supportée: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=データテーブル {0} があるため、シリアライザを変更することはできません 90141=データテーブル {0} があるため、シリアライザを変更することはできません
90142=ステップサイズに0は指定できません 90142=ステップサイズに0は指定できません
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=一般エラー: {0} HY000=一般エラー: {0}
HY004=不明なデータ型: {0} HY004=不明なデータ型: {0}
HYC00=機能はサポートされていません: {0} HYC00=機能はサポートされていません: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=Serializator nie może być zmieniony ponieważ istnieje tabela z danymi: {0} 90141=Serializator nie może być zmieniony ponieważ istnieje tabela z danymi: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Błąd ogólny: {0} HY000=Błąd ogólny: {0}
HY004=Nieznany typ danych: {0} HY004=Nieznany typ danych: {0}
HYC00=Cecha nie jest wspierana: {0} HYC00=Cecha nie jest wspierana: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=#Serializer cannot be changed because there is a data table: {0} 90141=#Serializer cannot be changed because there is a data table: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Erro geral: {0} HY000=Erro geral: {0}
HY004=Tipo de dados desconhecido: {0} HY004=Tipo de dados desconhecido: {0}
HYC00=Recurso não suportado: {0} HYC00=Recurso não suportado: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=Serializer не может быть изменен, потому что есть таблица данных: {0} 90141=Serializer не может быть изменен, потому что есть таблица данных: {0}
90142=Размер шага не должен быть равен нулю 90142=Размер шага не должен быть равен нулю
90143=Строка {1} не найдена в первичном индексе {0} 90143=Строка {1} не найдена в первичном индексе {0}
90144=Внешняя аутентификация не включена в базе данных {0}
HY000=Внутренняя ошибка: {0} HY000=Внутренняя ошибка: {0}
HY004=Неизвестный тип данных: {0} HY004=Неизвестный тип данных: {0}
HYC00=Данная функция не поддерживается: {0} HYC00=Данная функция не поддерживается: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=#Serializer cannot be changed because there is a data table: {0} 90141=#Serializer cannot be changed because there is a data table: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=Všeobecná chyba: {0} HY000=Všeobecná chyba: {0}
HY004=Neznámy dátový typ: {0} HY004=Neznámy dátový typ: {0}
HYC00=Vlastnosť nie je podporovaná: {0} HYC00=Vlastnosť nie je podporovaná: {0}
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
90141=#Serializer cannot be changed because there is a data table: {0} 90141=#Serializer cannot be changed because there is a data table: {0}
90142=#Step size must not be zero 90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0} 90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
HY000=常规错误: {0} HY000=常规错误: {0}
HY004=位置数据类型: {0} HY004=位置数据类型: {0}
HYC00=不支持的特性: {0} HYC00=不支持的特性: {0}
......
...@@ -10,6 +10,7 @@ package org.h2.security.auth; ...@@ -10,6 +10,7 @@ package org.h2.security.auth;
* *
*/ */
public class AuthConfigException extends RuntimeException { public class AuthConfigException extends RuntimeException {
private static final long serialVersionUID = 1L;
public AuthConfigException() { public AuthConfigException() {
super(); super();
......
...@@ -9,6 +9,7 @@ package org.h2.security.auth; ...@@ -9,6 +9,7 @@ package org.h2.security.auth;
* Exception thrown in case of errors during authentication * Exception thrown in case of errors during authentication
*/ */
public class AuthenticationException extends Exception { public class AuthenticationException extends Exception {
private static final long serialVersionUID = 1L;
public AuthenticationException() { public AuthenticationException() {
super(); super();
......
...@@ -27,8 +27,8 @@ public class AuthenticationInfo { ...@@ -27,8 +27,8 @@ public class AuthenticationInfo {
public AuthenticationInfo(ConnectionInfo connectionInfo) { public AuthenticationInfo(ConnectionInfo connectionInfo) {
this.connectionInfo = connectionInfo; this.connectionInfo = connectionInfo;
this.realm = connectionInfo.getProperty("AUTHREALM", null); this.realm = connectionInfo.getProperty("AUTHREALM", null);
if (this.realm!=null) { if (this.realm != null) {
this.realm=StringUtils.toUpperEnglish(this.realm); this.realm = StringUtils.toUpperEnglish(this.realm);
} }
this.password = connectionInfo.getProperty("AUTHZPWD", null); this.password = connectionInfo.getProperty("AUTHZPWD", null);
} }
...@@ -50,15 +50,16 @@ public class AuthenticationInfo { ...@@ -50,15 +50,16 @@ public class AuthenticationInfo {
} }
public String getFullyQualifiedName() { public String getFullyQualifiedName() {
if (realm==null) { if (realm == null) {
return connectionInfo.getUserName(); return connectionInfo.getUserName();
} else { } else {
return connectionInfo.getUserName()+"@"+realm; return connectionInfo.getUserName() + "@" + realm;
} }
} }
/** /**
* get nested identity * get nested identity
*
* @return * @return
*/ */
public Object getNestedIdentity() { public Object getNestedIdentity() {
...@@ -66,8 +67,11 @@ public class AuthenticationInfo { ...@@ -66,8 +67,11 @@ public class AuthenticationInfo {
} }
/** /**
* Method used by authenticators to hold informations about authenticated user * Method used by authenticators to hold informations about authenticated
* @param nestedIdentity = nested identity object * user
*
* @param nestedIdentity
* = nested identity object
*/ */
public void setNestedIdentity(Object nestedIdentity) { public void setNestedIdentity(Object nestedIdentity) {
this.nestedIdentity = nestedIdentity; this.nestedIdentity = nestedIdentity;
......
...@@ -9,25 +9,27 @@ import org.h2.engine.Database; ...@@ -9,25 +9,27 @@ import org.h2.engine.Database;
import org.h2.engine.User; import org.h2.engine.User;
/** /**
* Low level interface to implement full authentication process * Low level interface to implement full authentication process.
*/ */
public interface Authenticator { public interface Authenticator {
/** /**
* perform user authentication * Perform user authentication.
* *
* @param authenticationInfo * @param authenticationInfo
* @param database * @param database
* @return valid database user or null if user doesn't exists in the database * @return valid database user or null if user doesn't exists in the
* database
* @throws AuthenticationException * @throws AuthenticationException
*/ */
User authenticate(AuthenticationInfo authenticationInfo, Database database) throws AuthenticationException; User authenticate(AuthenticationInfo authenticationInfo, Database database) throws AuthenticationException;
/** /**
* Initialize the authenticator. This method is invoked by databases when the authenticator is set * Initialize the authenticator. This method is invoked by databases when
* when the authenticator is set. * the authenticator is set when the authenticator is set.
* @param database = target database *
* @param database
* target database
* @throws AuthConfigException * @throws AuthConfigException
*/ */
void init(Database database) throws AuthConfigException; void init(Database database) throws AuthConfigException;
......
...@@ -23,16 +23,16 @@ public class ConfigProperties { ...@@ -23,16 +23,16 @@ public class ConfigProperties {
properties = new HashMap<>(); properties = new HashMap<>();
} }
public ConfigProperties(PropertyConfig...configProperties) { public ConfigProperties(PropertyConfig... configProperties) {
this(configProperties==null?null:Arrays.asList(configProperties)); this(configProperties == null ? null : Arrays.asList(configProperties));
} }
public ConfigProperties(Collection<PropertyConfig> configProperties) { public ConfigProperties(Collection<PropertyConfig> configProperties) {
properties = new HashMap<>(); properties = new HashMap<>();
if (properties != null) { if (properties != null) {
for (PropertyConfig currentProperty : configProperties) { for (PropertyConfig currentProperty : configProperties) {
if (properties.put(currentProperty.getName(), currentProperty.getValue())!=null) { if (properties.put(currentProperty.getName(), currentProperty.getValue()) != null) {
throw new AuthConfigException("duplicate property "+currentProperty.getName()); throw new AuthConfigException("duplicate property " + currentProperty.getName());
} }
} }
} }
...@@ -49,7 +49,7 @@ public class ConfigProperties { ...@@ -49,7 +49,7 @@ public class ConfigProperties {
public String getStringValue(String name) { public String getStringValue(String name) {
String result = properties.get(name); String result = properties.get(name);
if (result == null) { if (result == null) {
throw new AuthConfigException("missing config property "+name); throw new AuthConfigException("missing config property " + name);
} }
return result; return result;
} }
...@@ -65,7 +65,7 @@ public class ConfigProperties { ...@@ -65,7 +65,7 @@ public class ConfigProperties {
public int getIntValue(String name) { public int getIntValue(String name) {
String result = properties.get(name); String result = properties.get(name);
if (result == null) { if (result == null) {
throw new AuthConfigException("missing config property "+name); throw new AuthConfigException("missing config property " + name);
} }
return Integer.parseInt(result); return Integer.parseInt(result);
} }
......
...@@ -33,8 +33,8 @@ import org.h2.util.StringUtils; ...@@ -33,8 +33,8 @@ import org.h2.util.StringUtils;
* Default authenticator implementation. * Default authenticator implementation.
* <p> * <p>
* When client connectionInfo contains property AUTHREALM={realName} credentials * When client connectionInfo contains property AUTHREALM={realName} credentials
* (typically user id and password) are validated by * (typically user id and password) are validated by by
* by {@link org.h2.api.CredentialsValidator} configured for that realm. * {@link org.h2.api.CredentialsValidator} configured for that realm.
* </p> * </p>
* <p> * <p>
* When client connectionInfo doesn't contains AUTHREALM property credentials * When client connectionInfo doesn't contains AUTHREALM property credentials
...@@ -44,8 +44,9 @@ import org.h2.util.StringUtils; ...@@ -44,8 +44,9 @@ import org.h2.util.StringUtils;
* Rights assignment can be managed through {@link org.h2.api.UserToRolesMapper} * Rights assignment can be managed through {@link org.h2.api.UserToRolesMapper}
* </p> * </p>
* <p> * <p>
* Default configuration has a realm H2 that validate credentials through JAAS api (appName=h2). * Default configuration has a realm H2 that validate credentials through JAAS
* To customize configuration set h2.authConfigFile system property to refer a valid h2auth.xml config file * api (appName=h2). To customize configuration set h2.authConfigFile system
* property to refer a valid h2auth.xml config file
* </p> * </p>
*/ */
public class DefaultAuthenticator implements Authenticator { public class DefaultAuthenticator implements Authenticator {
...@@ -69,8 +70,8 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -69,8 +70,8 @@ public class DefaultAuthenticator implements Authenticator {
private static DefaultAuthenticator instance; private static DefaultAuthenticator instance;
protected static final DefaultAuthenticator getInstance() { protected static final DefaultAuthenticator getInstance() {
if (instance==null) { if (instance == null) {
instance= new DefaultAuthenticator(); instance = new DefaultAuthenticator();
} }
return instance; return instance;
} }
...@@ -119,8 +120,8 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -119,8 +120,8 @@ public class DefaultAuthenticator implements Authenticator {
} }
/** /**
* When set create roles not found in the database. If not set roles not found * When set create roles not found in the database. If not set roles not
* in the database are silently skipped * found in the database are silently skipped
* *
* @return * @return
*/ */
...@@ -135,8 +136,10 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -135,8 +136,10 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Add an authentication realm. Realms are case insensitive * Add an authentication realm. Realms are case insensitive
* *
* @param name realm name * @param name
* @param credentialsValidator credentials validator for realm * realm name
* @param credentialsValidator
* credentials validator for realm
*/ */
public void addRealm(String name, CredentialsValidator credentialsValidator) { public void addRealm(String name, CredentialsValidator credentialsValidator) {
realms.put(StringUtils.toUpperEnglish(name), credentialsValidator); realms.put(StringUtils.toUpperEnglish(name), credentialsValidator);
...@@ -160,17 +163,20 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -160,17 +163,20 @@ public class DefaultAuthenticator implements Authenticator {
} }
/** /**
* Initializes the authenticator (it is called by AuthententicationManager) * Initializes the authenticator.
* *
* this method is skipped if skipDefaultInitialization is set * this method is skipped if skipDefaultInitialization is set Order of
* Order of initialization is * initialization is
* <ol> * <ol>
* <li>Check h2.authConfigFile system property.</li> * <li>Check h2.authConfigFile system property.</li>
* <li>Use the default configuration hard coded</li> * <li>Use the default configuration hard coded</li>
* </ol> * </ol>
* @param database where authenticator is initialized *
* @param database
* where authenticator is initialized
* @throws AuthConfigException * @throws AuthConfigException
*/ */
@Override
public void init(Database database) throws AuthConfigException { public void init(Database database) throws AuthConfigException {
if (skipDefaultInitialization) { if (skipDefaultInitialization) {
return; return;
...@@ -182,13 +188,14 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -182,13 +188,14 @@ public class DefaultAuthenticator implements Authenticator {
if (initialized) { if (initialized) {
return; return;
} }
Trace trace=database.getTrace(Trace.DATABASE); Trace trace = database.getTrace(Trace.DATABASE);
URL h2AuthenticatorConfigurationUrl = null; URL h2AuthenticatorConfigurationUrl = null;
try { try {
String configFile = SysProperties.AUTH_CONFIG_FILE; String configFile = SysProperties.AUTH_CONFIG_FILE;
if (configFile != null) { if (configFile != null) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("DefaultAuthenticator.config: configuration read from system property h2auth.configurationfile={0}", configFile); trace.debug("DefaultAuthenticator.config: configuration read from system property"
+ " h2auth.configurationfile={0}", configFile);
} }
h2AuthenticatorConfigurationUrl = new URL(configFile); h2AuthenticatorConfigurationUrl = new URL(configFile);
} }
...@@ -201,11 +208,12 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -201,11 +208,12 @@ public class DefaultAuthenticator implements Authenticator {
configureFromUrl(h2AuthenticatorConfigurationUrl); configureFromUrl(h2AuthenticatorConfigurationUrl);
} }
} catch (Exception e) { } catch (Exception e) {
trace.error(e, "DefaultAuthenticator.config: an error occurred during configuration from {0} ", h2AuthenticatorConfigurationUrl); trace.error(e, "DefaultAuthenticator.config: an error occurred during configuration from {0} ",
throw new AuthConfigException("Failed to configure authentication from " + h2AuthenticatorConfigurationUrl, h2AuthenticatorConfigurationUrl);
e); throw new AuthConfigException(
"Failed to configure authentication from " + h2AuthenticatorConfigurationUrl, e);
} }
initialized=true; initialized = true;
} }
} }
...@@ -224,7 +232,8 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -224,7 +232,8 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Configure the authenticator from a configuration file * Configure the authenticator from a configuration file
* *
* @param configUrl URL of configuration file * @param configUrl
* URL of configuration file
* @throws Exception * @throws Exception
*/ */
public void configureFromUrl(URL configUrl) throws Exception { public void configureFromUrl(URL configUrl) throws Exception {
......
...@@ -25,9 +25,10 @@ public class PropertyConfig { ...@@ -25,9 +25,10 @@ public class PropertyConfig {
} }
public PropertyConfig(String name, String value) { public PropertyConfig(String name, String value) {
this.name=name; this.name = name;
this.value=value; this.value = value;
} }
public String getName() { public String getName() {
return name; return name;
} }
......
...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType; ...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
/**
* Configuration for authentication realm.
*/
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class RealmConfig { public class RealmConfig {
......
...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType; ...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
/**
* Configuration for class that maps users to roles.
*/
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class UserToRolesMapperConfig { public class UserToRolesMapperConfig {
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura
*/
package org.h2.security.auth.impl; package org.h2.security.auth.impl;
import java.util.Arrays; import java.util.Arrays;
......
...@@ -75,7 +75,8 @@ public class JaasCredentialsValidator implements CredentialsValidator { ...@@ -75,7 +75,8 @@ public class JaasCredentialsValidator implements CredentialsValidator {
@Override @Override
public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception { public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception {
LoginContext loginContext = new LoginContext(appName,new AuthenticationInfoCallbackHandler(authenticationInfo)); LoginContext loginContext = new LoginContext(appName,
new AuthenticationInfoCallbackHandler(authenticationInfo));
loginContext.login(); loginContext.login();
authenticationInfo.setNestedIdentity(loginContext.getSubject()); authenticationInfo.setNestedIdentity(loginContext.getSubject());
return true; return true;
......
...@@ -21,9 +21,10 @@ import org.h2.security.auth.ConfigProperties; ...@@ -21,9 +21,10 @@ import org.h2.security.auth.ConfigProperties;
* Configuration parameters: * Configuration parameters:
* </p> * </p>
* <ul> * <ul>
* <li>bindDnPattern bind dn pattern with %u instead of username (example: uid=%u,ou=users,dc=example,dc=com)</li> * <li>bindDnPattern bind dn pattern with %u instead of username
* (example: uid=%u,ou=users,dc=example,dc=com)</li>
* <li>host ldap server</li> * <li>host ldap server</li>
* <li>port of ldap service; optional, by default 389 for unsecure, 636 for secure</li> * <li>port of ldap service; optional, by default 389 for insecure, 636 for secure</li>
* <li>secure, optional by default is true (use SSL)</li> * <li>secure, optional by default is true (use SSL)</li>
* </ul> * </ul>
*/ */
......
/* /*
* Copyright 2004-2018 H2 Group. Mul tiple-Licensed under the MPL 2.0, * Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html). * and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura * Initial Developer: Alessandro Ventura
*/ */
...@@ -41,7 +41,6 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -41,7 +41,6 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
@Override @Override
public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException { public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException {
if (userNamePattern!=null) { if (userNamePattern!=null) {
if (!userNamePattern.matcher(authenticationInfo.getUserName()).matches()) { if (!userNamePattern.matcher(authenticationInfo.getUserName()).matches()) {
return false; return false;
...@@ -50,14 +49,15 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -50,14 +49,15 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
if (password!=null) { if (password!=null) {
return password.equals(authenticationInfo.getPassword()); return password.equals(authenticationInfo.getPassword());
} }
return Utils.compareSecure(hashWithSalt,SHA256.getHashWithSalt(authenticationInfo.getPassword().getBytes(), salt)); return Utils.compareSecure(hashWithSalt,
SHA256.getHashWithSalt(authenticationInfo.getPassword().getBytes(), salt));
} }
@Override @Override
public void configure(ConfigProperties configProperties) { public void configure(ConfigProperties configProperties) {
String userNamePatternString=configProperties.getStringValue("userNamePattern",null); String userNamePatternString=configProperties.getStringValue("userNamePattern",null);
if (userNamePatternString!=null) { if (userNamePatternString!=null) {
userNamePattern=userNamePattern.compile(userNamePatternString); userNamePattern = Pattern.compile(userNamePatternString);
} }
password=configProperties.getStringValue("password",password); password=configProperties.getStringValue("password",password);
String saltString =configProperties.getStringValue("salt",null); String saltString =configProperties.getStringValue("salt",null);
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0, Version 1.0,
and under the Eclipse Public License, Version 1.0
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
Authentication classes.
</p></body></html>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0, Version 1.0,
and under the Eclipse Public License, Version 1.0
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
Authentication classes.
</p></body></html>
\ No newline at end of file
...@@ -1072,8 +1072,8 @@ public class MetaTable extends Table { ...@@ -1072,8 +1072,8 @@ public class MetaTable extends Table {
Long.toString(fs.getWriteCount())); Long.toString(fs.getWriteCount()));
add(rows, "info.FILE_READ", add(rows, "info.FILE_READ",
Long.toString(fs.getReadCount())); Long.toString(fs.getReadCount()));
int updateFailureRatio = (int)(10000 * mvStore.getStore().getUpdateFailureRatio()); add(rows, "info.UPDATE_FAILURE_PERCENT",
add(rows, "info.UPDATE_FAILURE_PERCENT", "" + updateFailureRatio / 100 + "." + updateFailureRatio % 100 + "%"); String.format(Locale.ENGLISH, "%.2f%%", 100 * mvStore.getStore().getUpdateFailureRatio()));
long size; long size;
try { try {
size = fs.getFile().size(); size = fs.getFile().size();
......
...@@ -510,7 +510,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -510,7 +510,8 @@ public abstract class Table extends SchemaObjectBase {
try { try {
removeRow(session, o); removeRow(session, o);
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.CONCURRENT_UPDATE_1 || e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) { if (e.getErrorCode() == ErrorCode.CONCURRENT_UPDATE_1
|| e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) {
session.rollbackTo(rollback, false); session.rollbackTo(rollback, false);
session.startStatementWithinTransaction(); session.startStatementWithinTransaction();
rollback = session.setSavepoint(); rollback = session.setSavepoint();
......
...@@ -31,6 +31,9 @@ import org.h2.security.auth.impl.StaticRolesMapper; ...@@ -31,6 +31,9 @@ import org.h2.security.auth.impl.StaticRolesMapper;
import org.h2.security.auth.impl.StaticUserCredentialsValidator; import org.h2.security.auth.impl.StaticUserCredentialsValidator;
import org.h2.test.TestBase; import org.h2.test.TestBase;
/**
* Test for custom authentication.
*/
public class TestAuthentication extends TestBase { public class TestAuthentication extends TestBase {
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
...@@ -123,7 +126,7 @@ public class TestAuthentication extends TestBase { ...@@ -123,7 +126,7 @@ public class TestAuthentication extends TestBase {
protected void allTests() throws Exception { protected void allTests() throws Exception {
testInvalidPassword(); testInvalidPassword();
testExternalUserWihoutRealm(); testExternalUserWithoutRealm();
testExternalUser(); testExternalUser();
testAssignRealNameRole(); testAssignRealNameRole();
testStaticRole(); testStaticRole();
...@@ -143,7 +146,7 @@ public class TestAuthentication extends TestBase { ...@@ -143,7 +146,7 @@ public class TestAuthentication extends TestBase {
} }
} }
protected void testExternalUserWihoutRealm() throws Exception { protected void testExternalUserWithoutRealm() throws Exception {
try { try {
Connection wrongLoginConnection = DriverManager.getConnection(getDatabaseURL(), getExternalUser(), Connection wrongLoginConnection = DriverManager.getConnection(getDatabaseURL(), getExternalUser(),
getExternalUserPassword()); getExternalUserPassword());
...@@ -221,7 +224,8 @@ public class TestAuthentication extends TestBase { ...@@ -221,7 +224,8 @@ public class TestAuthentication extends TestBase {
try { try {
try { try {
Connection wrongLoginConnection = DriverManager.getConnection( Connection wrongLoginConnection = DriverManager.getConnection(
getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), "___" + getExternalUser(), ""); getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), "___" + getExternalUser(),
"");
wrongLoginConnection.close(); wrongLoginConnection.close();
throw new Exception( throw new Exception(
"unregistered external users should not be able to login when allowUserRegistration=false"); "unregistered external users should not be able to login when allowUserRegistration=false");
...@@ -261,8 +265,8 @@ public class TestAuthentication extends TestBase { ...@@ -261,8 +265,8 @@ public class TestAuthentication extends TestBase {
try { try {
try { try {
testExternalUser(); testExternalUser();
throw new Exception("External user shouldnt be allowed"); throw new Exception("External user shouldn't be allowed");
}catch (Exception e) { } catch (Exception e) {
} }
} finally { } finally {
configureAuthentication(database); configureAuthentication(database);
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0, Version 1.0,
and under the Eclipse Public License, Version 1.0
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
Tests for custom authentication.
</p></body></html>
\ No newline at end of file
...@@ -17,6 +17,7 @@ import java.util.ArrayList; ...@@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import org.h2.message.TraceSystem;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -297,6 +298,11 @@ public class TestBigResult extends TestBase { ...@@ -297,6 +298,11 @@ public class TestBigResult extends TestBase {
} }
private void testLOB() throws SQLException { private void testLOB() throws SQLException {
if (config.traceLevelFile == TraceSystem.DEBUG) {
// Trace system on this level can throw OOME with such large
// arguments as used in this test.
return;
}
deleteDb("bigResult"); deleteDb("bigResult");
Connection conn = getConnection("bigResult"); Connection conn = getConnection("bigResult");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -66,7 +66,6 @@ public class TestMvcc4 extends TestBase { ...@@ -66,7 +66,6 @@ public class TestMvcc4 extends TestBase {
c1.setAutoCommit(false); c1.setAutoCommit(false);
//Fire off a concurrent update. //Fire off a concurrent update.
final Thread mainThread = Thread.currentThread();
final CountDownLatch executedUpdate = new CountDownLatch(1); final CountDownLatch executedUpdate = new CountDownLatch(1);
new Thread() { new Thread() {
@Override @Override
...@@ -83,7 +82,8 @@ public class TestMvcc4 extends TestBase { ...@@ -83,7 +82,8 @@ public class TestMvcc4 extends TestBase {
executedUpdate.countDown(); executedUpdate.countDown();
// interrogate new "blocker_id" metatable field instead of // interrogate new "blocker_id" metatable field instead of
// relying on stacktraces!? to determine when session is blocking // relying on stacktraces!? to determine when session is blocking
PreparedStatement stmt = c2.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.SESSIONS WHERE BLOCKER_ID = SESSION_ID()"); PreparedStatement stmt = c2.prepareStatement(
"SELECT * FROM INFORMATION_SCHEMA.SESSIONS WHERE BLOCKER_ID = SESSION_ID()");
ResultSet resultSet; ResultSet resultSet;
do { do {
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
......
...@@ -39,7 +39,7 @@ public class TestMvccMultiThreaded2 extends TestBase { ...@@ -39,7 +39,7 @@ public class TestMvccMultiThreaded2 extends TestBase {
test.test(); test.test();
} }
private int getTestDuration() { int getTestDuration() {
// to save some testing time // to save some testing time
return config.big ? TEST_TIME_SECONDS : TEST_TIME_SECONDS / 10; return config.big ? TEST_TIME_SECONDS : TEST_TIME_SECONDS / 10;
} }
......
...@@ -299,7 +299,8 @@ public class TestScript extends TestBase { ...@@ -299,7 +299,8 @@ public class TestScript extends TestBase {
private void process(String sql, boolean allowReconnect) throws Exception { private void process(String sql, boolean allowReconnect) throws Exception {
if (allowReconnect && reconnectOften) { if (allowReconnect && reconnectOften) {
if (!containsTempTables() && ((JdbcConnection) conn).isRegularMode() && conn.getSchema().equals("PUBLIC")) { if (!containsTempTables() && ((JdbcConnection) conn).isRegularMode()
&& conn.getSchema().equals("PUBLIC")) {
boolean autocommit = conn.getAutoCommit(); boolean autocommit = conn.getAutoCommit();
if (autocommit && random.nextInt(10) < 1) { if (autocommit && random.nextInt(10) < 1) {
// reconnect 10% of the time // reconnect 10% of the time
......
...@@ -404,7 +404,7 @@ public class TestTransactionStore extends TestBase { ...@@ -404,7 +404,7 @@ public class TestTransactionStore extends TestBase {
} }
} }
// re-open TransactionStore, because we rolled back // re-open TransactionStore, because we rolled back
// underlying MVStore without rolling back TranactionStore // underlying MVStore without rolling back TransactionStore
s.close(); s.close();
s = MVStore.open(fileName); s = MVStore.open(fileName);
ts = new TransactionStore(s); ts = new TransactionStore(s);
......
...@@ -86,7 +86,6 @@ public class TestCrashAPI extends TestBase implements Runnable { ...@@ -86,7 +86,6 @@ public class TestCrashAPI extends TestBase implements Runnable {
} }
@Override @Override
@SuppressWarnings("deprecation")
public void run() { public void run() {
while (--maxWait > 0) { while (--maxWait > 0) {
try { try {
...@@ -103,11 +102,11 @@ public class TestCrashAPI extends TestBase implements Runnable { ...@@ -103,11 +102,11 @@ public class TestCrashAPI extends TestBase implements Runnable {
if (maxWait == 0 && running) { if (maxWait == 0 && running) {
objects.clear(); objects.clear();
if (running) { if (running) {
println("stopping (force)..."); println("stopping (trying to interrupt)...");
for (StackTraceElement e : mainThread.getStackTrace()) { for (StackTraceElement e : mainThread.getStackTrace()) {
System.out.println(e.toString()); System.out.println(e.toString());
} }
mainThread.stop(new SQLException("stop")); mainThread.interrupt();
} }
} }
} }
......
...@@ -777,4 +777,9 @@ geometries sourceschema destschema generatedcolumn alphanumerically usages ...@@ -777,4 +777,9 @@ geometries sourceschema destschema generatedcolumn alphanumerically usages
sizable instantiates renders sdt txcommit unhelpful optimiser treats rejects referring untrusted computes vacate inverted sizable instantiates renders sdt txcommit unhelpful optimiser treats rejects referring untrusted computes vacate inverted
reordered colliding evgenij archaic invocations apostrophe hypothetically testref ryazanov useless completes highlighting tends degrade reordered colliding evgenij archaic invocations apostrophe hypothetically testref ryazanov useless completes highlighting tends degrade
summands minuend subtrahend summands minuend subtrahend localtime localtimestamp governs unfinished pressure closure discovered victim seemingly
flaw capture coherent removals silence opentransactions picture tokar mailto andrei dur discarded blocker captures txdm
intentionally authenticator authrealm ventura credentials alessandro validator acquisition vital mariadb preventing
ewkt ewkb informations authzpwd realms mappers jaxb realmname configurationfile unmarshal jaas externals customize
authenticators appname interrogate metatable barrier preliminary staticuser staticpassword unregistered inquiry
ldapexample remoteuser assignments djava validators mock relate mapid tighten
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论