opends/src/quicksetup/org/opends/quicksetup/ApplicationException.java
@@ -89,6 +89,11 @@ APPLICATION, /** * Error invoking an OpenDS tool. */ TOOL_ERROR, /** * A bug (for instance when we throw an IllegalStateException). */ BUG opends/src/quicksetup/org/opends/quicksetup/BuildInformation.java
New file @@ -0,0 +1,205 @@ /* * 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 * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.quicksetup; import org.opends.quicksetup.util.Utils; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.io.InputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; /** * Represents information about the current build that is * publicly obtainable by invoking start-ds -F. */ public class BuildInformation implements Comparable { static private final String NAME = "Name"; static private final String BUILD_ID = "Build ID"; static private final String MAJOR_VERSION = "Major Version"; static private final String MINOR_VERSION = "Minor Version"; static private final String POINT_VERSION = "Point Version"; static private final String REVISION_NUMBER = "Revision Number"; /** * Reads build information for a particular installation by reading the * output from invoking the start-ds tool with the full information option. * @param installation from which to gather build information * @return BuildInformation object populated with information * @throws ApplicationException if all or some important information could * not be determined */ static public BuildInformation create(Installation installation) throws ApplicationException { BuildInformation bi = new BuildInformation(); List<String> args = new ArrayList<String>(); args.add(Utils.getPath(installation.getServerStartCommandFile())); args.add("-F"); // full verbose ProcessBuilder pb = new ProcessBuilder(args); InputStream is = null; try { Process process = pb.start(); is = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = reader.readLine(); bi.values.put(NAME, line); while (null != (line = reader.readLine())) { int colonIndex = line.indexOf(':'); if (-1 != colonIndex) { String name = line.substring(0, colonIndex).trim(); String value = line.substring(colonIndex + 1).trim(); bi.values.put(name, value); } } } catch (IOException e) { throw new ApplicationException(ApplicationException.Type.START_ERROR, "Error creating build info", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { // ignore; } } } // Make sure we got values for import properties checkNotNull(bi.values, NAME, MAJOR_VERSION, MINOR_VERSION, POINT_VERSION, REVISION_NUMBER); return bi; } private Map<String, String> values = new HashMap<String, String>(); /** * Gets the name of this build. This is the first line of the output * from invoking start-ds -F. * @return String representing the name of the build */ public String getName() { return values.get(NAME); } /** * Gets the build ID which is the 14 digit number code like 20070420110336. * * @return String representing the build ID */ public String getBuildId() { return values.get(BUILD_ID); } /** * Gets the major version. * * @return String representing the major version */ public Integer getMajorVersion() { return new Integer(values.get(MAJOR_VERSION)); } /** * Gets the minor version. * * @return String representing the minor version */ public Integer getMinorVersion() { return new Integer(values.get(MINOR_VERSION)); } /** * Gets the point version. * * @return String representing the point version */ public Integer getPointVersion() { return new Integer(values.get(POINT_VERSION)); } /** * Gets the SVN revision number. * * @return Integer representing the SVN revision number */ public Integer getRevisionNumber() { return new Integer(values.get(REVISION_NUMBER)); } /** * {@inheritDoc} */ public String toString() { return getName(); } /** * {@inheritDoc} */ public int compareTo(Object o) { BuildInformation bi = (BuildInformation) o; if (getMajorVersion().equals(bi.getMajorVersion())) { if (getMinorVersion().equals(bi.getMinorVersion())) { if (getPointVersion().equals(bi.getPointVersion())) { if (getRevisionNumber().equals(bi.getRevisionNumber())) { return 0; } else if (getRevisionNumber() < bi.getRevisionNumber()) { return -1; } } else if (getPointVersion() < bi.getPointVersion()) { return -1; } } else if (getMinorVersion() < bi.getMinorVersion()) { return -1; } } else if (getMajorVersion() < bi.getMajorVersion()) { return -1; } return 1; } static private void checkNotNull(Map values, String... props) throws ApplicationException { for (String prop : props) { if (null == values.get(prop)) { throw new ApplicationException(ApplicationException.Type.TOOL_ERROR, "'" + prop + "' could not be determined", null); } } } } opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -29,8 +29,6 @@ import java.io.*; import java.util.*; import java.util.regex.Pattern; import java.util.regex.Matcher; import org.opends.quicksetup.util.Utils; @@ -209,7 +207,9 @@ throws IllegalArgumentException { // TODO: i18n String failureReason = null; if (!rootDirectory.exists()) { if (rootDirectory == null) { failureReason = "root directory is null"; } else if (!rootDirectory.exists()) { failureReason = "is not a directory"; } else if (!rootDirectory.isDirectory()) { failureReason = "does not exist"; @@ -230,7 +230,7 @@ } if (failureReason != null) { throw new IllegalArgumentException("Install root '" + Utils.getPath(rootDirectory) + (rootDirectory != null ? Utils.getPath(rootDirectory) : "null") + "' is not an OpenDS installation root: " + " " + failureReason); } @@ -244,7 +244,7 @@ private Configuration baseConfiguration; private String buildId; private BuildInformation buildInformation; /** * Creates a new instance from a root directory specified as a string. @@ -278,14 +278,10 @@ * Sets the root directory of this installation. * * @param rootDirectory File of this installation * @throws NullPointerException if root directory is null */ public void setRootDirectory(File rootDirectory) throws NullPointerException { if (rootDirectory == null) { throw new NullPointerException("Install root cannot be null"); } public void setRootDirectory(File rootDirectory) { // Hold off on doing more validation of rootDirectory since // Hold off on doing validation of rootDirectory since // some applications (like the Installer) create an Installation // before the actual bits have been laid down on the filesyste. @@ -456,46 +452,6 @@ } /** * Gets the build ID which is the 14 digit number code like 20070420110336. * @return String representing the build ID * @throws ApplicationException if something goes wrong */ public String getBuildId() throws ApplicationException { if (buildId == null) { List<String> args = new ArrayList<String>(); args.add(Utils.getPath(getServerStartCommandFile())); args.add("-V"); // verbose ProcessBuilder pb = new ProcessBuilder(args); InputStream is = null; try { Process process = pb.start(); is = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; Pattern p = Pattern.compile("(Build )(\\d{14})"); while (null != (line = reader.readLine())) { Matcher m = p.matcher(line); if (m.matches()) { buildId = line.substring(m.start(2), m.end(2)); } } } catch (IOException e) { throw new ApplicationException(ApplicationException.Type.START_ERROR, "Error attempting to determine build ID", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { // ignore; } } } } return buildId; } /** * Returns the path to the configuration file of the directory server. Note * that this method assumes that this code is being run locally. * @@ -542,15 +498,6 @@ } /** * Returns the path to the LDIF files under the install path. * * @return the path to the LDIF files under the install path. */ public File geLdifDirectory() { return new File(getRootDirectory(), LDIFS_PATH_RELATIVE); } /** * Returns the path to the config files under the install path. * * @return the path to the config files under the install path. @@ -725,4 +672,18 @@ } return statusPanelCommandFile; } } /** * Gets information about the build that was used to produce the bits * for this installation. * @return BuildInformation object describing this installation * @throws ApplicationException if there is a problem obtaining the * build information */ public BuildInformation getBuildInformation() throws ApplicationException { if (buildInformation == null) { buildInformation = BuildInformation.create(this); } return buildInformation; } } opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -779,6 +779,7 @@ summary-upgrade-extracting=Extracting Build... summary-upgrade-backing-up-db=Backing Up Data... summary-upgrade-backing-up-files=Backing Up Files... summary-upgrade-check-server-health=Checking Server Health... summary-upgrade-calculating-schema-customization=Calculating Schema \ Customizations... summary-upgrade-calculating-config-customization=Calculating Configuration \ @@ -798,7 +799,7 @@ summary-upgrade-finished-successfully-cli=OpenDS QuickSetup Completed \ Successfully. The OpenDS installation at {0} has now been upgraded \ to version {1}. summary-upgrade-finished-with-errors=Upgrade Finished with Errors summary-upgrade-finished-with-errors=Upgrade Operation Aborted # # Progress messages @@ -903,7 +904,7 @@ upgrade-hypothetical-reversion-failure=Reversion from version {0} to version \ {1} is not supported. To revert versions you must uninstall the current \ server, install the new server, and manually migrate your data. upgrade-hypothetical-versions-the-same=This operation is unnecessary. Both \ upgrade-hypothetical-versions-the-same=Both \ new current and proposed version numbers are the same: {0} upgrade-mod-no-schema=Processed server modifications \ (schema checking disabled): {0} opends/src/quicksetup/org/opends/quicksetup/upgrader/RemoteBuildManager.java
@@ -68,10 +68,13 @@ * Creates an instance. * @param app using this tool * @param url base context for an OpenDS build list * @param proxy Proxy to use for connections; can be null if not proxy is * to be used */ public RemoteBuildManager(Application app, URL url) { public RemoteBuildManager(Application app, URL url, Proxy proxy) { this.app = app; this.buildListUrl = url; this.proxy = proxy; } /** opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
@@ -28,6 +28,7 @@ package org.opends.quicksetup.upgrader; import org.opends.quicksetup.i18n.ResourceProvider; import org.opends.quicksetup.BuildInformation; /** * This class can answer questions important upgrade/reversion questions @@ -35,18 +36,18 @@ */ public class UpgradeOracle { private Integer currentVersion; private Integer newVersion; private BuildInformation currentBuildInfo; private BuildInformation newBuildInfo; /** * Creates a new instance that can analyze a hypothetical upgrade/reversion * operation from one version to another. * @param currentVersion Integer representing the current version * @param newVersion Integer representing the proposed next version * @param current BuildInformation representing the current version * @param neu BuildInformation representing the proposed next version */ public UpgradeOracle(Integer currentVersion, Integer newVersion) { this.currentVersion = currentVersion; this.newVersion = newVersion; public UpgradeOracle(BuildInformation current, BuildInformation neu) { this.currentBuildInfo = current; this.newBuildInfo = neu; } /** @@ -56,7 +57,7 @@ * false indicates that this would be a reversion. */ public boolean isUpgrade() { return newVersion > currentVersion; return currentBuildInfo.compareTo(newBuildInfo) < 0; } /** @@ -66,7 +67,7 @@ * false indicates that this would be an upgrade. */ public boolean isReversion() { return newVersion < currentVersion; return currentBuildInfo.compareTo(newBuildInfo) < 0; } /** @@ -76,14 +77,7 @@ * an operation will succeed */ public boolean isSupported() { boolean supported; if (// newVersion.equals(currentVersion) || // support this for reinstall? newVersion < 1565) { supported = false; }else { supported = true; } return supported; return isUpgrade(); } /** @@ -95,8 +89,8 @@ */ public String getSummaryMessage() { String msg; String[] args = { currentVersion.toString(), newVersion.toString() }; String[] args = { currentBuildInfo.toString(), currentBuildInfo.toString() }; ResourceProvider rp = ResourceProvider.getInstance(); if (isSupported()) { if (isUpgrade()) { @@ -109,8 +103,10 @@ } else { if (isUpgrade()) { msg = rp.getMsg("upgrade-hypothetical-upgrade-failure", args); } else { } else if (isReversion()) { msg = rp.getMsg("upgrade-hypothetical-reversion-failure", args); } else { msg = rp.getMsg("upgrade-hypothetical-versions-the-same", args); } } return msg; opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -35,6 +35,7 @@ import org.opends.quicksetup.util.FileManager; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.ZipExtractor; import org.opends.quicksetup.util.OperationOutput; import org.opends.quicksetup.ui.*; import java.awt.event.WindowEvent; @@ -44,6 +45,9 @@ import java.io.*; import java.net.URL; import java.net.MalformedURLException; import java.net.Proxy; import java.net.SocketAddress; import java.net.InetSocketAddress; import static org.opends.quicksetup.Installation.*; @@ -93,6 +97,8 @@ INITIALIZING("summary-upgrade-initializing"), CHECK_SERVER_HEALTH("summary-upgrade-check-server-health"), CALCULATING_SCHEMA_CUSTOMIZATIONS( "summary-upgrade-calculating-schema-customization"), @@ -246,9 +252,24 @@ listUrlString = "http://www.opends.org/upgrade-builds"; } URL buildRepo = new URL(listUrlString); remoteBuildManager = new RemoteBuildManager(this, buildRepo); // See if system properties dictate use of a proxy Proxy proxy = null; String proxyHost = System.getProperty("http.proxyHost"); String proxyPort = System.getProperty("http.proxyPort"); if (proxyHost != null && proxyPort != null) { try { SocketAddress addr = new InetSocketAddress(proxyHost, new Integer(proxyPort)); proxy = new Proxy(Proxy.Type.HTTP, addr); } catch (NumberFormatException nfe) { LOG.log(Level.INFO, "Illegal proxy port number " + proxyPort); } } remoteBuildManager = new RemoteBuildManager(this, buildRepo, proxy); } catch (MalformedURLException e) { LOG.log(Level.INFO, "error", e); LOG.log(Level.INFO, "", e); } } return remoteBuildManager; @@ -438,7 +459,7 @@ new Thread(new Runnable() { public void run() { try { installation.getBuildId(); installation.getBuildInformation().getBuildId(); } catch (ApplicationException e) { LOG.log(Level.INFO, "error", e); } @@ -609,27 +630,12 @@ throw e; } // If the server has never been started and schema changes // have been made, the server will have never had the chance // to write schema.current. if (!getInstallation().getStatus().isServerRunning()) { try { startServerWithoutConnectionHandlers(); getServerController().stopServerInProcess(); } catch (ApplicationException e) { LOG.log(Level.INFO, "Error starting server to insure configuration" + " changes have been written to the filesystem", e); throw e; } } if (getInstallation().getStatus().isServerRunning()) { try { new ServerController(this).stopServer(); } catch (ApplicationException e) { LOG.log(Level.INFO, "Error stopping server", e); throw e; } try { setCurrentProgressStep(UpgradeProgressStep.CHECK_SERVER_HEALTH); checkServerHealth(); } catch (ApplicationException e) { LOG.log(Level.INFO, "Server failed initial health check", e); throw e; } try { @@ -819,12 +825,41 @@ } /** * Abort this upgrade and repair the installation. * * @param lastStep ProgressStep indicating how much work we will have to * do to get the installation back like we left it * @throws ApplicationException of something goes wrong * Stops and starts the server checking for serious errors. Also * has the side effect of having the server write schema.current * if it has never done so. */ private void checkServerHealth() throws ApplicationException { Installation installation = getInstallation(); ServerController control = new ServerController(this, installation); try { if (installation.getStatus().isServerRunning()) { control.stopServer(); } OperationOutput op = control.startServer(); List<String> errors = op.getErrors(); if (errors != null) { throw new ApplicationException( ApplicationException.Type.APPLICATION, "The server currently starts with errors with must" + "be resolved before an upgrade can occur: " + Utils.listToString(errors, " "), null); } control.stopServer(); } catch (Exception e) { throw new ApplicationException(ApplicationException.Type.APPLICATION, "Server health check failed", e); } } /** * Abort this upgrade and repair the installation. * * @param lastStep ProgressStep indicating how much work we will have to * do to get the installation back like we left it * @throws ApplicationException of something goes wrong */ private void abort(ProgressStep lastStep) throws ApplicationException { UpgradeProgressStep lastUpgradeStep = (UpgradeProgressStep) lastStep; EnumSet<UpgradeProgressStep> stepsStarted = @@ -866,11 +901,13 @@ } private void verifyUpgrade() throws ApplicationException { try { new ServerController(this).startServer(); } catch (ApplicationException e) { LOG.log(Level.INFO, "Error starting server: " + e.getLocalizedMessage(), e); ServerController sc = new ServerController(this); OperationOutput op = sc.startServer(); if (op.getErrors() != null) { throw new ApplicationException(ApplicationException.Type.APPLICATION, "Upgraded server failed verification test by signaling " + "errors during startup: " + Utils.listToString(op.getErrors(), " "), null); } } @@ -1253,24 +1290,24 @@ * day' types of changes to the codebase. */ private void insureUpgradability() throws ApplicationException { Integer currentVersion; Integer newVersion; BuildInformation currentVersion; BuildInformation newVersion; try { currentVersion = getInstallation().getSvnRev(); currentVersion = getInstallation().getBuildInformation(); } catch (ApplicationException e) { LOG.log(Level.INFO, "error", e); throw ApplicationException.createFileSystemException( "Could not determine current version number: " + "Could not determine current build information: " + e.getLocalizedMessage(), e); } try { newVersion = getStagedInstallation().getSvnRev(); newVersion = getStagedInstallation().getBuildInformation(); } catch (Exception e) { LOG.log(Level.INFO, "error", e); throw ApplicationException.createFileSystemException( "Could not determine upgrade version number: " + "Could not determine upgrade build information: " + e.getLocalizedMessage(), e); } @@ -1346,7 +1383,7 @@ String installPath = Utils.getPath(getInstallation().getRootDirectory()); String newVersion = null; try { newVersion = getInstallation().getBuildId(); newVersion = getInstallation().getBuildInformation().getBuildId(); } catch (ApplicationException e) { newVersion = getMsg("upgrade-build-id-unknown"); } opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java
@@ -185,7 +185,8 @@ private String getOldBuildString() { String oldVersion; try { oldVersion = getApplication().getInstallation().getBuildId(); oldVersion = getApplication().getInstallation(). getBuildInformation().getBuildId(); } catch (ApplicationException e) { LOG.log(Level.INFO, "error", e); oldVersion = getMsg("upgrade-build-id-unknown"); opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/WelcomePanel.java
@@ -192,7 +192,7 @@ String buildId = null; Installation installation = getApplication().getInstallation(); try { buildId = installation.getBuildId(); buildId = installation.getBuildInformation().getBuildId(); } catch (Exception e) { buildId = getMsg("upgrade-build-id-unknown"); } opends/src/quicksetup/org/opends/quicksetup/util/OperationOutput.java
New file @@ -0,0 +1,76 @@ /* * 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 * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.quicksetup.util; import java.util.List; /** * Contains information about an operation invoked by this class. */ public class OperationOutput { private Exception exception = null; private List<String> errors = null; /** * Gets a list of string representing error messages obtained * by invoking the operation. Null if there were no errors. * @return List of Strings representing errors */ public List<String> getErrors() { return errors; } /** * Gets an exception that occurred by invoking the operation. Null * if there were no exceptions. * @return Exception error */ public Exception getException() { return exception; } /** * Sets the exception that occurred during execution. Can be null to * indicate no exception was encountered. * @param exception Exception that occurred during invocation of the operation */ void setException(Exception exception) { this.exception = exception; } /** * Sets the list of error messages that occurred during execution. * Can be null to indicate no errors were encountered. * @param errors List of Strings representing error messages */ void setErrors(List<String> errors) { this.errors = errors; } } opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -33,6 +33,7 @@ import javax.naming.NamingException; import java.util.ArrayList; import java.util.Map; import java.util.List; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; @@ -224,19 +225,26 @@ /** * This methods starts the server. * @return OperationOutput object containing output from the start server * command invocation. * @throws org.opends.quicksetup.ApplicationException if something goes wrong. */ public void startServer() throws ApplicationException { startServer(true); public OperationOutput startServer() throws ApplicationException { return startServer(true); } /** * This methods starts the server. * @param verify boolean indicating whether this method will attempt to * connect to the server after starting to verify that it is listening. * @return OperationOutput object containing output from the start server * command invocation. * @throws org.opends.quicksetup.ApplicationException if something goes wrong. */ private void startServer(boolean verify) throws ApplicationException { private OperationOutput startServer(boolean verify) throws ApplicationException { OperationOutput output = new OperationOutput(); application.notifyListeners( application.getFormattedProgress( application.getMsg("progress-starting")) + @@ -275,7 +283,7 @@ StartReader errReader = new StartReader(err, startedId, true); StartReader outputReader = new StartReader(out, startedId, false); while (!errReader.isFinished() && !outputReader.isFinished()) while (!errReader.isFinished() || !outputReader.isFinished()) { try { @@ -284,6 +292,17 @@ { } } // Collect any errors found in the output List<String> errors = errReader.getErrors(); if (outputReader.getErrors() != null) { if (errors == null) { errors = new ArrayList<String>(); } errors.addAll(outputReader.getErrors()); } output.setErrors(errors); // Check if something wrong occurred reading the starting of the server ApplicationException ex = errReader.getException(); if (ex == null) @@ -292,6 +311,11 @@ } if (ex != null) { // This is meaningless right now since we throw // the exception below, but in case we change out // minds later or add the ability to return exceptions // in the output only instead of throwing... output.setException(ex); throw ex; } else if (verify) @@ -369,6 +393,7 @@ throw new ApplicationException(ApplicationException.Type.START_ERROR, application.getThrowableMsg("error-starting-server", ioe), ioe); } return output; } /** @@ -481,6 +506,8 @@ { private ApplicationException ex; private List<String> errors; private boolean isFinished; private boolean isFirstLine; @@ -530,6 +557,16 @@ { isFinished = true; } // Collect lines that would seem to indicate all is // not well with the server if (line.indexOf("severity=SEVERE_ERROR") != -1) { if (errors == null) { errors = new ArrayList<String>(); } errors.add(line); } line = reader.readLine(); } } catch (IOException ioe) @@ -563,6 +600,10 @@ return ex; } public List<String> getErrors() { return errors; } /** * Returns <CODE>true</CODE> if the server starting process finished * (successfully or not) and <CODE>false</CODE> otherwise.