#!/usr/bin/python # Copyright 2012 Red Hat # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging import lxml.etree import os import traceback import sys # Flag to activate debug output (it is activated when the -d or # -debug command line options are provided): debugEnabled = False # In some environments there are several versions of some of the # most used jar files, so it is good to be explicit and state them # here: preferredJars = { # In RHEL we prefer to use the commons-codec jar file provided # by EAP6, as the version provided by the base operating # system is missing some methods that we need: "commons-codec": "/usr/share/java/commons-codec-eap6/commons-codec.jar", # XXX: I expect this dictionary to grow ... } def getSettingsProperty(propertyName, settingsFile): # Create the namespace map used when parsing settings files: nsmap = { "p": "http://maven.apache.org/POM/4.0.0", } # Parse the settings file: settingsDoc = lxml.etree.parse(settingsFile) # Get the list of active profile names: activeProfilesPath = ( "/p:settings" "/p:activeProfiles" "/p:activeProfile" "/text()" ) activeProfiles = settingsDoc.xpath(activeProfilesPath, namespaces=nsmap) # Try to find the value of the property in each of the active # profiles: for activeProfile in activeProfiles: propertyValuePath = ( "/p:settings" "/p:profiles" "/p:profile[p:id/text()='" + activeProfile + "']" "/p:properties" "/p:" + propertyName + "" "/text()" ) propertyValues = settingsDoc.xpath(propertyValuePath, namespaces=nsmap) if propertyValues: return propertyValues[0] # No luck: return None def getProperty(propertyName): # First try with the user specific settings file, if it # exists: homeDir = os.getenv("HOME") if homeDir: settingsFile = os.path.join(homeDir, ".m2/settings.xml") if os.path.exists(settingsFile): propertyValue = getSettingsProperty(propertyName, settingsFile) if propertyValue: return propertyValue # Then try with the global setttings file, if it exists: settingsFile = "/etc/maven/settings.xml" if os.path.exists(settingsFile): propertyValue = getSettingsProperty(propertyName, settingsFile) if propertyValue: return propertyValue # No luck: return None def resolveJar(jarName, searchPath): # Don't try to search the jar if it is given as an absolute # path, as this means that the application wants to use that # particular file (or maybe the application is broken): if os.path.isabs(jarName): if os.path.exists(jarName): return jarName else: return None # If we have a preferred jar for this name then try it before # anything else: preferredJar = preferredJars.get(jarName) if preferredJar and os.path.exists(preferredJar): logging.debug("Jar \"%s\" has been replaced by preferred jar \"%s\"." % (jarName, preferredJar)) return preferredJar # Add the jar extension to the name if it has not been # provided: if not jarName.endswith(".jar"): jarName = jarName + ".jar" # Try to find the jar file in each of the jar directories, in # the order they are specified in the search path: for jarDirectory in searchPath: jarFile = os.path.join(jarDirectory, jarName) if os.path.exists(jarFile): logging.debug("Jar \"%s\" has been resolved as \"%s\"." % (jarName, jarFile)) return jarFile # No luck: return None def main(): # Configure logging: logHandler = logging.StreamHandler(sys.stdout) logHandler.setLevel(logging.INFO) logFormatter = logging.Formatter('%(message)s') logHandler.setFormatter(logFormatter) logging.root.addHandler(logHandler) logging.root.setLevel(logging.DEBUG) # Initially the classpath is empty: unresolvedJars = [] # Parse the command line looking for the classpath options, # and for each of them remove it from the list of arguments # and add its content to the list of unresolved jar files: args = [] index = 1 while index < len(sys.argv): arg = sys.argv[index] if arg in ["-d", "-debug"]: logHandler.setLevel(logging.DEBUG) elif arg in ["-cp", "-classpath"]: index += 1 if index < len(sys.argv): arg = sys.argv[index] unresolvedJars.extend(arg.split(":")) else: args.append(arg) index += 1 # Build the search path for jar files that will be later used # to resolve them: searchPath = [] # Add the system wide jars directory to the search path: systemJars = "/usr/share/java" if os.path.exists(systemJars): searchPath.append(systemJars) # Add the engine jars directory to the search path: engineJars = os.path.join(systemJars, "ovirt-engine") if os.path.exists(engineJars): searchPath.append(engineJars) # Add the ear and lib directory of the deployed engine to the # search path: engineEar = "/usr/share/ovirt-engine/engine.ear" if os.path.exists(engineEar): searchPath.append(engineEar) engineLib = os.path.join(engineEar, "lib") if os.path.exists(engineLib): searchPath.append(engineLib) # Try to find the application server installation used in # development environments and add the lib directory of the # deployed engine to the jar path: jbossHome = getProperty("jbossHome") if jbossHome: logging.debug("Application server home is \"%s\"." % jbossHome) engineEar = os.path.join(jbossHome, "standalone/deployments/engine.ear") if os.path.exists(engineEar): searchPath.append(engineEar) engineLib = os.path.join(engineEar, "lib") if os.path.exists(engineLib): searchPath.append(engineLib) # Try to find the actual path for each unresolved jar: resolvedJars = [] missingJars = [] for unresolvedJar in unresolvedJars: resolvedJar = resolveJar(unresolvedJar, searchPath) if resolvedJar: resolvedJars.append(resolvedJar) else: missingJars.append(unresolvedJar) # Don't proceed if there are unresolved paths: if missingJars: for missingJar in missingJars: sys.stderr.write("Can't find the actual location of jar \"%s\".\n" % missingJar) sys.exit(1) # Compute the class path used to invoke the java virtual # machine: classPath = ":".join(resolvedJars) logging.debug("Class path is \"%s\"." % classPath) # Execute tha java virtual machine with the given classpath # and arguments: javaArgs = ["java", "-classpath", classPath] javaArgs.extend(args) logging.debug("Running command \"%s\"." % " ".join(javaArgs)) os.execvp("java", javaArgs) if __name__ == "__main__": try: main() except SystemExit: raise except BaseException as exception: sys.stderr.write("%s\n" % traceback.format_exc()) sys.exit(1)