Skip to content

Commit a2d7714

Browse files
committed
[BACKLOG-48717] - list & test project support
- add "allLevels" parameter - add "level" to response database objects in list call - support Variables in test
1 parent e985844 commit a2d7714

File tree

5 files changed

+534
-7
lines changed

5 files changed

+534
-7
lines changed

api/src/main/resources/connection-api.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ paths:
289289
description: Optional project directory. If provided, the operation will be performed in the context of the project.
290290
schema:
291291
type: string
292+
- name: allLevels
293+
in: query
294+
required: false
295+
description: Optional flag to include connections from all supported levels for the request context.
296+
schema:
297+
type: boolean
292298
responses:
293299
'200':
294300
description: Successfully retrieved connections
@@ -568,6 +574,10 @@ components:
568574
description: Partitioning information
569575
items:
570576
type: object
577+
level:
578+
type: string
579+
description: Connection level for list results, present when allLevels=true
580+
example: "Repository"
571581
IDatabaseConnectionList:
572582
type: object
573583
description: List of database connections (maps to org.pentaho.ui.database.event.IDatabaseConnectionList)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package org.pentaho.platform.dataaccess.datasource.utils;
2+
3+
import org.pentaho.database.model.IDatabaseConnection;
4+
import org.pentaho.database.model.PartitionDatabaseMeta;
5+
import org.pentaho.di.core.variables.VariableSpace;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
/**
11+
* Utility class for applying variable substitution to database connection fields.
12+
* Applies environmentSubstitute to connection fields that may contain variable references
13+
* (in the form ${VARIABLE_NAME}).
14+
*/
15+
public class DatabaseConnectionUtils {
16+
17+
/**
18+
* Apply environment variable substitution to an IDatabaseConnection using the provided VariableSpace.
19+
* Substitutes variables in the following fields:
20+
* - name (connection identifier, may be used in pooling keys)
21+
* - hostname
22+
* - databaseName
23+
* - databasePort
24+
* - username
25+
* - password
26+
* - connectSql
27+
* - sqlServerInstance
28+
* - dataTablespace (Oracle and other database-specific tablespaces)
29+
* - indexTablespace (Oracle and other database-specific tablespaces)
30+
* - connectionPoolingProperties (all values)
31+
* - partitioning information (if present)
32+
*
33+
* @param connection The database connection to update (modified in-place)
34+
* @param variableSpace The variable space to use for substitution
35+
*/
36+
public static void applyEnvironmentSubstitution( final IDatabaseConnection connection,
37+
final VariableSpace variableSpace ) {
38+
if ( connection == null || variableSpace == null ) {
39+
return;
40+
}
41+
42+
// Substitute connection name (used for pooling and identification)
43+
if ( connection.getName() != null ) {
44+
connection.setName( variableSpace.environmentSubstitute( connection.getName() ) );
45+
}
46+
47+
// Substitute basic connection fields
48+
if ( connection.getHostname() != null ) {
49+
connection.setHostname( variableSpace.environmentSubstitute( connection.getHostname() ) );
50+
}
51+
52+
if ( connection.getDatabaseName() != null ) {
53+
connection.setDatabaseName( variableSpace.environmentSubstitute( connection.getDatabaseName() ) );
54+
}
55+
56+
if ( connection.getDatabasePort() != null ) {
57+
connection.setDatabasePort( variableSpace.environmentSubstitute( connection.getDatabasePort() ) );
58+
}
59+
60+
if ( connection.getUsername() != null ) {
61+
connection.setUsername( variableSpace.environmentSubstitute( connection.getUsername() ) );
62+
}
63+
64+
if ( connection.getPassword() != null ) {
65+
connection.setPassword( variableSpace.environmentSubstitute( connection.getPassword() ) );
66+
}
67+
68+
// Substitute connect SQL
69+
if ( connection.getConnectSql() != null ) {
70+
connection.setConnectSql( variableSpace.environmentSubstitute( connection.getConnectSql() ) );
71+
}
72+
73+
// Substitute SQL Server instance
74+
if ( connection.getSQLServerInstance() != null ) {
75+
connection.setSQLServerInstance( variableSpace.environmentSubstitute( connection.getSQLServerInstance() ) );
76+
}
77+
78+
// Substitute tablespace fields (Oracle and similar databases)
79+
if ( connection.getDataTablespace() != null ) {
80+
connection.setDataTablespace( variableSpace.environmentSubstitute( connection.getDataTablespace() ) );
81+
}
82+
83+
if ( connection.getIndexTablespace() != null ) {
84+
connection.setIndexTablespace( variableSpace.environmentSubstitute( connection.getIndexTablespace() ) );
85+
}
86+
87+
// Substitute connection pooling properties
88+
if ( connection.getConnectionPoolingProperties() != null
89+
&& !connection.getConnectionPoolingProperties().isEmpty() ) {
90+
Map<String, String> substitutedPoolingProps = new HashMap<>();
91+
for ( Map.Entry<String, String> entry : connection.getConnectionPoolingProperties().entrySet() ) {
92+
String substitutedValue = entry.getValue() != null ? variableSpace.environmentSubstitute( entry.getValue() )
93+
: null;
94+
substitutedPoolingProps.put( entry.getKey(), substitutedValue );
95+
}
96+
connection.setConnectionPoolingProperties( substitutedPoolingProps );
97+
}
98+
99+
// Substitute partitioning information if present
100+
if ( connection.isPartitioned() && connection.getPartitioningInformation() != null ) {
101+
for ( PartitionDatabaseMeta partition : connection.getPartitioningInformation() ) {
102+
applyEnvironmentSubstitutionToPartition( partition, variableSpace );
103+
}
104+
}
105+
}
106+
107+
/**
108+
* Apply environment variable substitution to a PartitionDatabaseMeta.
109+
* Substitutes variables in hostname, port, and database name fields.
110+
*
111+
* @param partition The partition metadata to update (modified in-place)
112+
* @param variableSpace The variable space to use for substitution
113+
*/
114+
private static void applyEnvironmentSubstitutionToPartition( final PartitionDatabaseMeta partition,
115+
final VariableSpace variableSpace ) {
116+
if ( partition == null || variableSpace == null ) {
117+
return;
118+
}
119+
120+
if ( partition.getHostname() != null ) {
121+
partition.setHostname( variableSpace.environmentSubstitute( partition.getHostname() ) );
122+
}
123+
124+
if ( partition.getPort() != null ) {
125+
partition.setPort( variableSpace.environmentSubstitute( partition.getPort() ) );
126+
}
127+
128+
if ( partition.getDatabaseName() != null ) {
129+
partition.setDatabaseName( variableSpace.environmentSubstitute( partition.getDatabaseName() ) );
130+
}
131+
}
132+
}

core/src/main/java/org/pentaho/platform/dataaccess/datasource/wizard/service/impl/ConnectionService.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
import org.pentaho.database.service.DatabaseDialectService;
2323
import org.pentaho.database.util.DatabaseUtil;
2424
import org.pentaho.di.core.encryption.Encr;
25+
import org.pentaho.di.core.variables.VariableSpace;
26+
import org.pentaho.di.core.variables.Variables;
2527
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
2628
import org.pentaho.platform.api.engine.PentahoAccessControlException;
29+
import org.pentaho.platform.dataaccess.datasource.utils.DatabaseConnectionUtils;
2730
import org.pentaho.platform.dataaccess.datasource.wizard.service.ConnectionServiceException;
2831
import org.pentaho.platform.dataaccess.datasource.wizard.service.api.ConnectionsApi;
2932
import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.utils.UtilHtmlSanitizer;
@@ -61,6 +64,7 @@ public class ConnectionService implements ConnectionsApi {
6164
private static final Log logger = LogFactory.getLog( ConnectionService.class );
6265
protected static final String MEDIA_TYPE_JSON = "application/json";
6366
protected static final String MEDIA_TYPE_TEXT_PLAIN = "text/plain";
67+
protected static final String CONNECTION_LEVEL_REPOSITORY = "Repository";
6468

6569
private ConnectionServiceImpl connectionService;
6670
private DatabaseDialectService dialectService;
@@ -283,7 +287,7 @@ public IDatabaseConnectionPoolParameterList getPoolingParameters() {
283287
@Override
284288
public String testConnection( IDatabaseConnection databaseConnection, String projectDir ) {
285289
try {
286-
applySavedPassword( databaseConnection, projectDir );
290+
applySavedPassword( databaseConnection, projectDir, true );
287291
boolean success = connectionService.testConnection( databaseConnection );
288292
if ( success ) {
289293
return Messages.getString( "ConnectionServiceImpl.INFO_0001_CONNECTION_SUCCEED", databaseConnection
@@ -319,7 +323,7 @@ public String testConnection( IDatabaseConnection databaseConnection ) {
319323
public void updateConnection( IDatabaseConnection databaseConnection, String projectDir ) {
320324
sanitizer.sanitizeConnectionParameters( databaseConnection );
321325
try {
322-
applySavedPassword( databaseConnection );
326+
applySavedPassword( databaseConnection, false );
323327
connectionService.updateConnection( databaseConnection );
324328
// explicitly return a 200 instead of 204 No Content
325329
throw new WebApplicationException( Response.ok().build() );
@@ -358,12 +362,22 @@ public void updateConnection( IDatabaseConnection databaseConnection ) {
358362
/**
359363
* If password is empty, that means connection sent from UI and user didn't change password. Since we cleaned password
360364
* during sending to UI, we need to use stored password.
365+
*
366+
* @param conn the connection to update
367+
* @param projectDir Optional project directory (used by subclasses)
368+
* @param resolveVariables whether to resolve variables in the connection
361369
*/
362-
protected void applySavedPassword( IDatabaseConnection conn, String projectDir ) throws ConnectionServiceException {
363-
applySavedPassword( conn );
370+
protected void applySavedPassword( IDatabaseConnection conn, String projectDir, boolean resolveVariables ) throws ConnectionServiceException {
371+
applySavedPassword( conn, resolveVariables );
364372
}
365373

366-
private void applySavedPassword( IDatabaseConnection conn ) throws ConnectionServiceException {
374+
private void applySavedPassword( IDatabaseConnection conn, boolean resolveVariables ) throws ConnectionServiceException {
375+
376+
if ( resolveVariables ) {
377+
VariableSpace variables = Variables.getADefaultVariableSpace();
378+
DatabaseConnectionUtils.applyEnvironmentSubstitution( conn, variables );
379+
}
380+
367381
if ( StringUtils.isBlank( conn.getPassword() ) ) {
368382
IDatabaseConnection savedConn;
369383
if ( conn.getId() != null ) {
@@ -519,19 +533,30 @@ private void validateAccess() throws PentahoAccessControlException {
519533
*
520534
*/
521535
@Override
522-
public IDatabaseConnectionList getConnections( String projectDir ) {
536+
public IDatabaseConnectionList getConnections( String projectDir, Boolean allLevels ) {
523537
try {
524538
IDatabaseConnectionList databaseConnections = new DefaultDatabaseConnectionList();
525539
List<IDatabaseConnection> conns = connectionService.getConnections( true );
540+
for ( IDatabaseConnection conn : conns ) {
541+
setConnectionLevel( conn, CONNECTION_LEVEL_REPOSITORY );
542+
}
526543
databaseConnections.setDatabaseConnections( conns );
527544
return databaseConnections;
528545
} catch ( ConnectionServiceException ex ) {
529546
throw new WebApplicationException( ex.getMessage(), Response.Status.INTERNAL_SERVER_ERROR );
530547
}
531548
}
532549

550+
public IDatabaseConnectionList getConnections( String projectDir ) {
551+
return getConnections( projectDir, Boolean.FALSE );
552+
}
553+
533554
public IDatabaseConnectionList getConnections() {
534-
return getConnections( null );
555+
return getConnections( null, Boolean.FALSE );
556+
}
557+
558+
protected void setConnectionLevel( IDatabaseConnection connection, String level ) {
559+
connection.setLevel( level );
535560
}
536561

537562
/**

0 commit comments

Comments
 (0)