# DCj2ee.ctl:310:Collects J2EE/OC4J Information # $Id: DCj2ee.ctl,v 1.7 2015/02/20 15:30:24 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/collect/OFM/DCj2ee.ctl,v 1.7 2015/02/20 15:30:24 RDA Exp $ # # Change History # 20150220 KRA Improve list management. =head1 NAME OFM:DCj2ee - Collects J2EE/OC4J Information =head1 DESCRIPTION This module collects J2EE/OC4J-related information (for example, configuration and log files). The following reports can be generated and are regrouped under C: =head1 REPORTS =cut echo tput('bold'),'Processing OFM.J2EE module ...',tput('off') # Initialization var $ORACLE_HOME = ${D_ORACLE_HOME/P:''} var $J2EE_TOP = ${D_TOP:''} var $J2EE_JDK = ${D_JDK:''} var $TAIL = ${DFT.N_TAIL:1000} var $OH = verbatim($ORACLE_HOME) var $TOC = '%TOC%' var $TOP = '[[#Top][Back to top]]' pretoc '^1:J2EE/OC4J' # Define the internal counter and duplicate file hash var ($CNT,%DUP) = (0) # Get the 'ps' command var $PS_EF run &{check(getOsName(),'aix', 'OS:OSaix',\ 'darwin', 'OS:OSdarwin',\ 'dec_osf', 'OS:OSosf',\ 'dynixptx', 'OS:OSptx',\ 'hpux', 'OS:OShpux',\ 'linux', 'OS:OSlinux',\ 'solaris', 'OS:OSsunos',\ cond(isUnix(),'OS:OSunix',\ isVms(), 'OS:OSvms'))}('PS') # Define the file sorting macros macro file_write return file_share(undef,undef,@arg) macro file_share {var ($shr,$ttl,$lvl,$lgt,$dir,$arg,$f10,@fil) = @arg import $CNT,$TOP,%DUP keep $CNT,$TOP,%DUP var @url = () # Filter the file list loop $fil (@fil) {if or($f10,$arg) next !?testFile('r',$fil) var $fil{dirname($fil),basename($fil)} = $fil } # Generate the reports and related index links if $flg = match($lvl,'^\d') {var $det = $lvl if $arg incr $det } loop $grp (keys(%fil)) {# Start a new section if $flg {if !$f10 toc $lvl,':',encode(cond($arg,replace($grp,$dir,$arg),$grp)),' ' elsif $arg toc $lvl,':',encode(catDir(splitDir($grp,$dir))),' ' } # Treat each file loop $nam (keys($fil{$grp})) {var $fil = $fil{$grp,$nam} debug ' Inside file_share, getting ',$fil if missing($DUP{$fil}) {incr $CNT report concat('log',$CNT,'_',$nam) if $shr share $shr,$fil if !or($f10,$arg) {prefix {write '---+ Display of ',encode($nam),' File ',$ttl write '---## Information Taken from ',encode($fil) } var ($min,$max) = getDataValue($fil) call writeLines($dir,$min,$max) next !isCreated(true) write $TOP } elsif match($nam,'^USData.xml$',true) {write '---+ Display of ',encode($nam),' File ',$ttl write '---## Information Taken from ',encode($fil) call statFile('b',$fil) write '**File was not collected, because of the file size.**%BR%' } elsif match($fil,'(logs?[\/\\]|log$)',true) {if exists($LOG{$fil}) var $cnt = $LOG{$fil} else var $cnt = $lgt if $cnt write '---+ Last ',$cnt,' Lines of ',encode($nam),' File ',$ttl else write '---+ Display of ',encode($nam),' File ',$ttl write '---## Information Taken from ',encode($fil) call statFile('b',$fil) if $cnt call writeTail($fil,$cnt) else call writeFile($fil) write $TOP } else {write '---+ Display of ',encode($nam),' File ',$ttl write '---## Information Taken from ',encode($fil) call statFile('b',$fil) call writeFile($fil) write $TOP } var $rpt = getFile() if or($f10,$arg) var $DUP{$fil} = $rpt } else var $rpt = $DUP{$fil} if $flg {if and($f10,not($arg)) var $nam = catDir(splitDir($grp,$dir)) toc $det,':[[',$rpt,'][rda_report][',encode($nam),']]' } else call push(@url,\ concat('[[../',$rpt,'][_blank][',encode(replace($fil,$dir,'$OH')),']]')) } } if !match($lvl,'^\d') return @url } =head2 J2EE/OC4J Gathers J2EE/OC4J Information. Determines the version of F, located in the C<$J2EE_TOP> directory. Checks for the available JDK. It uses this information to execute the command that gathers the F version. java -jar oc4j.jar -version Finds all mime.types, policy, properties, xml, and log files in the C<$J2EE_TOP> directory. Displays the information about OC4J instance processes (for UNIX only). Gathers information about all the library files located in the C<$J2EE_TOP> directory. For each of the file, the report collects file information and the output from C. =cut debug ' Inside J2EE module, gathering OC4J versions' report versions write '---+!! Information about OC4J Version' write $TOC prefix write '---+ JDK Information' var @tbl = grepDir($J2EE_JDK,'^java(\.exe)?$','inr') loop $cmd (@tbl) {if ?testFile('fx',$cmd) {write '---++ JDK Location: ',encode(addSymbol($cmd)) call statFile('p',$cmd) var $cmd = quote($cmd) write '---++++!! JDK Version' call writeCommand(concat($cmd,' -version 2>&1')) write '---++++!! JDK Full Version' call writeCommand(concat($cmd,' -fullversion 2>&1')) write $TOP } } if !hasOutput() {write '**No JDK found.**%BR%' write $TOP } if $J2EE_TOP {var @tbl = grepDir($J2EE_TOP,'^oc4j\.jar$','inr') write '---+ OC4J information' if @tbl {var $cmd = catCommand($J2EE_JDK,'bin','java') write 'Using the java located in ',encode($cmd),'%BR%' loop $jar (@tbl) {if ?testFile('f',$jar) {write '---++ oc4j.jar Location: ',encode(addSymbol($jar)) call statFile('p',$jar) write '---++++!! oc4j.jar version' call writeCommand(concat($cmd,' -jar ',quote($jar),' -version 2>&1')) write $TOP } } } else {write '**No OC4J found.**%BR%' write $TOP } } toc '1+:Generic' toc '2:[[',getFile(),'][rda_report][OC4J Version]]' # Get the OC4J instance processes if or(isUnix(),isVms()) {debug ' Inside J2EE module, getting information about OC4J instance processes' report oc4j_process prefix {write '---+ OC4J Instance Processes' write '' } loop $lin (grepCommand($PS_EF,$OH)) {if match($lin,'-Doracle\.oc4j\.instancename=') write $lin } if isCreated(true) {write '' toc '2:[[',getFile(),'][rda_report][OC4J Instance Processes]]' } } # Get the instance list var (@tbl,%grp,%prc) = () if ?testFile('r',catFile($ORACLE_HOME,'opmn','conf','opmn.xml')) {var $top = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) loop $xml (xmlFind($top,\ 'opmn/process-manager/ias-instance/ias-component/process-type \ module-id="OC4J"')) {var $ins = xmlValue($xml,'id') if xmlFind($xml,'process-set') {var ($set) = (last) var $grp{$ins} = xmlValue($set,'id') var $prc{$ins} = xmlValue($set,'numprocs') } call push(@tbl,$ins) } } elsif ?testDir('d',catDir($J2EE_TOP,'home')) var @tbl = ('home') # Collect Java libs information debug ' Inside J2EE module, gathering Java libs information' report libs prefix {write '---+!! Information about Java Libs' write '%TOC3-2%' } var ($cmd,@fil) = (findCommand('cksum')) loop $ins (@tbl) call push(@fil,grepDir(catDir($J2EE_TOP,$ins,'applib'),'^\.+$','drv'),\ grepDir(catDir($J2EE_TOP,$ins,'lib'),'^\.+$','drv'),\ grepDir(catDir($J2EE_TOP,$ins,'shared-lib'),'^\.+$','drv')) loop $fil (grepDir(catDir($ORACLE_HOME,'jdbc','lib'),'\.(jar|zip)$','dir'),\ grepDir(catDir($ORACLE_HOME,'jlib'),'^\.+$','drv'),\ grepDir(catDir($ORACLE_HOME,'lib'),'^\.+$','drv'),\ @fil) {if ?testFile('f',$fil) {write '---++ ',encode(addSymbol($fil)) call statFile('b',$fil) if $cmd {write '---++++!! cksum: (checksum size filename)' call writeCommand(concat($cmd,' ',quote($fil))) } write $TOP } } if isCreated(true) toc '2:[[',getFile(),'][rda_report][Java Libs]]' # Macro to collect a log file macro get_log_file {var ($pth) = @arg import %log if ?testDir('dr',$pth) {loop $fil (grepDir($pth,'\.(log|xml)$','ir')) var $log{$fil} = true } else var $log{$pth} = true } # Macro to clean a file path macro clean_path {var $pth = catFile(@arg) if match($pth,'\.+') {var @str = () loop $itm (splitDir($pth)) {if and(compare('eq',$itm,'..'),@str) {var ($itm,@str) = (@str) if compare('eq',$itm,'') var @str = ($itm,@str) if compare('eq',$itm,'..') var @str = ($itm,'..',@str) } else var @str = ($itm,@str) } var ($itm,@str) = @str if @str var $pth = catFile(reverse(@str),$itm) elsif !defined($itm) var $pth = '.' elsif compare('eq',$itm,'') var $pth = catFile('','') else var $pth = $itm } return $pth } # Macro to collect log files macro get_grp_files {var ($dir,$pth,$ins,$grp,$prc) = @arg if isAbsolute($pth) call get_log_file($pth) else {var $pth = clean_path($dir,$pth) var $bas = dirname($pth) var $fil = basename($pth) for $cnt (1,$prc) call get_log_file(catFile($bas,join('_',$ins,$grp,$cnt),$fil)) } } # OC4J Overview debug ' Inside J2EE module, gathering OC4J overview' report oc4j_info var $TTL = '---+!! OC4J Overview' # Gather the top level information of each OC4J instance prefix {if $TTL {write $TTL write $TOC var $TTL = undef } write '---+ Top Level Information' write '|*OC4J Component*|*Server.xml Location*|*Log Files Location*| \ *Cluster ID*|' } var %src = () loop $ins (@tbl) {next !?testFile('r',catFile($J2EE_TOP,$ins,'config','server.xml')) var ($ttl,$clu,@app,@cfg,%log,%flg) = (concat('(',$ins,')')) suspend main var ($loc) = file_share(\ cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_CFG',undef),\ $ttl,'-',$TAIL,$OH,true,true,\ lastFile()) var $top = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) next !xmlFind($top,'application-server') var ($obj) = (last) var $dir = dirname(lastFile()) var $apd = catDir($dir,xmlValue($obj,'deployment-directory')) var $grp = $grp{$ins} var $prc = $prc{$ins} # Collect the configuration and application name loop $nod (xmlContent($obj)) {var $nam = xmlName($nod) if match($nam,'-config') {if xmlExists($nod,'path') call push(@cfg,xmlValue($nod,'path')) } elsif match($nam,'web-site') {if xmlExists($nod,'path') call push(@cfg,xmlValue($nod,'path')) } elsif match($nam,'log') call get_grp_files($dir,xmlValue(xmlContent($nod),'path'),$ins,$grp,$prc) elsif match($nam,'^application') call push(@app,xmlValue($nod,'name')) elsif match($nam,'cluster') var $clu = xmlValue($nod,'id') elsif match($nam,'^global-application') {if xmlExists($nod,'path') {call push(@app,xmlValue($nod,'name')) var $cfg = xmlValue($nod,'path') call push(@cfg,$cfg) var $flg{$cfg} = true } } } # Get the path of the log files from the configuration files loop $cfg (@cfg) {next !?testFile('r',catFile($dir,$cfg)) var $obj = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) if $flg{$cfg} {if xmlFind($obj,'.../data-sources') var $src{$ins} = xmlValue(last,'path') } if xmlFind($obj,'.../log/file') call get_grp_files($dir,xmlValue(last,'path'),$ins,$grp,$prc) elsif xmlFind($obj,'.../log/odl') call get_grp_files($dir,catDir(xmlValue(last,'path')),$ins,$grp,$prc) elsif xmlFind($obj,'.../access-log') call get_grp_files($dir,xmlValue(last,'path'),$ins,$grp,$prc) elsif xmlFind($obj,'.../logging/location') call get_grp_files($dir,xmlData(last),$ins,$grp,$prc) elsif xmlFind($obj,'.../log_handler name="oc4j-handler"') {var $pth = catDir(xmlValue(xmlFind(last,'property name="^path$"'),'value')) if isAbsolute($pth) call get_log_file($pth) else {var $pth = replace(replace(replace($pth,'%ORACLE_HOME%',$ORACLE_HOME),\ '%OPMN_PROC_TYPE%',$ins,true),\ '%OPMN_PROC_SET%',$grp) for $cnt (1,$prc) call get_log_file(replace($pth,'%OPMN_PROC_INDEX%',$cnt)) } } } loop $fil (grepDir(catDir($J2EE_TOP,$ins,'log'),\ '(\.properties|\.xml|^mime.types|\.policy|\.log)$','inr')) var $log{$fil} = true var @fil = keys(%log) call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_LOG',undef),\ $ttl,'-',$TAIL,$OH,true,false,\ keys(%log)) # Get the path of the log files from the application files loop $app (@app) {next !?testFile('r',catFile($apd,$app,'orion-application.xml')) var ($ttl,%log) = (concat('(',$ins,'/',$app,')')) var $app = dirname(lastFile()) var $obj = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) if xmlFind($obj,'.../log/file') call get_grp_files($app,xmlValue(last,'path'),$ins,$grp,$prc) elsif xmlFind($obj,'.../log/odl') call get_grp_files($app,catDir(xmlValue(last,'path')),$ins,$grp,$prc) call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_DLOG',undef),\ $ttl,'-',$TAIL,$OH,true,false,\ keys(%log)) call push(@fil,keys(%log)) } var ($ttl,%log) = (concat('(',$ins,')')) loop $fil (@fil,grepDir(catDir($J2EE_TOP,$ins,'application-deployments'),\ '^application\.log$','inr')) var $log{$fil} = true var @url = \ file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_DLOG',undef),\ $ttl,'-',$TAIL,$OH,true,false,\ keys(%log)) # Add the component row in the report resume main write '|',$ins,' |',$loc,' |',join('%BR%',@url),' | ',$clu,'|' } if hasOutput(true) write $TOP # Gather the deployed applications information prefix {if $TTL {write $TTL write $TOC var $TTL = undef } write '---+ Applications Deployed' write '|*J2EE Container*|*Application*|*Name*|*Context Root*|' } var %dpl loop $ins (@tbl) {var $dir = catDir($J2EE_TOP,$ins,'config') next !?testFile('r',catFile($dir,'server.xml')) var $top = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) loop $xml (xmlFind($top,'application-server/web-site')) {var $pth = xmlValue($xml,'path') next !defined($pth) if !isAbsolute($pth) var $pth = catFile($dir,$pth) var $web = xmlLoadFile($pth,xmlDisable(xmlParser(),'DR')) loop $xml (xmlFind($web,'web-site/web-app application=".*"')) {var $apl = xmlValue($xml,'application') var $nam = xmlValue($xml,'name') var $ctx = xmlValue($xml,'root') write '|',$ins,' |',$apl,' |',$nam,' |',$ctx,' |' var $dpl{$ins,$nam} = $apl } } } if hasOutput(true) write $TOP # Macro to display the data sources macro dsp_sources {var ($ins,$fil,$app) = @arg var ($ttl,$src) = (concat('(',$ins,')')) var $top = xmlLoadFile($fil,xmlDisable(xmlParser(),'DR')) loop $xml (xmlFind($top,'data-sources/data-source')) {var $nam = xmlValue($xml,'name') var $ejb = xmlValue($xml,'ejb-location') var $url = xmlValue($xml,'url') var $emu = check(lc(xmlValue($xml,'class')),'pool','YES','NO') if !$src {suspend main var $src = get_source($ins,$fil,$app) resume main } write '|',join(' |',$ins,$src,$nam,$emu,$ejb,$url),' |' } loop $xml (xmlFind($top,'data-sources/managed-data-source')) {var $nam = xmlValue($xml,'name') var $ejb = xmlValue($xml,'jndi-name') var $con = xmlValue($xml,'connection-pool-name') if xmlFind($top,concat('data-sources/connection-pool name="',\ verbatim($con,'e'),'"/connection-factory')) {var ($det) = (last) var $url = xmlValue($det,'url') var $emu = check(lc(xmlValue($det,'factory-class')),'pool','YES','NO') } if !$src {suspend main var $src = get_source($ins,$fil,$app) resume main } write '|',join(' |',$ins,$src,$nam,$emu,$ejb,$url),' |' } } # Macro to get the data-sources.xml file macro get_source {var ($ins,$fil,$app) = @arg import $TAIL,$OH keep $TAIL,$OH if defined($app) {var ($src) = file_share(\ cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_DCFG',undef),\ concat('(',$ins,'/',$app,')'),'-',$TAIL,$OH,true,true,\ $fil) if match($src,'\[\_blank\]\[(.*)\]\]$') var $src = replace($src,verbatim(last),$app) } else {var ($src) = file_share(\ cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_CFG',undef),\ concat('(',$ins,')'),'-',$TAIL,$OH,true,true,\ $fil) if match($src,'\[\_blank\]\[(.*)\]\]$') var $src = replace($src,verbatim(last),'[Container]') } return $src } # Get the data sources defined for each OC4J and its applications prefix {if $TTL {write $TTL write $TOC var $TTL = undef } write '---+ Data Sources Defined' write '|*J2EE Container*|*Source*|*Name*|*Emulated*|*EJB Location*|*URL*|' } loop $ins (@tbl) {var $src = nvl($src{$ins},'data-sources.xml') if !isAbsolute($src) var $src = catFile($J2EE_TOP,$ins,'config',$src) if ?testFile('r',$src) call dsp_sources($ins,$src) next !?testFile('r',catFile($J2EE_TOP,$ins,'config','server.xml')) var $dir = dirname(lastFile()) var $top = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) next !xmlFind($top,'application-server') var ($obj) = (last) var $dpd = catDir($dir,xmlValue($obj,'deployment-directory')) loop $xml (xmlFind($obj,'global-application'),xmlFind($obj,'application')) {var $app = xmlValue($xml,'name') next !?testFile('r',catFile($dpd,$app,'orion-application.xml')) var $dat = xmlLoadFile(lastFile(),xmlDisable(xmlParser(),'DR')) next !xmlFind($dat,'orion-application/data-sources') next !sameFile(clean_path($dpd,$app,xmlValue(last,'path')),\ catFile($J2EE_TOP,$ins,'application-deployments',\ $app,'data-sources.xml')) next !?testFile('r',lastFile()) call dsp_sources($ins,lastFile(),$app) } } if isCreated(true) {write $TOP toc '2:[[',getFile(),'][rda_report][OC4J Overview]]' } # Collect the instance files loop $ins (@tbl) {pretoc '%SPLIT%' pretoc concat("^1+:'",$ins,"' Component") var $dir = catDir($J2EE_TOP,$ins) var $ttl = concat('(',$ins,')') debug ' Inside J2EE module, gathering configuration files' pretoc '1++:Configuration and Log Files' pretoc '2:Configuration Files' call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_CFG',undef),\ $ttl,3,$TAIL,$dir,true,true,\ grepDir(catDir($dir,'config'),\ '(\.properties|\.xml|^mime.types|\.policy|\.log)$',\ 'inr')) unpretoc debug ' Inside J2EE module, gathering log files' pretoc '2:Log Files' call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_LOG',undef),\ $ttl,3,$TAIL,$dir,true,true,\ grepDir(catDir($dir,'log'),\ '(\.properties|\.xml|^mime.types|\.policy|\.log)$',\ 'inr')) unpretoc 2 # List the applications var %app = () loop $bas (catDir($dir,'applications'),\ catDir($dir,'application-deployments')) {loop $app (grepDir($bas,'^[^\.]','n')) {next !?testDir('d',catDir($bas,$app)) next $app{$app} var $app{$app} = true } } # Collect application files pretoc '%SPLIT%' pretoc '1++:Applications' loop $app (keys(%app)) {pretoc concat("2:'",$app,"' Application") var $apd = catDir($dir,'applications') var $dpd = catDir($dir,'application-deployments') var ($ttl,@lst) = (concat('(',$ins,'/',$app,')')) pretoc '3:Applications Configuration' debug ' Inside J2EE module, gathering application config files' loop $pth (findDir(catDir($apd,$app),'^html$','r',2)) call push(@lst,grepDir($pth,'\.jsp$','inp')) loop $key (keys($dpl{$ins})) {next compare('ne',$dpl{$ins,$key},$app) call push(@lst,grepDir(catDir($apd,$app,$key),'(^index\.jsp|\.jspx)$','inp')) call push(@lst,grepDir(catDir($apd,$app,$key,'htdocs'),'\.jsp$','inr',1)) } loop $pth (findDir(catDir($apd,$app),'^WEB-INF$','r',1)) {call push(@lst,grepDir(catDir($pth,'mds'),'\.pxml$','inp')) call push(@lst,grepDir(catDir($pth,'wsdl'),'\.wsdl$','inp')) } call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_ACFG',undef),\ $ttl,4,$TAIL,$apd,true,true,\ grepDir(catDir($apd,$app),\ '(\.properties|\.xml|^mime.types|\.policy)$','inr'),\ @lst) unpretoc pretoc '3:Deployment Configuration' debug ' Inside J2EE module, gathering application-deployment config files' call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_DCFG',undef),\ $ttl,4,$TAIL,$dpd,true,true,\ grepDir(catDir($dpd,$app),\ '(\.properties|\.xml|^mime.types|\.policy)$','inr')) unpretoc pretoc '3:Application.log Files' debug ' Inside J2EE module, gathering application related log files' call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_ALOG',undef),\ $ttl,4,$TAIL,$dir,false,true,\ grepDir(catDir($apd,$app),\ '^application\.log$','inr')) debug ' Inside J2EE module, gathering application-deployment log files' call file_share(cond(compare('eq',$ins,'OC4J_Portal'),'J2EE_DLOG',undef),\ $ttl,4,$TAIL,$dir,false,true,\ grepDir(catDir($dpd,$app),\ '^application\.log$','inr')) unpretoc 2 } unpretoc 4 } # Collect remaining J2EE information debug ' Inside J2EE module, gathering J2EE Misc Information' pretoc '%SPLIT%' pretoc cond(scalar(@tbl),'1+:J2EE Miscellaneous','1+:J2EE') var @tbl = grepDir($J2EE_TOP,\ '(\.properties|\.xml|^mime.types|\.policy|\.log)$','inr') call file_write(2,$TAIL,$OH,'$OH',false,\ grep(@tbl,code(missing($DUP{last})))) unpretoc 3 =head1 SEE ALSO L, L, L, L, L, L, L, L, L =begin credits =over 10 =item RDA 4.2: Greg Cook, Michael Ferrante. =item RDA 4.4: Wes Root. =item RDA 4.6: Ian Reid. =item RDA 4.9: Greg Cook, Albert Girona. =item RDA 4.10: Greg Cook, Albert Girona, Stanislav Hejny, Daniel Mortimer, Ian Reid. =item RDA 4.11: Greg Cook, Andrew Salt. =item RDA 4.12: Greg Cook, Andrew Salt. =item RDA 4.14: Misato Tsukagawa. =item RDA 4.24: Pramod Vasista. =item RDA 4.28: Miguel Hernandez, Ian Reid. =back =end credits =head1 COPYRIGHT NOTICE Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. =head1 TRADEMARK NOTICE Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. =cut