Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java
38867 views
1
/*
2
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
import sun.management.jmxremote.ConnectorBootstrap;
24
25
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.FilenameFilter;
28
import java.io.IOException;
29
import java.net.BindException;
30
import java.net.ServerSocket;
31
import java.rmi.server.ExportException;
32
33
import java.util.Properties;
34
import java.util.Iterator;
35
import java.util.Set;
36
import java.util.ArrayList;
37
import java.util.HashMap;
38
import java.util.Map;
39
import java.util.Enumeration;
40
41
import javax.management.remote.*;
42
import javax.management.*;
43
44
import sun.management.AgentConfigurationError;
45
46
import java.security.Security;
47
48
import util.TestLogger;
49
50
/**
51
* <p>This class implements unit test for RMI Bootstrap.
52
* When called with no arguments main() looks in the directory indicated
53
* by the "test.src" system property for files called management*ok.properties
54
* or management*ko.properties. The *ok.properties files are assumed to be
55
* valid Java M&M config files for which the bootstrap should succeed.
56
* The *ko.properties files are assumed to be configurations for which the
57
* bootstrap & connection test will fail.</p>
58
*
59
* <p>The rmi port number can be specified with the "rmi.port" system property.
60
* If not, this test will use the first available port</p>
61
*
62
* <p>When called with some argument, the main() will interprete its args to
63
* be Java M&M configuration file names. The filenames are expected to end
64
* with ok.properties or ko.properties - and are interpreted as above.</p>
65
*
66
* <p>Note that a limitation of the RMI registry (bug 4267864) prevent
67
* this test from succeeding if more than 1 configuration is used.
68
* As long as 4267864 isn't fix, this test must be called as many times
69
* as needed but with a single argument (no arguments, or several arguments
70
* will fail).</p>
71
*
72
* <p>Debug traces are logged in "sun.management.test"</p>
73
**/
74
public class RmiBootstrapTest {
75
// the number of consecutive ports to test for availability
76
private static final int PORT_TEST_LEN = 800;
77
static TestLogger log =
78
new TestLogger("RmiBootstrapTest");
79
80
/**
81
* When launching several registries, we increment the port number
82
* to avoid falling into "port number already in use" problems.
83
**/
84
static int testPort = 0;
85
static int basePort = 0;
86
87
/**
88
* Default values for RMI configuration properties.
89
**/
90
public static interface DefaultValues {
91
public static final String PORT="0";
92
public static final String CONFIG_FILE_NAME="management.properties";
93
public static final String USE_SSL="true";
94
public static final String USE_AUTHENTICATION="true";
95
public static final String PASSWORD_FILE_NAME="jmxremote.password";
96
public static final String ACCESS_FILE_NAME="jmxremote.access";
97
public static final String KEYSTORE="keystore";
98
public static final String KEYSTORE_PASSWD="password";
99
public static final String TRUSTSTORE="truststore";
100
public static final String TRUSTSTORE_PASSWD="trustword";
101
public static final String SSL_NEED_CLIENT_AUTH="false";
102
}
103
104
/**
105
* Names of RMI configuration properties.
106
**/
107
public static interface PropertyNames {
108
public static final String PORT=
109
"com.sun.management.jmxremote.port";
110
public static final String CONFIG_FILE_NAME=
111
"com.sun.management.config.file";
112
public static final String USE_SSL=
113
"com.sun.management.jmxremote.ssl";
114
public static final String USE_AUTHENTICATION=
115
"com.sun.management.jmxremote.authenticate";
116
public static final String PASSWORD_FILE_NAME=
117
"com.sun.management.jmxremote.password.file";
118
public static final String ACCESS_FILE_NAME=
119
"com.sun.management.jmxremote.access.file";
120
public static final String INSTRUMENT_ALL=
121
"com.sun.management.instrumentall";
122
public static final String CREDENTIALS =
123
"jmx.remote.credentials";
124
public static final String KEYSTORE=
125
"javax.net.ssl.keyStore";
126
public static final String KEYSTORE_PASSWD=
127
"javax.net.ssl.keyStorePassword";
128
public static final String TRUSTSTORE=
129
"javax.net.ssl.trustStore";
130
public static final String TRUSTSTORE_PASSWD=
131
"javax.net.ssl.trustStorePassword";
132
public static final String SSL_ENABLED_CIPHER_SUITES =
133
"com.sun.management.jmxremote.ssl.enabled.cipher.suites";
134
public static final String SSL_ENABLED_PROTOCOLS =
135
"com.sun.management.jmxremote.ssl.enabled.protocols";
136
public static final String SSL_NEED_CLIENT_AUTH =
137
"com.sun.management.jmxremote.ssl.need.client.auth";
138
public static final String SSL_CLIENT_ENABLED_CIPHER_SUITES =
139
"javax.rmi.ssl.client.enabledCipherSuites";
140
}
141
142
/**
143
* A filter to find all filenames who match <prefix>*<suffix>.
144
* Note that <prefix> and <suffix> can overlap.
145
**/
146
private static class ConfigFilenameFilter implements FilenameFilter {
147
final String suffix;
148
final String prefix;
149
ConfigFilenameFilter(String prefix, String suffix) {
150
this.suffix=suffix;
151
this.prefix=prefix;
152
}
153
public boolean accept(File dir, String name) {
154
return (name.startsWith(prefix) && name.endsWith(suffix));
155
}
156
}
157
158
/**
159
* Get all "management*ok.properties" files in the directory
160
* indicated by the "test.src" management property.
161
**/
162
private static File[] findConfigurationFilesOk() {
163
final String testSrc = System.getProperty("test.src");
164
final File dir = new File(testSrc);
165
final FilenameFilter filter =
166
new ConfigFilenameFilter("management_test","ok.properties");
167
return dir.listFiles(filter);
168
}
169
170
/**
171
* Get all "management*ko.properties" files in the directory
172
* indicated by the "test.src" management property.
173
**/
174
private static File[] findConfigurationFilesKo() {
175
final String testSrc = System.getProperty("test.src");
176
final File dir = new File(testSrc);
177
final FilenameFilter filter =
178
new ConfigFilenameFilter("management_test","ko.properties");
179
return dir.listFiles(filter);
180
}
181
182
/**
183
* List all MBeans and their attributes. Used to test communication
184
* with the Java M&M MBean Server.
185
* @return the number of queried MBeans.
186
*/
187
public static int listMBeans(MBeanServerConnection server)
188
throws IOException {
189
return listMBeans(server,null,null);
190
}
191
192
/**
193
* List all matching MBeans and their attributes.
194
* Used to test communication with the Java M&M MBean Server.
195
* @return the number of matching MBeans.
196
*/
197
public static int listMBeans(MBeanServerConnection server,
198
ObjectName pattern, QueryExp query)
199
throws IOException {
200
201
final Set names = server.queryNames(pattern,query);
202
for (final Iterator i=names.iterator(); i.hasNext(); ) {
203
ObjectName name = (ObjectName)i.next();
204
log.trace("listMBeans","Got MBean: "+name);
205
try {
206
MBeanInfo info =
207
server.getMBeanInfo((ObjectName)name);
208
MBeanAttributeInfo[] attrs = info.getAttributes();
209
if (attrs == null) continue;
210
for (int j=0; j<attrs.length; j++) {
211
if (attrs[j].isReadable()) {
212
try {
213
Object o =
214
server.getAttribute(name,attrs[j].getName());
215
if (log.isDebugOn())
216
log.debug("listMBeans","\t\t" +
217
attrs[j].getName() +
218
" = "+o);
219
} catch (Exception x) {
220
log.trace("listMBeans","JmxClient failed to get " +
221
attrs[j].getName() + ": " + x);
222
final IOException io =
223
new IOException("JmxClient failed to get " +
224
attrs[j].getName());
225
io.initCause(x);
226
throw io;
227
}
228
}
229
}
230
} catch (Exception x) {
231
log.trace("listMBeans",
232
"JmxClient failed to get MBeanInfo: " + x);
233
final IOException io =
234
new IOException("JmxClient failed to get MBeanInfo: "+x);
235
io.initCause(x);
236
throw io;
237
}
238
}
239
return names.size();
240
}
241
242
/**
243
* Compute the full path name for a default file.
244
* @param basename basename (with extension) of the default file.
245
* @return ${JRE}/lib/management/${basename}
246
**/
247
private static String getDefaultFileName(String basename) {
248
final String fileSeparator = File.separator;
249
final StringBuffer defaultFileName =
250
new StringBuffer(System.getProperty("java.home")).
251
append(fileSeparator).append("lib").append(fileSeparator).
252
append("management").append(fileSeparator).
253
append(basename);
254
return defaultFileName.toString();
255
}
256
257
/**
258
* Compute the full path name for a default file.
259
* @param basename basename (with extension) of the default file.
260
* @return ${JRE}/lib/management/${basename}
261
**/
262
private static String getDefaultStoreName(String basename) {
263
final String fileSeparator = File.separator;
264
final StringBuffer defaultFileName =
265
new StringBuffer(System.getProperty("test.src")).
266
append(fileSeparator).append("ssl").append(fileSeparator).
267
append(basename);
268
return defaultFileName.toString();
269
}
270
271
272
/**
273
* Parses the password file to read the credentials.
274
* Returns an ArrayList of arrays of 2 string:
275
* {<subject>, <password>}.
276
* If the password file does not exists, return an empty list.
277
* (File not found = empty file).
278
**/
279
private ArrayList readCredentials(String passwordFileName)
280
throws IOException {
281
final Properties pws = new Properties();
282
final ArrayList result = new ArrayList();
283
final File f = new File(passwordFileName);
284
if (!f.exists()) return result;
285
FileInputStream fin = new FileInputStream(passwordFileName);
286
try {pws.load(fin);}finally{fin.close();}
287
for (Enumeration en=pws.propertyNames();en.hasMoreElements();) {
288
final String[] cred = new String[2];
289
cred[0]=(String)en.nextElement();
290
cred[1]=pws.getProperty(cred[0]);
291
result.add(cred);
292
}
293
return result;
294
}
295
296
297
/**
298
* Connect with the given url, using all given credentials in turn.
299
* A null entry in the useCredentials arrays indicate a connection
300
* where no credentials are used.
301
* @param url JMXServiceURL of the server.
302
* @param useCredentials An array of credentials (a credential
303
* is a two String array, so this is an array of arrays
304
* of strings:
305
* useCredentials[i][0]=subject
306
* useCredentials[i][1]=password
307
* if useCredentials[i] == null means no credentials.
308
* @param expectConnectOk true if connection is expected to succeed
309
* Note: if expectConnectOk=false and the test fails to connect
310
* the number of failure is not incremented. Conversely,
311
* if expectConnectOk=false and the test does not fail to
312
* connect the number of failure is incremented.
313
* @param expectReadOk true if communication (listMBeans) is expected
314
* to succeed.
315
* Note: if expectReadOk=false and the test fails to read MBeans
316
* the number of failure is not incremented. Conversely,
317
* if expectReadOk=false and the test does not fail to
318
* read MBeans the number of failure is incremented.
319
* @return number of failure.
320
**/
321
public int connectAndRead(JMXServiceURL url,
322
Object[] useCredentials,
323
boolean expectConnectOk,
324
boolean expectReadOk)
325
throws IOException {
326
327
int errorCount = 0;
328
329
for (int i=0 ; i<useCredentials.length ; i++) {
330
final Map m = new HashMap();
331
final String[] credentials = (String[])useCredentials[i];
332
final String crinfo;
333
if (credentials != null) {
334
crinfo = "{"+credentials[0] + ", " + credentials[1] + "}";
335
m.put(PropertyNames.CREDENTIALS,credentials);
336
} else {
337
crinfo="no credentials";
338
}
339
log.trace("testCommunication","using credentials: " + crinfo);
340
341
final JMXConnector c;
342
try {
343
c = JMXConnectorFactory.connect(url,m);
344
} catch (IOException x ) {
345
if (expectConnectOk) {
346
final String err = "Connection failed for " + crinfo +
347
": " + x;
348
System.out.println(err);
349
log.trace("testCommunication",err);
350
log.debug("testCommunication",x);
351
errorCount++;
352
continue;
353
} else {
354
System.out.println("Connection failed as expected for " +
355
crinfo + ": " + x);
356
continue;
357
}
358
} catch (RuntimeException x ) {
359
if (expectConnectOk) {
360
final String err = "Connection failed for " + crinfo +
361
": " + x;
362
System.out.println(err);
363
log.trace("testCommunication",err);
364
log.debug("testCommunication",x);
365
errorCount++;
366
continue;
367
} else {
368
System.out.println("Connection failed as expected for " +
369
crinfo + ": " + x);
370
continue;
371
}
372
}
373
try {
374
MBeanServerConnection conn =
375
c.getMBeanServerConnection();
376
if (log.isDebugOn()) {
377
log.debug("testCommunication","Connection is:" + conn);
378
log.debug("testCommunication","Server domain is: " +
379
conn.getDefaultDomain());
380
}
381
final ObjectName pattern =
382
new ObjectName("java.lang:type=Memory,*");
383
final int count = listMBeans(conn,pattern,null);
384
if (count == 0)
385
throw new Exception("Expected at least one matching "+
386
"MBean for "+pattern);
387
if (expectReadOk) {
388
System.out.println("Communication succeeded " +
389
"as expected for "+
390
crinfo + ": found " + count
391
+ ((count<2)?"MBean":"MBeans"));
392
} else {
393
final String err = "Expected failure didn't occur for " +
394
crinfo;
395
System.out.println(err);
396
errorCount++;
397
}
398
} catch (IOException x ) {
399
if (expectReadOk) {
400
final String err = "Communication failed with " + crinfo +
401
": " + x;
402
System.out.println(err);
403
log.trace("testCommunication",err);
404
log.debug("testCommunication",x);
405
errorCount++;
406
continue;
407
} else {
408
System.out.println("Communication failed as expected for "+
409
crinfo + ": " + x);
410
continue;
411
}
412
} catch (RuntimeException x ) {
413
if (expectReadOk) {
414
final String err = "Communication failed with " + crinfo +
415
": " + x;
416
System.out.println(err);
417
log.trace("testCommunication",err);
418
log.debug("testCommunication",x);
419
errorCount++;
420
continue;
421
} else {
422
System.out.println("Communication failed as expected for "+
423
crinfo + ": " + x);
424
}
425
} catch (Exception x) {
426
final String err = "Failed to read MBeans with " + crinfo +
427
": " + x;
428
System.out.println(err);
429
log.trace("testCommunication",err);
430
log.debug("testCommunication",x);
431
errorCount++;
432
continue;
433
} finally {
434
c.close();
435
}
436
}
437
return errorCount;
438
}
439
440
441
private void setSslProperties(String clientEnabledCipherSuites) {
442
final String defaultKeyStore =
443
getDefaultStoreName(DefaultValues.KEYSTORE);
444
final String defaultTrustStore =
445
getDefaultStoreName(DefaultValues.TRUSTSTORE);
446
447
final String keyStore =
448
System.getProperty(PropertyNames.KEYSTORE, defaultKeyStore);
449
System.setProperty(PropertyNames.KEYSTORE,keyStore);
450
log.trace("setSslProperties",PropertyNames.KEYSTORE+"="+keyStore);
451
452
final String password =
453
System.getProperty(PropertyNames.KEYSTORE_PASSWD,
454
DefaultValues.KEYSTORE_PASSWD);
455
System.setProperty(PropertyNames.KEYSTORE_PASSWD,password);
456
log.trace("setSslProperties",
457
PropertyNames.KEYSTORE_PASSWD+"="+password);
458
459
final String trustStore =
460
System.getProperty(PropertyNames.TRUSTSTORE,
461
defaultTrustStore);
462
System.setProperty(PropertyNames.TRUSTSTORE,trustStore);
463
log.trace("setSslProperties",
464
PropertyNames.TRUSTSTORE+"="+trustStore);
465
466
final String trustword =
467
System.getProperty(PropertyNames.TRUSTSTORE_PASSWD,
468
DefaultValues.TRUSTSTORE_PASSWD);
469
System.setProperty(PropertyNames.TRUSTSTORE_PASSWD,trustword);
470
log.trace("setSslProperties",
471
PropertyNames.TRUSTSTORE_PASSWD+"="+trustword);
472
473
if (clientEnabledCipherSuites != null) {
474
System.setProperty("javax.rmi.ssl.client.enabledCipherSuites",
475
clientEnabledCipherSuites);
476
} else {
477
System.clearProperty("javax.rmi.ssl.client.enabledCipherSuites");
478
}
479
}
480
481
private void checkSslConfiguration() {
482
try {
483
final String defaultConf =
484
getDefaultFileName(DefaultValues.CONFIG_FILE_NAME);
485
final String confname =
486
System.getProperty(PropertyNames.CONFIG_FILE_NAME,defaultConf);
487
488
final Properties props = new Properties();
489
final File conf = new File(confname);
490
if (conf.exists()) {
491
FileInputStream fin = new FileInputStream(conf);
492
try {props.load(fin);} finally {fin.close();}
493
}
494
495
// Do we use SSL?
496
final String useSslStr =
497
props.getProperty(PropertyNames.USE_SSL,
498
DefaultValues.USE_SSL);
499
final boolean useSsl =
500
Boolean.valueOf(useSslStr).booleanValue();
501
502
log.debug("checkSslConfiguration",
503
PropertyNames.USE_SSL+"="+useSsl+
504
": setting SSL");
505
// Do we use SSL client authentication?
506
final String useSslClientAuthStr =
507
props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH,
508
DefaultValues.SSL_NEED_CLIENT_AUTH);
509
final boolean useSslClientAuth =
510
Boolean.valueOf(useSslClientAuthStr).booleanValue();
511
512
log.debug("checkSslConfiguration",
513
PropertyNames.SSL_NEED_CLIENT_AUTH+"="+useSslClientAuth);
514
515
// Do we use customized SSL cipher suites?
516
final String sslCipherSuites =
517
props.getProperty(PropertyNames.SSL_ENABLED_CIPHER_SUITES);
518
519
log.debug("checkSslConfiguration",
520
PropertyNames.SSL_ENABLED_CIPHER_SUITES + "=" +
521
sslCipherSuites);
522
523
// Do we use customized SSL protocols?
524
final String sslProtocols =
525
props.getProperty(PropertyNames.SSL_ENABLED_PROTOCOLS);
526
527
log.debug("checkSslConfiguration",
528
PropertyNames.SSL_ENABLED_PROTOCOLS + "=" +
529
sslProtocols);
530
531
if (useSsl) {
532
setSslProperties(props.getProperty(
533
PropertyNames.SSL_CLIENT_ENABLED_CIPHER_SUITES));
534
}
535
} catch (Exception x) {
536
System.out.println("Failed to setup SSL configuration: " + x);
537
log.debug("checkSslConfiguration",x);
538
}
539
}
540
541
/**
542
* Tests the server bootstraped at the given URL.
543
* Uses the system properties to determine which config file is used.
544
* Loads the config file to determine which password file is used.
545
* Loads the password file to find out wich credentials to use.
546
* Also checks that unregistered user/passwords are not allowed to
547
* connect when a password file is used.
548
*
549
* This method calls connectAndRead().
550
**/
551
public void testCommunication(JMXServiceURL url)
552
throws IOException {
553
554
final String defaultConf =
555
getDefaultFileName(DefaultValues.CONFIG_FILE_NAME);
556
final String confname =
557
System.getProperty(PropertyNames.CONFIG_FILE_NAME,defaultConf);
558
559
final Properties props = new Properties();
560
final File conf = new File(confname);
561
if (conf.exists()) {
562
FileInputStream fin = new FileInputStream(conf);
563
try {props.load(fin);} finally {fin.close();}
564
}
565
566
// Do we use authentication?
567
final String useAuthenticationStr =
568
props.getProperty(PropertyNames.USE_AUTHENTICATION,
569
DefaultValues.USE_AUTHENTICATION);
570
final boolean useAuthentication =
571
Boolean.valueOf(useAuthenticationStr).booleanValue();
572
573
// Get Password File
574
final String defaultPasswordFileName = Utils.convertPath(
575
getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME));
576
final String passwordFileName = Utils.convertPath(
577
props.getProperty(PropertyNames.PASSWORD_FILE_NAME,
578
defaultPasswordFileName));
579
580
// Get Access File
581
final String defaultAccessFileName = Utils.convertPath(
582
getDefaultFileName(DefaultValues.ACCESS_FILE_NAME));
583
final String accessFileName = Utils.convertPath(
584
props.getProperty(PropertyNames.ACCESS_FILE_NAME,
585
defaultAccessFileName));
586
587
if (useAuthentication) {
588
System.out.println("PasswordFileName: " + passwordFileName);
589
System.out.println("accessFileName: " + accessFileName);
590
}
591
592
final Object[] allCredentials;
593
final Object[] noCredentials = { null };
594
if (useAuthentication) {
595
final ArrayList l = readCredentials(passwordFileName);
596
if (l.size() == 0) allCredentials = null;
597
else allCredentials = l.toArray();
598
} else allCredentials = noCredentials;
599
600
int errorCount = 0;
601
if (allCredentials!=null) {
602
// Tests that the registered user/passwords are allowed to
603
// connect & read
604
//
605
errorCount += connectAndRead(url,allCredentials,true,true);
606
} else {
607
// Tests that no one is allowed
608
// connect & read
609
//
610
final String[][] someCredentials = {
611
null,
612
{ "modify", "R&D" },
613
{ "measure", "QED" }
614
};
615
errorCount += connectAndRead(url,someCredentials,false,false);
616
}
617
618
if (useAuthentication && allCredentials != noCredentials) {
619
// Tests that the registered user/passwords are not allowed to
620
// connect & read
621
//
622
final String[][] badCredentials = {
623
{ "bad.user", "R&D" },
624
{ "measure", "bad.password" }
625
};
626
errorCount += connectAndRead(url,badCredentials,false,false);
627
}
628
if (errorCount > 0) {
629
final String err = "Test " + confname + " failed with " +
630
errorCount + " error(s)";
631
log.debug("testCommunication",err);
632
throw new RuntimeException(err);
633
}
634
}
635
636
637
/**
638
* Test the configuration indicated by `file'.
639
* Sets the appropriate System properties for config file and
640
* port and then calls ConnectorBootstrap.initialize().
641
* eventually cleans up by calling ConnectorBootstrap.terminate().
642
* @return null if the test succeeds, an error message otherwise.
643
**/
644
private String testConfiguration(File file,int port) throws BindException {
645
646
final String path;
647
try {
648
path=(file==null)?null:file.getCanonicalPath();
649
} catch(IOException x) {
650
final String err = "Failed to test configuration " + file +
651
": " + x;
652
log.trace("testConfiguration",err);
653
log.debug("testConfiguration",x);
654
return err;
655
}
656
final String config = (path==null)?"Default config file":path;
657
658
System.out.println("***");
659
System.out.println("*** Testing configuration (port=" + port + "): "
660
+ path);
661
System.out.println("***");
662
663
System.setProperty("com.sun.management.jmxremote.port",
664
Integer.toString(port));
665
if (path != null)
666
System.setProperty("com.sun.management.config.file", path);
667
else
668
System.getProperties().remove("com.sun.management.config.file");
669
670
log.trace("testConfiguration","com.sun.management.jmxremote.port="+port);
671
if (path != null && log.isDebugOn())
672
log.trace("testConfiguration",
673
"com.sun.management.config.file="+path);
674
675
checkSslConfiguration();
676
677
final JMXConnectorServer cs;
678
try {
679
cs = ConnectorBootstrap.initialize();
680
} catch (AgentConfigurationError x) {
681
if (x.getCause() instanceof ExportException) {
682
if (x.getCause().getCause() instanceof BindException) {
683
throw (BindException)x.getCause().getCause();
684
}
685
}
686
final String err = "Failed to initialize connector:" +
687
"\n\tcom.sun.management.jmxremote.port=" + port +
688
((path!=null)?"\n\tcom.sun.management.config.file="+path:
689
"\n\t"+config) +
690
"\n\tError is: " + x;
691
log.trace("testConfiguration",err);
692
log.debug("testConfiguration",x);
693
return err;
694
} catch (Exception x) {
695
log.debug("testConfiguration",x);
696
return x.toString();
697
}
698
699
try {
700
JMXServiceURL url =
701
new JMXServiceURL("rmi",null,0,"/jndi/rmi://localhost:"+
702
port+"/jmxrmi");
703
704
try {
705
testCommunication(url);
706
} catch (Exception x) {
707
final String err = "Failed to connect to agent {url="+url+
708
"}: " + x;
709
log.trace("testConfiguration",err);
710
log.debug("testConfiguration",x);
711
return err;
712
}
713
} catch (Exception x) {
714
final String err = "Failed to test configuration "+config+
715
": "+x;
716
log.trace("testConfiguration",err);
717
log.debug("testConfiguration",x);
718
return err;
719
} finally {
720
try {
721
cs.stop();
722
} catch (Exception x) {
723
final String err = "Failed to terminate: "+x;
724
log.trace("testConfiguration",err);
725
log.debug("testConfiguration",x);
726
}
727
}
728
System.out.println("Configuration " + config + " successfully tested");
729
return null;
730
}
731
732
/**
733
* Test a configuration file which should make the bootstrap fail.
734
* The test is assumed to have succeeded if the bootstrap fails.
735
* @return null if the test succeeds, an error message otherwise.
736
**/
737
private String testConfigurationKo(File conf,int port) {
738
String errStr = null;
739
for (int i = 0; i < PORT_TEST_LEN; i++) {
740
try {
741
errStr = testConfiguration(conf,port+testPort++);
742
break;
743
} catch (BindException e) {
744
// port conflict; try another port
745
}
746
}
747
if (errStr == null) {
748
return "Configuration " +
749
conf + " should have failed!";
750
}
751
System.out.println("Configuration " +
752
conf + " failed as expected");
753
log.debug("runko","Error was: " + errStr);
754
return null;
755
}
756
757
/**
758
* Test a configuration file. Determines whether the bootstrap
759
* should succeed or fail depending on the file name:
760
* *ok.properties: bootstrap should succeed.
761
* *ko.properties: bootstrap or connection should fail.
762
* @return null if the test succeeds, an error message otherwise.
763
**/
764
private String testConfigurationFile(String fileName) {
765
File file = new File(fileName);
766
final String portStr = System.getProperty("rmi.port",null);
767
final int port = portStr != null ?
768
Integer.parseInt(portStr) : basePort;
769
770
if (fileName.endsWith("ok.properties")) {
771
String errStr = null;
772
for (int i = 0; i < PORT_TEST_LEN; i++) {
773
try {
774
errStr = testConfiguration(file,port+testPort++);
775
return errStr;
776
} catch (BindException e) {
777
// port conflict; try another port
778
}
779
}
780
return "Can not locate available port";
781
}
782
if (fileName.endsWith("ko.properties")) {
783
return testConfigurationKo(file,port+testPort++);
784
}
785
return fileName +
786
": test file suffix must be one of [ko|ok].properties";
787
}
788
789
/**
790
* Find all *ko.property files and test them.
791
* (see findConfigurationFilesKo() and testConfigurationKo())
792
* @throws RuntimeException if the test fails.
793
**/
794
public void runko() {
795
final String portStr = System.getProperty("rmi.port",null);
796
final int port = portStr != null ?
797
Integer.parseInt(portStr) : basePort;
798
final File[] conf = findConfigurationFilesKo();
799
if ((conf == null)||(conf.length == 0))
800
throw new RuntimeException("No configuration found");
801
802
String errStr;
803
for (int i=0;i<conf.length;i++) {
804
errStr = testConfigurationKo(conf[i],port+testPort++);
805
if (errStr != null) {
806
throw new RuntimeException(errStr);
807
}
808
}
809
810
}
811
812
/**
813
* Find all *ok.property files and test them.
814
* (see findConfigurationFilesOk() and testConfiguration())
815
* @throws RuntimeException if the test fails.
816
**/
817
public void runok() {
818
final String portStr = System.getProperty("rmi.port",null);
819
final int port = portStr != null ?
820
Integer.parseInt(portStr) : basePort;
821
final File[] conf = findConfigurationFilesOk();
822
if ((conf == null)||(conf.length == 0))
823
throw new RuntimeException("No configuration found");
824
825
String errStr = null;
826
for (int i=0;i<conf.length;i++) {
827
for (int j = 0; j < PORT_TEST_LEN; j++) {
828
try {
829
errStr = testConfiguration(conf[i],port+testPort++);
830
break;
831
} catch (BindException e) {
832
// port conflict; try another port
833
}
834
}
835
if (errStr != null) {
836
throw new RuntimeException(errStr);
837
}
838
}
839
840
// FIXME: No jmxremote.password is not installed in JRE by default.
841
// - disable the following test case.
842
//
843
// Test default config
844
//
845
// errStr = testConfiguration(null,port+testPort++);
846
// if (errStr != null) {
847
// throw new RuntimeException(errStr);
848
// }
849
}
850
851
/**
852
* Finds all configuration files (*ok.properties and *ko.properties)
853
* and tests them.
854
* (see runko() and runok()).
855
* @throws RuntimeException if the test fails.
856
**/
857
public void run() {
858
runok();
859
runko();
860
}
861
862
/**
863
* Tests the specified configuration files.
864
* If args[] is not empty, each element in args[] is expected to be
865
* a filename ending either by ok.properties or ko.properties.
866
* Otherwise, the configuration files will be automatically determined
867
* by looking at all *.properties files located in the directory
868
* indicated by the System property "test.src".
869
* @throws RuntimeException if the test fails.
870
**/
871
public void run(String args[]) {
872
if (args.length == 0) {
873
run() ; return;
874
}
875
for (int i=0; i<args.length; i++) {
876
final String errStr =testConfigurationFile(args[i]);
877
if (errStr != null) {
878
throw new RuntimeException(errStr);
879
}
880
}
881
}
882
883
/**
884
* Calls run(args[]).
885
* exit(1) if the test fails.
886
**/
887
public static void main(String args[]) throws Exception {
888
Security.setProperty("jdk.tls.disabledAlgorithms", "");
889
890
setupBasePort();
891
RmiBootstrapTest manager = new RmiBootstrapTest();
892
try {
893
manager.run(args);
894
} catch (RuntimeException r) {
895
System.out.println("Test Failed: "+ r.getMessage());
896
System.exit(1);
897
} catch (Throwable t) {
898
System.out.println("Test Failed: "+ t);
899
t.printStackTrace();
900
System.exit(2);
901
}
902
System.out.println("**** Test RmiBootstrap Passed ****");
903
}
904
905
private static void setupBasePort() throws IOException {
906
try (ServerSocket s = new ServerSocket(0)) {
907
basePort = s.getLocalPort() + 1;
908
}
909
}
910
}
911
912