mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

kenneth_suter
23.25.2007 e1e9596f6ae81d9aeb74177cf2792533966f45eb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
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 VersionIssueNotifier {
 
  static private final Logger LOG =
          Logger.getLogger(VersionIssueNotifier.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 VersionIssueNotifier(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);
  }
 
}