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

Jean-Noel Rouvignac
23.07.2014 382b9cfecc5f1d44ae1ade68cae766ada69d9890
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
/*
 * 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 legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * 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 legal-notices/CDDLv1_0.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 */
package org.opends.server.tools.dsreplication;
 
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.messages.CoreMessages.*;
 
import java.io.File;
 
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
 
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.server.replication.plugin.LDAPReplicationDomain;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryEnvironmentConfig;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.OpenDsException;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.util.EmbeddedUtils;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.TimeThread;
import com.forgerock.opendj.cli.ConsoleApplication;
import org.opends.server.util.cli.PointAdder;
 
/**
 * The class that is in charge of taking the different information provided
 * by the user through the command-line and actually executing the local
 * purge.
 *
 */
public class LocalPurgeHistorical
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
  private final PurgeHistoricalUserData uData;
  private final ConsoleApplication app;
  private final ProgressMessageFormatter formatter;
  private final String configFile;
  private final String configClass;
 
  /**
   * The default constructor.
   * @param uData the object containing the information provided by the user.
   * @param app the console application that is used to write the progress
   * and error messages.
   * @param formatter the formatter to be used to generated the messages.
   * @param configFile the file that contains the configuration.  This is
   * required to initialize properly the server.
   * @param configClass the class to be used to read the configuration.  This is
   * required to initialize properly the server.
   */
  public LocalPurgeHistorical(PurgeHistoricalUserData uData,
      ConsoleApplication app,
      ProgressMessageFormatter formatter, String configFile,
      String configClass)
  {
    this.uData = uData;
    this.app = app;
    this.formatter = formatter;
    this.configFile = configFile;
    this.configClass = configClass;
  }
 
  /**
   * Executes the purge historical operation locally.
   * @return the result code.
   */
  public ReplicationCliReturnCode execute()
  {
    boolean applyTimeout = uData.getMaximumDuration() > 0;
 
    long startTime = TimeThread.getTime();
    long purgeMaxTime = getTimeoutInSeconds() * 1000L;
 
    long endMaxTime = startTime + purgeMaxTime;
 
    app.print(formatter.getFormattedProgress(
        INFO_REPLICATION_PURGE_HISTORICAL_LOCAL_ENVIRONMENT.get()));
 
    PointAdder pointAdder = new PointAdder(app);
    pointAdder.start();
 
    Class<?> cfgClass;
 
    try
    {
      cfgClass = Class.forName(configClass);
    }
    catch (Exception e)
    {
      pointAdder.stop();
      LocalizableMessage message =
        ERR_CANNOT_LOAD_CONFIG_HANDLER_CLASS.get(
            configClass, StaticUtils.stackTraceToSingleLineString(e));
      app.println(message);
      logger.error(LocalizableMessage.raw("Error loading configuration class "+configClass+
          ": "+e, e));
      return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_CLASS_LOAD;
    }
 
    try
    {
      // Create a configuration for the server.
      DirectoryEnvironmentConfig environmentConfig =
        new DirectoryEnvironmentConfig();
      environmentConfig.setConfigClass(cfgClass);
      environmentConfig.setConfigFile(new File(configFile));
      environmentConfig.setDisableConnectionHandlers(true);
      EmbeddedUtils.startServer(environmentConfig);
    }
    catch (OpenDsException ode)
    {
      pointAdder.stop();
      LocalizableMessage message = ode.getMessageObject();
        ERR_CANNOT_LOAD_CONFIG_HANDLER_CLASS.get(
            configClass, StaticUtils.stackTraceToSingleLineString(ode));
      app.println(message);
      logger.error(LocalizableMessage.raw("Error starting server with file "+configFile+
          ": "+ode, ode));
      return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_SERVER_START;
    }
    pointAdder.stop();
    app.print(formatter.getFormattedDone());
    app.println();
    app.println();
    app.print(formatter.getFormattedProgress(
        INFO_REPLICATION_PURGE_HISTORICAL_LOCAL_STARTING.get()));
    app.println();
 
    if (applyTimeout && timeoutOccurred(endMaxTime))
    {
      return handleTimeout();
    }
 
    try
    {
      // launch the job
      for (String baseDN : uData.getBaseDNs())
      {
        DN dn = DN.valueOf(baseDN);
        // We can assume that this is an LDAP replication domain
        LDAPReplicationDomain domain =
            LDAPReplicationDomain.retrievesReplicationDomain(dn);
 
        domain.purgeConflictsHistorical(null, startTime + purgeMaxTime);
      }
 
    }
    catch (DirectoryException de)
    {
      if (de.getResultCode() == ResultCode.ADMIN_LIMIT_EXCEEDED)
      {
        return handleTimeout();
      }
      else
      {
        return handleGenericExecuting(de);
      }
    }
    return ReplicationCliReturnCode.SUCCESSFUL;
  }
 
  private ReplicationCliReturnCode handleGenericExecuting(OpenDsException ode)
  {
    logger.error(LocalizableMessage.raw("Error executing purge historical: "+ode, ode));
    app.println();
    app.println(ERR_REPLICATION_PURGE_HISTORICAL_EXECUTING.get(
        ode.getMessageObject()));
    return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_EXECUTING;
  }
 
  private ReplicationCliReturnCode handleTimeout()
  {
    app.println();
    app.println(ERR_REPLICATION_PURGE_HISTORICAL_TIMEOUT.get(
        getTimeoutInSeconds()));
    return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_TIMEOUT;
  }
 
  /**
   * Returns the time-out provided by the user in seconds.
   * @return the time-out provided by the user in seconds.
   */
  private int getTimeoutInSeconds()
  {
    return uData.getMaximumDuration();
  }
 
  /**
   * A method that tells whether the maximum time to execute the operation was
   * elapsed or not.
   * @param endMaxTime the latest time in milliseconds when the operation should
   * be completed.
   * @return {@code true} if the time-out occurred and {@code false} otherwise.
   */
  private boolean timeoutOccurred(long endMaxTime)
  {
    return TimeThread.getTime() > endMaxTime;
  }
}