Configuration for Tomcat 6.x application server on Windows

Microsoft.JEE.Tomcat.6.Windows.Configuration.Discovery (Discovery)

Discovers all Tomcat web application server configurations on Windows.

Knowledge Base article:

Summary

The configuration discovery locates configurations for Tomcat web application server. After they have been discovered, a monitoring template should be applied to enable monitoring.

Element properties:

TargetMicrosoft.Windows.Server.Computer
EnabledTrue
Frequency14400
RemotableFalse

Object Discovery Details:

Discovered Classes and their attribuets:
Discovered relationships and their attribuets:

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Microsoft.Windows.TimedScript.DiscoveryProvider Default

Source Code:

<Discovery ID="Microsoft.JEE.Tomcat.6.Windows.Configuration.Discovery" Target="Windows!Microsoft.Windows.Server.Computer" Remotable="true" Enabled="true">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="Microsoft.JEE.Tomcat.6.Windows.Configuration"/>
<DiscoveryRelationship TypeID="Microsoft.JEE.Tomcat.6.WindowsComputerContainsConfiguration.Relationship"/>
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.DiscoveryProvider">
<IntervalSeconds>14400</IntervalSeconds>
<SyncTime/>
<ScriptName>Microsoft.JEE.Tomcat.6.Configuration.Discover.vbs</ScriptName>
<Arguments>$Target/ManagementGroup/Id$ $MPElement$ "$MPElement[Name='Microsoft.JEE.Tomcat.6.Windows.Configuration']$" "$MPElement[Name='Microsoft.JEE.Tomcat.6.WindowsComputerContainsConfiguration.Relationship']$" $Target/Id$ $Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Arguments>
<ScriptBody><Script>
''' Copyright (c) Microsoft Corporation. All rights reserved.
'''
''' Date Created: Mar 21st, 2011
'
SetLocale("en-us")
'' Check if a file is too big (larger than or equal to 100 MB).
'' Return true if too big, else return false.
'' If a file does not exist, return false.
FUNCTION isFileTooBig(userSuppliedFSO, filePath, fileName)
''Set the maximum file size to 100MB
const maxFileSize = 104857600
Dim strFile, myFSO
isFileTooBig = false
strFile = filePath &amp; fileName
IF userSuppliedFSO is Nothing THEN
SET myFSO = CreateObject("Scripting.FileSystemObject")
ELSE
SET myFSO = userSuppliedFSO
END IF
IF myFSO.FileExists(strFile) = true then
'' Get a File object from a file system
set objFile = myFSO.GetFile(strFile)
'' Get the file size
fileSize = objFile.Size
IF fileSize &gt;= maxFileSize THEN
isFileTooBig = true
END IF
END IF
END FUNCTION
'
' Method to parse out a command line arguments
' The arguments can be
'
'
Function ParseOutCommandLineArg(cmdLine, arg)
Dim done
Dim pos
Dim quoted
Dim startpos
Dim gotKey
gotkey = false
quoted = false
pos = 1
startpos = 1
done = false
While not done
Select Case mid ( cmdLine , pos , 1 )
Case ""&amp;chr(34)
If gotkey and quoted Then
ParseOutCommandLineArg = mid(cmdLine,startpos,pos-startpos)
done = true
else
quoted = not quoted
End If
startpos = pos+1
Case "="
If arg = mid(cmdline,startpos,pos-startpos) Then
startpos = pos+1
gotkey = true
End If
Case " "
If gotkey Then
If not quoted Then
ParseOutCommandLineArg = mid(cmdLine,startpos,pos-startpos)
done = true
End If
Else
If arg = mid(cmdline,startpos,pos-startpos) Then
startpos = pos+1
gotkey = true
End If
End If
If not quoted Then
startpos = pos+1
End If
End Select
pos = pos + 1
if not done then
if pos &gt;len(cmdLine) Then
If gotkey Then
If not quoted Then
ParseOutCommandLineArg = mid(cmdLine,startpos,pos-startpos)
done = true
End If
End If
done = true
End If
End If
Wend
End Function
'
' Method to log an error to the windows event log
'
Function LogError(oAPI, scriptName, description)
Call oAPI.LogScriptEvent(scriptName, 100, 1, description)
End Function
'
' Method to log an error when failing to find a file
'
Function LogErrorFileNotFound(oAPI, scriptName, fileName)
LogError oAPI, scriptName, "Could not find expected configuration file: " &amp; fileName
End Function
'
' Method to log an error when failing to find a folder
'
Function LogErrorFolderNotFound(oAPI, scriptName, folderName)
LogError oAPI, scriptName, "Could not find expected folder: " &amp; folderName
End Function
'
' Method to log an error when failing to parse a file
'
Function LogErrorParsingFile(oAPI, scriptName, fileName)
LogError oAPI, scriptName, "Failed to parse configuration file: " &amp; fileName
End Function
'
' Method to log an error when failing to commuincate over HTTP
'
Function LogErrorHTTP(oAPI, scriptName, url, description, errorNumber)
LogError oAPI, scriptName, "HTTP commucation failed with: " &amp; url &amp; " - " &amp; description &amp; " - " &amp; CStr(errorNumber)
End Function

'' Copyright (c) Microsoft Corporation. All rights reserved.
'''
''' Filters out discovered instances that do not match the specified major version
''' Returns true if the desired version is the Major version.
'''
''' i.e. if desired major version is 6 and given 6.0.22, the result is true.
''' if desired major version is 6 and given 5.0.12, the result is false
'''
PUBLIC FUNCTION FilterVersion(strDesiredMajorVersion, strActualVersion)
FilterVersion = FALSE
' Filter out specific version.
' Need to be careful that the given filter is not longer
' than the string to be filtered, otherwise just make sure that
' what is at the beginning of one string matches the filter
IF (0 &lt; Len(strDesiredMajorVersion)) AND (Len(strDesiredMajorVersion) &lt;= Len(strActualVersion)) THEN
IF (0 = StrComp(strDesiredMajorVersion, Left(strActualVersion, Len(strDesiredMajorVersion)))) THEN
FilterVersion = TRUE
END IF
END IF
END FUNCTION

''' Copyright (c) Microsoft Corporation. All rights reserved.
''' Date Created: July 29th, 2010
'
SetLocale("en-us")
'''
''' Constants for Registry Access
'''
CONST HKEY_LOCAL_MACHINE = &amp;H80000002
CONST KEY_QUERY_VALUE = &amp;H0001
CONST KEY_SET_VALUE = &amp;H0002
CONST KEY_CREATE_SUB_KEY = &amp;H0004
CONST DELETE = &amp;H00010000
CONST PERSISTED_DISCOVERY = "PersistedDiscovery"
CONST REGISTRY_PROP_APP_SERVER_TYPE = "APPLICATION_SERVER_TYPE"
CONST REGISTRY_PROP_APP_SERVER_TYPE_JBOSS = "JBOSS"
CONST REGISTRY_PROP_APP_SERVER_TYPE_TOMCAT = "TOMCAT"
CONST REGISTRY_PROP_CONFIGURATION = "CONFIGURATION"
CONST REGISTRY_PROP_HTTP_PORT = "HTTP_PORT"
CONST REGISTRY_PROP_HTTPS_PORT = "HTTPS_PORT"
CONST REGISTRY_PROP_PATH = "PATH"
CONST REGISTRY_PROP_VERSION = "VERSION"
'''
''' Simple CLASS defining all the Discovery data
'''
CLASS ApplicationServerDiscoveryInfo
PUBLIC DiscoveredInstances
PUBLIC RegistryAdds
PUBLIC RegistryDeletes
PRIVATE SUB CLASS_initialize()
SET DiscoveredInstances = CreateObject("Scripting.Dictionary")
SET RegistryAdds = CreateObject("Scripting.Dictionary")
SET RegistryDeletes = CreateObject("Scripting.Dictionary")
END SUB
END CLASS
'
' Class to abstractly represent information for discovery data that
' can be used to populate the registry as well as Operations Mangaer.
' This is shared between the registry, Tomcat, and JBoss scripts.
'
CLASS ApplicationServerInstance
PUBLIC AppServerType
PUBLIC Configuration
PUBLIC HttpPort
PUBLIC HttpsPort
PUBLIC Version
PRIVATE SUB CLASS_INITIALIZE()
AppServerType = "Undefined"
Configuration = "Undefined"
HttpPort = "0"
HttpsPort = "0"
Version = "0"
END SUB
'
' Generate a unique key that can be used internally
' for updating the registry with discovered instances.
'
PUBLIC FUNCTION GetKey()
GetKey = Configuration
END FUNCTION
'
' A Compare method to determine if the this current object
' matches the given argument (expecting the argument to be
' of the same type.
'
PUBLIC FUNCTION Matches(otherAppSrv)
Matches = FALSE
IF (Not (otherAppSrv IS NOTHING)) THEN
IF (AppServerType = otherAppSrv.AppServerType) AND (Configuration = LCase(otherAppSrv.Configuration)) AND (HttpPort = otherAppSrv.HttpPort) AND (HttpsPort = otherAppSrv.HttpsPort) AND (Version = otherAppSrv.Version) THEN
Matches = TRUE
END IF
END IF
END FUNCTION
END CLASS
'
' Registry C.R.U.D.
' Create
' Read
' Update
' Delete
'
CLASS RegistryCrud
PUBLIC objRegistry
PUBLIC DesiredApplicationServerType
PUBLIC ManagementGroup
PUBLIC objScriptAPI
PRIVATE SUB class_initialize()
SET objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
ManagementGroup = "Default"
END SUB
PRIVATE FUNCTION GetBaseRegistryPath()
IF objScriptAPI IS NOTHING THEN
SET objScriptAPI = CreateObject("MOM.ScriptAPI")
END IF
GetBaseRegistryPath = objScriptAPI.GetScriptStateKeyPath(ManagementGroup)
END FUNCTION
PRIVATE FUNCTION GetPersistedDiscoveryRegistryPath()
GetPersistedDiscoveryRegistryPath = GetBaseRegistryPath() &amp; "\" &amp; PERSISTED_DISCOVERY
END FUNCTION
'
' A boolean FUNCTION that checks IF the given registry key has sub keys.
' Returns true IF the key exisits, otherwise false
'
FUNCTION CheckIfRegistryKeyHasSubKeys(keyToCheck)
DIM arrSubKeys
objRegistry.EnumKey HKEY_LOCAL_MACHINE, keyToCheck, arrSubKeys
DIM returnValue
returnValue = FALSE
IF NOT IsNull(arrSubKeys) THEN
returnValue = TRUE
END IF
CheckIfRegistryKeyHasSubKeys = returnValue
END FUNCTION
FUNCTION GetListOfRegistryEntries()
SET GetListOfRegistryEntries = ReadRegistryForPreviouslyDiscoveredAppServers(ManagementGroup)
END FUNCTION
'
' Look in registry and return a list of the previously
' known items.
'
FUNCTION ReadRegistryForPreviouslyDiscoveredAppServers(ManagementGroup)
DIM returnValue
SET returnValue = CreateObject("Scripting.Dictionary")
DIM PersistentRegKey
PersistentRegKey = GetPersistedDiscoveryRegistryPath()
IF CheckIfRegistryKeyHasSubKeys(PersistentRegKey) THEN
' Registry key exists, so loop through the entries and
' place this information into the discovery objects.
DIM arrSubKeys
objRegistry.EnumKey HKEY_LOCAL_MACHINE, PersistentRegKey, arrSubKeys
IF NOT IsNull(arrSubKeys) THEN
DIM subKey
FOR EACH subKey In arrSubKeys
DIM theKey, foundEntry, strValueName, strValue
SET foundEntry = NEW ApplicationServerInstance
'
' To determine a unique instance, a string representing a combination
' of HTTP and HTTPS ports will be used
'
DIM fullSubKey
fullSubKey = PersistentRegKey &amp; "\" &amp; subKey
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_APP_SERVER_TYPE, strValue
foundEntry.AppServerType = strValue
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_CONFIGURATION, strValue
foundEntry.Configuration = LCase(strValue)
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_HTTP_PORT, strValue
foundEntry.HttpPort = strValue
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_HTTPS_PORT, strValue
foundEntry.HttpsPort = strValue
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_VERSION, strValue
foundEntry.Version = strValue
IF DesiredApplicationServerType = foundEntry.AppServerType THEN
returnValue.Add foundEntry.GetKey, foundEntry
END IF
Next
END IF
END IF
SET ReadRegistryForPreviouslyDiscoveredAppServers = returnValue
END FUNCTION
'
' Remove the supplied entries from the Registry
'
' Parameter ListOfDeletes: a dictionary that contains a list
' of name/value of path/string that represents a list of objects
' to delete from the Registry. The value is not used, only the
' key is important to this function.
'
FUNCTION UpdateRegistryWithDeletedAppServers(ListOfDeletes)
DIM PersistentRegKey
PersistentRegKey = GetPersistedDiscoveryRegistryPath()
IF CheckIfRegistryKeyHasSubKeys(PersistentRegKey) THEN
DIM itemToDelete
FOR EACH itemToDelete IN ListOfDeletes
' The current item is of a type ApplicationServerInstance
DIM currentItem
SET currentItem = ListOfDeletes.Item(itemToDelete)
DIM keyToDelete
keyToDelete = "NotFound"
'
' For each of the items in the registry, we need to examine if the current entry
' matches all of the discovery items. If everything exactly matches, then delete
' the item from the registry.
'
' Registry key exists, so loop through the entries and
' place this information into the discovery objects.
DIM arrSubKeys
objRegistry.EnumKey HKEY_LOCAL_MACHINE, PersistentRegKey, arrSubKeys
IF NOT IsNull(arrSubKeys) THEN
DIM subKey
FOR EACH subKey In arrSubKeys
DIM fullSubKey
fullSubKey = PersistentRegKey &amp; "\" &amp; subKey
DIM entryAppServerType, entryConfiguration, entryHttpPort, entryHttpsPort, entryPath, entryVersion
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_APP_SERVER_TYPE, entryAppServerType
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_CONFIGURATION, entryConfiguration
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_HTTP_PORT, entryHttpPort
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_HTTPS_PORT, entryHttpsPort
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_PATH, entryPath
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, fullSubKey, REGISTRY_PROP_VERSION, entryVersion
IF (entryAppServerType = currentItem.AppServerType) AND (entryConfiguration = currentItem.Configuration) AND (entryHttpPort = currentItem.HttpPort) AND (entryHttpsPort = currentItem.HttpsPort) AND (entryVersion = currentItem.Version) THEN
keyToDelete = fullSubKey
EXIT FOR
END IF
NEXT
END IF
objRegistry.DeleteKey HKEY_LOCAL_MACHINE, keyToDelete
NEXT
END IF
END FUNCTION
'
' Add the supplied entries to the registry
'
' Parameter ListOfAdds: a dictionary that contains a list
' of name/value of path/Discovery-Object that
'
FUNCTION UpdateRegistryWithNewlyAddedAppServers(ListOfAdds)
DIM baseRegSubKeyToAdd
baseRegSubKeyToAdd = GetBaseRegistryPath()
objRegistry.CreateKey HKEY_LOCAL_MACHINE, baseRegSubKeyToAdd
baseRegSubKeyToAdd = baseRegSubKeyToAdd &amp; "\" &amp; PERSISTED_DISCOVERY
objRegistry.CreateKey HKEY_LOCAL_MACHINE, baseRegSubKeyToAdd
DIM entry
FOR EACH entry IN ListOfAdds
DIM regSubKeyToAdd
regSubKeyToAdd = baseRegSubKeyToAdd
'
' Registry Key should look like:
'
' SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Modules\Default\S-1-5-21-124525095-708259637-1543119021-711584\Script\PersistedDiscovery\{A GUID}
'
' Turns out the GUID returned in a struct and not a string, hence the
' shell game of getting the object and then removing the last two parts.
' Also it is important to set the typeLib back to nothing as otherwise you
' will get the same GUID again(!) - see Bug #36417
DIM typeLib, objGuid, strGuid
SET typeLib = CreateObject("Scriptlet.TypeLib")
objGuid = typeLib.Guid
strGuid = Left(objGuid, Len(objGuid)-2)
SET typeLib = Nothing
regSubKeyToAdd = regSubKeyToAdd &amp; "\" &amp; strGuid
objRegistry.CreateKey HKEY_LOCAL_MACHINE, regSubKeyToAdd
objRegistry.SetStringValue HKEY_LOCAL_MACHINE, regSubKeyToAdd, REGISTRY_PROP_APP_SERVER_TYPE, ListOfAdds.Item(entry).AppServerType
objRegistry.SetStringValue HKEY_LOCAL_MACHINE, regSubKeyToAdd, REGISTRY_PROP_CONFIGURATION, LCase(ListOfAdds.Item(entry).Configuration)
objRegistry.SetStringValue HKEY_LOCAL_MACHINE, regSubKeyToAdd, REGISTRY_PROP_HTTP_PORT, ListOfAdds.Item(entry).HttpPort
objRegistry.SetStringValue HKEY_LOCAL_MACHINE, regSubKeyToAdd, REGISTRY_PROP_HTTPS_PORT, ListOfAdds.Item(entry).HttpsPort
objRegistry.SetStringValue HKEY_LOCAL_MACHINE, regSubKeyToAdd, REGISTRY_PROP_VERSION, ListOfAdds.Item(entry).Version
NEXT
END FUNCTION
END CLASS
'
' Public interface to that the Tomcat and JBoss code will call
' to persist the running processes (for the actual algorithm
' details, see below).
'
' Parameter 1: Object which returns back a list of object representing running
' application server processes.
' Parameter 2: Management Group Name
' Parameter 3: File system object. For production code, leave this as NOTHING
'
FUNCTION DiscoveryWithPersistence(userSuppliedWmi, userSuppliedRegistry, userSuppliedMomApi, strManagementGroupName, strAppSrvType, userSuppliedFileSystemObject)
DIM algorithmOutput
DIM registryUpdater
SET registryUpdater = NEW RegistryCrud
IF NOT (userSuppliedRegistry IS NOTHING) THEN
SET registryUpdater.objRegistry = userSuppliedRegistry
END IF
IF (userSuppliedMomApi IS NOTHING) THEN
SET registryUpdater.objScriptAPI = CreateObject("MOM.ScriptAPI")
ELSE
SET registryUpdater.objScriptAPI = userSuppliedMomApi
END IF
registryUpdater.DesiredApplicationServerType = strAppSrvType
registryUpdater.ManagementGroup = strManagementGroupName
SET algorithmOutput = DiscoveryWithPersistenceAlgorithm(userSuppliedWmi, registryUpdater, userSuppliedFileSystemObject)
registryUpdater.UpdateRegistryWithDeletedAppServers(algorithmOutput.RegistryDeletes)
registryUpdater.UpdateRegistryWithNewlyAddedAppServers(algorithmOutput.RegistryAdds)
SET DiscoveryWithPersistence = algorithmOutput.DiscoveredInstances
END FUNCTION
'
' 1) Query WMI for a list of java processes, add this to list A
' 2) Query for registry and to get a list of the previously known instances, add this to list B
' 3) For each entry in A, create a discovery item
' 4) For each entry in A, find a corresponding entry for B
' a. If the entry is there, remove the entry from B
' A match is where the path, all ports match, and version matches
' b. If there is not a entry, add this to the addToRegistry list
' c. Assumption: when this step completes, B will only contain a list of entries that are not running either because they have been stopped or removed
' 5) For each entry in B, verify that the directory still exists
' a. If the entries "path to installation" folder exists, create a discovery item (this instance is currently stopped)
' b. If the entries "path to installation" folder does not exists, add this to the deleteFromRegistry list
' 6) Update registry
' a. Remove out-dated registry items
' b. Add new registry items for "first-time-run" processes
'
FUNCTION DiscoveryWithPersistenceAlgorithm(userSuppliedWmi, userSuppliedRegistry, userSuppliedFileSystemObject)
DIM objDiscoveryResults
SET objDiscoveryResults = NEW ApplicationServerDiscoveryInfo
DIM listOfDiscoveryData, listOfAddToRegistry, listOfDeleteFromRegistry
DIM listOfCurrentRunningProcesses, listOfCurrentRegistryEntries
SET listOfDiscoveryData = CreateObject("Scripting.Dictionary")
SET listOfAddToRegistry = CreateObject("Scripting.Dictionary")
SET listOfDeleteFromRegistry = CreateObject("Scripting.Dictionary")
SET listOfCurrentRunningProcesses = GetListOfRunningInstances(userSuppliedWmi)
SET listOfCurrentRegistryEntries = GetListOfRegistryEntries(userSuppliedRegistry)
DIM runningProcess, runningProcessInLowerCase
'
' For running process, create a discovery item. Also for each process,
' check IF there is a corresponding registry entry. IF there is an entry,
' remove it so we can narrow down the list of out-of-date registry entries.
' IF a running process does not have an entry in the registry list, then it
' is NEW and a entry should be added to the registry.
'
FOR EACH runningProcess IN listOfCurrentRunningProcesses
'
' All running processes should have a discovery item.
'
runningProcessInLowerCase = LCase(runningProcess)
listOfDiscoveryData.Add runningProcessInLowerCase, CopyApplicationServerInstance(listOfCurrentRunningProcesses.Item(runningProcess))
'
' IF a key exists in the registry representation, remove it (because that means)
' the cached value is correct. IF there is a miss, this this value is "new" and
' should be added to the registry/cache
'
' This is a workaround. So it turns out that if you call Item(a) on
' a dictionary and the key is NOT in the dictionary, an entry will
' be added. The key will 'a' and the value will be Empty. This is a
' problem. The code assumes that the value is an object and mixing
' Empty and Nothing does work.
'
' To bypass this troublesome scenaro, the code below will insert a NOTHING
' just to be safe. This is a workaround, and elsewhere we must not rely
' on the Exists function.
'
DIM keyExistsInRegistry
keyExistsInRegistry = listOfCurrentRegistryEntries.Exists(runningProcessInLowerCase)
IF NOT keyExistsInRegistry THEN
SET listOfCurrentRegistryEntries.Item(runningProcessInLowerCase) = NOTHING
END IF
IF keyExistsInRegistry AND (listOfDiscoveryData.Item(runningProcessInLowerCase).Matches(CopyApplicationServerInstance(listOfCurrentRegistryEntries.Item(runningProcessInLowerCase)))) THEN
listOfCurrentRegistryEntries.Remove runningProcessInLowerCase
ELSE
listOfAddToRegistry.Add runningProcessInLowerCase, CopyApplicationServerInstance(listOfCurrentRunningProcesses.Item(runningProcess))
END IF
NEXT
'
' Assumption: now that the above loop has completed, the
' listOfCurrentRegistryEntries should only contain a list of
' entries that are not running either because the instance
' has been stopped or deleted.
'
DIM fso
IF userSuppliedFileSystemObject Is Nothing Then
SET fso = CreateObject("Scripting.FileSystemObject")
ELSE
SET fso = userSuppliedFileSystemObject
END IF
'
' For each entry in listOfCurrentRegistryEntries, verify that the
' directory still exists. IF the entry's "path to installation"
' folder exists and if there is not already an entry (i.e. a port change),
' create a discovery item (because this instance is
' currently stopped). IF the entry's "path to installation" folder
' does NOT exists, then the instance has been deleted and the registry
' entry should be removed.
'
DIM remainingRegistryEntry
FOR EACH remainingRegistryEntry IN listOfCurrentRegistryEntries
'
' Due to how the Item method works, if the value is not available an Empty
' is inserted into the dictionary. To work around this, other parts of the
' code replace this with NOTHING so that the VBScript won't break. This
' IF statement is necessary to bypass that workaround.
'
IF NOT listOfCurrentRegistryEntries.Item(remainingRegistryEntry) IS NOTHING THEN
IF fso.FolderExists(listOfCurrentRegistryEntries.Item(remainingRegistryEntry).Configuration) AND (NOT listOfDiscoveryData.Exists(remainingRegistryEntry)) THEN
listOfDiscoveryData.Add remainingRegistryEntry, CopyApplicationServerInstance(listOfCurrentRegistryEntries.Item(remainingRegistryEntry))
ELSE
listOfDeleteFromRegistry.Add remainingRegistryEntry, CopyApplicationServerInstance(listOfCurrentRegistryEntries.Item(remainingRegistryEntry))
END IF
END IF
NEXT
SET objDiscoveryResults.DiscoveredInstances = listOfDiscoveryData
SET objDiscoveryResults.RegistryAdds = listOfAddToRegistry
SET objDiscoveryResults.RegistryDeletes = listOfDeleteFromRegistry
SET DiscoveryWithPersistenceAlgorithm = objDiscoveryResults
END FUNCTION
'
' Helper Method to copy the ApplicationServerInstance object.
' This is necessary b/c VBscript does not support 'shallow' copies
'
FUNCTION CopyApplicationServerInstance(oldAppSrvInstance)
DIM newAppSrvInstance
IF oldAppSrvInstance IS NOTHING THEN
SET newAppSrvInstance = NOTHING
ELSE
SET newAppSrvInstance = NEW ApplicationServerInstance
newAppSrvInstance.AppServerType = oldAppSrvInstance.AppServerType
newAppSrvInstance.Configuration = LCase(oldAppSrvInstance.Configuration)
newAppSrvInstance.HttpPort = oldAppSrvInstance.HttpPort
newAppSrvInstance.HttpsPort = oldAppSrvInstance.HttpsPort
newAppSrvInstance.Version = oldAppSrvInstance.Version
END IF
SET CopyApplicationServerInstance = newAppSrvInstance
END FUNCTION
'
' Abstraction for getting a list of the objects that represent running processes.
' The caller of the DiscoveryWithPersistence() method is expected to supply an object
' that returns a list of these objects. In practice, this is a dictionary where the
' key is path and the value associated is an ApplicationServerInstance object with
' the necessary items to populate a dicovery data item in Operations Manager.
'
PRIVATE FUNCTION GetListOfRunningInstances(userSuppliedWmi)
SET GetListOfRunningInstances = userSuppliedWmi.GetListOfRunningInstances()
END FUNCTION
'
' Abstraction for getting a list of the objects that represent registry
' entries. For the production code, please review the RegistryCrud object.
'
PRIVATE FUNCTION GetListOfRegistryEntries(userSuppliedRegistry)
SET GetListOfRegistryEntries = userSuppliedRegistry.GetListOfRegistryEntries()
END FUNCTION

' Copyright (c) Microsoft Corporation. All rights reserved.
' Date Created: July 6th, 2010
'
' This script is to be incorporated into the Tomcat JEE MP.
' This script will discover the running java process of Tomcat
' Web Application server Configurations.
'
SetLocale("en-us")
'
' String found before the version in the Tomcat RELEASE NOTES file
'
CONST TOMCAT_VERSION_PRECURSOR = "Apache Tomcat Version "
'''
''' Constants for use in this script
'''
CONST TOMCAT_DISCOVERY_SCRIPT_NAME = "TomcatDiscovery.vbs"
'''
''' Simple Class defining the Process Discovery data
'''
Class ProcessInfo
Public CatalinaHomePath
Public Profile
End Class
'''
''' Simple Class defining the Tomact Configuration Discovery data
'''
Class ProfileDiscoveryInfoClass
Public ListOfProfiles
Private Sub CLASS_initialize()
Set ListOfProfiles = CreateObject("Scripting.Dictionary")
End Sub
Function GetListOfRunningInstances()
Set GetListOfRunningInstances = ListOfProfiles
End Function
End Class
'
' From the base folder for a Tomcat installation, look in the
' conf/server.xml file to locate the configurations for
' this installation.
'
Function getTomcatProfileInfo (oAPI, objProcessInfo, userSuppliedFSO, userSuppliedXmlDom)
Dim fso
Dim counter
Dim objXMLDoc, objNodeList, objNode
Dim strProfileServerXmlPath
Dim objProfileInfo
Dim strFilePath, strFileName
Set getTomcatProfileInfo = nothing
If userSuppliedFso Is Nothing Then
Set fso = CreateObject("Scripting.FileSystemObject")
Else
Set fso = userSuppliedFso
End If
If objProcessInfo.Profile = "" Then
Wscript.Echo "getTomcatProfileInfo: No folder parameter supplied, script exiting in error."
Exit Function
End If
strProfileServerXmlPath = objProcessInfo.Profile &amp; "\conf\server.xml"
strFilePath = objProcessInfo.Profile &amp; "\conf\"
strFileName = "server.xml"
IF fso.FileExists(strProfileServerXmlPath) and (Not isFileTooBig(fso, strFilePath, strFileName)) THEN
If userSuppliedXmlDom Is Nothing Then
Set objXMLDoc = CreateObject("Microsoft.XMLDOM")
Else
Set objXMLDoc = userSuppliedXmlDom
End If
objXMLDoc.async = False
objXMLDoc.load(strProfileServerXmlPath)
Set objProfileInfo = new ApplicationServerInstance
objProfileInfo.AppServerType = REGISTRY_PROP_APP_SERVER_TYPE_TOMCAT
objProfileInfo.Configuration = objProcessInfo.Profile
objProfileInfo.Version = getTomcatVersion(objProcessInfo, fso)
'
' Extract necessary information from the server.xml file
' This gives us the HttpPort and HttpsPort
' Try use the &lt;Service name="Catalina"&gt; if that fails use the first &lt;Service&gt; entry in the file
Dim ServerName
Set objNodeList = objXMLDoc.selectNodes("/Server/Service/@name")
If objNodeList is nothing then
Wscript.Echo "getTomcatProfileInfo: server.xml does not contain a service, script exiting in error."
LogErrorParsingFile oAPI, TOMCAT_DISCOVERY_SCRIPT_NAME, strProfileServerXmlPath
Exit Function
End If
ServerName = objNodeList.Item(0).text
Dim acounter
for acounter = 0 to objNodeList.length-1
If "Catalina" = objNodeList.Item(acounter).text Then
ServerName = objNodeList.Item(acounter).text
End If
Next
' Retrieve the http and https port from the service found
Set objNodeList = objXMLDoc.selectNodes("/Server/Service[@name='"&amp;ServerName&amp;"']/Connector")
If not objNodeList is nothing then
If objNodeList.length &gt; 0 Then
' Step through all the connectors looking for the HTTP and HTTPS connector
FOR acounter = 0 to objNodeList.length-1
Dim strProtocol
strProtocol = objNodeList.item(acounter).GetAttribute("protocol")
' For Tomcat 5.5 the protocol attribute is not specified
' It is supplied for Tomcat 6 and 7
If "HTTP/1.1" = strProtocol OR IsEmpty(strProtocol) OR IsNull(strProtocol) Then
Dim strSecure
strSecure = objNodeList.item(acounter).GetAttribute("secure")
If IsEmpty(strSecure) OR IsNull(strSecure) THEN
' Use the first available connector that does not have the 'Secure' attribute
IF 0 = objProfileInfo.HttpPort THEN
objProfileInfo.HttpPort = objNodeList.item(acounter).GetAttribute("port")
END IF
ELSE
' Use the first available connector that has the 'Secure' attribute
IF 0 = objProfileInfo.HttpsPort THEN
objProfileInfo.HttpsPort = objNodeList.item(acounter).GetAttribute("port")
END IF
END IF
END IF
NEXT
End If
End If
if objProfileInfo.HttpsPort = 0 and objProfileInfo.HttpPort = 0 then
Set getTomcatProfileInfo = nothing
else
Set getTomcatProfileInfo = objProfileInfo
End If
ELSE
LogErrorFileNotFound oAPI, TOMCAT_DISCOVERY_SCRIPT_NAME, strProfileServerXmlPath
Set getTomcatProfileInfo = nothing
END IF
End Function
'
' Function to parse the text of the RELEASE-NOTES text file for version information.
' The parser assumes that there is a line in the file like:
'
' Apache Tomcat Version 5.5.30
'
' The method will search for said line and then take the string after
' "Apache Tomcat Version " and return this as the version parameter. If the string
' cannot be found (or say the file does not exist), then UNKNOWN will be returned.
'
' Argument objProcessInfo : Object Describing Tomcat (Process) Instance
' (needed for providing path to the Tomcat Configuration)
' Argument objFso : File System Object
' (needed for determing existence of the RELEASE-NOTES
' file and reading it)
PRIVATE FUNCTION getTomcatVersion(objProcessInfo, objFso)
getTomcatVersion = "UNKNOWN"
DIM strReleaseNotes, strLine
strReleaseNotes = objProcessInfo.CatalinaHomePath &amp; "\RELEASE-NOTES"
IF objFso.FileExists(strReleaseNotes) THEN
DIM objTextFile
' The second argument represents the constant ForReading
SET objTextFile = objFSO.OpenTextFile (strReleaseNotes, 1)
DO UNTIL objTextFile.AtEndOfStream
strLine = objTextFile.Readline
DIM intFindResult
intFindResult = InStr(strLine, TOMCAT_VERSION_PRECURSOR)
IF 0 &lt; intFindResult THEN
'
' Parse out the version information from a line that should look
' similar to:
'
' Apache Tomcat Version 5.5.30
'
' Assuming the string only appears once in the file, then
' we can stop reading the file too.
'
getTomcatVersion = Mid(strLine, intFindResult + Len(TOMCAT_VERSION_PRECURSOR))
EXIT DO
END IF ' Found Tomcat Version String
LOOP ' Read File Loop
END IF ' File Existence Check
END FUNCTION
'
' Scan the running processes on the local machine for 'JAVA%.EXE' or 'CONHOST.EXE'
' to locate running tomcat instances.
'
Function GetTomcatProcessesInfo(userSuppliedWmi, userSuppliedRegExp)
DIM objWMIService
DIM objProcessInfoList
Set objProcessInfoList = CreateObject("Scripting.Dictionary")
If userSuppliedWmi Is Nothing Then
Set objWMIService = GetObject("winmgmts:\root\cimv2")
Else
Set objWMIService = userSuppliedWmi
End If
' Get a list of the running processes
DIM collectionOfProcesses
SET collectionOfProcesses = objWMIService.ExecQuery("SELECT CommandLine FROM Win32_Process WHERE Name LIKE 'java%.exe' or Name = 'conhost.exe'")
FOR EACH processInstance IN collectionOfProcesses
If Len(processInstance.CommandLine) &gt; 0 Then
If CheckIfTomcatProcess(userSuppliedRegExp, processInstance.CommandLine) THEN
Dim objProcInfo
Set objProcInfo = NEW ProcessInfo
'Get CATALINA_HOME command line argument
DIM strCatalinaHome
strCatalinaHome = ParseOutCommandLineArg(processInstance.CommandLine, "-Dcatalina.home")
IF NOT (IsEmpty(strCatalinaHome) ) THEN
objProcInfo.CatalinaHomePath = LCase(strCatalinaHome)
'Get CATALINA_BASE command line argument
'CATALINA_BASE is used to point to a configuration folder which contains conf and webapps folders
Dim instance
instance = ParseOutCommandLineArg(processInstance.CommandLine, "-Dcatalina.base")
IF NOT (IsEmpty(instance) ) THEN
instance = LCase(instance)
objProcInfo.Profile = instance
objProcessInfoList.Add objProcInfo.Profile, objProcInfo
END IF ' empty instance
End If ' empty strCatalinaHome
End If ' Tomcat Process Check
End If
Next
Set GetTomcatProcessesInfo = objProcessInfoList
End Function
'
' Method to verify if the given command line is a Tomcat process.
' This is done by verifying the string contains:
' org.apache.catalina.startup.Bootstrap
'
Public Function CheckIfTomcatProcess(userSuppliedRegExp, strInput)
Dim objIsRegExp
If userSuppliedRegExp is Nothing Then
Set objIsRegExp = New RegExp
objIsRegExp.IgnoreCase = True
objIsRegExp.Global = True
objIsRegExp.Pattern = " org\.apache\.catalina\.startup\.Bootstrap"
Else
Set objIsRegExp = userSuppliedRegExp
End If
DIM objMatchesCol, boolIsTomcat
boolIsTomcat = false
Set objMatchesCol = objIsRegExp.Execute(strInput)
If (1 = objMatchesCol.Count) Then
boolIsTomcat = true
End If
CheckIfTomcatProcess = boolIsTomcat
End Function
'''
''' Returns a list of Tomcat instances after checkinf running process
''' and parsing the data from server.xml in the conf directory
'''
Function GetTomcatInstances (oAPI, userSuppliedWmi, userSuppliedRegExp, userSuppliedFSO, userSuppliedXmlDom)
Dim objProcessInfoList
Set objProcessInfoList = GetTomcatProcessesInfo(userSuppliedWmi, userSuppliedRegExp)
Dim objProfileDiscoveryInfoList
Set objProfileDiscoveryInfoList = CreateObject("Scripting.Dictionary")
Dim objProcessInfo
For Each objProcessInfo in objProcessInfoList
Dim profDiscInfo
Set profDiscInfo = getTomcatProfileInfo (oAPI, objProcessInfoList.Item(objProcessInfo), userSuppliedFSO, userSuppliedXmlDom)
If Not (profDiscInfo is nothing) Then
objProfileDiscoveryInfoList.Add profDiscInfo.GetKey, profDiscInfo
End if
Next
Set GetTomcatInstances = objProfileDiscoveryInfoList
End Function
'''
''' Create instances in OpsMgr for all found instances of Tomcat configuration
'''
Public Function ReturnTomcatProfiles(oAPI, ManagementGroup, SourceId, TomcatClassGuid, TomcatReleationGuid, ManagedEntityId, TargetComputer, MajorTomcatVersion)
Dim oDiscoveryData, oInst
set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
Dim objProfileDiscoveryInfoClass
Set objProfileDiscoveryInfoClass = New ProfileDiscoveryInfoClass
Set objProfileDiscoveryInfoClass.ListOfProfiles = GetTomcatInstances(oAPI, Nothing, Nothing, Nothing, Nothing)
DIM objProfileMonitoringInfo
SET objProfileMonitoringInfo = objProfileDiscoveryInfoClass.ListOfProfiles
Set objProfileMonitoringInfo = DiscoveryWithPersistence(objProfileDiscoveryInfoClass, Nothing, Nothing, ManagementGroup, REGISTRY_PROP_APP_SERVER_TYPE_TOMCAT, Nothing)
DIM entry
FOR EACH entry IN objProfileMonitoringInfo
IF FilterVersion(MajorTomcatVersion, objProfileMonitoringInfo.Item(entry).Version) THEN
set oInst = oDiscoveryData.CreateClassInstance(TomcatClassGuid)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/HostName$", TargetComputer)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/Id$", objProfileMonitoringInfo.Item(entry).Configuration)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/HttpPort$", objProfileMonitoringInfo.Item(entry).HttpPort)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/HttpsPort$", objProfileMonitoringInfo.Item(entry).HttpsPort)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/Version$", objProfileMonitoringInfo.Item(entry).Version)
call oInst.AddProperty("$MPElement[Name='JEE!Microsoft.JEE.ApplicationServer.Instance']/DiskPath$", objProfileMonitoringInfo.Item(entry).Configuration)
call oInst.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", "Tomcat|" &amp; objProfileMonitoringInfo.Item(entry).Configuration)
call oDiscoveryData.AddInstance(oInst)
set oComputer = oDiscoveryData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Computer']$")
call oComputer.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", TargetComputer)
set oContains = oDiscoveryData.CreateRelationShipInstance(TomcatReleationGuid)
oContains.Source = oComputer
oContains.Target = oInst
call oDiscoveryData.AddInstance(oContains)
Set oHealthServiceInstance = oDiscoveryData.CreateClassInstance( "$MPElement[Name='SC!Microsoft.SystemCenter.HealthService']$" )
call oHealthServiceInstance.AddProperty ("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", TargetComputer )
set oHsCnRel = oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='SC!Microsoft.SystemCenter.HealthServiceShouldManageEntity']$")
oHsCnRel.Source = oHealthServiceInstance
oHsCnRel.Target = oInst
call oDiscoveryData.AddInstance(oHsCnRel)
END IF
NEXT
Call oAPI.Return(oDiscoveryData)
End Function

Dim oArgs, oAPI, guidManagementGroup, guidMpElement, guidConfiguration, guidRelation, guidId, strMachineName, strTomcatMajorVersion

Set oArgs = WScript.Arguments

if oArgs.Count &lt; 6 Then
Wscript.Quit -1
End If

guidManagementGroup = oArgs(0)
guidMpElement = oArgs(1)
guidConfiguration = oArgs(2)
guidRelation = oArgs(3)
guidId = oArgs(4)
strMachineName = oArgs(5)
strTomcatMajorVersion = "6"

Set oAPI = CreateObject("MOM.ScriptAPI")
ReturnTomcatProfiles oAPI, guidManagementGroup, guidMpElement, guidConfiguration, guidRelation, guidId, strMachineName, strTomcatMajorVersion
</Script></ScriptBody>
<TimeoutSeconds>300</TimeoutSeconds>
</DataSource>
</Discovery>