diff --git a/.gitignore b/.gitignore index 56cca2347ce..2dda9bee184 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,5 @@ integration-tests/mdi/files/excelwriter-mdi-test.xlsx integration-tests/spreadsheet/files/sample-file-append.xlsx assemblies/debug/audit + +local-snapshots-dir/ diff --git a/assemblies/static/src/main/resources/hop-gui.sh b/assemblies/static/src/main/resources/hop-gui.sh index ff120be589e..df7c04c05cb 100755 --- a/assemblies/static/src/main/resources/hop-gui.sh +++ b/assemblies/static/src/main/resources/hop-gui.sh @@ -22,6 +22,9 @@ ORIGINDIR=$(pwd) BASEDIR=$(dirname "$0") cd "${BASEDIR}" || exit 1 +# Compliance Engine customization to add MASKING HOME lib dir to classpath +ADDITIONAL_CLASSPATH=":lib" + # set java primary is HOP_JAVA_HOME fallback to JAVA_HOME or default java if [ -n "${HOP_JAVA_HOME}" ]; then _HOP_JAVA="${HOP_JAVA_HOME}/bin/java" @@ -109,7 +112,7 @@ Darwin) esac CLASSPATH="lib/core/*:lib/beam/*:lib/swt/$os_path/$arch_path/*" -"${_HOP_JAVA}" ${HOP_OPTIONS} -Djava.library.path="${LIBPATH}" -classpath "${CLASSPATH}" org.apache.hop.ui.hopgui.HopGui "$@" +"${_HOP_JAVA}" ${HOP_OPTIONS} -Djava.library.path="${LIBPATH}" -classpath "${CLASSPATH}${ADDITIONAL_CLASSPATH}" org.apache.hop.ui.hopgui.HopGui "$@" EXITCODE=$? cd "${ORIGINDIR}" || exit 1 diff --git a/assemblies/static/src/main/resources/hop-run.sh b/assemblies/static/src/main/resources/hop-run.sh index 69b3172a014..443caa98f12 100755 --- a/assemblies/static/src/main/resources/hop-run.sh +++ b/assemblies/static/src/main/resources/hop-run.sh @@ -22,6 +22,9 @@ ORIGINDIR=$(pwd) BASEDIR=$(dirname "$0") cd "${BASEDIR}" || exit 1 +# Compliance Engine customization to add MASKING HOME lib dir to classpath +ADDITIONAL_CLASSPATH=":lib:$MASKING_DATA/resources/jarfiles/db2jcc_license_cisuz.jar" + # set java primary is HOP_JAVA_HOME fallback to JAVA_HOME or default java if [ -n "${HOP_JAVA_HOME}" ]; then _HOP_JAVA="${HOP_JAVA_HOME}/bin/java" @@ -91,7 +94,7 @@ Darwin) ;; esac -"${_HOP_JAVA}" ${HOP_OPTIONS} -Djava.library.path="${LIBPATH}" -classpath "${CLASSPATH}" org.apache.hop.run.HopRun "$@" +"${_HOP_JAVA}" ${HOP_OPTIONS} -Djava.library.path="${LIBPATH}" -classpath "${CLASSPATH}${ADDITIONAL_CLASSPATH}" org.apache.hop.run.HopRun "$@" EXITCODE=$? cd "${ORIGINDIR}" || exit 1 diff --git a/core/src/main/java/org/apache/hop/core/database/Database.java b/core/src/main/java/org/apache/hop/core/database/Database.java index 79cde7173ad..8674b25611f 100644 --- a/core/src/main/java/org/apache/hop/core/database/Database.java +++ b/core/src/main/java/org/apache/hop/core/database/Database.java @@ -119,6 +119,8 @@ public class Database implements IVariables, ILoggingObject, AutoCloseable { private int rowlimit; private int commitsize; + private boolean delphixSpecial = false; + private int fetchSize = 0; private Connection connection; @@ -655,6 +657,23 @@ public void cancelStatement(Statement statement) throws HopDatabaseException { * @param commsize The number of rows to wait before doing a commit on the connection. */ public void setCommit(int commsize) { + /* + * We override this method to set fetch size in the case where it was called + * previously with a "magic" value. It would be much cleaner to just add a + * setFetchSize() method, but the way we build dms-core-gate, changes here + * aren't visible to link against when building our code. + */ + if (commsize == Integer.MIN_VALUE + 42) { + delphixSpecial = true; + return; + } + if (delphixSpecial) { + fetchSize = commsize; + delphixSpecial = false; + return; + } + // End Delphix extra-special case. + commitsize = commsize; String onOff = (commitsize <= 0 ? "on" : "off"); try { @@ -1119,7 +1138,8 @@ && getDatabaseMetaData().supportsBatchUpdates() && databaseMeta.supportsBatchUpdates() && Utils.isEmpty(connectionGroup); } catch (SQLException e) { - throw createHopDatabaseBatchException("Error determining whether to use batch", e); + throw createHopDatabaseBatchException( + "Error determining whether to use batch", e, this.log.getLogLevel()); } } @@ -1186,10 +1206,11 @@ public boolean insertRow(PreparedStatement ps, boolean batch, boolean handleComm return rowsAreSafe; } catch (BatchUpdateException ex) { - throw createHopDatabaseBatchException(CONST_ERROR_UPDATING_BATCH, ex); + throw createHopDatabaseBatchException(CONST_ERROR_UPDATING_BATCH, ex, this.log.getLogLevel()); } catch (SQLException ex) { if (isBatchUpdate) { - throw createHopDatabaseBatchException(CONST_ERROR_UPDATING_BATCH, ex); + throw createHopDatabaseBatchException( + CONST_ERROR_UPDATING_BATCH, ex, this.log.getLogLevel()); } else { throw new HopDatabaseException("Error inserting/updating row", ex); } @@ -1299,7 +1320,12 @@ public void emptyAndCommit( public static HopDatabaseBatchException createHopDatabaseBatchException( String message, SQLException ex) { - HopDatabaseBatchException kdbe = new HopDatabaseBatchException(message, ex); + return createHopDatabaseBatchException(message, ex, DefaultLogLevel.getLogLevel()); + } + + public static HopDatabaseBatchException createHopDatabaseBatchException( + String message, SQLException ex, LogLevel logLevel1) { + HopDatabaseBatchException kdbe = new HopDatabaseBatchException(message, ex, logLevel1); if (ex instanceof BatchUpdateException batchUpdateException) { kdbe.setUpdateCounts(batchUpdateException.getUpdateCounts()); } else { @@ -1546,13 +1572,13 @@ public ResultSet openQuery( if (canWeSetFetchSize(pstmt)) { int maxRows = pstmt.getMaxRows(); - int fs = Const.FETCH_SIZE <= maxRows ? maxRows : Const.FETCH_SIZE; + int fs = Math.max(maxRows, fetchSize > 0 ? fetchSize : Const.FETCH_SIZE); if (databaseMeta.isMySqlVariant()) { setMysqlFetchSize(pstmt, fs, maxRows); } else { pstmt.setFetchSize(fs); } - + log.logBasic("Statement fetch size set to " + fs); pstmt.setFetchDirection(fetchMode); } @@ -1568,13 +1594,14 @@ public ResultSet openQuery( selStmt = connection.createStatement(); log.snap(Metrics.METRIC_DATABASE_CREATE_SQL_STOP, databaseMeta.getName()); if (canWeSetFetchSize(selStmt)) { - int fs = - Const.FETCH_SIZE <= selStmt.getMaxRows() ? selStmt.getMaxRows() : Const.FETCH_SIZE; + int fs = Math.max(selStmt.getMaxRows(), fetchSize > 0 ? fetchSize : Const.FETCH_SIZE); if (databaseMeta.getIDatabase().isMySqlVariant() && databaseMeta.isStreamingResults()) { selStmt.setFetchSize(Integer.MIN_VALUE); } else { selStmt.setFetchSize(fs); } + log.logBasic("Statement fetch size set to " + fs); + selStmt.setFetchDirection(fetchMode); } if (rowlimit > 0 && databaseMeta.supportsSetMaxRows()) { @@ -1604,10 +1631,16 @@ public ResultSet openQuery( } private boolean canWeSetFetchSize(Statement statement) throws SQLException { - return databaseMeta.isFetchSizeSupported() - && (statement.getMaxRows() > 0 - || databaseMeta.getIDatabase().isPostgresVariant() - || (databaseMeta.isMySqlVariant() && databaseMeta.isStreamingResults())); + if (!databaseMeta.isFetchSizeSupported()) { + return false; + } + // Override for delphix + if (fetchSize > 0) { + return true; + } + return statement.getMaxRows() > 0 + || databaseMeta.getIDatabase().isPostgresVariant() + || (databaseMeta.isMySqlVariant() && databaseMeta.isStreamingResults()); } public ResultSet openQuery(PreparedStatement ps, IRowMeta params, Object[] data) @@ -1622,9 +1655,13 @@ public ResultSet openQuery(PreparedStatement ps, IRowMeta params, Object[] data) setValues(params, data, ps); // set the parameters! log.snap(Metrics.METRIC_DATABASE_SQL_VALUES_STOP, databaseMeta.getName()); + if (rowlimit > 0 && databaseMeta.supportsSetMaxRows()) { + ps.setMaxRows(rowlimit); + } + if (canWeSetFetchSize(ps)) { int maxRows = ps.getMaxRows(); - int fs = Const.FETCH_SIZE <= maxRows ? maxRows : Const.FETCH_SIZE; + int fs = Math.max(maxRows, fetchSize > 0 ? fetchSize : Const.FETCH_SIZE); // mysql have some restriction on fetch size assignment if (databaseMeta.isMySqlVariant()) { setMysqlFetchSize(ps, fs, maxRows); @@ -1632,14 +1669,11 @@ public ResultSet openQuery(PreparedStatement ps, IRowMeta params, Object[] data) // other databases seems not. ps.setFetchSize(fs); } + log.logBasic("Statement fetch size set to " + fs); ps.setFetchDirection(ResultSet.FETCH_FORWARD); } - if (rowlimit > 0 && databaseMeta.supportsSetMaxRows()) { - ps.setMaxRows(rowlimit); - } - log.snap(Metrics.METRIC_DATABASE_EXECUTE_SQL_START, databaseMeta.getName()); res = ps.executeQuery(); log.snap(Metrics.METRIC_DATABASE_EXECUTE_SQL_STOP, databaseMeta.getName()); diff --git a/core/src/main/java/org/apache/hop/core/exception/HopDatabaseBatchException.java b/core/src/main/java/org/apache/hop/core/exception/HopDatabaseBatchException.java index bff51ddfe78..200e2c224ef 100644 --- a/core/src/main/java/org/apache/hop/core/exception/HopDatabaseBatchException.java +++ b/core/src/main/java/org/apache/hop/core/exception/HopDatabaseBatchException.java @@ -18,7 +18,11 @@ package org.apache.hop.core.exception; import java.io.Serial; +import java.sql.SQLException; import java.util.List; +import org.apache.hop.core.Const; +import org.apache.hop.core.logging.DefaultLogLevel; +import org.apache.hop.core.logging.LogLevel; /** This exception is used by the Database class. */ public class HopDatabaseBatchException extends HopDatabaseException { @@ -28,6 +32,8 @@ public class HopDatabaseBatchException extends HopDatabaseException { private List exceptionsList; + private LogLevel logLevel = DefaultLogLevel.getLogLevel(); + /** Constructs a new throwable with null as its detail message. */ public HopDatabaseBatchException() { super(); @@ -66,6 +72,19 @@ public HopDatabaseBatchException(String message, Throwable cause) { super(message, cause); } + /** + * Constructs a new throwable with the specified detail message and cause. + * + * @param message the detail message (which is saved for later retrieval by the getMessage() + * method). + * @param cause the cause (which is saved for later retrieval by the getCause() method). (A null + * value is permitted, and indicates that the cause is nonexistent or unknown.) + */ + public HopDatabaseBatchException(String message, Throwable cause, LogLevel logLevel) { + super(message, cause); + this.logLevel = logLevel; + } + /** * @return Returns the updateCounts. */ @@ -87,4 +106,45 @@ public void setExceptionsList(List exceptionsList) { public List getExceptionsList() { return exceptionsList; } + + /* + * This method exists to fix DLPX-56268 (Masking does not see Hop getNextException to surface the cause of a SQLException). + * + * The HopException class overrides this method of Exception class to get the root cause. This + * class is a subclass of HopException class. It has an additional member field to store list + * of exceptions. The static method createHopDatabaseBatchException in Database class is used + * to create an instance of this class. In that method all the exceptions associated with SQLException + * are retrieved using the getNextException and stored in this list. + * + * While logging the error message, the getMessage method is used. Since it is a subclass of HopException class, it + * uses the method defined there. That definition ignores this list of exceptions. Thus these messages are supressed. + * + * We fix this by overriding the getMessage method here and log all the exceptions present in the exceptionList variable. + * It also calls the HopException's getMessage method so that the previous behavior is maintained while adding + * additional log messages. + */ + @Override + public String getMessage() { + String retval = Const.CR; + retval += super.getMessage() + Const.CR; + + for (Exception exc : exceptionsList) { + if (exc instanceof SQLException) { + SQLException sqlException = (SQLException) exc; + retval += + "Next Exception: SQLState( " + + sqlException.getSQLState() + + ") ErrorCode(" + + sqlException.getErrorCode() + + ")"; + if (this.logLevel.isDetailed()) { + retval += " Message: " + sqlException.getMessage(); + } + retval += Const.CR; + } else { + retval += "Next Exception: " + exc.getClass() + Const.CR; + } + } + return retval; + } } diff --git a/core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java b/core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java index e609666665f..83b18073cdc 100644 --- a/core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java +++ b/core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java @@ -250,6 +250,9 @@ public class ValueMetaBase implements IValueMeta { @JsonIgnore protected int originalNullable; @JsonIgnore protected boolean originalSigned; + // Added for DLPX-46230 / DLPX-82789 to prevent using setBlob on non-blob columns in Oracle + protected boolean isLargeObject = false; + protected boolean ignoreWhitespace; protected final Comparator comparator; @@ -4528,11 +4531,7 @@ public Object convertDataFromString( boolean isStringValue = outValueType == IValueMeta.TYPE_STRING; Object emptyValue = isStringValue ? Const.NULL_STRING : null; - boolean isEmptyAndNullDiffer = - convertStringToBoolean( - Const.NVL(System.getProperty(Const.HOP_EMPTY_STRING_DIFFERS_FROM_NULL, "N"), "N")); - - if (pol == null && isStringValue && isEmptyAndNullDiffer) { + if (pol == null && isStringValue && emptyStringAndNullAreDifferent) { pol = Const.NULL_STRING; } @@ -5141,6 +5140,7 @@ public IValueMeta getValueFromSqlType( int precision = -1; int valtype = IValueMeta.TYPE_NONE; boolean isClob = false; + isLargeObject = false; int type = rm.getColumnType(index); boolean signed = false; @@ -5556,6 +5556,32 @@ public IValueMeta getMetadataPreview( } } + /* + * This logic exists to fix DLPX-51415 (Sybase - Numeric Conversion Error). + * + * The logic above will typically force DECIMAL/NUMERIC types with a scale ('precision' in Kettle terms) > 0 + * to be cast to Java Doubles. A Double is a binary type, so it can not exactly represent arbitrary decimal + * values. + * + * This is particularly problematic for Sybase, because Sybase has some inconsistencies related to how it + * deals with inserts/updates of values with greater precision than can be held by type of the column, for + * instance inserting a value 1.2345 into a column with a type DECIMAL(4,2). For certain combinations of + * jTDS/jConnect and batched/non-batched mode, Sybase will throw an error of the form + * + * Scale error during implicit conversion of NUMERIC value '1.2345' to a DECIMAL field. + * + * This causes a problem when the inexact floating point values read from Sybase columns are inserted back + * into Sybase NUMERIC/DECIMAL columns. We fix this by reading NUMERIC/DECIMAL values into a Java decimal + * type which can store the exact value correctly. We will likely want this behavior for all platforms + * eventually, but for now we restrict this behavior to Sybase, in order to minimize the change, and + * thereby the risk associated with the patch. + */ + if (databaseMeta.getIDatabase().isSybaseVariant() + && (type == Types.NUMERIC || type == Types.DECIMAL) + && precision > 0) { + valtype = IValueMeta.TYPE_BIGNUMBER; + } + break; case Types.TIMESTAMP: @@ -5588,7 +5614,12 @@ public IValueMeta getMetadataPreview( valtype = IValueMeta.TYPE_BOOLEAN; break; - case Types.BINARY, Types.BLOB, Types.VARBINARY, Types.LONGVARBINARY: + case Types.BINARY: + case Types.BLOB: + isLargeObject = true; + // fallthrough + case Types.VARBINARY: + case Types.LONGVARBINARY: valtype = IValueMeta.TYPE_BINARY; IDatabase db = databaseMeta.getIDatabase(); @@ -5601,9 +5632,10 @@ public IValueMeta getMetadataPreview( } else if ((databaseMeta.getIDatabase().isOracleVariant()) && (originalColumnType == Types.VARBINARY || originalColumnType == Types.LONGVARBINARY)) { - // set the length for Oracle "RAW" or "LONGRAW" data types - valtype = IValueMeta.TYPE_STRING; - length = originalColumnDisplaySize; + // set the length for Oracle "RAW" or "LONGRAW" data + // For DLPX-82789, these type are fundamentally binary and should be treated as such + // valtype = IValueMeta.TYPE_STRING; + // length = originalColumnDisplaySize; } else if (databaseMeta.isMySqlVariant() && (originalColumnType == Types.VARBINARY || originalColumnType == Types.LONGVARBINARY)) { @@ -5680,7 +5712,7 @@ public Object getValueFromResultSet(IDatabase iDatabase, ResultSet resultSet, in } break; case IValueMeta.TYPE_BINARY: - if (iDatabase.isSupportsGetBlob()) { + if (isLargeObject && iDatabase.isSupportsGetBlob()) { Blob blob = resultSet.getBlob(index + 1); if (blob != null) { data = blob.getBytes(1L, (int) blob.length()); @@ -5748,19 +5780,23 @@ public void setPreparedStatementValue( } break; case IValueMeta.TYPE_INTEGER: - if (!isNull(data)) { - if (databaseMeta.supportsSetLong()) { + if (databaseMeta.supportsSetLong()) { + if (!isNull(data)) { preparedStatement.setLong(index, getInteger(data)); } else { + preparedStatement.setNull(index, Types.BIGINT); + } + } else { + if (!isNull(data)) { double d = getNumber(data); if (databaseMeta.supportsFloatRoundingOnUpdate() && getPrecision() >= 0) { preparedStatement.setDouble(index, d); } else { preparedStatement.setDouble(index, Const.round(d, getPrecision())); } + } else { + preparedStatement.setNull(index, Types.DOUBLE); } - } else { - preparedStatement.setNull(index, Types.INTEGER); } break; case IValueMeta.TYPE_STRING: diff --git a/core/src/test/java/org/apache/hop/core/row/value/ValueMetaBaseTest.java b/core/src/test/java/org/apache/hop/core/row/value/ValueMetaBaseTest.java index f535e33fecb..c19958f5eb2 100644 --- a/core/src/test/java/org/apache/hop/core/row/value/ValueMetaBaseTest.java +++ b/core/src/test/java/org/apache/hop/core/row/value/ValueMetaBaseTest.java @@ -348,9 +348,8 @@ public void testConvertDataFromStringToString() throws HopValueException { outValueMetaString.convertDataFromString( inputValueNullString, inValueMetaString, nullIf, ifNull, trimType); assertEquals( - "HOP_EMPTY_STRING_DIFFERS_FROM_NULL = Y: " - + "Conversion from null string must return empty string", - StringUtils.EMPTY, + "HOP_EMPTY_STRING_DIFFERS_FROM_NULL = Y: " + "Conversion from null string must return null", + null, result); } diff --git a/engine/src/main/java/org/apache/hop/pipeline/transform/BaseTransform.java b/engine/src/main/java/org/apache/hop/pipeline/transform/BaseTransform.java index 6af1dd69d9e..c45d7a54250 100644 --- a/engine/src/main/java/org/apache/hop/pipeline/transform/BaseTransform.java +++ b/engine/src/main/java/org/apache/hop/pipeline/transform/BaseTransform.java @@ -55,7 +55,6 @@ import org.apache.hop.core.row.IValueMeta; import org.apache.hop.core.row.RowDataUtil; import org.apache.hop.core.row.value.ValueMetaBase; -import org.apache.hop.core.util.EnvUtil; import org.apache.hop.core.util.Utils; import org.apache.hop.core.variables.IVariables; import org.apache.hop.core.variables.Variables; @@ -1626,13 +1625,7 @@ private Object[] handleGetRow() throws HopException { // We can use timeouts to switch from one to another... // if (waitingTime == null) { - Integer waitTime = - Const.toInt(EnvUtil.getSystemProperty(Const.HOP_DEFAULT_BUFFER_POLLING_WAITTIME), 20); - if (pipeline.getPipelineRunConfiguration().getEngineRunConfiguration() - instanceof LocalPipelineRunConfiguration runconfig) { - waitTime = Const.toInt(runconfig.getWaitTime(), waitTime); - } - waitingTime = DynamicWaitTimes.build(inputRowSets, this::getCurrentInputRowSetNr, waitTime); + waitingTime = DynamicWaitTimes.build(inputRowSets, this::getCurrentInputRowSetNr, 20); } while (row == null && !isStopped()) { // Get a row from the input in row set ... diff --git a/plugins/databases/oracle/src/test/java/org/apache/hop/databases/oracle/OracleValueMetaBaseTest.java b/plugins/databases/oracle/src/test/java/org/apache/hop/databases/oracle/OracleValueMetaBaseTest.java index f93cbfcc235..0a3e602fc89 100644 --- a/plugins/databases/oracle/src/test/java/org/apache/hop/databases/oracle/OracleValueMetaBaseTest.java +++ b/plugins/databases/oracle/src/test/java/org/apache/hop/databases/oracle/OracleValueMetaBaseTest.java @@ -18,6 +18,7 @@ package org.apache.hop.databases.oracle; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -69,21 +70,21 @@ void setUp() throws HopException { } @Test - void testMetadataPreviewSqlVarBinaryToString() throws SQLException, HopDatabaseException { + void testMetadataPreviewSqlVarBinaryNotToString() throws SQLException, HopDatabaseException { when(resultSet.getInt("DATA_TYPE")).thenReturn(Types.VARBINARY); when(resultSet.getInt("COLUMN_SIZE")).thenReturn(16); IValueMeta valueMeta = valueMetaBase.getMetadataPreview(variables, databaseMeta, resultSet); - assertTrue(valueMeta.isString()); - assertEquals(16, valueMeta.getLength()); + assertFalse(valueMeta.isString()); + assertEquals(-1, valueMeta.getLength()); } @Test - void testMetadataPreviewSqlLongVarBinaryToString() throws SQLException, HopDatabaseException { + void testMetadataPreviewSqlLongVarBinaryNotToString() throws SQLException, HopDatabaseException { when(resultSet.getInt("DATA_TYPE")).thenReturn(Types.LONGVARBINARY); IValueMeta valueMeta = valueMetaBase.getMetadataPreview(variables, databaseMeta, resultSet); - assertTrue(valueMeta.isString()); + assertFalse(valueMeta.isString()); } @Test diff --git a/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/metadata/MongoDbConnectionTest.java b/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/metadata/MongoDbConnectionTest.java index 83c55056b3d..c27ed542442 100644 --- a/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/metadata/MongoDbConnectionTest.java +++ b/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/metadata/MongoDbConnectionTest.java @@ -24,12 +24,15 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; +import org.apache.hop.core.HopClientEnvironment; +import org.apache.hop.core.exception.HopException; import org.apache.hop.core.logging.ILogChannel; import org.apache.hop.core.variables.IVariables; import org.apache.hop.mongo.MongoDbException; import org.apache.hop.mongo.MongoProp; import org.apache.hop.mongo.MongoProperties; import org.apache.hop.mongo.wrapper.MongoClientWrapper; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -43,6 +46,16 @@ class MongoDbConnectionTest { private MongoDbConnection connection; + /* + * testCreatePropertiesBuilderWithCredentials resolves a password, which needs Encr initialised. + * Nothing else in this class or the sibling mongo tests does that, so the test only passed when + * an earlier class in the same JVM happened to initialise it. init() is idempotent. + */ + @BeforeAll + static void initHopEnvironment() throws HopException { + HopClientEnvironment.init(); + } + @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); diff --git a/pom.xml b/pom.xml index fd7d382e109..f988e67ddfd 100644 --- a/pom.xml +++ b/pom.xml @@ -90,6 +90,16 @@ + + central + 3c6d86eebdcd-releases + https://artifactory.delphix.com:443/artifactory/masking-maven + + + snapshots + 3c6d86eebdcd-snapshots + https://artifactory.delphix.com:443/artifactory/masking-maven + apache.website ${site-repo-url} diff --git a/settings.xml b/settings.xml new file mode 100644 index 00000000000..9ddf0afee28 --- /dev/null +++ b/settings.xml @@ -0,0 +1,75 @@ + + + + + + + ${artifactory_user} + ${artifactory_password} + central + + + ${artifactory_user} + ${artifactory_password} + snapshots + + + + + + + + false + + central + remote-repos + https://artifactory.delphix.com:443/artifactory/remote-repos + + + + snapshots + remote-repos + https://artifactory.delphix.com:443/artifactory/remote-repos + + + + + + false + + central + remote-repos + https://artifactory.delphix.com:443/artifactory/remote-repos + + + + snapshots + remote-repos + https://artifactory.delphix.com:443/artifactory/remote-repos + + + artifactory + + + + artifactory + +