/** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ import groovy.util.logging.* import ProjectInformation import Feature import FeatureParser import java.util.Properties import java.util.List import java.util.ArrayList import java.util.regex.Matcher import java.util.regex.Pattern import DeployESB import DeployPythonPackages import DeployEdexSiteLocalization import IPluginCustomDeployer /** * Initial version of the deploy-install driver. Temporarily * wrapped by and executed by an ant script until the Groovy * plugins become a standard part of the uframe Eclipse distribution. * *
 *
 * SOFTWARE HISTORY
 *
 * Date         Ticket#    Engineer    Description
 * ------------ ---------- ----------- --------------------------
 * Dec 4, 2014  3836       bkowal      Initial Commit
 * Dec 9, 2015  5388       dhladky     Fix multi WA deploy
 *
 * 
* * @author bkowal * @version 1.0 */ @Log class DeployInstall { private static final String edexFeatureRegex = '^.*\\.edex\\..*\\.feature$' private static final Pattern EDEX_FEATURE_PATTERN = Pattern.compile(edexFeatureRegex) // temporarily have to declare and add this feature to the list of deployed features // manually. there are improvements that can be made in 15.1. private static final String COMMON_BASE_FEATURE = "com.raytheon.uf.common.base.feature" // temporary. maintain backwards compatibility until baseline cleanup private final List blacklistedEdexFeatures private projectInformationMap = [:] private List edexFeaturesToDeploy private String edexRootDirectory private String[] localizationSitesToDeploy = [] private boolean deployPythonPackages private String pythonRootDirectory private String[] pythonPackagesToDeploy = [] private String architecture private List customPluginDeployers // a list of features that have been deployed to ensure that a feature is not deployed // more than once. private List featuresDeployed = [] // a list of the plugins that we will be deploying. private List pluginsToDeploy = [] // used to track which feature a plugin was discovered in; will be used to // verify that a plugin is not listed in more than one feature. private pluginToFeatureMap = [:] public DeployInstall(final String workspaceDirectory, final String localizationSites, final boolean deployPythonPackages, final String edexRootDirectory, final String pythonRootDirectory, final String pythonPackages, final String architecture) { blacklistedEdexFeatures = new ArrayList() // never deploy these features blacklistedEdexFeatures.add("com.raytheon.edex.wa.feature") blacklistedEdexFeatures.add("com.raytheon.edex.feature.uframe") this.init(workspaceDirectory.trim()) if (localizationSites.trim() != "") { this.localizationSitesToDeploy = localizationSites.trim().split(":") } this.deployPythonPackages = deployPythonPackages this.edexRootDirectory = edexRootDirectory.trim() this.pythonRootDirectory = pythonRootDirectory.trim() if (pythonPackages.trim() != "") { this.pythonPackagesToDeploy = pythonPackages.trim().split(":") } this.architecture = architecture.trim() } public void deploy() { // recursively build the list of plugins that will be deployed. for (String featureToDeploy : edexFeaturesToDeploy) { this.buildPluginList(featureToDeploy) } log.info "Found " + this.pluginsToDeploy.size() + " Plugins To Deploy." this.cleanup() this.deployPlugins() // complete the esb deployment // we need to determine the location of the build.edex project ProjectInformation projectInformation = this.projectInformationMap["deploy.edex.awips2"] if (projectInformation == null) { log.log(java.util.logging.Level.SEVERE, "Unable to find project - deploy.edex.awips2") System.exit(-1) } final String esbDirectory = projectInformation.projectFullLocation + File.separator + "esb" DeployESB.deploy(this.edexRootDirectory, esbDirectory, this.architecture) DeployESB.deployEdexConfiguration(this.edexRootDirectory, esbDirectory) if (this.deployPythonPackages) { DeployPythonPackages.deploy(this.pythonRootDirectory, this.projectInformationMap["pythonPackages"], this.pythonPackagesToDeploy) } if (this.localizationSitesToDeploy.length > 0) { for (String localizationSite : this.localizationSitesToDeploy) { String localizationProject = "localization." + localizationSite DeployEdexSiteLocalization.deploy(this.edexRootDirectory, this.projectInformationMap[localizationProject], localizationSite) } } } // remove the existing deployment private void cleanup() { // remove the contents of the edex lib directory (execluding native) log.info "Cleaning EDEX lib directory ..." final String EDEX_LIB_DIRECTORY = this.edexRootDirectory + File.separator + "lib" for (File file : new File(EDEX_LIB_DIRECTORY).listFiles()) { if (file.getName() == "native") { continue } file.deleteDir() } // remove the shell scripts and the yajsw sub-directory from the edex bin directory log.info "Cleaning EDEX bin directory ..." final String EDEX_BIN_DIRECTORY = this.edexRootDirectory + File.separator + "bin" for (File file : new File(EDEX_BIN_DIRECTORY).listFiles()) { if (file.getName() == "yajsw") { file.deleteDir() } // we really should be checking the file extension here instead of just doing a // basic String comparison if (file.getName().endsWith(".sh") || file.getName() == "setup.env") { file.delete() } } // remove the contents of the edex conf directory log.info "Cleaning EDEX conf directory ..." final String EDEX_CONF_DIRECTORY = this.edexRootDirectory + File.separator + "conf" for (File file : new File(EDEX_CONF_DIRECTORY).listFiles()) { if (file.isDirectory()) { file.deleteDir() } else { file.delete() } } } private void deployPlugins() { // we will need ant to complete this AntBuilder ant = new AntBuilder() ant.project.getBuildListeners().firstElement().setMessageOutputLevel(0) log.info "Deploying plugins ..." for (String plugin : this.pluginsToDeploy) { this.deployPlugin(plugin, ant) } } // FOSS plugins are plugins that include jar files. private boolean isFOSSPlugin(ProjectInformation projectInformation) { final String jarSuffix = ".jar" // loop through the files in the plugin directory; true if a single // jar file is found. for (String pluginFile : new File(projectInformation.projectFullLocation).listFiles()) { if (pluginFile.endsWith(".jar")) { return true } } return false } private void deployPlugin(String plugin, AntBuilder ant) { // first, attempt to find the plugin in the plugin map ProjectInformation projectInformation = this.projectInformationMap[plugin] if (projectInformation == null) { log.log(java.util.logging.Level.SEVERE, "Unable to find plugin - " + plugin) System.exit(-1) } // next, attempt to access the build.properties file for the plugin final String PLUGIN_BUILD_PROPERTIES = projectInformation.projectFullLocation + File.separator + "build.properties" if (new File(PLUGIN_BUILD_PROPERTIES).exists() == false) { log.log(java.util.logging.Level.SEVERE, "Unable to find the build.properties file for plugin - " + plugin) System.exit(-1) } log.info "Deploying plugin ... " + plugin // read the plugin build.properties file BufferedReader br = new BufferedReader(new FileReader(PLUGIN_BUILD_PROPERTIES)) Properties properties = new Properties() properties.load(br) final String output = properties.getProperty("output..") final String binIncludes = properties.getProperty("bin.includes") if (output == null) { // we will not be producing a jar file and are most likely deploying a FOSS plugin this.deployFOSSPlugin(projectInformation, binIncludes, ant) return } // jar the plugin final String pluginJarName = plugin + ".jar" final String edexLibPlugins = this.edexRootDirectory + File.separator + "lib" + File.separator + "plugins" new File(edexLibPlugins).mkdirs() final String fullJarPath = edexLibPlugins + File.separator + pluginJarName ant.jar( destfile : fullJarPath, manifest : projectInformation.projectFullLocation + File.separator + "META-INF" + File.separator + "MANIFEST.MF" ) { fileset( dir : projectInformation.projectFullLocation + File.separator + output ) } // is the plugin FOSS? if (this.isFOSSPlugin(projectInformation)) { this.deployFOSSPlugin(projectInformation, binIncludes, ant) return } // finish the plugin based on build.properties for (String binInclude : binIncludes.split(",")) { binInclude = binInclude.trim() if (binInclude == ".") { continue } // ensure that the artifact exists final String artifact = projectInformation.projectFullLocation + File.separator + binInclude if (new File(artifact).exists() == false) { log.log(java.util.logging.Level.SEVERE, artifact + " specified in build.properties for plugin " + projectInformation.project + " was not found") System.exit(-1) } // add the artifact to the jar if (new File(artifact).isDirectory()) { ant.jar( destfile : fullJarPath, update : true ) { fileset( dir : projectInformation.projectFullLocation, includes : binInclude ) } } else { ant.jar( destfile : fullJarPath, update : true ) { fileset( file : artifact ) } } } // run "custom" deployment steps for (IPluginCustomDeployer pluginCustomDeployer : this.customPluginDeployers) { pluginCustomDeployer.deploy(this.edexRootDirectory, projectInformation.project, projectInformation.projectFullLocation) } } private void deployFOSSPlugin(ProjectInformation projectInformation, String binIncludes, AntBuilder ant) { final String edexLibDependencies = this.edexRootDirectory + File.separator + "lib" + File.separator + "dependencies" + File.separator + projectInformation.project // create the destination directory new File(edexLibDependencies).mkdirs() for (String binInclude : binIncludes.split(",")) { binInclude = binInclude.trim() if (binInclude == ".") { continue } // ensure that the artifact exists final String artifact = projectInformation.projectFullLocation + File.separator + binInclude if (new File(artifact).exists() == false) { log.log(java.util.logging.Level.SEVERE, artifact + " specified in build.properties for plugin " + projectInformation.project + " was not found") System.exit(-1) } if (new File(artifact).isDirectory()) { ant.copy( todir : edexLibDependencies ) { fileset( dir : artifact ) } } else { ant.copy( todir : edexLibDependencies, file : artifact ) } } } private void buildPluginList(String featureName) { if (this.featuresDeployed.contains(featureName)) { log.log(java.util.logging.Level.WARNING, "Feature " + featureName + " has been included more than once; skipping the duplicate.") return } log.info "Analyzing feature ... " + featureName // first, attempt to find the feature in the project map ProjectInformation projectInformation = this.projectInformationMap[featureName] // verify that the feature exists if (projectInformation == null) { log.log(java.util.logging.Level.SEVERE, "Unable to find the specified feature - " + featureName) System.exit(-1) } final String featureFullPath = projectInformation.projectFullLocation + File.separator + "feature.xml" // verify that the feature exists if (new File(featureFullPath).exists() == false) { log.log(java.util.logging.Level.SEVERE, "Unable to find the specified feature - " + featureName + "; '" + featureFullPath + "' does not exist") System.exit(-1) } Feature feature = FeatureParser.parseFeature(featureFullPath, featureName) // first, process any features that the feature includes for (String featureInclude : feature.getIncludes()) { this.buildPluginList(featureInclude) } // should we also check dependencies? // complete an initial analysis of the plugins that we will be deploying for (String plugin : feature.getPlugins()) { final String featureWithPlugin = this.pluginToFeatureMap[plugin] if (featureWithPlugin == null) { // we have not seen this plugin yet this.pluginToFeatureMap[plugin] = featureName } else { // we have seen this plugin before, verify that the plugin // is not in more than one feature if (featureWithPlugin != featureName) { log.log(java.util.logging.Level.SEVERE, "Plugin is listed in more than one feature - " + featureWithPlugin + " AND " + featureName) } } if (this.pluginsToDeploy.contains(plugin) == false) { this.pluginsToDeploy.add(plugin) } } } private void init(final String workspaceDirectory) { this.edexFeaturesToDeploy = new ArrayList() final String metadataProjectsDirectory = workspaceDirectory + File.separator + ".metadata" + File.separator + ".plugins" + File.separator + "org.eclipse.core.resources" + File.separator + ".projects" for (String project : new File(metadataProjectsDirectory).list()) { // determine if the project is an EDEX feature. Matcher matcher = EDEX_FEATURE_PATTERN.matcher(project) if (matcher.matches() || project == COMMON_BASE_FEATURE) { // this is an EDEX feature. if (blacklistedEdexFeatures.contains(project) == false) { this.edexFeaturesToDeploy.add(project) log.log(java.util.logging.Level.INFO, 'Found EDEX Feature: ' + project) } } final String expectedLocationFile = metadataProjectsDirectory + File.separator + project + File.separator + ".location" if (new File(expectedLocationFile).exists()) { this.catalogProject(expectedLocationFile) } } /* * previously this was dynamically loaded via spring. However, spring * was removed from groovy. */ this.customPluginDeployers = new ArrayList() this.customPluginDeployers.add(new DeployWeb()) this.customPluginDeployers.add(new DeployEdexLocalization()) this.customPluginDeployers.add(new DeployEdexResources()) this.customPluginDeployers.add(new CustomDeploymentRunner()) this.customPluginDeployers.add(new DeployModes()) } private void catalogProject(String locationFile) { byte[] contents = new File(locationFile).getBytes() final String FILE_ = "file:" StringBuilder stringBuilder = new StringBuilder() boolean buildLocationString = false for (int i = 0; i < contents.length; i++) { if (contents[i] < 0 || contents[i] > 127) { continue } if (buildLocationString) { if (contents[i] == 0) { // the end of the file path (ideally). break } char c = (char) contents[i] stringBuilder.append(c) } else { // first: we want to find the letter 'f' char c = (char) contents[i] if ( c == 'f') { stringBuilder.append(c) // we have found 'f'; determine if we have found "file:" int counter = 0 while (counter < 4) { ++i c = (char) contents[i] stringBuilder.append(c) ++counter } if (FILE_ == stringBuilder.toString()) { buildLocationString = true } stringBuilder = new StringBuilder() } } } String projectLocationString = stringBuilder.toString() // get the .project file File projectMetadataFile = new File(projectLocationString + File.separator + ".project") // ensure that the project metadata file actually exists if (projectMetadataFile.exists() == false) { return } // read the file def projectMetadataXML = new XmlSlurper().parse(projectMetadataFile) // extract the plugin name (as Eclipse sees it) final String projectName = projectMetadataXML.name ProjectInformation projectInformation = new ProjectInformation() projectInformation.project = projectName projectInformation.projectDirectory = new File(projectLocationString).getName() projectInformation.projectFullLocation = projectLocationString this.projectInformationMap[projectName] = projectInformation } } DeployInstall deployInstall = new DeployInstall(args[0], args[1], Boolean.parseBoolean(args[2]), args[3], args[4], args[5], args[6]) deployInstall.deploy()