Skip to content

Commit

Permalink
Adds a test for the changes checked in previously by Paul. I've also …
Browse files Browse the repository at this point in the history
…refactored some string literals into enumeration members and I've documented the new XMLA driver properties that it introduces.

git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@490 c6a108a4-781c-0410-a6c6-c2d559e19af0
  • Loading branch information
lucboudreau committed Jan 23, 2012
1 parent bbe5864 commit c6c0808
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 50 deletions.
44 changes: 18 additions & 26 deletions src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,7 @@ abstract class XmlaOlap4jConnection implements OlapConnection {

this.databaseProperties = new HashMap<String,String>();
for (String infoKey : map.keySet()) {
boolean addProperty = true;
for (XmlaOlap4jDriver.Property p
: XmlaOlap4jDriver.Property.values())
{
if (infoKey.equals(p.name())
|| "USER".equals(infoKey)
|| "PASSWORD".equals(infoKey))
{
addProperty = false;
}
}
if (addProperty) {
databaseProperties.put(infoKey, map.get(infoKey));
}
databaseProperties.put(infoKey, map.get(infoKey));
}

this.databaseName =
Expand Down Expand Up @@ -238,10 +225,12 @@ abstract class XmlaOlap4jConnection implements OlapConnection {
new XmlaOlap4jServerInfos() {
private String sessionId = null;
public String getUsername() {
return map.get("user");
return map.get(
XmlaOlap4jDriver.Property.USER.name());
}
public String getPassword() {
return map.get("password");
return map.get(
XmlaOlap4jDriver.Property.PASSWORD.name());
}
public URL getUrl() {
return serverUrlObject;
Expand Down Expand Up @@ -286,9 +275,7 @@ private XmlaHelper getHelper() {
*/
private void initSoapCache(Map<String, String> map) throws OlapException {
// Test if a SOAP cache class was defined
if (map.containsKey(XmlaOlap4jDriver.Property.CACHE.name()
.toUpperCase()))
{
if (map.containsKey(XmlaOlap4jDriver.Property.CACHE.name())) {
// Create a properties object to pass to the proxy
// so it can configure it's cache
Map<String, String> props = new HashMap<String, String>();
Expand Down Expand Up @@ -941,13 +928,18 @@ public String generateRequest(
+ " <PropertyList>\n");

for (String prop : databaseProperties.keySet()) {
buf.append(" <");
xmlEncode(buf,prop);
buf.append(">");
xmlEncode(buf, databaseProperties.get(prop));
buf.append("</");
xmlEncode(buf, prop);
buf.append(">");
try {
XmlaOlap4jDriver.Property.valueOf(prop);
continue;
} catch (IllegalArgumentException e) {
buf.append(" <");
xmlEncode(buf,prop);
buf.append(">");
xmlEncode(buf, databaseProperties.get(prop));
buf.append("</");
xmlEncode(buf, prop);
buf.append(">");
}
}

// Add the datasource node only if this request requires it.
Expand Down
61 changes: 41 additions & 20 deletions src/org/olap4j/driver/xmla/XmlaOlap4jDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@
* <p>Unless otherwise stated, properties are optional. If a property occurs
* multiple times in the connect string, the first occurrence is used.
*
* <p>It is also possible to pass properties to the server end-point using
* JDBC connection properties as part of the XMLA driver connection properties.
* If the JDBC URL contains properties that are not enumerated in
* {@link Property}, they will be included as part of the SOAP PropertyList
* element.
*
*
* <table border="1">
* <tr><th>Property</th> <th>Description</th> </tr>
*
Expand All @@ -75,35 +82,47 @@
* By default, the first one returned by the
* XMLA server will be used.</td></tr>
*
* <tr><td>Database</td> <td>Name of the XMLA database.
* <tr><td>Database</td> <td>Name of the XMLA database.
* By default, the first one returned by the
* XMLA server will be used.</td></tr>
*
* <tr><td>Cache</td> <td><p>Class name of the SOAP cache to use.
* Must implement interface
* <tr><td>Cache</td> <td><p>Class name of the SOAP cache to use.
* Must implement interface
* {@link org.olap4j.driver.xmla.proxy.XmlaOlap4jCachedProxy}.
* A built-in memory cache is available with
* A built-in memory cache is available with
* {@link org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache}.
*
* <p>By default, no SOAP query cache will be
* used.</td></tr>
*
* <tr> <td>Cache.*</td> <td>Properties to transfer to the selected cache
* implementation. See
* <p>By default, no SOAP query cache will be
* used.
* </td></tr>
* <tr><td>Cache.*</td> <td>Properties to transfer to the selected cache
* implementation. See
* {@link org.olap4j.driver.xmla.cache.XmlaOlap4jCache}
* or your selected implementation for properties
* details.</td></tr>
*
* or your selected implementation for properties
* details.
* </td></tr>
* <tr><td>TestProxyCookie</td><td>String that uniquely identifies a proxy
* object in {@link #PROXY_MAP} via which to
* send XMLA requests for testing
* purposes.</td></tr>
* <tr><td>Role</td> <td>Comma separated list of role names used for
* this connection (Optional). <br />
* Available role names can be retrieved via
* object in {@link #PROXY_MAP} via which to
* send XMLA requests for testing
* purposes.
* </td></tr>
* <tr><td>Role</td> <td>Comma separated list of role names used for
* this connection (Optional). <br />
* Available role names can be retrieved via
* {@link org.olap4j.driver.xmla.XmlaOlap4jConnection#getAvailableRoleNames}
* </td></tr>
*
* <tr><td>User</td> <td>User name to use when establishing a
* connection to the server. The credentials are passed
* using the HTTP Basic authentication protocol,
* but are also sent as part of the SOAP Security
* headers.
* </td></tr>
* <tr><td>Password</td> <td>Password to use when establishing a
* connection to the server. The credentials are passed
* using the HTTP Basic authentication protocol,
* but are also sent as part of the SOAP Security
* headers.
* </td></tr>
* </table>
*
* @author jhyde, Luc Boudreau
Expand Down Expand Up @@ -366,7 +385,9 @@ public enum Property {
CATALOG("Catalog name"),
SCHEMA("Name of the schema"),
CACHE("Class name of the SOAP cache implementation"),
ROLE("Comma separated list of roles this connection impersonates");
ROLE("Comma separated list of roles this connection impersonates"),
USER("Username to use when creating connections to the server."),
PASSWORD("Password to use when creating connections to the server.");

/**
* Creates a property.
Expand Down
100 changes: 100 additions & 0 deletions testsrc/org/olap4j/XmlaConnectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,106 @@ public void testNoDoubleQuerySubmission() throws Exception {
}
}

/**
* This is a test to verify that server specific properties
* can be sent to the server in the PropertyList element
* of SOAP messages. A property that is not part of those enumerated
* in {@link org.olap4j.driver.xmla.XmlaOlap4jDriver.Property} must
* not be sent to the server.
*/
public void testPropertyList() throws Exception {
if (!testContext.getTester().getFlavor()
.equals(Tester.Flavor.XMLA)
&& !testContext.getTester().getFlavor()
.equals(Tester.Flavor.REMOTE_XMLA))
{
return;
}
final String oldValue = XmlaTester.getProxyClassName();
try {
XmlaTester.setProxyClassName(
PropertyListTestProxy.class.getName());
final TestContext.Tester tester =
testContext.getTester();

Connection connection = tester.createConnection();
Statement statement = connection.createStatement();
OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
assertEquals(0, PropertyListTestProxy.count);
connection.close();

connection = tester.createConnectionWithUserPassword();
statement = connection.createStatement();
olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
assertEquals(0, PropertyListTestProxy.count);
connection.close();

final Properties props = new Properties();
props.put("FOOBAR", "Bacon");
connection =
((XmlaTester)tester).createConnectionWithUserPassword(props);
statement = connection.createStatement();
olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
try {
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
} catch (Throwable e) {
assertTrue(e.getCause().getMessage().contains("FOOBAR"));
}
connection.close();
} finally {
XmlaTester.setProxyClassName(oldValue);
}
}

/**
* This is a class for the test
* {@link XmlaConnectionTest#testPropertyList()}.
*/
public static class PropertyListTestProxy extends DelegatingTestProxy {
public PropertyListTestProxy(XmlaOlap4jProxy proxy) {
super(proxy);
}
private final static String[] lookup =
new String[] {
"<PASSWORD>"
};
private static int count = 0;
public byte[] get(
XmlaOlap4jServerInfos serverInfos, String request)
throws XmlaOlap4jProxyException
{
for (String token : lookup) {
if (request.contains(token)) {
count++;
}
}
return super.get(serverInfos, request);
}
}

private static class Encoder {
/**
* Converts an array of bytes to a hex string.
Expand Down
20 changes: 16 additions & 4 deletions testsrc/org/olap4j/XmlaTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,28 @@ public Connection createConnection() throws SQLException {
}

public Connection createConnectionWithUserPassword() throws SQLException {
final Properties props = new Properties();
return createConnectionWithUserPassword(props);
}

public Connection createConnectionWithUserPassword(
Properties props)
throws SQLException
{
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException("oops", e);
}
Properties info = new Properties();
info.setProperty(
props.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMart");
return DriverManager.getConnection(
getURL(), USER, PASSWORD);
if (USER != null) {
props.put("user", USER);
}
if (PASSWORD != null) {
props.put("password", PASSWORD);
}
return DriverManager.getConnection(getURL(), props);
}

public String getDriverUrlPrefix() {
Expand Down

0 comments on commit c6c0808

Please sign in to comment.