# S313ASIT.def: Collects Oracle Application Server Installation Information
# $Id: S313ASIT.def,v 1.12 2009/08/05 12:43:07 mschenke Exp $
# ARCS: $Header: /u02/webapps/workbench/cvs/RDA_4/src/scripting/lib/modules/S313ASIT.def,v 1.12 2009/08/05 12:43:07 mschenke Exp $
#
# Change History
# 20090729  KRA  Improve AS 11g classic install inventory finding.

=head1 NAME

S313ASIT - Collects Information for Multiple Oracle Application Server
Installation Types

=head1 DESCRIPTION

This module collects information related to a Classic, an Identity Management,
or a Web Tier installation, for a single or all Oracle instances.

Oracle Application Server 11g Business Intelligence Enterprise Edition includes:

=over 3

=item o Oracle Cluster Controller

=item o Oracle JavaHost

=item o Oracle Presentation Services

=item o Oracle Process Management Node

=item o Oracle Scheduler

=item o Oracle Server

=back

Oracle Application Server 11g Classic includes:

=over 3

=item o Oracle Discoverer

=item o Oracle Forms/Reports

=item o Oracle HTTP Server

=item o Oracle Process Management Node

=item o Portal Diagnostics

=item o Oracle Web Cache

=back

Oracle Application Server 11g Identity Management includes:

=over 3

=item o Oracle Directory Integration Platform

=item o Oracle Directory Server Manager

=item o Oracle Identity Federation

=item o Oracle Internet Directory

=item o Oracle Virtual Directory

=back

Oracle Application Server 11g WebTier includes:

=over 3

=item o Oracle HTTP Server

=item o Oracle Process Management Node

=item o Oracle Web Cache

=back

The following reports can be generated and are regrouped under C<Oracle
AS 11g Installation>:

=head1 REPORTS

=cut

echo tput('bold'),'Processing ASIT module ...',tput('off')

# Initialization
var $INSTANCE_HOME = catDir(getSetting('ASIT_INSTANCE_HOME',''))
var $ODL_SIZE      = getSetting('ASIT_ODL_TAIL',65536)
var $ORACLE_HOME   = catDir(getSetting('ASIT_ORACLE_HOME',\
                                       getSetting('ORACLE_HOME','')))
var $OVD_HOME      = getSetting('OVD_HOME',catDir($ORACLE_HOME,'ovd'))
var $TAIL          = getSetting('RDA_TAIL',1000)

if getSetting('ASIT_MERGE',true)
{var $BI   = getSetting('BI_IN_USE')
 var $DEV  = getSetting('DEVELOPER_IN_USE')
 var $DSCV = getSetting('DISCO_IN_USE')
 var $OID  = getSetting('INTERNET_DIRECTORY_IN_USE')
 var $OVD  = getSetting('OVD_IN_USE')
 var $PDA  = getSetting('PDA_IN_USE')
 var $WEBC = getSetting('WEBCACHE_IN_USE')
}

var $APACHE_TOP       = catDir($ORACLE_HOME,'ohs')
var $ASSISTANTS_HOME  = catDir($ORACLE_HOME,'assistants')
var $BI_HOME          = catDir($ORACLE_HOME,'bifoundation')
var $CFGTOOLLOGS_HOME = catDir($ORACLE_HOME,'cfgtoollogs')
var $DEV_BIN          = catDir($ORACLE_HOME,'bin')
var $DISCOVERER_HOME  = catDir($ORACLE_HOME,'discoverer')
var $FORMS_HOME       = catDir($ORACLE_HOME,'forms')
var $INSTALL_HOME     = catDir($ORACLE_HOME,'install')
var $LDAP_HOME        = catDir($ORACLE_HOME,'ldap')
var $OPMN_HOME        = catDir($ORACLE_HOME,'opmn')
var $PORTAL_HOME      = catDir($ORACLE_HOME,'portal')
var $REPORTS_HOME     = catDir($ORACLE_HOME,'reports')
var $WEBCACHE_HOME    = catDir($ORACLE_HOME,'webcache')

var $OH  = quote($ORACLE_HOME)
var $OH1 = concat('^',$OH,'[\\\/]')
var $OH2 = concat('^',$OH,'\b')
var $VER = 'Version:\w+\s+[\d\.]+'

var $MNU = '1:Oracle Application Server 11g'
var $TOC = '%TOC%'
var $TOP = '[[#Top][Back to top]]'

set $NOT_OWNER_STATEMENT
{**Note:**
"
"The RDA was executed with an operating system user which is different from
"the operating system user who installed the Oracle Application Server 11g.
"
"Therefore, no information are available in this section.
"
}

# Define global variables
var %cmp
var %HTTPDCONF
var %HTTPDERRLOG
var %HTTPDREQLOG

# Define the report counter, and duplicate file hash
var ($CNT,%DUP) = (0)

# Load the common macros
run ASITlib()
run IAS()

=head1 ORACLE HOME COLLECTIONS

=head2 error - Installation Type Error

Indicates that the specified Oracle home does not contain information related
to a Classic, an Identity Management, or a Web Tier installation type.

=cut

# Indicate installation type error
macro dsp_error
{echo ' Error: The specified Oracle home does not contain appropriate \
               information'
 report error
 write '** Error: The specified Oracle home is not a Classic, an Identity \
        Management, or a Web Tier installation of Oracle Application Server \
        11g.**%BR%'
 write '%BR%'
 if @arg
 {write '|*Oracle Home*|',encode($arg[0]),' |'
  write '|*Install Name*|',$arg[1],' |'
  write '|*Install Version*|',$arg[2],' |'
 }
 toc '2:[[',getFile(),'][rda_report][Installation Type Error]]'
}

# Validate the installation type
debug ' Inside ASIT module, validating the installation type'
var $flg = false
var $fil = catFile($ORACLE_HOME,'inventory','ContentsXML','comps.xml')
if testFile('fr',$fil)
{if xmlFind(xmlLoadFile($fil),'PRD_LIST/TL_LIST/COMP')
 {var ($xml) = (last)
  var $ver = xmlValue($xml,'VER')
  var $dsc = xmlData(xmlFind($xml,'EXT_NAME'))
  if and(match($dsc,'^(Classic Application Server 11g|\
                       Oracle Identity Management 11g|\
                       Oracle Portal, Forms, Reports and Discoverer 11g|\
                       Oracle WebTier)',true),\
         match($ver,'^11\.'))
   var $MNU = concat('1:',$dsc)
  else
   var $flg = true
 }
}
pretoc $MNU
pretoc '1+:Oracle Home'
if $flg
 call dsp_error($ORACLE_HOME,$dsc,$ver)
elsif !testDir('d',$OPMN_HOME)
 call dsp_error()

=head2 Install and Configuration

Gathers the Oracle Application Server configuration and installation files.

=cut

debug ' Inside ASIT module, gathering instal and configuration information'
pretoc '2:Installation and Configuration'
call sort_results(3,$TAIL,$OH2,'$OH',\
  grepDir($ASSISTANTS_HOME,'\.log$','dir'),\
  grepDir($CFGTOOLLOGS_HOME,'\.(ini|log|properties|xml)','dir'),\
  grepDir($INSTALL_HOME,'\.(ini|log)','dir'))
unpretoc

if testDir('d',catDir($ORACLE_HOME,'diagnostics'))
{debug ' Inside ASIT module, gathering diagnostics information'
 pretoc '2:Diagnostics'
 call sort_results(3,$TAIL,$OH2,'$OH',\
   grepDir(lastDir(),'\.((conf|ini|xml|properties|err)$|log)|\~','dir'))
 unpretoc
}

# Check the user
var $uid = getOwner(getToc(true))
if grepDir(catDir($OPMN_HOME,'bin'),'^opmnctl(\.(bat|exe))?$','fip')
 var $own = getOwner(last)
else
 var $own = undef
if compare('eq',$uid,$own)
 var $NOT_OWNER = false
else
{var $NOT_OWNER = true
 echo tput('reverse'),'Warning:'
 echo '========'
 echo 'The RDA is started as userid: ',$uid
 echo 'The Oracle Application Server 11g was installed on your system using \
       userid: ',nvl($own,'[not found]')
 echo 'The RDA script will continue, but it will skip some Oracle Application \
       Server 11g RDA steps.',tput('off')
}

=head2 Oracle Business Intelligence Enterprise Edition

Gathers Oracle Business Intelligence Enterprise Edition version and its
executable.

=cut

if and($BI,testDir('d',$BI_HOME))
{# Load Business Intelligence macros
 run BIr11()

 # Collect the generic BI information
 pretoc '1++:Oracle Business Intelligence Enterprise Edition'
 var $abr = setAbbr('ASIT_BI')
 call collect_bi_generic($BI_HOME)
 call setAbbr($abr)
 unpretoc
}

=head2 Oracle Discoverer

Gathers Oracle Discoverer executable and library versions.

=cut

if and($DSCV,testDir('d',$DISCOVERER_HOME))
{var $MAX = getSetting('DISCO_LOG_MAX',20)

 # Collect the generic DSCV information
 pretoc '1++:Oracle Discoverer'
 var $abr = setAbbr('ASIT_DSCV')
 run DSCVinfo(true)
 call setAbbr($abr)
 unpretoc

 # Load Discoverer macros
 run DSCVr11()
}

=head2 Oracle Forms/Reports

Gathers Oracle Forms/Reports installation files and also collects all general
Application Server information for Oracle Forms/Reports.

=cut

if and($DEV,or(testDir('d',$FORMS_HOME),testDir('d',$REPORTS_HOME)))
{var $PS_EF
 var %ENV

 var $DEV_VER = undef
 var $IAS_VER = undef
 var $IAS_ALONE = 'unknown'
 var $IAS_HOME = undef
 var $APPS_INST = undef
 var $OAH_TOP = undef

 # Load the common macros
 run DEVr11()

 # Collect the generic information
 pretoc '1++:Oracle Forms/Reports'
 var $abr = setAbbr('ASIT_DEV')
 run DEVinfo(\%ENV,\$PS_EF,\$DEV_VER,\$IAS_VER,\$IAS_ALONE,\$IAS_HOME,\
             \$APPS_INST,\$OAH_TOP)
 call collect_dev_generic()
 call setAbbr($abr)
 unpretoc
}

=head2 Oracle HTTP Server

Gathers Oracle HTTP server executable list and F<apachectl> script.

=cut

pretoc '1++:Oracle HTTP Server'

debug ' Inside ASIT module, listing Oracle HTTP Server executables'
report ohs_bin
var $dir = catDir($APACHE_TOP,'bin')
prefix
 write '---+ List of Files in ',encode($dir)
call statDir('an',$dir)
if isCreated(true)
 toc '2:[[',getFile(),'][rda_report][Executable List]]'

var $fil = catFile($dir,'apachectl')
if testFile('fr',$fil)
{debug ' Inside ASIT module, getting apachectl start script'
 report ohs_apachectl
 write '---+ Content Taken from File ',encode($fil)
 call writeFile($fil)
 toc '2:[[',getFile(),'][rda_report][apachectl]]'
}

unpretoc

=head2 Oracle Internet Directory

Displays the output of the F<oiddiag> command.

Displays the C<oidctl> status.

Displays the information about processes.

Lists details from C<ods_process> table.

Lists details from C<ds_attrstore> table.

Displays the contents of the F<$OH/ldap/odi/conf/odi.properties> file.

=cut

if and($OID,testDir('d',$LDAP_HOME))
{# Collect the generic OID information
 pretoc '1++:Oracle Internet Directory'
 var $abr = setAbbr('ASIT_OID')
 run OIDinfo(true)
 call setAbbr($abr)
 unpretoc

 # Load OID macros
 run OIDr11()
}

=head2 LDAP

Gathers LDAP executable list.

=cut

var $dir = catDir($LDAP_HOME,'bin')
if testDir('d',$dir)
{debug ' Inside ASIT module, gathering LDAP information'
 report ldap_bin
 prefix
  write '---+ List of Files in ',encode($dir)
 call statDir('an',$dir)
 if isCreated(true)
 {toc '1++:LDAP'
  toc '2:[[',getFile(),'][rda_report][Executable List]]'
 }
}

=head2 OPMN

Gathers OPMN executable list.

=cut

debug ' Inside ASIT module, getting OPMN information'
var $dir = catDir($OPMN_HOME,'bin')
report opmn_bin
prefix
 write '---+ List of Files in ',encode($dir)
call statDir('an',$dir)
if isCreated(true)
{toc '1++:OPMN'
 toc '2:[[',getFile(),'][rda_report][Executable List]]'
}

=head2 Portal Diagnostics

Collects the repository information from the Portal database. Run PDA in
advanced mode for a detailed report collection.

Gathers the list of Portal users from C<WWSEC_Person$>.

Gathers the HTTP status of URLs from Portal and Infrastructure tier.

Gathers the OID connection information.

=cut

if and($PDA,testDir('d',$PORTAL_HOME))
{# Define the common variables
 var $OC4J_USED
 var $VERSION

 # Collect the portal repository information
 pretoc '1++:Portal Diagnostics'
 var $abr = setAbbr('ASIT_PDA')
 run PDAinfo(\$OC4J_USED,\$VERSION)
 call setAbbr($abr)
 unpretoc

 # Load the Portal macros
 run PDAr11()
}

=head2 Oracle Virtual Directory

Gathers Oracle Virtual Directory executable list.

=cut

if and($OVD,testDir('d',$OVD_HOME))
{# Load the OVD macros
 run OVDr11()

 # Collect the generic information
 pretoc '1++:Oracle Virtual Directory'
 var $abr = setAbbr('ASIT_OVD')
 call collect_ovd_generic($OVD_HOME)
 call setAbbr($abr)
 unpretoc
}

=head2 Oracle Web Cache

Gathers Oracle Web Cache file permissions and DTD files.

=cut

if and($WEBC,testDir('d',$WEBCACHE_HOME))
{var $WEBC_TAIL = getSetting('WEBCACHE_TAIL',5000)

 # Load the common macros
 run WEBCr11()

 # Collect the generic information
 pretoc '1++:Oracle Web Cache'
 var $abr = setAbbr('ASIT_WEBC')
 call collect_webc_generic($WEBCACHE_HOME)
 call setAbbr($abr)
 unpretoc
}
unpretoc

=head1 INSTANCES COLLECTIONS

It performs the following collections on all specified instances.

=cut

# Identify the BI repository opted
if and($BI,testDir('d',$BI_HOME))
{var %rep
 call collect_bi_repo_list(\%rep)
}

# Collect the data for each instance
loop $ins (get_instances($INSTANCE_HOME,'ASIT_INSTANCES'))
{# Instance variables
 var $top = catDir($INSTANCE_HOME,$ins)
 var $OI  = quote($top)
 var $OI1 = concat('^',$OI,'[\\\/]')
 var $OI2 = concat('^',$OI,'\b')

 # Get the instance name and its associated components
 var ($dsc) = get_components(\%cmp,$top,$ins,'.')

 debug ' Inside ASIT module, analyzing instance ',$dsc
 if isTocCreated()
  toc '%SPLIT%'
 toc "1+:'",$dsc,"' Instance"

=head2 Oracle Business Intelligence Enterprise Edition

Gathers Oracle Business Intelligence Enterprise Edition configuration and log
files. It also includes a DMS dump along with its repositories.

=cut

 if and($BI,testDir('d',$BI_HOME))
 {pretoc '1++:Oracle Business Intelligence Enterprise Edition'
  call collect_bi_instance($dsc,$top,\%cmp,\%rep)
  unpretoc
 }

=head2 Oracle Discoverer

Gathers Oracle Discoverer configuration and log files. It also runs the
checkdiscoverer script.

=cut

 if and($DSCV,testDir('d',$DISCOVERER_HOME))
 {pretoc '1++:Oracle Discoverer'
  call collect_dscv_instance($dsc,$top,\%cmp)
  unpretoc
 }

=head2 Oracle Forms/Reports

Collects all startup scripts.

Collects the toolkit files (such as F<uiprint.txt>, F<uifont.ali>, and
F<Tk2Motif.rgb>).

Reports on versions used.

Gathers Oracle Forms/Reports configuration and log files.

=cut

 if and($DEV,or(testDir('d',$FORMS_HOME),testDir('d',$REPORTS_HOME)))
 {pretoc '1++:Oracle Forms/Reports'
  call collect_dev_instance($dsc,$top,\%cmp)
  call collect_forms_instance($dsc,$top,\%cmp)
  call collect_reports_instance($dsc,$top,\%cmp)
  unpretoc
 }

=head2 Oracle HTTP Server

Gathers Oracle HTTP server configuration and log files. It also includes a DMS
dump.

=cut

 debug ' - Getting Oracle HTTP Server configuration and log files'
 pretoc '1++:Oracle HTTP Server'
 loop $key (keys(%cmp))
 {var ($typ,$cmp) = split('\|',$key,2)
  next !match($typ,'^OHS$',true)
  var (%HTTPDCONF,%HTTPDERRLOG,%HTTPDREQLOG) = ()
  var ($fil) = (grepDir(catDir(\
    $top,'config',$typ,$cmp),'^httpd(s)?\.conf$','pf'))
  call setTempSetting('HTTPD_CONF_LOCATION',$fil)

  var $abr = setAbbr(concat('ASIT_i_',$dsc,'_c_',$cmp))
  pretoc "2:'",$cmp,"' OHS Component"

  # Collect the configuration files
  call httpServer_getListenerConf(true,$top,$typ,$cmp)
  pretoc '3:Configuration Files'
  loop $fil (keys(%HTTPDCONF))
  {var $nam = replace($fil,$OI1)
   report concat('lc_',$nam)
   prefix
    write '---+ Content Taken from File ',encode($nam)
   call writeFile($fil)
   if isCreated(true)
    toc '4:[[',getFile(),'][rda_report][',encode(replace($fil,$OI,'$OI')),']]'
  }
  unpretoc

  # Collect the log files
  call httpServer_getListenerLogs(true,$top,$typ,$cmp)
  pretoc '3:Log Files'
  loop $fil (keys(%HTTPDERRLOG),keys(%HTTPDREQLOG),\
             grepDir(catDir($top,'diagnostics','logs',$typ,$cmp),\
                     '^console.*?\.log$','ip'))
  {var $nam = replace($fil,$OI1)
   report concat('ll_',$nam)
   prefix
    write '---+ Last ',$TAIL,' Lines from File ',encode($nam)
   call writeTail($fil,$TAIL)
   if isCreated(true)
    toc '4:[[',getFile(),'][rda_report][',encode(replace($fil,$OI,'$OI')),']]'
  }
  call httpServer_getOdlLog(true,$top,$typ,$cmp)
  unpretoc

  # Collect the DMS dump
  if $cmp{$key}
  {report dms_metrics
   var ($opmnctl) = grepDir(catDir($top,'bin'),'^opmnctl(\.(bat|exe))?$','fip')
   var $cmd = concat(quote($opmnctl,'x'),' @instance:',$dsc,\
                     ' metric op=query PROCESS_UID=',$cmp{$key},\
                     ' dmsarg="format=raw&nountype=opmn_process" 2>&1')
   prefix
   {write '---+ Display of DMS Dump Metrics'
    write '---## Using: ',encode($cmd)
   }
   call writeCommand($cmd)
   if isCreated(true)
   {write $TOP
    toc '3:[[',getFile(),'][rda_report][DMS Dump]]'
   }
  }
  unpretoc
  call setAbbr($abr)
 }
 unpretoc

=head2 Oracle Internet Directory

Displays the last lines of the monitor log.

Displays the last lines of the LDAP log.

Displays the last lines of the replication log.

Displays the contents of the files in the F<$INSTANCE_HOME/OID/load> directory.

=cut

 if and($OID,testDir('d',$LDAP_HOME))
 {pretoc '1++:Oracle Internet Directory'
  call collect_oid_instance($dsc,$top,\%cmp)
  unpretoc
 }

=head2 OPMN

Gathers OPMN information using F<opmnctl>. It collects all C<*.conf>, C<*.log>,
and C<*.xml> files. It also includes a DMS dump.

=cut

 # Collect the opmnctl information
 debug ' - Executing opmnctl'
 toc '1++:OPMN'
 var $abr = setAbbr(concat('ASIT_i_',$dsc))
 if $NOT_OWNER
 {report no_opmnctl
  write '---+ opmnctl'
  write $NOT_OWNER_STATEMENT
  toc '2:[[',getFile(),'][rda_report][opmnctl]]'
 }
 else
 {toc '2:opmnctl'
  var ($opmnctl) = grepDir(catDir($top,'bin'),'^opmnctl(\.(bat|exe))?$','fip')
  var $pgm = concat(quote($opmnctl,'x'),' @instance:',$dsc)

  report opmnctl_status
  write '---+ opmnctl status'
  var $cmd = concat($pgm,' status -l 2>&1')
  write '---## Using: ',encode($cmd)
  call writeCommand($cmd)
  toc '3:[[',getFile(),'][rda_report][opmnctl status]]'

  report opmnctl_debug_pm
  write '---+ opmnctl debug comp=pn'
  var $cmd = concat($pgm,' debug comp=pm 2>&1')
  write '---## Using: ',encode($cmd)
  call writeCommand($cmd)
  toc '3:[[',getFile(),'][rda_report][opmnctl debug comp=pn]]'

  report opmnctl_debug_ons
  write '---+ opmnctl debug comp=ons'
  var $cmd = concat($pgm,' debug comp=ons 2>&1')
  write '---## Using: ',encode($cmd)
  call writeCommand($cmd)
  toc '3:[[',getFile(),'][rda_report][opmnctl debug comp=ons]]'
 }

 # Collect the configuration files
 debug ' - Getting OPMN config and log files'
 pretoc '2:Configuration Files'
 call sort_results(3,$TAIL,$OI2,'$OI',\
   grepDir(catDir($top,'config','OPMN'),'\.(conf$|xml)','dir'))
 unpretoc

 # Collect the log files
 pretoc '2:Log Files'
 call sort_results(3,$TAIL,$OI2,'$OI',\
   grepDir(catDir($top,'diagnostics','logs','OPMN'),'\.log$','dir'))
 unpretoc

 # Collect the DMS dump
 report opmn_metrics
 prefix
 {write '---+ Display of DMS Dump Metrics'
  write '---## Using: ',encode($cmd)
 }
 var $cmd = concat($pgm,' metric op=query PROCESS_UID=0 \
                          dmsarg="format=raw&nountype=opmn_process" 2>&1')
 call writeCommand($cmd)
 if isCreated(true)
 {write $TOP
  toc '2:[[',getFile(),'][rda_report][DMS Dump]]'
 }
 call setAbbr($abr)

=head2 Portal Diagnostics

Provides a summary of the performance information logged by mod_plsql.

=cut

 if and($PDA,testDir('d',$PORTAL_HOME))
 {pretoc '1++:Portal Diagnostics'
  call analyze_ohs_logs($dsc,$top,$OC4J_USED,$VERSION,\%cmp)
  unpretoc
 }

=head2 Oracle Virtual Directory

Collects Oracle Virtual Directory-related configuration and log files.

=cut

 if and($OVD,testDir('d',$OVD_HOME))
 {pretoc '1++:Oracle Virtual Directory'
  call collect_ovd_instance($dsc,$top,\%cmp)
  unpretoc
 }

=head2 Oracle Web Cache

Gathers Oracle Web Cache configuration and log files. It also includes a DMS
dump.

=cut

 if and($WEBC,testDir('d',$WEBCACHE_HOME))
 {pretoc '1++:Oracle Web Cache'
  call collect_webc_instance($dsc,$top,\%cmp)
  unpretoc
 }
}
unpretoc

# Restore the initial environment
loop $key (keys(%ENV))
 call setEnv($key,$ENV{$key})

=head1 SEE ALSO

L<ASITlib.def|modules::ASITlib>,
L<DEVinfo.def|modules::DEVinfo>,
L<DEVlib.def|modules::DEVlib>,
L<DEVr11.def|modules::DEVr11>,
L<DSCVinfo.def|modules::DSCVinfo>,
L<DSCVr11.def|modules::DSCVr11>,
L<IAS.def|modules::IAS>,
L<OIDinfo.def|modules::OIDinfo>,
L<OIDr11.def|modules::OIDr11>,
L<OVDr11.def|modules::OVDr11>,
L<PDAinfo.def|modules::PDAinfo>,
L<PDAr11.def|modules::PDAr11>,
L<WEBCr11.def|modules::WEBCr11>

=begin credits

=over 10

=item RDA 4.14: Greg Cook, Gaurav Pathak, Andrew Salt.

=item RDA 4.15: Greg Cook, Andrew Salt, Olaf Stullich.

=item RDA 4.16: Greg Cook, Daniel Mortimer, Andrew Salt.

=back

=end credits

=head1 COPYRIGHT NOTICE

Copyright (c) 2002-2009, Oracle. All rights reserved.

=head1 TRADEMARK NOTICE

Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of Oracle
Corporation and/or its affiliates. Other names may be trademarks of their
respective owners.

=cut
