/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.management.*;
import util.TestLogger;
/**
* <p>This class implements unit test for RMI Bootstrap.
* When called with no arguments main() looks in the directory indicated
* by the "test.src" system property for files called management*ok.properties
* or management*ko.properties. The *ok.properties files are assumed to be
* valid Java M&M config files for which the bootstrap should succeed.
* The *ko.properties files are assumed to be configurations for which the
* bootstrap & connection test will fail.</p>
*
* <p>The rmi port number can be specified with the "rmi.port" system property.
* If not, this test will use 12424</p>
*
* <p>When called with some argument, the main() will interprete its args to
* be Java M&M configuration file names. The filenames are expected to end
* with ok.properties or ko.properties - and are interpreted as above.</p>
*
* <p>Note that a limitation of the RMI registry (bug 4267864) prevent
* this test from succeeding if more than 1 configuration is used.
* As long as 4267864 isn't fix, this test must be called as many times
* as needed but with a single argument (no arguments, or several arguments
* will fail).</p>
*
* <p>Debug traces are logged in "sun.management.test"</p>
**/
public class RmiBootstrapTest {
new TestLogger("RmiBootstrapTest");
/**
* When launching several registries, we increment the port number
* to avoid falling into "port number already in use" problems.
**/
/**
* Default values for RMI configuration properties.
**/
public static interface DefaultValues {
}
/**
* Names of RMI configuration properties.
**/
public static interface PropertyNames {
"com.sun.management.jmxremote.port";
"com.sun.management.config.file";
"com.sun.management.jmxremote.ssl";
"com.sun.management.jmxremote.authenticate";
"com.sun.management.jmxremote.password.file";
"com.sun.management.jmxremote.access.file";
"com.sun.management.instrumentall";
"jmx.remote.credentials";
"javax.net.ssl.keyStore";
"javax.net.ssl.keyStorePassword";
"javax.net.ssl.trustStore";
"javax.net.ssl.trustStorePassword";
"com.sun.management.jmxremote.ssl.enabled.cipher.suites";
"com.sun.management.jmxremote.ssl.enabled.protocols";
"com.sun.management.jmxremote.ssl.need.client.auth";
}
/**
* A filter to find all filenames who match <prefix>*<suffix>.
* Note that <prefix> and <suffix> can overlap.
**/
}
}
}
/**
* Get all "management*ok.properties" files in the directory
* indicated by the "test.src" management property.
**/
final FilenameFilter filter =
}
/**
* Get all "management*ko.properties" files in the directory
* indicated by the "test.src" management property.
**/
final FilenameFilter filter =
}
/**
* List all MBeans and their attributes. Used to test communication
* with the Java M&M MBean Server.
* @return the number of queried MBeans.
*/
throws IOException {
}
/**
* List all matching MBeans and their attributes.
* Used to test communication with the Java M&M MBean Server.
* @return the number of matching MBeans.
*/
throws IOException {
try {
if (attrs[j].isReadable()) {
try {
Object o =
" = "+o);
} catch (Exception x) {
final IOException io =
new IOException("JmxClient failed to get " +
throw io;
}
}
}
} catch (Exception x) {
"JmxClient failed to get MBeanInfo: " + x);
final IOException io =
new IOException("JmxClient failed to get MBeanInfo: "+x);
throw io;
}
}
}
/**
* Compute the full path name for a default file.
* @param basename basename (with extension) of the default file.
* @return ${JRE}/lib/management/${basename}
**/
final StringBuffer defaultFileName =
return defaultFileName.toString();
}
/**
* Compute the full path name for a default file.
* @param basename basename (with extension) of the default file.
* @return ${JRE}/lib/management/${basename}
**/
final StringBuffer defaultFileName =
return defaultFileName.toString();
}
/**
* Parses the password file to read the credentials.
* Returns an ArrayList of arrays of 2 string:
* {<subject>, <password>}.
* If the password file does not exists, return an empty list.
* (File not found = empty file).
**/
throws IOException {
}
return result;
}
/**
* Connect with the given url, using all given credentials in turn.
* A null entry in the useCredentials arrays indicate a connection
* where no credentials are used.
* @param url JMXServiceURL of the server.
* @param useCredentials An array of credentials (a credential
* is a two String array, so this is an array of arrays
* of strings:
* useCredentials[i][0]=subject
* useCredentials[i][1]=password
* if useCredentials[i] == null means no credentials.
* @param expectConnectOk true if connection is expected to succeed
* Note: if expectConnectOk=false and the test fails to connect
* the number of failure is not incremented. Conversely,
* if expectConnectOk=false and the test does not fail to
* connect the number of failure is incremented.
* @param expectReadOk true if communication (listMBeans) is expected
* to succeed.
* Note: if expectReadOk=false and the test fails to read MBeans
* the number of failure is not incremented. Conversely,
* if expectReadOk=false and the test does not fail to
* read MBeans the number of failure is incremented.
* @return number of failure.
**/
boolean expectConnectOk,
boolean expectReadOk)
throws IOException {
int errorCount = 0;
if (credentials != null) {
} else {
crinfo="no credentials";
}
final JMXConnector c;
try {
} catch (IOException x ) {
if (expectConnectOk) {
": " + x;
errorCount++;
continue;
} else {
crinfo + ": " + x);
continue;
}
} catch (RuntimeException x ) {
if (expectConnectOk) {
": " + x;
errorCount++;
continue;
} else {
crinfo + ": " + x);
continue;
}
}
try {
conn.getDefaultDomain());
}
final ObjectName pattern =
new ObjectName("java.lang:type=Memory,*");
if (count == 0)
throw new Exception("Expected at least one matching "+
"MBean for "+pattern);
if (expectReadOk) {
"as expected for "+
} else {
errorCount++;
}
} catch (IOException x ) {
if (expectReadOk) {
": " + x;
errorCount++;
continue;
} else {
crinfo + ": " + x);
continue;
}
} catch (RuntimeException x ) {
if (expectReadOk) {
": " + x;
errorCount++;
continue;
} else {
crinfo + ": " + x);
}
} catch (Exception x) {
": " + x;
errorCount++;
continue;
} finally {
c.close();
}
}
return errorCount;
}
private void setSslProperties() {
final String defaultKeyStore =
final String defaultTrustStore =
final String trustStore =
}
private void checkSslConfiguration() {
try {
final String defaultConf =
}
// Do we use SSL?
final boolean useSsl =
": setting SSL");
// Do we use SSL client authentication?
final String useSslClientAuthStr =
final boolean useSslClientAuth =
// Do we use customized SSL cipher suites?
final String sslCipherSuites =
// Do we use customized SSL protocols?
final String sslProtocols =
if (useSsl) setSslProperties();
} catch (Exception x) {
}
}
/**
* Tests the server bootstraped at the given URL.
* Uses the system properties to determine which config file is used.
* Loads the config file to determine which password file is used.
* Loads the password file to find out wich credentials to use.
* connect when a password file is used.
*
* This method calls connectAndRead().
**/
throws IOException {
final String defaultConf =
}
// Do we use authentication?
final String useAuthenticationStr =
final boolean useAuthentication =
// Get Password File
// Get Access File
if (useAuthentication) {
}
final Object[] allCredentials;
if (useAuthentication) {
else allCredentials = l.toArray();
} else allCredentials = noCredentials;
int errorCount = 0;
if (allCredentials!=null) {
// connect & read
//
} else {
// Tests that no one is allowed
// connect & read
//
final String[][] someCredentials = {
null,
{ "modify", "R&D" },
{ "measure", "QED" }
};
}
// connect & read
//
final String[][] badCredentials = {
{ "bad.user", "R&D" },
{ "measure", "bad.password" }
};
}
if (errorCount > 0) {
errorCount + " error(s)";
throw new RuntimeException(err);
}
}
/**
* Test the configuration indicated by `file'.
* Sets the appropriate System properties for config file and
* port and then calls ConnectorBootstrap.initialize().
* eventually cleans up by calling ConnectorBootstrap.terminate().
* @return null if the test succeeds, an error message otherwise.
**/
try {
} catch(IOException x) {
": " + x;
return err;
}
+ path);
else
"com.sun.management.config.file="+path);
final JMXConnectorServer cs;
try {
} catch (AgentConfigurationError x) {
"\n\tcom.sun.management.jmxremote.port=" + port +
"\n\t"+config) +
"\n\tError is: " + x;
return err;
} catch (Exception x) {
return x.toString();
}
try {
port+"/jmxrmi");
try {
} catch (Exception x) {
"}: " + x;
return err;
}
} catch (Exception x) {
": "+x;
return err;
} finally {
try {
} catch (Exception x) {
}
}
return null;
}
/**
* Test a configuration file which should make the bootstrap fail.
* The test is assumed to have succeeded if the bootstrap fails.
* @return null if the test succeeds, an error message otherwise.
**/
return "Configuration " +
conf + " should have failed!";
}
conf + " failed as expected");
return null;
}
/**
* Test a configuration file. Determines whether the bootstrap
* should succeed or fail depending on the file name:
* *ok.properties: bootstrap should succeed.
* *ko.properties: bootstrap or connection should fail.
* @return null if the test succeeds, an error message otherwise.
**/
}
}
return fileName +
": test file suffix must be one of [ko|ok].properties";
}
/**
* Find all *ko.property files and test them.
* (see findConfigurationFilesKo() and testConfigurationKo())
* @throws RuntimeException if the test fails.
**/
public void runko() {
throw new RuntimeException("No configuration found");
throw new RuntimeException(errStr);
}
}
}
/**
* Find all *ok.property files and test them.
* (see findConfigurationFilesOk() and testConfiguration())
* @throws RuntimeException if the test fails.
**/
public void runok() {
throw new RuntimeException("No configuration found");
throw new RuntimeException(errStr);
}
}
// FIXME: No jmxremote.password is not installed in JRE by default.
// - disable the following test case.
//
// Test default config
//
// errStr = testConfiguration(null,port+testPort++);
// if (errStr != null) {
// throw new RuntimeException(errStr);
// }
}
/**
* Finds all configuration files (*ok.properties and *ko.properties)
* and tests them.
* (see runko() and runok()).
* @throws RuntimeException if the test fails.
**/
public void run() {
runok();
runko();
}
/**
* Tests the specified configuration files.
* If args[] is not empty, each element in args[] is expected to be
* a filename ending either by ok.properties or ko.properties.
* Otherwise, the configuration files will be automatically determined
* by looking at all *.properties files located in the directory
* indicated by the System property "test.src".
* @throws RuntimeException if the test fails.
**/
run() ; return;
}
throw new RuntimeException(errStr);
}
}
}
/**
* Calls run(args[]).
* exit(1) if the test fails.
**/
try {
} catch (RuntimeException r) {
} catch (Throwable t) {
t.printStackTrace();
}
}
}