1 | /** |
2 | * Copyright 2007 ATG DUST Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * |
7 | * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 |
8 | * |
9 | * Unless required by applicable law or agreed to in writing, software |
10 | * distributed under the License is distributed on an "AS IS" BASIS, |
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | * See the License for the specific language governing permissions and limitations under the License. |
13 | */ |
14 | |
15 | package atg.junit.nucleus; |
16 | |
17 | import java.io.BufferedReader; |
18 | import java.io.ByteArrayOutputStream; |
19 | import java.io.File; |
20 | import java.io.FileOutputStream; |
21 | import java.io.IOException; |
22 | import java.io.InputStreamReader; |
23 | import java.io.PrintStream; |
24 | import java.lang.reflect.Method; |
25 | import java.net.InetAddress; |
26 | import java.net.MalformedURLException; |
27 | import java.net.URL; |
28 | import java.net.UnknownHostException; |
29 | import java.util.Iterator; |
30 | import java.util.LinkedList; |
31 | import java.util.List; |
32 | import java.util.Map; |
33 | import java.util.Properties; |
34 | import java.util.StringTokenizer; |
35 | import java.util.jar.Manifest; |
36 | |
37 | import javax.activation.DataHandler; |
38 | import javax.activation.FileDataSource; |
39 | import javax.mail.BodyPart; |
40 | import javax.mail.Message; |
41 | import javax.mail.Multipart; |
42 | import javax.mail.internet.MimeBodyPart; |
43 | import javax.mail.internet.MimeMultipart; |
44 | |
45 | import org.apache.log4j.Logger; |
46 | import org.w3c.dom.Node; |
47 | |
48 | import atg.applauncher.AppLauncher; |
49 | import atg.applauncher.AppModule; |
50 | import atg.nucleus.DynamoEnv; |
51 | import atg.nucleus.Nucleus; |
52 | import atg.service.dynamo.LicenseImpl; |
53 | import atg.service.email.ContentPart; |
54 | import atg.service.email.EmailEvent; |
55 | import atg.service.email.MimeMessageUtils; |
56 | import atg.service.email.SMTPEmailSender; |
57 | import atg.servlet.ServletUtil; |
58 | |
59 | /** |
60 | * This class is used to hold useful utilty methods people may |
61 | * need when running tests. |
62 | */ |
63 | public class TestUtils |
64 | extends atg.nucleus.GenericService |
65 | { |
66 | |
67 | private static Logger log = Logger.getLogger(TestUtils.class); |
68 | // names of app servers types that may be specified by the |
69 | // 'atg.dynamo.appserver' system property |
70 | // Dynamo currently does not distinguish between generic |
71 | // Tomcat and JBoss, everything is just referred to as 'tomcat' |
72 | public static final String APP_SERVER_DAS = "das"; |
73 | public static final String APP_SERVER_BEA = "weblogic"; |
74 | public static final String APP_SERVER_IBM = "websphere"; |
75 | public static final String APP_SERVER_TOMCAT = "tomcat"; |
76 | |
77 | // names of various vendors that ATG works with |
78 | public static final String VENDOR_ATG = "ATG"; |
79 | public static final String VENDOR_BEA = "BEA"; |
80 | public static final String VENDOR_IBM = "IBM"; |
81 | public static final String VENDOR_JBOSS = "JBOSS"; |
82 | |
83 | // the variable that points to the installation directory for dynamo |
84 | private static final String ROOT_VAR = "atg.dynamo.root"; |
85 | private static final String HOME_VAR = "atg.dynamo.home"; |
86 | private static final String ATG_J2EESERVER_ROOT = "atg.j2eeserver.root"; |
87 | |
88 | // these are used to lookup some system settings from the VM |
89 | private static final String JAVA_VAR = "java.vm.info"; |
90 | private static final String JAVA_VERSION = "java.vm.version"; |
91 | private static final String JAVA_BUILD_VERSION = "java.version"; |
92 | private static final String COMPILER_VAR = "java.compiler"; |
93 | private static final String OS_VAR = "os.name"; |
94 | private static final String OS_VERSION_VAR = "os.version"; |
95 | |
96 | // the system variable that returns the name of the app server being used |
97 | private static final String APP_SERVER = "atg.dynamo.appserver"; |
98 | |
99 | // the Configuration component used by Dynamo |
100 | private static final String CONFIGURATION_COMPONENT = "/atg/dynamo/Configuration"; |
101 | |
102 | // mailhost used to send email |
103 | private static final String MAILHOST = "mailsvr.atg.com"; |
104 | |
105 | // value returned by several methods, as noted in javadoc, if a |
106 | // piece of information can not be definitively determined. in |
107 | // particular, used when reporting about product build and version |
108 | // information |
109 | public static final String UNKNOWN_INFO = "unknown"; |
110 | |
111 | /** property to track the DUST version being used. utilized by |
112 | * ATGXMLFileTestResultReported so we can tag XML result files for |
113 | * compatibility validation when passed to the XML file logger */ |
114 | public static int DUST_VERSION = 1; |
115 | |
116 | /** specifies the DUST version being used. utilized by |
117 | * ATGXMLFileTestResultReporter so XML result files can be tagged |
118 | * for compatibility validation when passed to the XML file |
119 | * logger */ |
120 | public void setDustVersion( int pVersion ) { DUST_VERSION = pVersion; } |
121 | |
122 | /** returns the DUST version being used. utilized by |
123 | * ATGXMLFileTestResultReporter so XML result files can be tagged |
124 | * for compatibility validation when passed to the XML file |
125 | * logger */ |
126 | public int getDustVersion() { return DUST_VERSION; } |
127 | |
128 | /** property to track the DUST user. utilized when results are |
129 | * logged to the database to correlate the result with a user |
130 | * account in the test management system. */ |
131 | public static String DUST_USERNAME = System.getProperty( "user.name" ); |
132 | |
133 | /** specifies the DUST user. utilized when results are logged to |
134 | * the database to correlate the result with a user account in the |
135 | * test management system. */ |
136 | public void setDustUsername( String pUsername ) { DUST_USERNAME = pUsername; } |
137 | /** returns the DUST user name. utilized when results are logged to |
138 | * the database to correlate the result with a user account in the |
139 | * test management system. */ |
140 | public String getDustUsername() { |
141 | if ( DUST_USERNAME == null || DUST_USERNAME.trim().length() == 0 ) |
142 | return System.getProperty( "user.name" ); |
143 | else return DUST_USERNAME; |
144 | } |
145 | |
146 | /** property to track which testrun a result is part of. utilized |
147 | * by TSM to correlate a specifid result with the testrun used to |
148 | * install and configure the test Dynamo. */ |
149 | public static String TSM_TESTRUN = null; |
150 | |
151 | /** Specifies the TSM testrun this result is part of. utilized by |
152 | * TSM to correlate a specifid result with the testrun used to |
153 | * install and configure the test Dynamo. */ |
154 | public void setTsmTestrun( String pId ) { TSM_TESTRUN = pId; } |
155 | |
156 | /** Returns the TSM testrun this result is part of. utilized by TSM |
157 | * to correlate a specifid result with the testrun used to install |
158 | * and configure the test Dynamo. */ |
159 | public String getTsmTestrun() { return TSM_TESTRUN; } |
160 | |
161 | /** property to track the p4 sync time for tests. utilized by TSM |
162 | * to inform end-users of time at which machine was last synced. |
163 | * must be specified by test setup before test is run. */ |
164 | public static String P4SYNCTIME = null; |
165 | |
166 | /** property to track the p4 sync time for tests. utilized by TSM |
167 | * to inform end-users of time at which machine was last synced. |
168 | * must be specified by test setup before test is run. */ |
169 | public void setP4Synctime( String pTime ) { P4SYNCTIME = pTime; } |
170 | |
171 | /** property to track the p4 sync time for tests. utilized by TSM |
172 | * to inform end-users of time at which machine was last synced. |
173 | * must be specified by test setup before test is run. */ |
174 | public String setP4Synctime() { return P4SYNCTIME; } |
175 | |
176 | /** Returns the directory in which Dynamo was installed. If the |
177 | * installation directory was not specified during the DUST |
178 | * installation, returns null. Should <b>only</b> be used by |
179 | * System tests. */ |
180 | public static File DYNAMO_INSTALL_DIR = null; |
181 | |
182 | /** Returns the directory in which Dynamo was installed. If the |
183 | * installation directory can not be successfully determined returns |
184 | * null. |
185 | * <br><b>NOTE:</b> There is no reliable System property (or |
186 | * other inherent mechanism) to determine the Dynamo installation |
187 | * directory when running as BigEar, so this value is set during the |
188 | * DUST build process. The SystemTests.base build step writes the |
189 | * file |
190 | * SystemTests/base/config/atg/junit/nucleus/TestUtils.properties |
191 | * with the proper value. Consequently, this method should only be |
192 | * used by System tests, not Unit tests. |
193 | */ |
194 | public File getDynamoInstallDir() { return DYNAMO_INSTALL_DIR; } |
195 | |
196 | /** Specifies the directory in which Dynamo was installed. */ |
197 | public void setDynamoInstallDir( File pDir ) { DYNAMO_INSTALL_DIR = pDir; } |
198 | |
199 | /** Returns the root directory for this Dynamo. If the root |
200 | * directory can not be successfully located returns null. Operates |
201 | * according to this logic: |
202 | * <ul> |
203 | * <li>If "home" Dynamo module can be found, return parent directory |
204 | * containing that module. (This should resolve when running 'BigEar') |
205 | * <li>Otherwise, return value of System property 'atg.dynamo.root'. |
206 | * (this could still be null) |
207 | * </ul> |
208 | */ |
209 | public static File getDynamoRootDir() { |
210 | File root = null; |
211 | try { root = getDynamoHomeDir().getParentFile(); } |
212 | catch (Throwable t) {} |
213 | if ( root == null ) { |
214 | try { root = new File( System.getProperty( ROOT_VAR ) ); } |
215 | catch (Throwable t) {} |
216 | } |
217 | return root; |
218 | } |
219 | |
220 | /** Returns Dynamo's "home" module installation directory. If the |
221 | * directory can not be successfully located returns null. |
222 | * <br>Logic works like this: |
223 | * <ul> |
224 | * <li>If "home" Dynamo module can be found, return directory representing |
225 | * that module. This should resolve when running 'BigEar' and may |
226 | * point to a subdirectory of the application server's directory used |
227 | * to deploy ear files. On DAS it should resolve to |
228 | * <DYNAMO_INSTALL_DIR>/home. |
229 | * <li>Otherwise, return value of System property 'atg.dynamo.home'. |
230 | * (this could be null) |
231 | * </ul> |
232 | */ |
233 | public static File getDynamoHomeDir() { |
234 | File root = null; |
235 | try { root = getModuleResourceFile("home",".").getCanonicalFile(); } |
236 | catch (Throwable t) {} |
237 | if ( root == null ) { |
238 | try { root = new File( System.getProperty( HOME_VAR ) ); } |
239 | catch (Throwable t) {} |
240 | } |
241 | |
242 | return root; |
243 | } |
244 | |
245 | /** returns the root install directory for the ATG J2EE Server, or null if |
246 | * the ATG J2EE Server is not installed. */ |
247 | public static File getAtgJ2eeServerInstallDir() { |
248 | try { return new File(System.getProperty( ATG_J2EESERVER_ROOT )); } |
249 | catch (Throwable t) { return null; } |
250 | } |
251 | |
252 | |
253 | /** Returns the product name of the app server being used. For ATG |
254 | * we currently assume it's called 'ATGDAS' if it's a separate |
255 | * product, since there is no definitive way to figure out the |
256 | * product name from MANIFEST files. For all other app servers it |
257 | * returns the value of getAppServerType(). |
258 | */ |
259 | public static String getAppServerProductName() { |
260 | if ( getAppServerType().equals( APP_SERVER_DAS ) ) return getAtgJ2eeServerProductName(); |
261 | else return getAppServerType(); |
262 | } |
263 | |
264 | /** Returns the name of the ATG J2EE Server product this is installed, or |
265 | * null if a separate ATG J2EE Server build is not installed. */ |
266 | public static String getAtgJ2eeServerProductName() { |
267 | // TODO: Bug 78552 was opened to add a MANIFEST entry containing |
268 | // the product name so we don't have to hard code this to |
269 | // 'ATGDAS'. |
270 | if ( getAtgJ2eeServerInstallDir() != null ) return "ATGDAS"; |
271 | else return null; |
272 | } |
273 | |
274 | /** Returns the version number of the app server being used. For |
275 | * DAS this version comes from the J2EEServer MANIFEST file, or is |
276 | * UNKNOWN_INFO if the MANIFEST can't be found. Such may be the |
277 | * case if a person is using devtools to build their product. For |
278 | * 3PAS the version number is extracted from their configuration |
279 | * file (typically some well known XML file). |
280 | */ |
281 | public static String getAppServerVersion() { |
282 | String apptype = getAppServerType(); |
283 | if ( apptype.equals( APP_SERVER_DAS ) ) { |
284 | return getAtgVersion( getAtgJ2eeServerModule() ); |
285 | } else if ( apptype.equals( APP_SERVER_BEA ) ) { |
286 | return getBeaVersion(); |
287 | } else if ( apptype.equals( APP_SERVER_IBM ) ) { |
288 | return getWasVersion(); |
289 | } else if ( apptype.equals( APP_SERVER_TOMCAT ) ) { |
290 | return getJBossVersion(); |
291 | } else { |
292 | return UNKNOWN_INFO; |
293 | } |
294 | } |
295 | |
296 | /** Returns the build number of the app server being used. For DAS |
297 | * this version comes from the J2EEServer MANIFEST file, or is |
298 | * UNKNOWN_INFO if the MANIFEST can't be found. Such may be the |
299 | * case if a person is using devtools to build their product. For |
300 | * 3PAS the build number is always UNKNOWN_INFO. |
301 | */ |
302 | public static String getAppServerBuildNumber() { |
303 | String apptype = getAppServerType(); |
304 | if ( apptype.equals( APP_SERVER_DAS ) ) { |
305 | return getAtgBuildNumber( getAtgJ2eeServerModule() ); |
306 | } else { |
307 | return UNKNOWN_INFO; |
308 | } |
309 | } |
310 | |
311 | /** Returns the patch version of the app server being used. For DAS |
312 | * this version comes from the J2EEServer MANIFEST file, or is |
313 | * UNKNOWN_INFO if the MANIFEST can't be found. Such may be the |
314 | * case if a person is using devtools to build their product. For |
315 | * 3PAS the patch version is always UNKNOWN_INFO. |
316 | */ |
317 | public static String getAppServerPatchVersion() { |
318 | String apptype = getAppServerType(); |
319 | if ( apptype.equals( APP_SERVER_DAS ) ) { |
320 | return getAtgPatchVersion( getAtgJ2eeServerModule() ); |
321 | } else { |
322 | return UNKNOWN_INFO; |
323 | } |
324 | } |
325 | |
326 | /** Returns the patch build number of the app server being used. |
327 | * For DAS this version comes from the J2EEServer MANIFEST file, or |
328 | * is UNKNOWN_INFO if the MANIFEST can't be found. Such may be the |
329 | * case if a person is using devtools to build their product. For |
330 | * 3PAS the patch build number is always UNKNOWN_INFO. |
331 | */ |
332 | public static String getAppServerPatchBuildNumber() { |
333 | String apptype = getAppServerType(); |
334 | if ( apptype.equals( APP_SERVER_DAS ) ) { |
335 | return getAtgPatchBuildNumber( getAtgJ2eeServerModule() ); |
336 | } else { |
337 | return UNKNOWN_INFO; |
338 | } |
339 | } |
340 | |
341 | /** Returns the vendor name of the App server manufacturer. if a |
342 | * vendor can not be determined it returns UNKNOWN_INFO. |
343 | */ |
344 | public static String getAppServerVendor() { |
345 | String apptype = getAppServerType(); |
346 | if ( apptype.equals( APP_SERVER_DAS ) ) { |
347 | return VENDOR_ATG; |
348 | } else if ( apptype.equals( APP_SERVER_BEA ) ) { |
349 | return VENDOR_BEA; |
350 | } else if ( apptype.equals( APP_SERVER_IBM ) ) { |
351 | return VENDOR_IBM; |
352 | } else if ( apptype.equals( APP_SERVER_TOMCAT ) ) { |
353 | return VENDOR_JBOSS; |
354 | } else { |
355 | return UNKNOWN_INFO; |
356 | } |
357 | } |
358 | |
359 | /** Returns true if the Dynamo product is being used; false if only the ATG |
360 | * J2EE Server product is running. |
361 | **/ |
362 | public static boolean isDynamoInstalled() |
363 | { |
364 | try { |
365 | // if j2ee server is not installed then Dynamo must be... |
366 | if ( getAtgJ2eeServerInstallDir() == null ) return true; |
367 | // if the j2ee server root is the same as the dynamo root then |
368 | // we're running only the j2ee server |
369 | else return ( ! getAtgJ2eeServerInstallDir().getCanonicalFile().equals(getDynamoRootDir().getCanonicalFile() ) ); |
370 | } catch ( IOException ioe ) { |
371 | // this should never happen, but if it does return false... |
372 | return false; |
373 | } |
374 | } |
375 | |
376 | /** This method returns the name of the Dynamo product that is |
377 | * installed. Because there is no guaranteed way to determine the |
378 | * installed product this method makes a best-guess. If the |
379 | * version is less than 5.5 then the method skips down from DCS, to |
380 | * DPS, etc. until it finds a product that exists. If the version |
381 | * 5.5, 5.6, or 5.6.1 then this method just returns 'AppDAP' since |
382 | * that is the only Dynamo product we have for those versions. |
383 | * Likewise, if the version is NOT anything between 4 and 5.6, then |
384 | * we return 'ATG' since that is the only version we have for |
385 | * copper, etc. If the method can't determine a version it returns |
386 | * UNKNOWN_INFO |
387 | */ |
388 | public static String getDynamoProductName() |
389 | { |
390 | AppModule module = getAtgDynamoModule(); |
391 | if ( module == null ) return UNKNOWN_INFO; |
392 | String version = getAtgVersion(module); |
393 | |
394 | if ( version == null ) { |
395 | return UNKNOWN_INFO; |
396 | } else if ( version.startsWith("5.5") || version.startsWith("5.6") ) { |
397 | // this is an AppDAP build of 5.5, 5.6, or 5.6.1 |
398 | return "AppDAP"; |
399 | } else if ( ! version.startsWith("4") && ! version.startsWith("5.0") && ! version.startsWith("5.1") ) { |
400 | // assume this is an ATG build from version 6.x |
401 | // TODO: Bug 78552 was opened to add a MANIFEST entry containing |
402 | // the product name so we don't have to guess at it. |
403 | return "ATG"; |
404 | } else { |
405 | return UNKNOWN_INFO; |
406 | } |
407 | } |
408 | |
409 | /** Returns information about the ATG Dynamo product being used. |
410 | * does not include information about the app server that may be in |
411 | * use. returns null if Dynamo is not running. |
412 | **/ |
413 | public static String getDynamoProductInfo() |
414 | { |
415 | StringBuffer sb = new StringBuffer(); |
416 | AppModule dynamo = getAtgDynamoModule(); |
417 | |
418 | if ( dynamo == null ) return null; |
419 | |
420 | sb.append( getDynamoProductName() + " version " + getAtgVersion(dynamo) ); |
421 | String build = getAtgBuildNumber(dynamo); |
422 | if ( ! build.equals(UNKNOWN_INFO) ) sb.append( " build " + build); |
423 | String patch_version = getAtgPatchVersion(dynamo); |
424 | String patch_build = getAtgPatchBuildNumber(dynamo); |
425 | if ( ! (patch_version == null) && ! patch_version.equals(UNKNOWN_INFO) ) |
426 | sb.append( " with patch " + patch_version + " build " + patch_build ); |
427 | |
428 | return sb.toString(); |
429 | } |
430 | |
431 | /** Returns a summary of information about the App Server product |
432 | * being used. |
433 | */ |
434 | public static String getAppServerProductInfo() { |
435 | StringBuffer sb = new StringBuffer(); |
436 | |
437 | sb.append(getAppServerProductName() + " version " + getAppServerVersion()); |
438 | String build = getAppServerBuildNumber(); |
439 | if ( ! build.equals(UNKNOWN_INFO) ) sb.append( " build " + build); |
440 | String patch_version = getAppServerPatchVersion(); |
441 | String patch_build = getAppServerPatchBuildNumber(); |
442 | if ( ! (patch_version == null) && ! patch_version.equals(UNKNOWN_INFO) ) |
443 | sb.append( " with patch " + patch_version + " build " + patch_build ); |
444 | |
445 | return sb.toString(); |
446 | } |
447 | |
448 | /** returns the java version that Dynamo is using |
449 | * |
450 | * @return String version of java Dynamo is using |
451 | */ |
452 | public static String getJavaVersion() { |
453 | return System.getProperty( JAVA_VERSION ); |
454 | } |
455 | |
456 | /** returns the java build version (java.version) that Dynamo is using |
457 | * |
458 | * @return String build version of java Dynamo is using |
459 | */ |
460 | public static String getJavaBuildVersion() { |
461 | return System.getProperty( JAVA_BUILD_VERSION ); |
462 | } |
463 | |
464 | /** returns detailed version information about the jdk being used */ |
465 | public static String getJavaVersionDetails() { |
466 | return TestUtils.getJavaInfo() + " - " + TestUtils.getJavaVersion(); |
467 | } |
468 | |
469 | /** returns info about the java build that Dynamo is using |
470 | * |
471 | * @return String info about java build Dynamo is using |
472 | */ |
473 | public static String getJavaInfo() { |
474 | return System.getProperty( JAVA_VAR ); |
475 | } |
476 | |
477 | /** returns the type of compiler that Dynamo is using |
478 | * |
479 | * @return String compiler Dynamo is using |
480 | */ |
481 | public static String getCompilerType() { |
482 | return System.getProperty( COMPILER_VAR ); |
483 | } |
484 | |
485 | /** returns the type of Operating System that Dynamo is running on |
486 | */ |
487 | public static String getOperatingSystemType() { |
488 | return System.getProperty( OS_VAR ) |
489 | + " version " + System.getProperty( OS_VERSION_VAR ); |
490 | } |
491 | |
492 | /** returns the hostname of the machine that Dynamo is running on |
493 | */ |
494 | public static String getHostname() { |
495 | try { |
496 | InetAddress address = InetAddress.getLocalHost(); |
497 | return address.getHostName(); |
498 | } catch (UnknownHostException uhe) {} |
499 | |
500 | return "unknown"; |
501 | } |
502 | |
503 | /** returns the name of the app server that dynamo is using */ |
504 | public static String getAppServerType() { |
505 | if ( ServletUtil.isWebLogic() ) return APP_SERVER_BEA; |
506 | else if ( ServletUtil.isWebSphere() ) return APP_SERVER_IBM; |
507 | else if ( ServletUtil.isDynamoJ2EEServer() ) return APP_SERVER_DAS; |
508 | else if ( isGenericAppServer() ) return APP_SERVER_TOMCAT; |
509 | else return System.getProperty( APP_SERVER ); |
510 | } |
511 | |
512 | /** Returns true if Dynamo is running on a 'generic' (aka Tomcat) |
513 | * j2ee appserver; false otherwise. |
514 | * ServletUtil.isGenericJ2EEServer() method call does not exist in |
515 | * early Dynamo versions, so use reflection to invoke it. As of |
516 | * ATG 7x, isGenericJ2EEServer() really means "are we running on |
517 | * JBOSS" - I'm not sure whether we intend to differentiate between |
518 | * JBOSS and other 'generic' Tomcat app servers. |
519 | */ |
520 | public static boolean isGenericAppServer() { |
521 | try { |
522 | ServletUtil.class.newInstance(); |
523 | return ((Boolean) invokeMethod(dynamoEnv(), "isGenericJ2EEServer", null, null, null)).booleanValue(); |
524 | } catch (Throwable t) {} |
525 | return false; |
526 | } |
527 | |
528 | /** returns the WAS home directory if running on WAS. otherwise, |
529 | * returns null */ |
530 | public static String getWasHomeDir() { |
531 | return System.getProperty( "was.install.root" ); |
532 | } |
533 | |
534 | /** returns the WAS version number. if not running against WAS, or |
535 | * if the {WAS.install.root}/properties/version/BASE.product file |
536 | * can not be found, or if an error occurs parsing the file then |
537 | * returns UNKNOWN_INFO. |
538 | */ |
539 | public static String getWasVersion() { |
540 | String version = null; |
541 | try { |
542 | // WAS 5 |
543 | File f = new File( getWasHomeDir(), "properties/version/BASE.product" ); |
544 | // WAS 6 |
545 | if (!f.exists()) |
546 | f = new File( getWasHomeDir(),"properties/version/WAS.product" ); |
547 | |
548 | String[] children1 = { "version" }; |
549 | List<Node> nodes1 = XmlUtils.getNodes(f, false, children1); |
550 | if (nodes1 != null ) { |
551 | Iterator<Node> iter1 = nodes1.iterator(); |
552 | while (iter1.hasNext()) { |
553 | Node n1 = iter1.next(); |
554 | version = XmlUtils.getNodeTextValue(n1); |
555 | } |
556 | } |
557 | } catch (Throwable e) {} |
558 | |
559 | if ( version != null ) return version; |
560 | else return UNKNOWN_INFO; |
561 | } |
562 | |
563 | |
564 | /** returns the full file path of specified was log if |
565 | * getWasHomeDir() is not null. otherwise returns null. */ |
566 | private static File getWasLogFile( String pServerName, String pLogName ) |
567 | { |
568 | if ( getWasHomeDir() == null ) return null; |
569 | else return new File( getWasHomeDir(), "logs" + File.separator + pServerName + File.separator + pLogName ); |
570 | } |
571 | |
572 | private static String mWasSystemOutLogFile = null; |
573 | |
574 | /** Specifies the log file to return when asked for the WAS |
575 | * 'SystemOut.log' file. if this value is null we attempt to |
576 | * calculate a default location */ |
577 | public void setWasSystemOutLogFile( String pFile ) { |
578 | mWasSystemOutLogFile = pFile; |
579 | } |
580 | |
581 | /** returns the expected location of the WAS 'SystemOut.log' file if |
582 | * running on WAS. otherwise returns null.*/ |
583 | public static String getWasSystemOutLogFile() { |
584 | if ( getWasHomeDir() == null ) return null; |
585 | else if (mWasSystemOutLogFile != null |
586 | && mWasSystemOutLogFile.trim().length() > 0) |
587 | return mWasSystemOutLogFile.trim(); |
588 | else { |
589 | File f = getWasLogFile(ServletUtil.getWebsphereServerName(),"SystemOut.log"); |
590 | if (f == null || ! f.exists()) |
591 | f = getWasLogFile( "server1", "SystemOut.log" ); |
592 | |
593 | if ( f != null ) return f.getAbsolutePath(); |
594 | } |
595 | return null; |
596 | } |
597 | |
598 | private static String mWasSystemErrLogFile = null; |
599 | |
600 | /** Specifies the log file to return when asked for the WAS |
601 | * 'SystemErr.log' file. if this value is null we attempt to |
602 | * calculate a default location */ |
603 | public void setWasSystemErrLogFile( String pFile ) { |
604 | mWasSystemErrLogFile = pFile; |
605 | } |
606 | |
607 | /** returns the expected location of the WAS 'SystemErr.log' file if |
608 | * running on WAS. otherwise returns null.*/ |
609 | public static String getWasSystemErrLogFile() { |
610 | if ( getWasHomeDir() == null ) return null; |
611 | else if (mWasSystemErrLogFile != null |
612 | && mWasSystemErrLogFile.trim().length() > 0) |
613 | return mWasSystemErrLogFile.trim(); |
614 | else { |
615 | File f = getWasLogFile(ServletUtil.getWebsphereServerName(),"SystemErr.log"); |
616 | if ( f == null || ! f.exists() ) |
617 | f = getWasLogFile( "server1", "SystemErr.log" ); |
618 | |
619 | if ( f != null ) return f.getAbsolutePath(); |
620 | } |
621 | return null; |
622 | } |
623 | |
624 | /** returns the BEA home directory if running on BEA. otherwise, |
625 | * returns null */ |
626 | public static String getBeaHomeDir() { |
627 | String homedir = System.getProperty( "bea.home" ); |
628 | if ( homedir != null ) return homedir; |
629 | |
630 | // sometimes (like on bea 8) 'bea.home' is not specified, so try |
631 | // to determine bea.home base on another property... |
632 | String startfile = System.getProperty( "java.security.policy" ); |
633 | if ( startfile != null ) { |
634 | // the policy file is (hopefully) always located at a location like: |
635 | // /root/to/bea/<weblogic>/server/lib/weblogic.policy |
636 | // so we basically want to go up four levels from there... |
637 | homedir = atg.core.io.FileUtils.getParent( startfile ); |
638 | // should now be in /root/to/bea/<weblogic>/server/lib |
639 | homedir = atg.core.io.FileUtils.getParent( homedir ); |
640 | // should now be in /root/to/bea/<weblogic>/server |
641 | homedir = atg.core.io.FileUtils.getParent( homedir ); |
642 | // should now be in /root/to/bea/<weblogic> |
643 | homedir = atg.core.io.FileUtils.getParent( homedir ); |
644 | // should now be in /root/to/bea |
645 | } |
646 | |
647 | return homedir; |
648 | } |
649 | |
650 | private static String mBeaMyServerLogFile = null; |
651 | |
652 | /** Specifies the log file to return when asked for the BEA |
653 | * 'myserver.log' file. if this value is null then a default value |
654 | * will be calculated. */ |
655 | public static void setBeaMyServerLogFile( String pFile ) { |
656 | mBeaMyServerLogFile = pFile; |
657 | } |
658 | |
659 | /** returns the expected location of the BEA 'myserver.log' file if |
660 | * running on BEA. otherwise returns null.*/ |
661 | public static String getBeaMyServerLogFile() { |
662 | if ( getBeaHomeDir() == null ) return null; |
663 | else if (mBeaMyServerLogFile != null |
664 | && mBeaMyServerLogFile.trim().length() > 0 ) |
665 | return mBeaMyServerLogFile.trim(); |
666 | else { |
667 | // try this default location.... |
668 | String name = "user_projects" + File.separator + |
669 | "mydomain" + File.separator + |
670 | "myserver" + File.separator + |
671 | "myserver.log"; |
672 | File log = new File( getBeaHomeDir(), name ); |
673 | |
674 | if ( log.exists() ) { |
675 | return log.getAbsolutePath(); |
676 | } else { |
677 | // the default didn't work (as we shouldn't always expect it |
678 | // to) so try this location... 'user.dir' typically points to |
679 | // the domain dir: /path/to/bea/user_projects/mydomain |
680 | // 'weblogic.Name' should be like : myserver |
681 | name = System.getProperty( "user.dir" ) + File.separator + |
682 | System.getProperty( "weblogic.Name" ) + File.separator + |
683 | System.getProperty( "weblogic.Name" ) + ".log"; |
684 | log = new File( name ); |
685 | if ( log.exists() ) return log.getAbsolutePath(); |
686 | } |
687 | } |
688 | return null; |
689 | } |
690 | |
691 | /** returns the BEA version number. if not running against BEA, or if |
692 | * the {BEA_HOME}/registry.xml file can not be found, or if an error occurs |
693 | * parsing the file then returns UNKNOWN_INFO. |
694 | */ |
695 | public static String getBeaVersion() |
696 | { |
697 | String version = null; |
698 | try { |
699 | File f = new File( new File( getBeaHomeDir() ), "registry.xml" ); |
700 | String[] children = { "host", "product", "release" }; |
701 | List<Node> nodes = XmlUtils.getNodes(f, false, children); |
702 | if ( nodes != null ) { |
703 | Iterator<Node> iter = nodes.iterator(); |
704 | // I expect there to only be one <host><product><release> node |
705 | // so this iteration should really just loop over one node. |
706 | while ( iter.hasNext() ) { |
707 | Node n = iter.next(); |
708 | version = XmlUtils.getAttribute(n,"level","0") + "." + |
709 | XmlUtils.getAttribute(n,"ServicePackLevel","0") + "." + |
710 | XmlUtils.getAttribute(n,"PatchLevel","0"); |
711 | } |
712 | } |
713 | } catch (Throwable e) { |
714 | } |
715 | |
716 | if ( version != null ) return version; |
717 | else return UNKNOWN_INFO; |
718 | } |
719 | |
720 | // ---------------- JBOSS Utility Methods -------------------------- |
721 | // NOTE: Available JBoss System property names can be found in class |
722 | // org.jboss.system.server.ServerConfig |
723 | |
724 | /** Returns the JBOSS installation home directory, if Dynamo is |
725 | * running on JBOSS. Otherwise returns null. */ |
726 | public static File getJBossHomeDir() { |
727 | String dir = System.getProperty("jboss.home.dir"); |
728 | if ( dir == null ) return null; |
729 | else return new File(dir); |
730 | } |
731 | |
732 | /** Returns the JBOSS server home directory, if Dynamo is running on |
733 | * JBOSS. Otherwise returns null. */ |
734 | public static File getJBossServerHomeDir() { |
735 | String dir = System.getProperty("jboss.server.home.dir"); |
736 | if ( dir == null ) return null; |
737 | else return new File(dir); |
738 | } |
739 | |
740 | /** Returns the JBOSS server name, if Dynamo is running on JBOSS. |
741 | * Otherwise returns null. */ |
742 | public static String getJBossServerName() { |
743 | return System.getProperty("jboss.server.name"); |
744 | } |
745 | |
746 | /** Returns the path to the JBOSS server log file, if it can be |
747 | * found. Otherwise returns null */ |
748 | public static String getJBossServerLog() { |
749 | try { |
750 | File log = new File( getJBossServerHomeDir(), "log/server.log" ); |
751 | if ( log.exists() ) return log.getAbsolutePath(); |
752 | } catch ( Throwable t ) {} |
753 | return null; |
754 | } |
755 | |
756 | /** Returns the version of JBOSS being used, if it can be |
757 | * determined. Otherwise returns UNKNOWN_INFO. This method |
758 | * expects to find a 'jar-versions.xml' file in the JBoss home |
759 | * directory. It searches for the <jar> element whose 'name' |
760 | * attribute is "jboss.jar", and determines the version based on |
761 | * the value of the 'implVersion' attribute. |
762 | **/ |
763 | public static String getJBossVersion() { |
764 | try { |
765 | File versionFile = new File( getJBossHomeDir(), "jar-versions.xml"); |
766 | if (!versionFile.exists()) { |
767 | log("jar-versions.xml file does not exist; " |
768 | + "unable to determine version info"); |
769 | return UNKNOWN_INFO; |
770 | } |
771 | String[] children = { "jar" }; |
772 | Iterator<Node> nodes = XmlUtils.getNodes(versionFile,false,children).iterator(); |
773 | while ( nodes.hasNext() ) { |
774 | try { |
775 | Node node = nodes.next(); |
776 | String name = node.getAttributes().getNamedItem("name").getNodeValue(); |
777 | log("Checking node: " + name); |
778 | if ( name.equals("jboss.jar") ) { |
779 | String ver = node.getAttributes().getNamedItem("implVersion").getNodeValue().trim(); |
780 | log("JBOSS version string: " + ver); |
781 | // implVersion is typically something like |
782 | // "4.0.1sp1 (build: CVSTag=JBoss_4_0_1_SP1 date=200502160314)" |
783 | // so, strip off the build information since we don't care about it |
784 | int idx = ver.indexOf(" (build:"); |
785 | if ( idx != -1 ) ver = ver.substring(0,idx).trim(); |
786 | return ver; |
787 | } |
788 | } catch (Throwable ti) {} |
789 | } |
790 | } catch (Throwable t) {} |
791 | return UNKNOWN_INFO; |
792 | } |
793 | |
794 | private static atg.service.dynamo.Configuration DYN_CONFIG = null; |
795 | |
796 | /** returns the Configuration component being used by Dynamo */ |
797 | public static atg.service.dynamo.Configuration getDynamoConfiguration() { |
798 | if ( DYN_CONFIG == null ) { |
799 | try { |
800 | DYN_CONFIG = (atg.service.dynamo.Configuration) Nucleus.getGlobalNucleus().resolveName( CONFIGURATION_COMPONENT ); |
801 | } catch (Throwable t) {} |
802 | } |
803 | return DYN_CONFIG; |
804 | } |
805 | |
806 | /** returns the session limit of the specified license component |
807 | * @param String the component name of the license in question |
808 | * @param boolean true if Nucleus should attempt to create the license |
809 | * component if it does not exist |
810 | * @return int the session limit for the license. 0 if the license does not |
811 | * resolve. |
812 | **/ |
813 | public static int getSessionLimit( String pLicense, boolean pResolve ) |
814 | { |
815 | if ( pLicense == null ) return 0; |
816 | LicenseImpl license = (LicenseImpl) Nucleus.getGlobalNucleus().resolveName( pLicense, pResolve ); |
817 | if ( license == null ) return 0; |
818 | return license.getMaxSessions(); |
819 | } |
820 | |
821 | // ==================== EMAIL ====================== |
822 | |
823 | /** This method is used to send an email message and allows the user |
824 | * to specify the return address. |
825 | * @return boolean true if the mail was sent successfully; otherwise false. |
826 | */ |
827 | public static boolean sendEmailWithReturn(String pAddress, String pMsg, |
828 | String pSubject, |
829 | String pBodyEncoding, |
830 | String pReturnAddress ) |
831 | { |
832 | try { |
833 | // create a Message with the given From and Subject |
834 | Message msg = MimeMessageUtils.createMessage( pReturnAddress, pSubject); |
835 | // set the To recipient |
836 | MimeMessageUtils.setRecipient(msg, Message.RecipientType.TO, pAddress); |
837 | |
838 | // set the message content: multipart message + attachment |
839 | if ( pBodyEncoding == null || pBodyEncoding.trim().length() == 0 ) |
840 | pBodyEncoding = "text/plain"; |
841 | ContentPart[] content = |
842 | { new ContentPart( pMsg, pBodyEncoding) }; |
843 | MimeMessageUtils.setContent(msg, content); |
844 | |
845 | // create the email event |
846 | EmailEvent em = new EmailEvent(msg); |
847 | |
848 | // now send the event |
849 | SMTPEmailSender sender = new SMTPEmailSender(); |
850 | sender.setEmailHandlerHostName( MAILHOST ); |
851 | sender.sendEmailEvent( em ); |
852 | } catch (Exception e) { |
853 | log.info("Caught exception sending email: " + e.toString() ); |
854 | return false; |
855 | } |
856 | return true; |
857 | } |
858 | |
859 | /** This method is used to send an email message; returns true if |
860 | * everything went ok; otherwise, returns false |
861 | */ |
862 | public static boolean sendEmail(String pAddress, String pMsg, |
863 | String pSubject, String pBodyEncoding) |
864 | { |
865 | return sendEmailWithReturn(pAddress,pMsg,pSubject,pBodyEncoding,pAddress); |
866 | } |
867 | |
868 | /** This method is used to send an email message; returns true if |
869 | * everything went ok; otherwise, returns false |
870 | */ |
871 | public static boolean sendEmail(String pAddress, String pMsg, |
872 | String pSubject) |
873 | { |
874 | return sendEmail( pAddress, pMsg, pSubject, "text/plain" ); |
875 | } |
876 | |
877 | /** This method is used to send the same email message to a vector |
878 | * of recipients |
879 | */ |
880 | public static void sendEmails(List<String> pAddresses, String pMsg, |
881 | String pSubject, String pBodyEncoding ) |
882 | { |
883 | // make sure addresses are valid |
884 | if ( pAddresses == null || |
885 | pAddresses.size() <= 0 ) |
886 | return; |
887 | |
888 | // send emails |
889 | Iterator<String> addresses = pAddresses.iterator(); |
890 | String address = null; |
891 | while ( addresses.hasNext() ) { |
892 | try { |
893 | address = addresses.next(); |
894 | if ( address != null && address.trim().length() > 0 ) |
895 | sendEmail(address.trim(),pMsg,pSubject,null,null,null,pBodyEncoding); |
896 | } catch (Exception e) {} |
897 | } |
898 | } |
899 | |
900 | /** This method is used to send the same email message to a vector |
901 | * of recipients. It encodes the message body as "text/plain". |
902 | */ |
903 | public static void sendEmails(List<String> pAddresses, String pMsg, |
904 | String pSubject ) |
905 | { |
906 | sendEmails( pAddresses, pMsg, pSubject, "text/plain" ); |
907 | } |
908 | |
909 | /** This method is used to send an email message that contains |
910 | * several attachments. This method is specifically designed to |
911 | * accept a map of java.lang.Strings as content parts instead of |
912 | * java.io.Files. The key in the Map should be a String |
913 | * representing the name that you would like to show for the |
914 | * attached file. The value in the Map should be a String |
915 | * representing the contents of the attachment. |
916 | */ |
917 | public static void sendEmail(String pAddress, String pMsg, String pSubject, |
918 | Map<String, Object> pTextAttachments, Map<String, Object> pHTMLAttachments, |
919 | File[] pFiles, String pBodyEncoding ) |
920 | { |
921 | try { |
922 | // make sure addresses are valid |
923 | if ( pAddress == null || |
924 | pAddress.trim().length() == 0 ) |
925 | return; |
926 | |
927 | // create a Message with the given From and Subject |
928 | Message msg = MimeMessageUtils.createMessage( pAddress, pSubject); |
929 | |
930 | // set the To recipient |
931 | MimeMessageUtils.setRecipient(msg, Message.RecipientType.TO, pAddress); |
932 | |
933 | // create the MultiPart used to hold everything |
934 | Multipart mp = new MimeMultipart(); |
935 | |
936 | // set the message content: multipart message + attachment |
937 | BodyPart guts = new MimeBodyPart(); |
938 | if ( pBodyEncoding == null || pBodyEncoding.trim().length() == 0 ) |
939 | pBodyEncoding = "text/plain"; |
940 | guts.setContent( pMsg, pBodyEncoding ); |
941 | mp.addBodyPart( guts ); |
942 | |
943 | // add the text attachments |
944 | if ( pTextAttachments != null ) { |
945 | Iterator<String> textkeys = pTextAttachments.keySet().iterator(); |
946 | while ( textkeys.hasNext() ) { |
947 | String key = textkeys.next(); |
948 | Object val = pTextAttachments.get( key ); |
949 | if ( val != null ) { |
950 | MimeBodyPart part = new MimeBodyPart(); |
951 | part.setContent( val.toString(), "text/plain" ); |
952 | part.setDisposition( MimeBodyPart.ATTACHMENT ); |
953 | part.setDescription( key ); |
954 | part.setFileName( key ); |
955 | mp.addBodyPart( part ); |
956 | } |
957 | } |
958 | } |
959 | |
960 | // add the html attachments |
961 | if ( pHTMLAttachments != null ) { |
962 | Iterator<String> htmlkeys = pHTMLAttachments.keySet().iterator(); |
963 | while ( htmlkeys.hasNext() ) { |
964 | String key = htmlkeys.next(); |
965 | Object val = pHTMLAttachments.get( key ); |
966 | if ( val != null ) { |
967 | MimeBodyPart part = new MimeBodyPart(); |
968 | part.setContent( val.toString(), "text/html" ); |
969 | part.setDisposition( MimeBodyPart.ATTACHMENT ); |
970 | part.setDescription( key ); |
971 | part.setFileName( key ); |
972 | mp.addBodyPart( part ); |
973 | } |
974 | } |
975 | } |
976 | |
977 | // add the File attachments |
978 | if ( pFiles != null ) { |
979 | for ( int i=0; i<pFiles.length; i++ ) { |
980 | MimeBodyPart part = new MimeBodyPart(); |
981 | part.setDataHandler(new DataHandler(new FileDataSource(pFiles[i]))); |
982 | part.setFileName( pFiles[i].getName() ); |
983 | mp.addBodyPart( part ); |
984 | } |
985 | } |
986 | |
987 | msg.setContent( mp ); |
988 | |
989 | // create the email event |
990 | EmailEvent em = new EmailEvent(msg); |
991 | |
992 | // now send the event |
993 | SMTPEmailSender sender = new SMTPEmailSender(); |
994 | sender.setEmailHandlerHostName( MAILHOST ); |
995 | sender.sendEmailEvent( em ); |
996 | } catch (Exception e) { |
997 | log.info("Caught exception sending email: " + e.toString() ); |
998 | e.printStackTrace(); |
999 | } |
1000 | } |
1001 | |
1002 | /** This method is used to send an email message that contains |
1003 | * several attachments. This method is specifically designed to |
1004 | * accept a map of java.lang.Strings as content parts instead of |
1005 | * java.io.Files. The key in the Map should be a String |
1006 | * representing the name that you would like to show for the |
1007 | * attached file. The value in the Map should be a String |
1008 | * representing the contents of the attachment. If you wish to |
1009 | * attach java.io.Files, use the static methods found in |
1010 | * atg.service.email.MimeMessageUtils. |
1011 | */ |
1012 | public static void sendEmail(String pAddress, String pMsg, String pSubject, |
1013 | Map<String, Object> pTextAttachments, Map<String, Object> pHTMLAttachments, |
1014 | String pBodyEncoding ) |
1015 | { |
1016 | sendEmail( pAddress, pMsg, pSubject, pTextAttachments, pHTMLAttachments, null, pBodyEncoding ); |
1017 | } |
1018 | |
1019 | /** This method is used to send an email message that contains |
1020 | * several attachments. This method is specifically designed to |
1021 | * accept a map of java.lang.Strings as content parts instead of |
1022 | * java.io.Files. The key in the Map should be a String |
1023 | * representing the name that you would like to show for the |
1024 | * attached file. The value in the Map should be a String |
1025 | * representing the contents of the attachment. If you wish to |
1026 | * attach java.io.Files, use the static methods found in |
1027 | * atg.service.email.MimeMessageUtils. |
1028 | */ |
1029 | public static void sendEmail( String pAddress, String pMsg, String pSubject, |
1030 | Map<String, Object> pTextAttachments, Map<String, Object> pHTMLAttachments ) |
1031 | { |
1032 | sendEmail( pAddress,pMsg,pSubject,pTextAttachments,pHTMLAttachments,"text/plain"); |
1033 | } |
1034 | |
1035 | |
1036 | /** This method is used to send an email message that contains |
1037 | * several attachments. This method is specifically designed to |
1038 | * accept a map of java.lang.Strings as content parts instead of |
1039 | * java.io.Files. The key in the Map should be a String |
1040 | * representing the name that you would like to show for the |
1041 | * attached file. The value in the Map should be a String |
1042 | * representing the contents of the attachment. |
1043 | */ |
1044 | public static void sendEmails(List<String> pAddresses, String pMsg, |
1045 | String pSubject, Map<String, Object> pTextAttachments, |
1046 | Map<String, Object> pHTMLAttachments, File[] pFiles, |
1047 | String pBodyEncoding ) |
1048 | { |
1049 | // make sure addresses are valid |
1050 | if ( pAddresses == null || |
1051 | pAddresses.size() <= 0 ) |
1052 | return; |
1053 | |
1054 | // send emails |
1055 | Iterator<String> addresses = pAddresses.iterator(); |
1056 | String address = null; |
1057 | while ( addresses.hasNext() ) { |
1058 | try { |
1059 | address = addresses.next(); |
1060 | if ( address != null && address.trim().length() > 0 ) |
1061 | sendEmail(address.trim(), pMsg, pSubject, pTextAttachments, |
1062 | pHTMLAttachments, pFiles, pBodyEncoding ); |
1063 | } catch (Exception e) {} |
1064 | } |
1065 | } |
1066 | |
1067 | /** This method is used to send an email message that contains |
1068 | * several attachments to multiple recipients. This method is |
1069 | * specifically designed to accept a map of java.lang.Strings as |
1070 | * content parts instead of java.io.Files. The key in the Map |
1071 | * should be a String representing the name that you would like to |
1072 | * show for the attached file. The value in the Map should be a |
1073 | * String representing the contents of the attachment. |
1074 | */ |
1075 | public static void sendEmails(List<String> pAddresses, String pMsg, |
1076 | String pSubject, Map<String, Object> pTextAttachments, |
1077 | Map<String, Object> pHTMLAttachments, String pBodyEncoding ) |
1078 | { |
1079 | sendEmails( pAddresses, pMsg, pSubject, pTextAttachments, pHTMLAttachments, null, pBodyEncoding ); |
1080 | } |
1081 | |
1082 | /** This method is used to send an email message that contains |
1083 | * several attachments to multiple recipients. The message will |
1084 | * have it's main body part encoded as "text/plain". <br>This |
1085 | * method is specifically designed to accept a map of |
1086 | * java.lang.Strings as content parts instead of java.io.Files. |
1087 | * The key in the Map should be a String representing the name that |
1088 | * you would like to show for the attached file. The value in the |
1089 | * Map should be a String representing the contents of the |
1090 | * attachment. If you wish to attach java.io.Files, use the static |
1091 | * methods found in atg.service.email.MimeMessageUtils. |
1092 | */ |
1093 | public static void sendEmails(List<String> pAddresses, String pMsg, |
1094 | String pSubject, Map<String, Object> pTextAttachments, |
1095 | Map<String, Object> pHTMLAttachments ) |
1096 | { |
1097 | sendEmails(pAddresses,pMsg,pSubject,pTextAttachments,pHTMLAttachments,"text/plain"); |
1098 | } |
1099 | |
1100 | // ======================== EXCEPTIONS ===================== |
1101 | |
1102 | /** this method returns a String representation of an Exception's stacktrace |
1103 | */ |
1104 | public static String getStackTrace( Throwable pException ) { |
1105 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
1106 | PrintStream ps = new PrintStream( bos ); |
1107 | pException.printStackTrace( ps ); |
1108 | ps.flush(); |
1109 | return bos.toString(); |
1110 | } |
1111 | |
1112 | // ===================== URL ACCESS ======================== |
1113 | |
1114 | /** this method returns the contents of the page specified as the |
1115 | * URL. the URL should be a fully qualified request string. for |
1116 | * example, http://rygar.atg.com:8880/some/directory/page.jhtml |
1117 | * |
1118 | * If the boolean parameter is set to true then this method will |
1119 | * throw an Exception if an error occurs; otherwise it will simply |
1120 | * return the contents of the exception. |
1121 | * |
1122 | * @exception MalformedURLException if URL is malformed & pThrow is true |
1123 | * @exception IOException if error happens while reading and pThrow is true |
1124 | */ |
1125 | public static String accessURL( String pUrl, boolean pThrow ) |
1126 | throws MalformedURLException, IOException |
1127 | { |
1128 | URL url = null; |
1129 | StringBuffer results = new StringBuffer(); |
1130 | BufferedReader in = null; |
1131 | InputStreamReader isr = null; |
1132 | try { |
1133 | url = new URL( pUrl ); |
1134 | |
1135 | isr = new InputStreamReader( url.openStream() ); |
1136 | in = new BufferedReader( isr ); |
1137 | String line = null; |
1138 | while ( ( line = in.readLine() ) != null ) { |
1139 | results.append( line + "\n" ); |
1140 | } |
1141 | return results.toString(); |
1142 | } catch ( MalformedURLException e ) { |
1143 | if ( pThrow ) |
1144 | throw e; |
1145 | else |
1146 | results.append( "\nEncountered an unexpected error while trying to retrieve the configuration info." + |
1147 | "\nWhen the url " + url + " was requested, this error was received: \n" + getStackTrace( e ) + "\n" ); |
1148 | } catch ( IOException ioe ) { |
1149 | if ( pThrow ) |
1150 | throw ioe; |
1151 | else |
1152 | results.append( "\nEncountered an unexpected error while trying to retrieve the configuration info." + |
1153 | "\nWhen the url " + url + " was requested, this error was received: \n" + getStackTrace( ioe ) + "\n"); |
1154 | } finally { |
1155 | if ( in != null ) { |
1156 | try { in.close(); } |
1157 | catch (Exception e) {} |
1158 | } |
1159 | if ( isr != null ) { |
1160 | try { isr.close(); } |
1161 | catch (Exception e) {} |
1162 | } |
1163 | } |
1164 | return results.toString(); |
1165 | } |
1166 | |
1167 | /** this method returns the contents of the page specified as the URL. the |
1168 | * URL should be a fully qualified request string. for example, |
1169 | * http://rygar.atg.com:8880/some/directory/page.jhtml |
1170 | * |
1171 | * Unlike it's sister method with the boolean parameter, this method will |
1172 | * not throw an exception. |
1173 | */ |
1174 | public static String accessURL( String pUrl ) |
1175 | { |
1176 | try { |
1177 | return accessURL( pUrl, false ); |
1178 | } catch (Exception e) { |
1179 | return "\nEncountered an unexpected error while trying to retrieve the configuration info." + |
1180 | "\nWhen the url " + pUrl + " was requested, this error was received: \n" + getStackTrace( e ) + "\n"; |
1181 | } |
1182 | } |
1183 | |
1184 | // ==================== File IO ============================ |
1185 | |
1186 | /** |
1187 | * Writes the byte array into the specified file. |
1188 | * |
1189 | * @param File pFile the file to write to |
1190 | * @param byte[] the bytes to write |
1191 | * |
1192 | * @exception IOException if an error occurred opening or reading the file. |
1193 | */ |
1194 | public static void writeFileBytes(File pFile, byte[] pBytes) |
1195 | throws IOException |
1196 | { |
1197 | if ( pBytes == null ) pBytes = new byte[0]; |
1198 | FileOutputStream fos = null; |
1199 | try { |
1200 | fos = new FileOutputStream( pFile ); |
1201 | fos.write( pBytes ); |
1202 | } |
1203 | catch (IOException e) { |
1204 | throw e; |
1205 | } |
1206 | finally { |
1207 | try { if (fos != null) fos.close (); } |
1208 | catch (IOException exc) {} |
1209 | } |
1210 | } |
1211 | |
1212 | /** converts a delimiter separated String of file names into an |
1213 | * array and expands all System property variables in the Strings. |
1214 | * it does not check whether resolved file paths exist. |
1215 | * |
1216 | * @param String delimited string of files to be converted to array. |
1217 | * @param String delimiter string used to separated files |
1218 | * @return String[] array of expanded paths |
1219 | * @exception Exception if files can't be resolved properly |
1220 | */ |
1221 | public static String[] convertFileArray( String pFiles, String pDelimiter ) |
1222 | throws Exception |
1223 | { |
1224 | return convertFileArray( pFiles, pDelimiter, null ); |
1225 | } |
1226 | |
1227 | /** converts a delimiter separated String of file names into an array |
1228 | * and expands all variables in the Strings. it does not check whether |
1229 | * resolved file paths exist. |
1230 | * |
1231 | * @param String delimited string of files to be converted to array. |
1232 | * @param String delimiter string used to separated files |
1233 | * @param Properties optional primary mapping of key/value pairs to |
1234 | * substitute into file paths whererever the syntax <tt>{...}</tt> |
1235 | * is found. If parameter is null, or mapping not found, then |
1236 | * System.getProperties() is checked. |
1237 | * @return String[] array of expanded paths |
1238 | * @exception Exception if files can't be resolved properly |
1239 | */ |
1240 | public static String[] convertFileArray(String pFiles, String pDelimiter, |
1241 | Properties pPrimaryMapping ) |
1242 | throws Exception |
1243 | { |
1244 | if ( pDelimiter == null ) pDelimiter = ""; |
1245 | StringTokenizer st = new StringTokenizer( pFiles, pDelimiter ); |
1246 | List<String> files = new LinkedList<String>(); |
1247 | while ( st.hasMoreTokens() ) { |
1248 | files.add( expand(st.nextToken(), pPrimaryMapping) ); |
1249 | } |
1250 | return (String[]) files.toArray( new String[files.size()] ); |
1251 | } |
1252 | |
1253 | /** expands all System property variables specified in the supplied |
1254 | * String using curly braces syntax <tt>{...}</tt> and returns the |
1255 | * resulting String. |
1256 | * |
1257 | * @param String the string to expand. |
1258 | * @exception Exception if a System property resolves to null or if |
1259 | * the enclosing braces are not properly matched. |
1260 | */ |
1261 | public static String expand( String pString ) |
1262 | throws Exception |
1263 | { |
1264 | return expand( pString, null ); |
1265 | } |
1266 | |
1267 | /** expands all property variables specified in the supplied String |
1268 | * using curly braces syntax <tt>{...}</tt> and returns the |
1269 | * resulting String. Property names inside the curly braces can be |
1270 | * either a simple String referring to a Java System property, such |
1271 | * as "SystemProperty.X", or can be in AppModuleResource format, |
1272 | * such as |
1273 | * "appModuleResource?moduleID=MyModule&resource=my/resource/file". |
1274 | * |
1275 | * @param String the string to expand. |
1276 | * @param Properties an optional primary key/value mapping to use |
1277 | * for System property substitutions. If param is null, or if |
1278 | * mapping not found, then System.getProperties().getProperty(xxx) |
1279 | * is used. |
1280 | * @return String the expanded string. |
1281 | * @exception Exception if a System or AppModuleResource property |
1282 | * resolves to null or if the enclosing braces are not properly |
1283 | * matched. |
1284 | */ |
1285 | public static String expand( String pString, Properties pPrimaryMapping ) |
1286 | throws Exception |
1287 | { |
1288 | int idx = pString.indexOf("{"); |
1289 | while ( idx != -1 ) { |
1290 | int end = pString.indexOf("}"); |
1291 | if ( end == -1 ) |
1292 | throw new Exception("Unclosed braces in String " + pString ); |
1293 | String pname = pString.substring(idx+1,end); |
1294 | String prop = null; |
1295 | if ( pPrimaryMapping != null ) prop = pPrimaryMapping.getProperty(pname); |
1296 | if ( prop == null ) { |
1297 | if ( pname.startsWith("appModuleResource?") ) |
1298 | prop = resolveAppModuleResourceReference(pname).getPath(); |
1299 | // atg.dynamo.root and atg.dynamo.home are resolved specially |
1300 | // because of BigEar |
1301 | else if ( pname.equals(ROOT_VAR) ) prop = getDynamoRootDir().getPath(); |
1302 | else if ( pname.equals(HOME_VAR) ) prop = getDynamoHomeDir().getPath(); |
1303 | else prop = System.getProperty(pname); |
1304 | } |
1305 | if ( prop == null ) |
1306 | throw new Exception("System property '" |
1307 | + pString.substring(idx+1,end) |
1308 | + "' is null. String " + pString |
1309 | + " can not be resolved."); |
1310 | |
1311 | pString = pString.substring(0,idx) + prop + pString.substring(end+1); |
1312 | idx = pString.indexOf("{"); |
1313 | } |
1314 | return pString; |
1315 | } |
1316 | |
1317 | // ===================== atg dynamo info =================================== |
1318 | |
1319 | /** product module corresponding to ATG Dynamo */ |
1320 | public static String ATGDYNAMO_PRODUCT_MODULE = "DPS"; |
1321 | |
1322 | /** specifies the name of the ATG Dynamo product module that will be |
1323 | * loaded if Dynamo is being used. */ |
1324 | public static void setAtgDynamoProductModule( String pModule ) { |
1325 | ATGDYNAMO_PRODUCT_MODULE = pModule; |
1326 | } |
1327 | |
1328 | /** returns the name of the ATG Dynamo product module that will be |
1329 | * loaded if Dynamo is being used. */ |
1330 | public static String getAtgDynamoProductModule() { |
1331 | return ATGDYNAMO_PRODUCT_MODULE; |
1332 | } |
1333 | |
1334 | /** returns an AppModule corresponding to the ATG Dynamo if that |
1335 | * product is loaded. If it isn't loaded then returns null. |
1336 | */ |
1337 | public static AppModule getAtgDynamoModule() |
1338 | { |
1339 | // get all modules that were started with dynamo |
1340 | Iterator<?> modules = getAppLauncher().getModules().iterator(); |
1341 | |
1342 | while ( modules.hasNext() ) { |
1343 | AppModule module = (AppModule)modules.next(); |
1344 | if ( module.getName().equals( getAtgDynamoProductModule() ) ) |
1345 | return module; |
1346 | } |
1347 | |
1348 | return null; |
1349 | } |
1350 | |
1351 | // ==================== atg j2ee server info ============================== |
1352 | |
1353 | /** product module corresponding to ATG's J2EE Server */ |
1354 | public static String ATGJ2EESERVER_PRODUCT_MODULE = "J2EEServer"; |
1355 | |
1356 | /** specifies the name of the ATG J2EE Server product module that |
1357 | * will be loaded if ATG's J2EE Server is being used. */ |
1358 | public static void setAtgJ2eeServerProductModule( String pModule ) { |
1359 | ATGJ2EESERVER_PRODUCT_MODULE = pModule; |
1360 | } |
1361 | |
1362 | /** returns the name of the ATG J2EE Server product module that will |
1363 | * be loaded if ATG's J2EE Server is being used. */ |
1364 | public static String getAtgJ2eeServerProductModule() { |
1365 | return ATGJ2EESERVER_PRODUCT_MODULE; |
1366 | } |
1367 | |
1368 | /** returns an AppModule corresponding to the ATG J2EE Server if |
1369 | * that product is loaded. If it isn't loaded then returns null. |
1370 | */ |
1371 | public static AppModule getAtgJ2eeServerModule() |
1372 | { |
1373 | // get all modules that were started with dynamo |
1374 | Iterator<?> modules = getAppLauncher().getModules().iterator(); |
1375 | |
1376 | while ( modules.hasNext() ) { |
1377 | AppModule module = (AppModule)modules.next(); |
1378 | if ( module.getName().equals( getAtgJ2eeServerProductModule() ) ) |
1379 | return module; |
1380 | } |
1381 | |
1382 | return null; |
1383 | } |
1384 | |
1385 | // ==================== application info ============================ |
1386 | |
1387 | /** possible application product modules that may be installed */ |
1388 | public static String[] APPLICATION_PRODUCT_MODULES = {"ACA","ABTest","DCS-SO","CAF"}; |
1389 | |
1390 | /** specifies the names of possible application product modules that |
1391 | * may be installed in Dyanmo. used to help report on which |
1392 | * application modules are running. */ |
1393 | public void setApplicationProductModules( String[] pModules ) { |
1394 | APPLICATION_PRODUCT_MODULES = pModules; |
1395 | } |
1396 | |
1397 | /** returns the names of possible application product modules that |
1398 | * may be installed in Dyanmo. used to help report on which |
1399 | * application modules are running. NOTE: This method should not |
1400 | * be called. It is only provided so we can specify application |
1401 | * modules in a .properties file. Java classes should call method |
1402 | * getApplicationModules().*/ |
1403 | public String[] getApplicationProductModules() { |
1404 | return APPLICATION_PRODUCT_MODULES; |
1405 | } |
1406 | |
1407 | /** returns an array of AppModule items corresponding to the |
1408 | * currently running application products. |
1409 | */ |
1410 | public static AppModule[] getApplicationModules() |
1411 | { |
1412 | List<AppModule> apps = new LinkedList<AppModule>(); |
1413 | |
1414 | // get all modules that were started with dynamo |
1415 | Iterator<?> modules = getAppLauncher().getModules().iterator(); |
1416 | |
1417 | while ( modules.hasNext() ) { |
1418 | AppModule module = (AppModule)modules.next(); |
1419 | for ( int i=0; i<APPLICATION_PRODUCT_MODULES.length; i++ ) { |
1420 | // in order to work around bug 80207, we allow a colon ":" in |
1421 | // the specified module names. if a colon exists, the name |
1422 | // before the colon is the name of the module that would be |
1423 | // started if the application is running. the name after the |
1424 | // colon is the module containing the MANIFEST.MF file with |
1425 | // build info. if there is no colon, assume the two modules |
1426 | // are the same. |
1427 | int idx = APPLICATION_PRODUCT_MODULES[i].indexOf(":"); |
1428 | if ( idx == -1 ) { |
1429 | // no colon... |
1430 | if ((APPLICATION_PRODUCT_MODULES[i]).equals(module.getName())) |
1431 | apps.add( module ); |
1432 | } else { |
1433 | if (APPLICATION_PRODUCT_MODULES[i].substring(0,idx).equals(module.getName())) { |
1434 | // NOTE: getAppLauncher().getModule(...) will return a |
1435 | // module as long as it exists; the module does not need |
1436 | // to be running. |
1437 | try { |
1438 | AppModule mod = getAppLauncher().getModule(APPLICATION_PRODUCT_MODULES[i].substring(idx+1)); |
1439 | log.info("\nMod: " + mod ); |
1440 | if ( mod != null ) apps.add( mod ); |
1441 | else throw new Exception(APPLICATION_PRODUCT_MODULES[i].substring(idx+1) + " not found."); |
1442 | } catch (Exception ale) { |
1443 | log.info("*** WARNING [atg.junit.nucleus.TestUtils] " |
1444 | + "Can not resolve module '" |
1445 | + APPLICATION_PRODUCT_MODULES[i].substring(idx+1) |
1446 | + "'. " |
1447 | + ale.getMessage() ); |
1448 | } |
1449 | } |
1450 | } |
1451 | } |
1452 | } |
1453 | |
1454 | return (AppModule[]) apps.toArray( new AppModule[ apps.size() ] ); |
1455 | } |
1456 | |
1457 | // =========== generic AppModule info retrieval methods ==================== |
1458 | |
1459 | private static AppLauncher mAppLauncher = null; |
1460 | |
1461 | /** Returns the AppLauncher used to load this class. */ |
1462 | private static AppLauncher getAppLauncher() |
1463 | { |
1464 | if ( mAppLauncher == null ) |
1465 | mAppLauncher = AppLauncher.getAppLauncher( TestUtils.class ); |
1466 | return mAppLauncher; |
1467 | } |
1468 | |
1469 | /** Retrieves a File resource from a Dynamo Module. Note that the |
1470 | * module does not need to be started, it simply has to be |
1471 | * installed in the Dynamo. Returned file is <u>not</u> verified |
1472 | * to exist. |
1473 | * |
1474 | * @param String pModuleName the name of the Dynamo module to look in. e.g. "SystemTests.JSPTest" |
1475 | * @param String pResourceURI the URI of the File to get from the module. e.g. "mite.xml" |
1476 | * @return File the requested file. |
1477 | **/ |
1478 | public static File getModuleResourceFile(String pModuleName, String pResourceURI ) |
1479 | { |
1480 | return getAppLauncher().getAppModuleManager().getResourceFile(pModuleName, pResourceURI); |
1481 | } |
1482 | |
1483 | /** Resolves an appModuleResource reference by parsing the string |
1484 | * into its constituent ModuleID and ResourceURI. |
1485 | * |
1486 | * @param String pReference The AppModuleResource reference to resolve. Expected to be of format: |
1487 | * <br><tt>appModuleResource?moduleID=<i>moduleID</i>&resourceURI=<i>some/URI</i></tt> |
1488 | * @return File the referenced module resource. |
1489 | * @exception IllegalArgumentException if the specified reference does not have the proper structure. |
1490 | */ |
1491 | public static File resolveAppModuleResourceReference( String pReference ) |
1492 | { |
1493 | // there's probably a standard utility method in Dynamo to do this |
1494 | // resolution, but i can't find it... |
1495 | String moduleID = null; |
1496 | String resourceURI = null; |
1497 | String ref = pReference; |
1498 | try { |
1499 | int idx = ref.indexOf("moduleID="); // locate moduleID delimiter |
1500 | if ( idx == -1 ) throw new Exception(); |
1501 | ref = ref.substring( idx + 9 ); // strip up to and including 'moduleID=' |
1502 | idx = ref.indexOf("&resourceURI="); // get index of resourceURI delimiter |
1503 | moduleID = ref.substring( 0,idx ); // extract moduleID |
1504 | resourceURI = ref.substring( idx + 13 ); // extract resourceURI |
1505 | } catch (Throwable t) { |
1506 | throw new IllegalArgumentException("Can not resolve appModuleReference. " |
1507 | + "Illegal reference syntax: " |
1508 | + pReference); |
1509 | } |
1510 | return getModuleResourceFile(moduleID, resourceURI); |
1511 | } |
1512 | |
1513 | /** Retrieves a piece of information from the MANIFEST of the |
1514 | * supplied AppModule. Returns null if the specified information |
1515 | * can't be found. |
1516 | */ |
1517 | public static String getManifestInfo( AppModule pModule, String pEntry) |
1518 | { |
1519 | return getManifestInfo( pModule.getManifest(), pEntry ); |
1520 | } |
1521 | /** |
1522 | * Logs a message using Nucleus.logInfo() if Nucleus is available. |
1523 | * Otherwise it logs using log.info() |
1524 | * @param pMessage |
1525 | */ |
1526 | public static void log (String pMessage) { |
1527 | Nucleus n = Nucleus.getGlobalNucleus(); |
1528 | if (n != null) |
1529 | n.logInfo(pMessage); |
1530 | else |
1531 | log.info(new java.util.Date() + ":" + pMessage); |
1532 | } |
1533 | |
1534 | /** Retrieves a piece of information from the specified Manifest file. |
1535 | * Returns null if the specified information can't be found. |
1536 | */ |
1537 | public static String getManifestInfo( Manifest pManifest, String pEntry) |
1538 | { |
1539 | // if manifest or entry key is null return null... |
1540 | if ( pManifest == null || pEntry == null ) return null; |
1541 | |
1542 | if ( pManifest.getMainAttributes() == null ) return null; |
1543 | else return pManifest.getMainAttributes().getValue( pEntry ); |
1544 | } |
1545 | |
1546 | /** Returns the ATG product version ("ATG-Version") of the specified module. |
1547 | * Returns UNKNOWN_INFO if the product version can't be determined. |
1548 | **/ |
1549 | public static String getAtgVersion(AppModule pModule) { |
1550 | String version = getManifestInfo(pModule, "ATG-Version"); |
1551 | if ( version != null ) return version; |
1552 | else return UNKNOWN_INFO; |
1553 | } |
1554 | |
1555 | /** Returns the ATG product build number ("ATG-Build") of the |
1556 | * specified module. Returns UNKNOWN_INFO if the build number |
1557 | * can't be determined. |
1558 | **/ |
1559 | public static String getAtgBuildNumber(AppModule pModule) { |
1560 | String build = getManifestInfo(pModule, "ATG-Build"); |
1561 | if ( build != null ) return build; |
1562 | else return UNKNOWN_INFO; |
1563 | } |
1564 | |
1565 | /** Returns the ATG patch version ("ATG-Patch-Version") of the |
1566 | * specified module. Returns null if the module's version can be |
1567 | * determined, but a patch version can't. Returns UNKNOWN_INFO if |
1568 | * neither the product or patch version can be determined. |
1569 | **/ |
1570 | public static String getAtgPatchVersion(AppModule pModule) { |
1571 | String version = getManifestInfo(pModule, "ATG-Patch-Version"); |
1572 | if ( version != null ) return version; |
1573 | else if (getAtgVersion(pModule).equals(UNKNOWN_INFO)) return UNKNOWN_INFO; |
1574 | else return null; |
1575 | } |
1576 | |
1577 | /** Returns the ATG patch build number ("ATG-Patch-Build") of the |
1578 | * specified module. Returns null if the module's build number can |
1579 | * be determined, but a patch build number can't. Returns |
1580 | * UNKNOWN_INFO if neither the product or patch build number can be |
1581 | * determined. |
1582 | **/ |
1583 | public static String getAtgPatchBuildNumber(AppModule pModule) { |
1584 | String build = getManifestInfo(pModule, "ATG-Patch-Build"); |
1585 | if ( build != null ) return build; |
1586 | else if (getAtgBuildNumber(pModule).equals(UNKNOWN_INFO)) |
1587 | return UNKNOWN_INFO; |
1588 | else return null; |
1589 | } |
1590 | |
1591 | /** Returns the ATG full product version ("ATG-Version-Full") of the |
1592 | * specified module. Returns UNKNOWN_INFO if the full product |
1593 | * version can't be determined. |
1594 | **/ |
1595 | public static String getAtgFullVersion(AppModule pModule) { |
1596 | String version = getManifestInfo(pModule, "ATG-Version-Full"); |
1597 | if ( version != null ) return version; |
1598 | else return UNKNOWN_INFO; |
1599 | } |
1600 | |
1601 | // ==================== Dynamo Environment Information ===================== |
1602 | |
1603 | // some methods called on DynamoEnv are not available in older |
1604 | // versions of the class, so use reflection to maintain backward |
1605 | // compatibility. |
1606 | |
1607 | private static DynamoEnv mDynamoEnv = null; |
1608 | private static DynamoEnv dynamoEnv() { |
1609 | if ( mDynamoEnv == null ) { |
1610 | try { mDynamoEnv = (DynamoEnv) DynamoEnv.class.newInstance(); } |
1611 | catch (Throwable t) {} |
1612 | } |
1613 | return mDynamoEnv; |
1614 | } |
1615 | |
1616 | /** Returns true if Dynamo is running as BigEar; otherwise returns false. */ |
1617 | public static boolean isBigEar() |
1618 | { |
1619 | Boolean isBigEar = (Boolean) invokeMethod(dynamoEnv(), "isBigEar", |
1620 | null, null, Boolean.FALSE ); |
1621 | return isBigEar.booleanValue(); |
1622 | } |
1623 | |
1624 | /** Returns true if Dynamo is running as BigEar in standalone mode; |
1625 | * otherwise returns false. */ |
1626 | public static boolean isBigEarStandalone() |
1627 | { |
1628 | Boolean isStandalone = (Boolean) invokeMethod(dynamoEnv(), |
1629 | "getStandaloneMode", |
1630 | null, null, Boolean.FALSE ); |
1631 | return isStandalone.booleanValue(); |
1632 | } |
1633 | |
1634 | /** Returns true is Dynamo is running with liveconfig enabled; |
1635 | * otherwise returns false. */ |
1636 | public static boolean isLiveconfig() |
1637 | { |
1638 | // 'isLiveconfig' is a new method in Koko (pr 88105). try it, but |
1639 | // if that doesn't work try the 'getProperty' method that was used |
1640 | // for ATG 7.0. finally, if that doesn't work just examine System |
1641 | // properties as a last check. |
1642 | Boolean isliveconfig = (Boolean) invokeMethod(dynamoEnv(), |
1643 | "isLiveconfig", |
1644 | null, null, null); |
1645 | if ( isliveconfig == null ) { |
1646 | // that method didn't work, so try this method - which should |
1647 | // work in ATG 7 |
1648 | String[] args = { "atg.dynamo.liveconfig" }; |
1649 | String propval = (String) invokeMethod(dynamoEnv(), |
1650 | "getProperty", new Class[]{ String.class }, args, null); |
1651 | if ( propval != null ) { |
1652 | isliveconfig = Boolean.valueOf("on".equalsIgnoreCase(propval)); |
1653 | } else { |
1654 | isliveconfig = Boolean.valueOf("on".equalsIgnoreCase( System.getProperty("atg.dynamo.liveconfig") )); |
1655 | } |
1656 | } |
1657 | if ( isliveconfig != null ) return isliveconfig.booleanValue(); |
1658 | else return false; |
1659 | } |
1660 | |
1661 | public static Object invokeMethod(Object pObj, String pMethodName, |
1662 | Class<?>[] pSignature, Object[] pParams, |
1663 | Object pDefault ) |
1664 | { |
1665 | Object returnval = null; |
1666 | try { |
1667 | Method meth = pObj.getClass().getMethod( pMethodName, pSignature ); |
1668 | returnval = meth.invoke( pObj, pParams ); |
1669 | //if ( isLoggingDebug() ) logDebug("Method '" + pMethodName + "' |
1670 | //invoked - return value: " + returnval); |
1671 | } catch (Throwable t) { |
1672 | //if ( isLoggingDebug() ) logDebug("Method '" + pMethodName + "' |
1673 | //could not be invoked.", t); |
1674 | returnval = pDefault; |
1675 | } |
1676 | return returnval; |
1677 | } |
1678 | |
1679 | } // end of class |