opends/src/quicksetup/org/opends/quicksetup/BuildInformation.java
@@ -35,6 +35,10 @@ import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.logging.Logger; import java.util.logging.Level; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.io.InputStream; @@ -48,6 +52,9 @@ */ public class BuildInformation implements Comparable { static private final Logger LOG = Logger.getLogger(BuildInformation.class.getName()); // These string values must be synchronized with Directory // Server's main method. These string values are considered // stable by the server team and not candidates for @@ -59,6 +66,7 @@ static private final String POINT_VERSION = "Point Version"; static private final String REVISION_NUMBER = "Revision Number"; static private final String VERSION_QUALIFIER = "Version Qualifier"; static private final String INCOMPATIBILITY_EVENTS = "Upgrade Event IDs"; static private final String FIX_IDS = "Fix IDs"; static private final String DEBUG_BUILD = "Debug Build"; static private final String BUILD_OS = "Build OS"; @@ -68,7 +76,6 @@ static private final String BUILD_JVM_VERSION = "Build JVM Version"; static private final String BUILD_JVM_VENDOR = "Build JVM Vendor"; /** * Reads build information for a particular installation by reading the * output from invoking the start-ds tool with the full information option. @@ -264,6 +271,28 @@ } /** * Gets the set of IDs representing <code>IncompatibleVersionEvents</code>. * @return set of integers representing events * @see org.opends.server.util.VersionCompatibilityIssue */ public Set<Integer> getIncompatibilityEventIds() { HashSet<Integer> ids = null; String idString = values.get(INCOMPATIBILITY_EVENTS); if (idString != null) { ids = new HashSet<Integer>(); String[] sa = idString.split(","); for (String s : sa) { try { ids.add(Integer.parseInt(s)); } catch (NumberFormatException nfe) { LOG.log(Level.INFO, "invalid upgrade incompatability ID " + s); } } } return ids; } /** * Returns a build string representation of this object. A build * number is a string formatted MAJOR.MINOR.POINT.REVISION where * MAJOR, MINOR, POINT and REVISION are integers. @@ -331,9 +360,9 @@ * {@inheritDoc} */ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return compareTo(o) == 0; return this == o || !(o == null || getClass() != o.getClass()) && compareTo(o) == 0; } /** opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java
@@ -94,10 +94,9 @@ viewDetailsOption != null ? viewDetailsOption : "View Details")); } println(summary); println(); println(Utils.stripHtml(summary)); println(); println(Utils.stripHtml(details)); println(details); String returnValue = null; while (returnValue == null) { @@ -106,8 +105,8 @@ println(o); } System.out.print(getMsg("cli-uninstall-confirm-prompt", new String[] {"Enter a number or press Enter to accept the default", Integer.toString(defInt)})); "Enter a number or press Enter to accept the default", Integer.toString(defInt))); System.out.flush(); @@ -133,7 +132,20 @@ return returnValue; } /** * {@inheritDoc} */ public String createUnorderedList(List list) { StringBuilder sb = new StringBuilder(); if (list != null) { for (Object o : list) { sb.append(/*bullet=*/"\u2022 "); sb.append(o.toString()); sb.append(Constants.LINE_SEPARATOR); } } return sb.toString(); } private String createOption(int index, String option) { return new StringBuilder(). @@ -147,7 +159,10 @@ } private void println(String text) { out.println(StaticUtils.wrapText(text, Utils.getCommandLineMaxLineWidth())); text = Utils.convertHtmlBreakToLineSeparator(text); text = Utils.stripHtml(text); text = StaticUtils.wrapText(text, Utils.getCommandLineMaxLineWidth()); out.println(text); } } opends/src/quicksetup/org/opends/quicksetup/Constants.java
@@ -51,7 +51,31 @@ /** HTML italics close tag. */ public static final String HTML_ITALICS_CLOSE = "</i>"; /** HTML unordered list open tag. */ public static final Object HTML_UNORDERED_LIST_OPEN = "<ul>"; /** HTML unordered list close tag. */ public static final Object HTML_UNORDERED_LIST_CLOSE = "</ul>"; /** HTML unordered list open tag. */ public static final Object HTML_ORDERED_LIST_OPEN = "<ol>"; /** HTML unordered list close tag. */ public static final Object HTML_ORDERED_LIST_CLOSE = "</ol>"; /** HTML list item open tag. */ public static final String HTML_LIST_ITEM_OPEN = "<li>"; /** HTML list item close tag. */ public static final String HTML_LIST_ITEM_CLOSE = "</li>"; /** Default dynamic name of directory manager. */ public static final String DIRECTORY_MANAGER_DN = "cn=Directory Manager"; /** These HTML tags cause a line break in formatted text. */ public static final String[] BREAKING_TAGS = { HTML_LINE_BREAK, HTML_LIST_ITEM_CLOSE }; } opends/src/quicksetup/org/opends/quicksetup/UserInteraction.java
@@ -27,6 +27,8 @@ package org.opends.quicksetup; import java.util.List; /** * This class describes methods for supporting interaction with the user. */ @@ -94,4 +96,12 @@ String title, MessageType type, String[] options, String def, String viewDetailsOption); /** * Creates a list appropriate for the presentation implementation. * * @param list to format * @return String representing the list */ String createUnorderedList(List list); } opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -1142,18 +1142,39 @@ some database files.<br>If you continue with the setup the contents of these \ database files will be deleted. upgrade-hypothetical-upgrade-success=Upgrade from version {0} to version {1} \ upgrade-oracle-success=Upgrade from version {0} to version {1} \ is supported. upgrade-hypothetical-reversion-success=Reversion from version {0} to version \ {1} is supported. upgrade-hypothetical-upgrade-failure=Upgrade from version {0} to version {1} \ upgrade-oracle-action=Upgrade requires manual action upgrade-oracle-warning=Upgrade warning upgrade-oracle-info=Upgrade information upgrade-oracle-unsupported=Upgrade not supported\ from version {0} to version {1} \ is not supported. To upgrade You must uninstall the current server, install \ the new server, and manually migrate your data. 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=Both the 'upgrade to' and 'upgrade from' \ numbers are the same: {0} reversion-oracle-success=Reversion from version {0} to version \ {1} is supported. reversion-oracle-ei-action=Reversion from version {0} to version {1} \ requires further action. reversion-oracle-failure=reversion from version {0} to version {1} \ is not supported. To reversion You must uninstall the current server, install \ the new server, and manually migrate your data. oracle-desc-action=This operation requires that you perform specific tasks described \ in the details section before continuing. oracle-ei-action-step1=Before starting the operation you should export the entire \ data set for this server to LDIF format. <b>If you have not completed this \ step you should cancel this operation now</b>. oracle-ei-action-step2=Continue with this operation until this tool has finished. oracle-ei-action-step3=When this operation is complete, manually delete the files in the 'db' \ directory. oracle-ei-action-step4=Reimport that data from the LDIF file that you had created in the first step. oracle-action-prompt=Have you performed the tasks described? oracle-info-prompt=Would you like to continue with this operation? oracle-action-prompt-continue=Yes, Continue oracle-action-prompt-cancel=No, Cancel oracle-no-silent=This operation includes specific instructions and/or questions \ that you must follow. Silent mode is not supported for this version. upgrade-mod-no-schema=Processed server modifications \ (schema checking disabled): {0} upgrade-mod=Processed server modifications: {0} @@ -1285,6 +1306,10 @@ installandupgrader-rbupgrade-tooltip=Select to upgrade an existing server \ instance. general-action-required=Action Required general-warning=Warning general-info=Information general-unsupported=Unsupported general-checking-data=Checking Data... general-loading=Loading... general-see-for-details=See {0} for a detailed log of this operation. opends/src/quicksetup/org/opends/quicksetup/ui/GuiUserInteraction.java
@@ -38,6 +38,7 @@ import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.util.List; /** * This class supports user interactions for a graphical application. @@ -108,6 +109,7 @@ sb.append(Utils.breakHtmlString(summary, MAX_CHARS_PER_LINE)); sb.append(Constants.HTML_BOLD_CLOSE); sb.append(Constants.HTML_LINE_BREAK); sb.append(Constants.HTML_LINE_BREAK); sb.append(Utils.breakHtmlString(details, MAX_CHARS_PER_LINE)); JEditorPane ep = UIFactory.makeHtmlPane( sb.toString(), @@ -124,6 +126,23 @@ } /** * {@inheritDoc} */ public String createUnorderedList(List list) { StringBuilder sb = new StringBuilder(); if (list != null) { sb.append(Constants.HTML_UNORDERED_LIST_OPEN); for (Object o : list) { sb.append(Constants.HTML_LIST_ITEM_OPEN); sb.append(o.toString()); sb.append(Constants.HTML_LIST_ITEM_CLOSE); } sb.append(Constants.HTML_UNORDERED_LIST_CLOSE); } return sb.toString(); } /** * JOptionPane that controls the number of characters that are allowed * to appear on a single line in the input area of the dialog. */ opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
@@ -27,91 +27,194 @@ package org.opends.quicksetup.upgrader; import org.opends.quicksetup.i18n.ResourceProvider; import org.opends.quicksetup.BuildInformation; import org.opends.quicksetup.UserInteraction; import org.opends.quicksetup.ApplicationException; import org.opends.quicksetup.Constants; import org.opends.server.util.VersionCompatibilityIssue; import static org.opends.server.util.VersionCompatibilityIssue.*; import java.util.Set; import java.util.List; import java.util.logging.Logger; import java.util.logging.Level; /** * This class can answer questions important upgrade/reversion questions * like 'can I upgrade from verion X to version Y?' and 'if not then why?'. * {@link org.opends.quicksetup.upgrader.VersionOracle} specific * to upgrade tools. */ public class UpgradeOracle { public class UpgradeOracle extends VersionOracle { private BuildInformation currentBuildInfo; private BuildInformation newBuildInfo; static private final Logger LOG = Logger.getLogger(UpgradeOracle.class.getName()); /** * Creates a new instance that can analyze a hypothetical upgrade/reversion * operation from one version to another. * @param ui UserInteraction for relaying information to the user * @param current BuildInformation representing the current version * @param neu BuildInformation representing the proposed next version */ public UpgradeOracle(BuildInformation current, BuildInformation neu) { this.currentBuildInfo = current; this.newBuildInfo = neu; public UpgradeOracle(UserInteraction ui, BuildInformation current, BuildInformation neu) { super(ui, current, neu); } /** * Indicates whether or not this operation would be considered an * upgrade (as opposed to a reversion). * @return boolean where true indicates that this would be an upgrade; * false indicates that this would be a reversion. * {@inheritDoc} */ public boolean isUpgrade() { return currentBuildInfo.compareTo(newBuildInfo) < 0; } /** * Indicates whether or not this operation would be considered an * reversion (as opposed to an upgrade). * @return boolean where true indicates that this would be a reversion; * false indicates that this would be an upgrade. */ public boolean isReversion() { return currentBuildInfo.compareTo(newBuildInfo) > 0; } /** * Indicates whether or not this hypothetical operation should be allowed * to happen. * @return boolean where true indicates that we are confident that such * an operation will succeed */ public boolean isSupported() { return !isReversion(); } /** * Creates a string summarizing a hypothetical upgrade/reversion * from <code>currentVersion</code> to <code>newVersion</code> giving * reasons why such an attempt would not be successful. * @return String representing a localized message giving a summary of * this hypothetical operation. */ public String getLocalizedSummaryMessage() { String msg; String[] args = { currentBuildInfo.toString(), currentBuildInfo.toString() }; ResourceProvider rp = ResourceProvider.getInstance(); if (isSupported()) { if (isUpgrade()) { msg = rp.getMsg("upgrade-hypothetical-upgrade-success", args); } else if (isReversion()) { msg = rp.getMsg("upgrade-hypothetical-reversion-success", args); public void notifyUser() throws ApplicationException { String[] args = { currentBuildInfo.toString(), newBuildInfo.toString() }; String cont = getMsg("oracle-action-prompt-continue"); String cancel = getMsg("oracle-action-prompt-cancel"); if (hasIssues()) { List<Directive> issues = getIssues(); if (!isSupported()) { if (issues != null) { for (VersionOracle.Directive directive : issues) { LOG.log(Level.INFO, "Unsupported upgrade details: " + directive.getMessage()); } } throw new ApplicationException(ApplicationException.Type.APPLICATION, getMsg("upgrade-oracle-unsupported", args), null); } else { msg = rp.getMsg("upgrade-hypothetical-versions-the-same", args); if (ui != null) { for (VersionOracle.Directive directive : issues) { String title; String summary; String details; String defaultAction; UserInteraction.MessageType msgType; switch (directive.getType()) { case ACTION: title = getMsg("general-action-required"); summary = getMsg("upgrade-oracle-action", args); details = directive.getMessage() + Constants.HTML_LINE_BREAK + Constants.HTML_LINE_BREAK + getMsg("oracle-action-prompt"); msgType = UserInteraction.MessageType.WARNING; defaultAction = cancel; break; case INFO: title = getMsg("general-info"); summary = getMsg("upgrade-oracle-info"); details = directive.getMessage() + Constants.HTML_LINE_BREAK + Constants.HTML_LINE_BREAK + getMsg("oracle-info-prompt"); msgType = UserInteraction.MessageType.INFORMATION; defaultAction = cont; break; case WARNING: title = getMsg("general-warning"); summary = getMsg("upgrade-oracle-warning"); details = directive.getMessage() + Constants.HTML_LINE_BREAK + Constants.HTML_LINE_BREAK + getMsg("oracle-info-prompt"); msgType = UserInteraction.MessageType.WARNING; defaultAction = cont; break; default: LOG.log(Level.INFO, "Unexpected issue type " + directive.getType()); title = ""; summary = ""; details = directive.getMessage(); msgType = UserInteraction.MessageType.WARNING; defaultAction = cont; } if (cancel.equals(ui.confirm( summary, details, title, msgType, new String[]{cont, cancel}, defaultAction))) { throw new ApplicationException( ApplicationException.Type.CANCEL, getMsg("upgrade-canceled"), null); } } } else { throw new ApplicationException(ApplicationException.Type.APPLICATION, getMsg("oracle-no-silent"), null); } } } else { if (isUpgrade()) { msg = rp.getMsg("upgrade-hypothetical-upgrade-failure", args); } else if (isReversion()) { msg = rp.getMsg("upgrade-hypothetical-reversion-failure", args); } else { msg = rp.getMsg("upgrade-hypothetical-versions-the-same", args); } } } /** * {@inheritDoc} */ protected String getLocalizedDetailMessage( VersionCompatibilityIssue.Cause cause) { String msg = cause.getLocalizedUpgradeMessage(); // See if we need to supply a generic message Set<VersionCompatibilityIssue.Effect> effects = cause.getEffects(); // If the import/export effect is present, append the detailed // instructions. if (effects.contains(Effect.UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED)) { if (msg == null) msg = ""; msg = msg + Constants.HTML_LINE_BREAK + ui.createUnorderedList(getExportImportInstructions()); } return msg; } /** * {@inheritDoc} */ protected boolean isActionRequired(VersionCompatibilityIssue.Cause cause) { boolean isAction = false; if (cause != null) { Set<VersionCompatibilityIssue.Effect> effects = cause.getEffects(); isAction = effects.contains( Effect.UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED) || (effects.contains( Effect.UPGRADE_MANUAL_ACTION_REQUIRED) && cause.getLocalizedUpgradeMessage() != null); } return isAction; } /** * {@inheritDoc} */ protected boolean isWarning(VersionCompatibilityIssue.Cause cause) { boolean isWarning = false; if (cause != null && !isActionRequired(cause)) { Set<VersionCompatibilityIssue.Effect> effects = cause.getEffects(); isWarning = effects.contains(Effect.UPGRADE_SHOW_WARNING_MESSAGE) && cause.getLocalizedUpgradeMessage() != null; } return isWarning; } /** * {@inheritDoc} */ protected boolean isUnsupported(VersionCompatibilityIssue.Cause cause) { boolean isUnsupported = false; if (cause != null) { Set<VersionCompatibilityIssue.Effect> effects = cause.getEffects(); for (VersionCompatibilityIssue.Effect effect : effects) { switch (effect) { case UPGRADE_NOT_POSSIBLE: isUnsupported = true; break; default: // assume not an tion; } } } return isUnsupported; } } opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -725,7 +725,7 @@ ZipExtractor extractor; try { LOG.log(Level.INFO, "Waiting for Java Web Start jar download"); waitForLoader(15); // TODO: ratio waitForLoader(15); LOG.log(Level.INFO, "Downloaded build file"); String zipName = WebStartDownloader.getZipFileName(); InputStream in = @@ -1470,7 +1470,6 @@ private void insureUpgradability() throws ApplicationException { BuildInformation currentVersion; BuildInformation newVersion; try { currentVersion = getInstallation().getBuildInformation(); } catch (ApplicationException e) { @@ -1488,14 +1487,19 @@ LOG.log(Level.INFO, "error getting build information for " + "staged installation", e); throw ApplicationException.createFileSystemException( getMsg("error-determining-upgrade-build"), e); } UpgradeOracle uo = new UpgradeOracle(currentVersion, newVersion); if (!uo.isSupported()) { throw new ApplicationException(ApplicationException.Type.APPLICATION, uo.getLocalizedSummaryMessage(), null); getMsg("error-determining-upgrade-build"), e); } UpgradeOracle uo = new UpgradeOracle( userInteraction(), currentVersion, newVersion); uo.notifyUser(); if (uo.noServerStartFollowingOperation()) { // Some issue dicatates that we don't try and restart the server // after this operation. It may be that the databases are no // longer readable after the upgrade or something equally earth // shattering. getUserData().setStartServer(false); } } private Installation getStagedInstallation() opends/src/quicksetup/org/opends/quicksetup/upgrader/VersionOracle.java
New file @@ -0,0 +1,376 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup.upgrader; import org.opends.quicksetup.BuildInformation; import org.opends.quicksetup.ApplicationException; import org.opends.quicksetup.UserInteraction; import org.opends.quicksetup.i18n.ResourceProvider; import org.opends.server.util.VersionCompatibilityIssue; import org.opends.server.util.BuildVersion; import static org.opends.server.util.VersionCompatibilityIssue.*; import java.util.List; import java.util.Set; import java.util.ArrayList; import java.util.Collections; import java.util.logging.Logger; import java.util.logging.Level; /** * This class can answer questions important upgrade/reversion questions * like 'can I upgrade from verion X to version Y?' and 'if not then why?'. * This is also responsible for obtaining and translating any applicable * {@link org.opends.server.util.VersionCompatibilityIssue}s and * interacting with the user to inform them of an actions or information * that they dictate. */ public abstract class VersionOracle { static private final Logger LOG = Logger.getLogger(VersionOracle.class.getName()); /** Descriptor for a directive. */ protected enum DirectiveType { /** Causes the tools to refuse to continue. */ NOT_SUPPORTED, /** Causes the tools to display an action dialog. */ ACTION, /** Causes the tools to display an informational dialog. */ INFO, /** Causes the tools to display a warning dialog. */ WARNING } /** * Holds information that directs tool behavior. */ protected class Directive { DirectiveType type; String msg; /** * Creates a parameterized instance. * * @param type of directive * @param localizedMsg for displaying to the user */ public Directive(DirectiveType type, String localizedMsg) { this.type = type; this.msg = localizedMsg; } /** * Gets the type of issue. * @return type of issue */ public DirectiveType getType() { return this.type; } /** * Gets the issue's message. * @return string message */ public String getMessage() { return this.msg; } } /** Used for interacting with the user. */ protected UserInteraction ui; /** Version issues applicable to this operation. */ protected List<Directive> directives; /** Information about the current build version. */ protected BuildInformation currentBuildInfo; /** Information about the proposed new build version. */ protected BuildInformation newBuildInfo; private boolean isSupported = true; private boolean noServerStart = false; /** * Creates a parameterized instance. * @param ui for interacting with the user * @param current build version * @param neu build version */ public VersionOracle(UserInteraction ui, BuildInformation current, BuildInformation neu) { this.ui = ui; this.currentBuildInfo = current; this.newBuildInfo = neu; // Get the list of possible version incompatibility events (aka flag days) List<VersionCompatibilityIssue> compatibilityIssues; Set<Integer> excludeIds = current.getIncompatibilityEventIds(); if (excludeIds != null) { compatibilityIssues = getEvents(excludeIds); } else { // This method is only used as a fallback for pre 1.0.0 servers which // do not advertise incompatible version events. LOG.log(Level.INFO, "Legacy method for obtaining compatibility issues"); BuildVersion bv = new BuildVersion( current.getMajorVersion(), current.getMinorVersion(), current.getPointVersion(), current.getRevisionNumber()); compatibilityIssues = getEvents(bv); } directives = processEvents(compatibilityIssues); } /** * Interacts with the user to let them know about any * version issues applicable to operations between the * builds supplied in the constructor. * * @throws ApplicationException if something goes wrong or * the user cancels the operation. */ public abstract void notifyUser() throws ApplicationException; /** * Indicates whether or not this operation would be considered an * upgrade (as opposed to a reversion). * * @return boolean where true indicates that this would be an upgrade; * false indicates that this would be a reversion. */ public boolean isUpgrade() { return currentBuildInfo.compareTo(newBuildInfo) < 0; } /** * Indicates whether or not this operation would be considered an * reversion (as opposed to an upgrade). * * @return boolean where true indicates that this would be a reversion; * false indicates that this would be an upgrade. */ public boolean isReversion() { return currentBuildInfo.compareTo(newBuildInfo) > 0; } /** * Returns whether or not this operation is supported. * @return true to indicate this operation is supported; false otherwise */ public boolean isSupported() { return isSupported; } /** * Indicates whether the set of version issues dictates that the server * not be restarted afterward. * * @return true meaning the server won't be restarted; false otherwise */ public boolean noServerStartFollowingOperation() { return noServerStart; } /** * Gets a list of issues applicable to this operation. * @return list of issues */ protected List<Directive> getIssues() { return directives; } /** * Indicates whether or not there are issues with this operation. * @return true indicating there are issues; false otherwise */ protected boolean hasIssues() { return (directives != null && directives.size() > 0); } /** * Given a particular cause return a detail message appropriate * for this operation. * * @param cause of issue * @return message for presenting to the user */ protected abstract String getLocalizedDetailMessage( VersionCompatibilityIssue.Cause cause); /** * Given a particular cause indicates whether or not the user * will be confronted with verbage explaining that they will * have to perform extra actions for this operation. * * @param cause of issue * @return message for presenting to the user */ protected abstract boolean isActionRequired( VersionCompatibilityIssue.Cause cause); /** * Given a particular cause indicates whether or not this * operation should be allowed to continue. * * @param cause of issue * @return message for presenting to the user */ protected abstract boolean isUnsupported( VersionCompatibilityIssue.Cause cause); /** * Given a particular cause indicates whether or not this * the user will be shown a warning dialog containing * a warning message regarding this operation. * * @param cause of issue * @return message for presenting to the user */ protected abstract boolean isWarning( VersionCompatibilityIssue.Cause cause); /** * Given a particular cause indicates whether or not this * the user will be shown some verbage that may contain * information about this operation. * * @param cause of issue * @return message for presenting to the user */ protected boolean isNotification(Cause cause) { boolean isNotification = false; if (cause != null) { String msg = getLocalizedDetailMessage(cause); if (msg != null && !isWarning(cause) && !isActionRequired(cause)) { isNotification = true; } } return isNotification; } /** * Gets a list of strings representing the steps neccessary * to export and then reimport the data. * * @return List containing strings representing intruction steps */ protected List<String> getExportImportInstructions() { // Creates the steps by accessing messages starting with // 'oracle-ei-action-step' starting with 'oracle-ei-action-step1' // until there are no more message having List<String> instructions = new ArrayList<String>(); try { int i = 1; while (true) { String m = getMsg("oracle-ei-action-step" + i++); if (m != null) { instructions.add(m); } else { break; } } } catch (Exception e) { // ignore } return instructions; } /** * Returns a localized message for a key value. In the properties file we * have something of type: * key=value * * For instance if we pass as key "mykey" and as arguments {"value1"} and * in the properties file we have: * mykey=value with argument {0}. * * This method will return "value with argument value1". * @see org.opends.quicksetup.i18n.ResourceProvider#getMsg(String, String[]) * @param key the key in the properties file. * @param args the arguments to be passed to generate the resulting value. * @return the value associated to the key in the properties file. */ protected String getMsg(String key, String... args) { return ResourceProvider.getInstance().getMsg(key, args); } /** * Converts a set of compatibility issues into a set of set of * action oriented issues for directing tool behavior. * * @param compatibilityIssues list of issues * @return list of directives */ private List<Directive> processEvents( List<VersionCompatibilityIssue> compatibilityIssues) { List<Directive> directives = new ArrayList<Directive>(); if (compatibilityIssues != null) { for (VersionCompatibilityIssue evt : compatibilityIssues) { VersionCompatibilityIssue.Cause cause = evt.getCause(); Set<Effect> effects = cause.getEffects(); String msg = getLocalizedDetailMessage(cause); if (isUnsupported(cause)) { isSupported = false; directives.add(new Directive(DirectiveType.NOT_SUPPORTED, msg)); } else if (isActionRequired(cause)) { directives.add(new Directive(DirectiveType.ACTION, msg)); } else if (isWarning(cause)) { directives.add(new Directive(DirectiveType.WARNING, msg)); } else if (isNotification(cause)) { directives.add(new Directive(DirectiveType.INFO, msg)); } if ((effects.contains( Effect.NO_SERVER_RESTART_FOLLOWING_REVERSION) || effects.contains( Effect.REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED) || effects.contains( Effect.UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED))) { noServerStart = true; } } } return Collections.unmodifiableList(directives); } } opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -1196,7 +1196,8 @@ * Inserts HTML break tags into <code>d</code> breaking it up * so that ideally no line is longer than <code>maxll</code> * assuming no single word is longer then <code>maxll</code>. * If the string already contains HTML line breaks, they are * If the string already contains HTML tags that cause a line * break (e.g break and closing list item tags) they are * respected by this method when calculating where to place * new breaks to control the maximum line length. * @@ -1210,18 +1211,29 @@ if (len <= 0) return d; if (len > maxll) { int p = d.lastIndexOf(Constants.HTML_LINE_BREAK, maxll); if (p > 0 && p < len) { return d.substring(0, p + Constants.HTML_LINE_BREAK.length()) + breakHtmlString( d.substring(p + Constants.HTML_LINE_BREAK.length()), maxll); } else { p = d.lastIndexOf(' ', maxll); if (p <= 0) { p = d.indexOf(' ', maxll); // First see if there are any tags that would cause a // natural break in the line. If so start line break // point evaluation from that point. for (String tag : Constants.BREAKING_TAGS) { int p = d.lastIndexOf(tag, maxll); if (p > 0 && p < len) { return d.substring(0, p + tag.length()) + breakHtmlString( d.substring(p + tag.length()), maxll); } } // Now look for spaces in which to insert a break. // First see if there are any spaces counting backward // from the max line length. If there aren't any, then // use the first space encountered after the max line // lenght. int p = d.lastIndexOf(' ', maxll); if (p <= 0) { p = d.indexOf(' ', maxll); } if (p > 0 && p < len) { return d.substring(0, p) + Constants.HTML_LINE_BREAK + @@ -1235,6 +1247,15 @@ } /** * Converts existing HTML break tags to native line sparators. * @param s string to convert * @return converted string */ static public String convertHtmlBreakToLineSeparator(String s) { return s.replaceAll("\\<br\\>", Constants.LINE_SEPARATOR); } /** * Strips any potential HTML markup from a given string. * @param s string to strip * @return resulting string opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -84,6 +84,8 @@ import org.opends.server.util.SetupUtils; import org.opends.server.util.TimeThread; import org.opends.server.util.Validator; import org.opends.server.util.VersionCompatibilityIssue; import org.opends.server.util.StaticUtils; import org.opends.server.util.args.ArgumentException; import org.opends.server.util.args.ArgumentParser; import org.opends.server.util.args.BooleanArgument; @@ -8817,6 +8819,10 @@ System.out.println("Build JVM Version: " + BUILD_JVM_VERSION); System.out.println("Build JVM Vendor: " + BUILD_JVM_VENDOR); System.out.println("Upgrade Event IDs: " + StaticUtils.listToString( VersionCompatibilityIssue.getAllEvents(), ",")); return; } else if (systemInfo.isPresent()) opends/src/server/org/opends/server/messages/MessageHandler.java
@@ -65,6 +65,7 @@ * <LI>00C -- Access Control</LI> * <LI>00D -- Administration framework</LI> * <LI>00E -- Synchronization</LI> * <LI>00E -- Version Compatibility (Flag Days)</LI> * <LI>800 through FFE -- Reserved for third-party modules</LI> * <LI>FFF -- User-defined processing</LI> * </UL> @@ -193,7 +194,10 @@ */ public static final int CATEGORY_MASK_SYNC = 0x0E000000; /** * The category bitmask used for messages associated with flag day messages. */ public static final int CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES = 0x0F000000; /** * The category bitmask that will be used for messages associated with @@ -294,6 +298,7 @@ AdminMessages.registerMessages(); AciMessages.registerMessages(); ReplicationMessages.registerMessages(); VersionMessages.registerMessages(); } opends/src/server/org/opends/server/messages/VersionMessages.java
New file @@ -0,0 +1,151 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.server.messages; import static org.opends.server.messages.MessageHandler.registerMessage; import static org.opends.server.messages.MessageHandler. CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES; import static org.opends.server.messages.MessageHandler. SEVERITY_MASK_INFORMATIONAL; /** * Messages relating to incompatible version events (also known as 'flag-days') * that might cause potential issues or problems with upgrade or reversions * of a particular installation from one version to another. These messages * are usually shown to the user during an upgrade or reversion process to * alert them to any postential issues. */ public class VersionMessages { /** * Message detailing possible upgrade issues caused by the upgrade of the * Berkley DB libraries in SVN rev 890. */ public static final int MSGID_890_UPGRADE = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 1; /** * Message detailing possible reversion issues caused by the upgrade of the * Berkley DB libraries in SVN rev 890. */ public static final int MSGID_890_REVERSION = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 2; /** * Message detailing possible upgrade issues cause by the database * record format change committed with SVN rev 1582. */ public static final int MSGID_1582_UPGRADE = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 3; /** * Message detailing possible reversion issues cause by the database * record format change committed with SVN rev 1582. */ public static final int MSGID_1582_REVERSION = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 4; /** * Message detailing possible reversion issues cause by the database * record format change committed with SVN rev 2049. */ public static final int MSGID_2049_UPGRADE = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 5; /** * Message detailing possible reversion issues cause by the database * record format change committed with SVN rev 2049. */ public static final int MSGID_2049_REVERSION = CATEGORY_MASK_VERSION_COMPATIBITY_ISSUES | SEVERITY_MASK_INFORMATIONAL | 6; /** * Associates a set of generic messages with the message IDs defined in this * class. */ public static void registerMessages() { registerMessage(MSGID_890_UPGRADE, "With this upgrade, the Berkley DB Java Edition JAR " + "will be upgraded to version 3.2.13 which introduces " + "incompatibilities to the data format. Consequently " + "if at a later time you wish to revert this installation " + "to its prior version you will have to export the data " + "from this server and reimport it once the reversion " + "has finished"); registerMessage(MSGID_890_REVERSION, "With this reversion, the Berkley DB Java Editiong JAR " + "will be downgraded to an older version which uses a " + "different data format than the current version." + "In order to revert this server you will have to export " + "the data from this server and reimport it after the " + "reversion has finished"); registerMessage(MSGID_1582_UPGRADE, "This upgrade introduces improvements to the data format " + "which are not backward compatible with the current " + "version. Consequently " + "if at a later time you wish to revert this installation " + "to its prior version you will have to export the data " + "from this server and reimport it once the reversion " + "has finished"); registerMessage(MSGID_1582_REVERSION, "With this reversion the data format used to store data by the " + "server will be reverted to a prior version. " + "In order to revert this server you will have to export " + "the data from this server and reimport it after the " + "reversion has finished"); registerMessage(MSGID_2049_UPGRADE, "This upgrade introduces improvements to the data format " + "which are not backward compatible with the current " + "version. Consequently " + "if at a later time you wish to revert this installation " + "to its prior version you will have to export the data " + "from this server and reimport it once the reversion " + "has finished"); registerMessage(MSGID_2049_REVERSION, "With this reversion the data format used to store data by the " + "server will be reverted to a prior version. " + "In order to revert this server you will have to export " + "the data from this server and reimport it after the " + "reversion has finished"); } } opends/src/server/org/opends/server/util/BuildVersion.java
New file @@ -0,0 +1,131 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.server.util; /** * Represents a particular version of OpenDS useful for making * comparisons between versions. */ public class BuildVersion implements Comparable<BuildVersion> { /** Major release number. */ int major; /** Minor release number. */ int minor; /** Point release number. */ int point; /** Subversion revision number. */ long rev; /** * Creates a new instance using current build data. * * @return BuildVersion representing current data */ static public BuildVersion getCurrent() { return new BuildVersion( DynamicConstants.MAJOR_VERSION, DynamicConstants.MINOR_VERSION, DynamicConstants.POINT_VERSION, DynamicConstants.REVISION_NUMBER); } /** * Constructs an instance from build data. * @param major release number * @param minor release number * @param point release number * @param rev Subversion revision number */ public BuildVersion(int major, int minor, int point, long rev) { this.major = major; this.minor = minor; this.point = point; this.rev = rev; } /** * Gets the major release number. * @return int major release number */ public int getMajorVersion() { return major; } /** * Gets the minor release number. * @return int minor release number */ public int getMinorVersion() { return minor; } /** * Gets the point release number. * @return int point release number */ public int getPointVersion() { return point; } /** * Gets the Subversion revision number. * @return long Subversion revision number */ public long getRevisionNumber() { return rev; } /** * {@inheritDoc} */ public int compareTo(BuildVersion version) { if (major == version.major) { if (minor == version.minor) { if (point == version.point) { if (rev == version.rev) { return 0; } else if (rev < version.rev) { return -1; } } else if (point < version.point) { return -1; } } else if (minor < version.minor) { return -1; } } else if (major < version.major) { return -1; } return 1; } } opends/src/server/org/opends/server/util/StaticUtils.java
@@ -3256,7 +3256,26 @@ return stringArray; } /** * Creates a string representation of the elements in the * <code>list</code> separated by <code>separator</code>. * * @param list the list to print * @param separator to use between elements * * @return String representing the list */ static public String listToString(List<?> list, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < list.size(); i++) { sb.append(list.get(i)); if (i < list.size() - 1) { sb.append(separator); } } return sb.toString(); } /** * Retrieves an array list containing the contents of the provided array. opends/src/server/org/opends/server/util/VersionCompatibilityIssue.java
New file @@ -0,0 +1,530 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.server.util; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.VersionMessages.*; import java.util.Set; import java.util.List; import java.util.Collections; import java.util.HashSet; import java.util.ArrayList; import java.util.EnumSet; import java.util.Comparator; import java.util.Collection; /** * Record for version compatibility issues (also known as 'flag days') which * are events associated with particular builds or builds between which upgrade * or reversion may required additional steps, notification of issues, or * be prohibitted altogether. */ public class VersionCompatibilityIssue { //*************************************************** // // TO DEFINE A NEW ISSUE: // // Step 1: Select (or add to) effects from the list // below that will cause the upgrade or // reversion tools to behave in particular // ways. If you add to this list you will // likely need to update the UpgradeOracle // and ReversionOracle code. // // Step 2: [scroll down]... // //*************************************************** /** * Effects cause the upgrade and revision tools to behave * in specific ways in response to compatibility issues. */ public enum Effect { /** * Before a reversion can take place there must be a complete * data export to LDIF followed by a complete data import after * the operation has completed. Assigning this effect to an * issue will cause a detailed set of instructions to appear in * the reversion tool explaining how to perform the task. */ REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED, /** * Before an upgrade can take place there must be a complete * data export to LDIF followed by a complete data import after * the operation has completed. Assigning this effect to an * issue will cause a detailed set of instructions to appear in * the upgrade tool explaining how to perform the task. */ UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED, /** * Indicates that the upgrader will show an informational message to the * administrator. Use this effect when you want to have the * upgrader show the user an informational message during upgrade * but the message does not dictate that an action be performed. * For instance you might want to let the user know that due to * a data format incompatibility, it will be more difficult to * revert this build to its previous version following this upgrade. * * If you want the message to be scarier, use * <code>UPGRADE_SHOW_WARNING_MESSAGE</code> instead. */ UPGRADE_SHOW_INFO_MESSAGE, /** * Indicates that the reverter tool will show a message to the * administrator. Use this effect when you want to have the * reverter show the user an informational message during upgrade * but the message does not dictate that an action be performed. * * If you want the message to be scarier, use * <code>REVERSION_SHOW_WARNING_MESSAGE</code> instead. */ REVERSION_SHOW_INFO_MESSAGE, /** * Indicates that the upgrader will show a message to the * administrator. Use this effect when you want to have the * upgrader show the user an informational message during upgrade * but the message does not dictate that an action be performed. * For instance you might want to let the user know that due to * a data format incompatibility, it will be more difficult to * revert this build to its previous version following this upgrade. * * If you want the message to be less scary, use * <code>UPGRADE_SHOW_INFO_MESSAGE</code> instead. */ UPGRADE_SHOW_WARNING_MESSAGE, /** * Indicates that the reverter tool will show a message to the * administrator. Use this effect when you want to have the * reverter show the user an informational message during upgrade * but the message does not dictate that an action be performed. * * If you want the message to be less scary, use * <code>REVERSION_SHOW_INFO_MESSAGE</code> instead. */ REVERSION_SHOW_WARNING_MESSAGE, /** * Indicates that the user needs to perform some manual action * (for which there is not effect currently defined such as * <code>UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED</code>) in order for * the operation to be successful. The action itself should * be described in detail in the upgrade message. */ UPGRADE_MANUAL_ACTION_REQUIRED, /** * Indicates that the user needs to perform some manual action * (for which there is not effect currently defined such as * <code>REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED</code>) in order for * the operation to be successful. The action itself should * be described in detail in the reversion message. */ REVERSION_MANUAL_ACTION_REQUIRED, /** * Indicates that it is not possible to upgrade between to builds * between which lies a flag day. The upgrader will refuse to * operate in this case. */ UPGRADE_NOT_POSSIBLE, /** * Indicates that it is not possible to revert between to builds * between which lies a flag day. The reverter will refuse to run * in this case. */ REVERSION_NOT_POSSIBLE, /** * Indicates that for some reason the server should not be restarted * following a reversion. There might be situations where the admin * needs to perform some actions before the server restarts (such as * the database format being incompatible and the data needing an * export followed by a reimport). This effect need not be included * with <code>UPGRADE_DATA_EXPORT_AND_REIMPORT_REQUIRED</code> and * <code>REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED</code> as this * is assumed. */ NO_SERVER_RESTART_FOLLOWING_REVERSION, } //*************************************************** // // TO DEFINE A NEW ISSUE: // // STEP 1: [scroll up] // // STEP 2: Define an cause below. A cause must be a specific // event. For instance 'upgrade of the database libraries' // on 12/17/2006. A cause associates the effect you selected // in Step 1, detailed reversion and/or upgrade messages and // a unique ID. // // A single issue may be apply to multiple branches of the // codebase. For instance a single event might cause a flag // day between upgrade/reversions from 1.0 to 2.0 as well as // upgrading from 1.0 to 1.1. Therefore you must make sure // that causes that appear in multiple branches have the same // ID. Also, IDs should be unique among all causes in the // codebase. // // STEP 3: [scroll down] // //*************************************************** /** * Unique descriptor of an event that created a flag day for one * or more versions of the OpenDS codebase. */ public enum Cause { /** * Database format change committed on 6/7/2007 * and described in the SVN log for rev 2049. */ DB_FORMAT_CHANGE_2( 3, // Unique ID. See javadoc for more information. getMessage(MSGID_2049_UPGRADE), getMessage(MSGID_2049_REVERSION), Effect.REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED, Effect.UPGRADE_SHOW_WARNING_MESSAGE), /** * Database format change committed on 4/6/2007 * and described in the SVN log for rev 1582. */ DB_FORMAT_CHANGE_1( 2, // Unique ID. See javadoc for more information. getMessage(MSGID_1582_UPGRADE), getMessage(MSGID_1582_REVERSION), Effect.REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED, Effect.UPGRADE_SHOW_WARNING_MESSAGE), /** * Upgrade of Berkley DB library to 3.2.13 on * 12/17/2006. */ BERKLEY_UPGRADE_1( 1, // Unique ID. See javadoc for more information. getMessage(MSGID_890_UPGRADE), getMessage(MSGID_890_REVERSION), Effect.REVERSION_DATA_EXPORT_AND_REIMPORT_REQUIRED, Effect.UPGRADE_SHOW_WARNING_MESSAGE); /** * Gets a <code>Cause</code> from its unique ID. If no cause * is associated with <code>id</code> this method returns null. * @param id of a cause * @return Cause with <code>id</code> */ static Cause fromId(int id) { Cause cause = null; EnumSet<Cause> es = EnumSet.allOf(Cause.class); for (Cause c : es) { if (c.getId() == id) { cause = c; break; } } return cause; } private int id; private Set<Effect> effects = new HashSet<Effect>(); private String upgradeMsg; private String reversionMsg; /** * Creates a parameterized instance. * * @param id of this cause. It would get very complicated to try to * deal with releases as a graph and attempting to compare * versions to see what issues apply during an upgrade/reversion * between two releases. Therefore IDs are used by the tools * to identify issues would have already been seen during a previous * upgrade and do not need to be rehashed. * <p> * So if an issue exists in the 1.0 branch, an upgrade from 2.0 * to 3.0 will suppress the issue since it would presumably already * been dealt with when 2.0 was installed or upgraded to. Likewise * if an issue is assocated with a particular minor version (1.1 for * instance) major upgrades (1.0 to 2.0) will avoid presenting the * issue. * * <ol> * <li>IDs must be unique among different causes in all branches * of the OpenDS code.</li> * * <li>Causes in different branches representing the same issue * must have identical IDs.</li> * * <li>The IDs are advertised by the server when start-ds -F * is invoked. Therefore they should be kept to as few * characters as possible.</li> * </ol> * * @param upgradeMessage a message to be shown to the user during an * upgrade between two different version between which this issue * lies. This message might detail instructions for manual actions * that must be performed (when used with the * <code>UPGRADE_MANUAL_ACTION_REQUIRED</code>) or give the * user a warning message (when used with * <code>UPGRADE_SHOW_WARNING_MESSAGE</code>). If a message is * present but no effects that would dictate how message is to * be presented <code>UPGRADE_SHOW_INFO_MESSAGE</code> is * assumed. This parameter may also be null in which case no * action will be taken during upgrade. * * @param reversionMessage a message to be shown to the user during a * reversion between two different version between which this issue * lies. This message might detail instructions for manual actions * that must be performed (when used with the * <code>REVERSION_MANUAL_ACTION_REQUIRED</code>) or give the * user a warning message (when used with * <code>REVERSION_SHOW_WARNING_MESSAGE</code>). If a message is * present but no effects that would dictate how message is to * be presented <code>REVERSION_SHOW_INFO_MESSAGE</code> is * assumed. This parameter may also be null in which case no * action will be taken during reversion. * * @param effects of this cause which cause the upgrade/reversion tools * to behave in particular ways */ private Cause(int id, String upgradeMessage, String reversionMessage, Effect... effects) { this.id = id; this.upgradeMsg = upgradeMessage; this.reversionMsg = reversionMessage; if (effects != null) { for (Effect c : effects) { this.effects.add(c); } } } /** * Gets the ID of this cause. * @return id of this cause */ public int getId() { return this.id; } /** * Gets the set of effects that cause the upgrade/reversion * tools to behave in particular ways. * * @return set of effects */ public Set<Effect> getEffects() { return Collections.unmodifiableSet(effects); } /** * Gets a localized message to be shown to the user during * the upgrade process. * * @return a message to be shown to the user during an * upgrade between two different version between which this issue * lies. This message might detail instructions for manual actions * that must be performed (when used with the * <code>UPGRADE_MANUAL_ACTION_REQUIRED</code>) or just give the * user useful information (when used with * <code>UPGRADE_SHOW_INFO_MESSAGE</code>) */ public String getLocalizedUpgradeMessage() { return upgradeMsg; } /** * Gets a localized message to be shown to the user during * the reversion process. * * @return a message to be shown to the user during an * upgrade between two different version between which this issue * lies. This message might detail instructions for manual actions * that must be performed (when used with the * <code>REVERSION_MANUAL_ACTION_REQUIRED</code>) or just give the * user useful information (when used with * <code>REVERSION_SHOW_INFO_MESSAGE</code>) */ public String getLocalizedReversionMessage() { return reversionMsg; } } /** * Container for registered issues. */ static private final Set<VersionCompatibilityIssue> VERSION_COMPATIBILITY_ISSUES = new HashSet<VersionCompatibilityIssue>(); //*************************************************** // // TO DEFINE A NEW ISSUE: // // STEP 2: [scroll up] // // STEP 3: Associate the cause with a particular build. // // DONE // //*************************************************** static { register(Cause.DB_FORMAT_CHANGE_2, new BuildVersion(0, 9, 0, 2049)); register(Cause.DB_FORMAT_CHANGE_1, new BuildVersion(0, 1, 0, 1582)); register(Cause.BERKLEY_UPGRADE_1, new BuildVersion(0, 1, 0, 890)); } static private void register(Cause cause, BuildVersion version) { VERSION_COMPATIBILITY_ISSUES.add(new VersionCompatibilityIssue(cause, version)); } /** * Gets the list of all registered issues. * * @return list of issues sorted by build version in which * they appear */ static public List<VersionCompatibilityIssue> getAllEvents() { List<VersionCompatibilityIssue> issueList = new ArrayList<VersionCompatibilityIssue> (VERSION_COMPATIBILITY_ISSUES); Collections.sort(issueList, VERSION_COMPARATOR); return Collections.unmodifiableList(issueList); } /** * Gets the list of all registered issues excluding the * issues specified by <code>excludeIds</code>. * * @param excludeIds collection of IDs representing issues * that will not be returned in the list * * @return list of issues sorted by build version in which * they appear */ static public List<VersionCompatibilityIssue> getEvents( Collection<Integer> excludeIds) { if (excludeIds == null) excludeIds = Collections.emptySet(); List<VersionCompatibilityIssue> issueList = new ArrayList<VersionCompatibilityIssue>(); for (VersionCompatibilityIssue evt : VERSION_COMPATIBILITY_ISSUES) { if (!excludeIds.contains(evt.getCause().getId())) { issueList.add(evt); } } Collections.sort(issueList, VERSION_COMPARATOR); return Collections.unmodifiableList(issueList); } /** * Returns events that have happened in between the SVN revision numbers * of two different builds. Note that this method does not necessarily * return all events that are pertinent. For instance a partilar event * may have happend in a branch that we don't care about for the current * upgrade. So this method should really just be used as a fall-back * in the case where we are upgrading/reverting a build that was not * instrumented to return the Upgrade Event IDs using start-ds -F. * * @param from build from which events will be returned * @return List or IncompatibleVersionEvent objects */ static public List<VersionCompatibilityIssue> getEvents(BuildVersion from) { List<VersionCompatibilityIssue> issueList = new ArrayList<VersionCompatibilityIssue>(); for (VersionCompatibilityIssue evt : VERSION_COMPATIBILITY_ISSUES) { BuildVersion evtVer = evt.getVersion(); if (evtVer.compareTo(from) >= 0) { issueList.add(evt); } } Collections.sort(issueList, VERSION_COMPARATOR); return issueList; } /** * Comparator used to sort issues by the build version for * which they apply. */ static private final Comparator<VersionCompatibilityIssue> VERSION_COMPARATOR = new Comparator<VersionCompatibilityIssue>() { public int compare(VersionCompatibilityIssue o1, VersionCompatibilityIssue o2) { return o1.getVersion().compareTo(o2.getVersion()); } }; private Cause cause; private BuildVersion version; private VersionCompatibilityIssue(Cause cause, BuildVersion version) { this.cause = cause; this.version = version; } /** * Gets the cause of this issue. * @return the cause */ public Cause getCause() { return this.cause; } /** * Gets the build version for which this issue applies. * @return build version */ public BuildVersion getVersion() { return this.version; } /** * {@inheritDoc} */ public String toString() { return Integer.toString(cause.getId()); } }