/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2007-2008 Sun Microsystems, Inc. * Portions Copyright 2012 Delta-Victor Consultants * Portions Copyright 2013 ForgeRock AS */ package org.opends.build.tools; import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; import static org.opends.build.tools.Utilities.*; import java.io.File; import java.io.FileFilter; import java.io.PrintWriter; /** * Generates an RPM spec file. */ public class GenerateRpm extends Task { private File topDir; private String topDirAbsolutePath; private String sourceDirName; private File destFile; private String prefix; private String productName; private String referenceURL; private String shortName; private String version; private String release; private boolean overwrite; private StringBuilder sb; private final String filePrefix = "%{_prefix}"; private final String dirPrefix = "%dir %{_prefix}"; /** * Sets the top directory for the rpm build. * * @param topDir * File representing top directory for rpm build directory */ public void setTopDir(File topDir) { this.topDir = topDir; topDirAbsolutePath = topDir.getAbsolutePath(); } /** * Sets the prefix for the RPM. * * @param prefix * Used for package relocation */ public void setPrefix(String prefix) { this.prefix = prefix; } /** * Sets the short description for the RPM. * * @param productName * The RPM short description */ public void setproductName(String productName) { this.productName = productName; } /** * Sets the application name for the RPM. * * @param shortName * The RPM application name */ public void setshortName(String shortName) { this.shortName = shortName; } /** * Sets the reference URL for the RPM. * * @param referenceURL * The RPM reference URL */ public void setreferenceURL(String referenceURL) { this.referenceURL = referenceURL; } /** * Sets the name of the source directory. * * @param sourceDirName * name of the source directory. */ public void setSourceDirName(String sourceDirName) { this.sourceDirName = sourceDirName; } /** * Sets the RPM spec file that will be generated. * * @param dest * The spec file */ public void setSpecFileName(File dest) { this.destFile = dest; } /** * Sets the version number. * * @param version * The version number */ public void setVersion(String version) { this.version = version; } /** * Sets the release number. * * @param release * The release number */ public void setRelease(String release) { this.release = release; } /** * Indicates when true that an existing destination file will be overwritten. * * @param o * boolean where true means overwrite */ public void setOverwrite(boolean o) { this.overwrite = o; } /** * {@inheritDoc} */ @Override public void execute() throws BuildException { try { if (!topDir.exists()) { throw new BuildException("directory " + topDir.getName() + " does not exist"); } if (!topDir.isDirectory()) { throw new BuildException(topDir.getName() + " is not a directory"); } if (destFile.exists()) { if (this.overwrite) { destFile.delete(); log("Regenerating " + destFile.getName() + " from " + topDir.getName()); } else { log(destFile.getName() + " has not been regenerated"); } } sb = new StringBuilder(); final File rootDir = new File(sourceDirName); final String opendsDir = rootDir.getName(); final File[] listFiles = rootDir.listFiles(new PkgFileFilter()); // Generate the package information sb.append("%define _topdir " + topDirAbsolutePath + EOL); sb.append("%define _arch noarch" + EOL); sb.append("%define _prefix " + prefix + EOL); sb.append("%define _pre " + opendsDir + EOL); sb.append("%define __os_install_post %{nil}" + EOL); sb.append(EOL); sb.append("# =========================" + EOL); sb.append("# Header" + EOL); sb.append("# =========================" + EOL); sb.append("# Short Description" + EOL); sb.append("Summary: " + productName + EOL); sb.append("# Application Name" + EOL); sb.append("Name: " + shortName + EOL); sb.append("# Application Version" + EOL); sb.append("Version: " + version + EOL); sb.append("# Packaging Revision" + EOL); // If VERSION_QUALIFIER is empty, need to remove '.' char. if (release.endsWith(".")) { release = release.substring(0, release.length() - 1); } sb.append("Release: " + release + EOL); sb.append("# Software Licenced Under" + EOL); sb.append("License: CDDL" + EOL); sb.append("# RPM Group" + EOL); sb.append("Group: Applications/Network" + EOL); sb.append("# Link to Application web site" + EOL); sb.append("URL: " + referenceURL + EOL); sb.append("# Distributing Organisation" + EOL); sb.append("Vendor: ForgeRock AS" + EOL); sb.append("# Build Architecture" + EOL); sb.append("BuildArch: noarch" + EOL); sb.append(EOL); sb.append("Requires: jre >= 1.6" + EOL); sb.append(EOL); sb.append("# Long Description" + EOL); sb.append("%Description" + EOL); sb.append("OpenDJ LDAP Server" + EOL); sb.append("OpenDJ is an LDAPv3 compliant directory service, developed for the Java" + EOL); sb.append("platform, providing a high performance, highly available and secure store" + EOL); sb.append("for the identities managed by enterprises. Its easy installation process," + EOL); sb.append("combined with the power of the Java platform makes OpenDJ one of the" + EOL); sb.append("simplest and fastest directory servers to deploy and manage." + EOL); sb.append(EOL); sb.append("# =========================" + EOL); sb.append("# Pre & Post Install" + EOL); sb.append("# =========================" + EOL); sb.append("# If the first argument to %pre is 1, the RPM operation is an initial" + EOL); sb.append("# installation. If the argument to %pre is 2, the operation is an upgrade" + EOL); sb.append("# from an existing version to a new one." + EOL); sb.append("# Similarly, the arguments to a %post are 1 and 2 for a new installation" + EOL); sb.append("# and upgrade, respectively. (%pre and %post aren't executed during" + EOL); sb.append("# an uninstallation.)" + EOL); sb.append(EOL); sb.append("# Pre Install" + EOL); sb.append("%pre" + EOL); sb.append("if [ \"$1\" == \"1\" ]; then" + EOL); sb.append(" echo \"Pre Install - initial install\"" + EOL); sb.append("else if [ \"$1\" == \"2\" ] ; then" + EOL); sb.append("# Only if the instance has been configured" + EOL); sb.append(" if [ -f %{_prefix}/config/buildinfo ] && [ \"$(ls -A %{_prefix}/config/archived-configs)\" ]" + EOL); sb.append(" then" + EOL); sb.append(" echo \"Pre Install - upgrade install\"" + EOL); sb.append("# If the server is running before upgrade, creates a file flag" + EOL); sb.append(" if [ -f %{_prefix}/logs/server.pid ] " + EOL); sb.append(" then" + EOL); sb.append(" touch %{_prefix}/logs/status" + EOL); sb.append(" fi" + EOL); sb.append(" stopds=$(%{_prefix}/bin/stop-ds)" + EOL); sb.append(" echo $stopds" + EOL); sb.append(" fi" + EOL); sb.append(" fi" + EOL); sb.append("fi" + EOL); sb.append(EOL); sb.append("# Post Install" + EOL); sb.append("%post" + EOL); sb.append("if [ \"$1\" == \"1\" ] ; then" + EOL); sb.append(" echo \"Post Install - initial install\"" + EOL); sb.append(" [[ `java -version 2>&1 | /bin/sed 's/java version \"\\(.*\\)\\.\\(.*\\)\\.\\(.*\\)\\_\\(.*\\)\\.*\"/\\1\\2\\3\\4/; 1q'` < 16022 ]] && echo \"WARNING - For best server performance, use at least Java 1.6.0_22, which includes a major security fix for TLS.\"" + EOL); sb.append(" echo \"\"" + EOL); sb.append("else if [ \"$1\" == \"2\" ] ; then" + EOL); sb.append(" echo \"Post Install - upgrade install\"" + EOL); sb.append("# Only if the instance has been configured" + EOL); sb.append(" if [ -f %{_prefix}/config/buildinfo ] && [ \"$(ls -A %{_prefix}/config/archived-configs)\" ]" + EOL); sb.append(" then" + EOL); // Starts the upgrade. The new files are automatically imported // by rpm manager, which compares files between last & actual version. // Copies / deletes files depending of new package. sb.append(" %{_prefix}/./upgrade -n --acceptLicense" + EOL); sb.append("# Upgrade ok " + EOL); sb.append(" if [ \"$?\" == \"0\" ] ; then " + EOL); sb.append("# Checks the server status flag for restart. " + EOL); sb.append(" if [ -f %{_prefix}/logs/status ] " + EOL); sb.append(" then" + EOL); sb.append(" echo \"\"" + EOL); sb.append(" echo \"Restarting server...\" " + EOL); sb.append(" %{_prefix}/./bin/start-ds " + EOL); sb.append(" echo \"\"" + EOL); sb.append(" rm -f %{_prefix}/logs/status " + EOL); sb.append(" fi" + EOL); sb.append(" fi" + EOL); sb.append("# Upgrade fails, needs user interaction (eg. manual mode)" + EOL); sb.append(" if [ \"$?\" == \"2\" ] ; then " + EOL); sb.append(" exit \"0\" " + EOL); sb.append(" fi " + EOL); sb.append(" else" + EOL); sb.append(" echo \"Instance is not configured. Upgrade aborded.\"" + EOL); sb.append(" exit -1" + EOL); sb.append(" fi" + EOL); sb.append(" fi " + EOL); sb.append("fi" + EOL); sb.append(EOL); sb.append("# =========================" + EOL); sb.append("# Pre & Post Uninstall" + EOL); sb.append("# =========================" + EOL); sb.append("# If the first argument to %preun and %postun is 0, the action is" + EOL); sb.append("# uninstallation." + EOL); sb.append("# If the first argument to %preun and %postun is 1, the action is an upgrade." + EOL); sb.append("# Pre Uninstall" + EOL); sb.append("%preun" + EOL); sb.append("if [ \"$1\" == \"0\" ] ; then" + EOL); sb.append(" echo \"Pre Uninstall - uninstall\"" + EOL); sb.append("# Only if the instance has been configured" + EOL); sb.append(" if [ -f %{_prefix}/config/buildinfo ] && [ \"$(ls -A %{_prefix}/config/archived-configs)\" ]" + EOL); sb.append(" then" + EOL); sb.append(" %{_prefix}/bin/stop-ds" + EOL); sb.append(" fi" + EOL); sb.append("else if [ \"$1\" == \"1\" ] ; then" + EOL); sb.append(" echo \"Pre Uninstall - upgrade uninstall\"" + EOL); sb.append(" fi" + EOL); sb.append("fi" + EOL); sb.append("# Post Uninstall" + EOL); sb.append("%postun" + EOL); sb.append("if [ \"$1\" == \"0\" ] ; then" + EOL); sb.append(" echo \"Post Uninstall - uninstall\"" + EOL); sb.append(" echo \"OpenDJ successfully removed.\"" + EOL); sb.append("else if [ \"$1\" == \"1\" ] ; then" + EOL); sb.append(" echo \"Post Uninstall - upgrade uninstall\"" + EOL); sb.append(" fi" + EOL); sb.append("fi" + EOL); sb.append(EOL); sb.append("# =========================" + EOL); sb.append("# Prepare, Build, Install" + EOL); sb.append("# =========================" + EOL); sb.append("# %prep" + EOL); sb.append(EOL); sb.append("# %build" + EOL); sb.append(EOL); sb.append("%install" + EOL); sb.append("mkdir -p $RPM_BUILD_ROOT%{_prefix}" + EOL); sb.append("cd $RPM_BUILD_ROOT%{_prefix}" + EOL); for (final File f : listFiles) { sb.append("cp -r " + f.getPath() + " ." + EOL); } sb.append(EOL); sb.append("# =========================" + EOL); sb.append("# Files Layout" + EOL); sb.append("# =========================" + EOL); sb.append("%files" + EOL); sb.append(dirPrefix + EOL); // In order to handle upgrades, we need to start // with the contents of the rootDir rather than // the actual directory, because the // rootDir has the OpenDJ version number included // into it for (final File build : listFiles) { generatedLevel("", build); } // flush the spec file. PrintWriter destWriter = new PrintWriter(destFile); destWriter.print(sb.toString()); destWriter.close(); } catch (Exception e) { // Don't leave a malformed file laying around. Delete // it so it will be forced to be regenerated. if (destFile.exists()) { destFile.deleteOnExit(); } e.printStackTrace(); throw new BuildException("Error processing " + topDir + ": " + e.getMessage()); } } private void generatedLevel(String parent, File source) { if (source.isDirectory()) { sb.append(dirPrefix + parent + "/" + source.getName()); sb.append(EOL); for (File child : source.listFiles()) { generatedLevel(parent + "/" + source.getName(), child); } } else { sb.append(filePrefix + parent + "/" + source.getName()); sb.append(EOL); } } /** * A file filter for the rpm. Excludes all '.bat', '.exe' and '.app' files. */ static final class PkgFileFilter implements FileFilter { /** {@inheritDoc} */ public boolean accept(File file) { final String fileName = file.getName().toLowerCase(); if (file.isDirectory() && (fileName.equals("bat") || fileName.endsWith(".app") || fileName .endsWith(".bat"))) { return false; } else if (file.isFile()) { if (fileName.endsWith(".app") || fileName.endsWith(".bat") || fileName.endsWith(".exe")) { return false; } } return true; } } }