/*
|
* CDDL HEADER START
|
*
|
* The contents of this file are subject to the terms of the
|
* Common Development and Distribution License, Version 1.0 only
|
* (the "License"). You may not use this file except in compliance
|
* with the License.
|
*
|
* You can obtain a copy of the license at
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
|
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
|
* See the License for the specific language governing permissions
|
* and limitations under the License.
|
*
|
* When distributing Covered Code, include this CDDL HEADER in each
|
* file and include the License file at
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
|
* add the following below this CDDL HEADER, with the fields enclosed
|
* by brackets "[]" replaced with your own identifying information:
|
* Portions Copyright [yyyy] [name of copyright owner]
|
*
|
* CDDL HEADER END
|
*
|
*
|
* Copyright 2006-2009 Sun Microsystems, Inc.
|
*/
|
|
package org.opends.quicksetup.installer;
|
|
import java.io.BufferedReader;
|
import java.io.BufferedWriter;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.FileWriter;
|
import java.io.IOException;
|
import java.io.InputStreamReader;
|
import java.util.ArrayList;
|
import java.util.HashSet;
|
import java.util.Map;
|
import java.util.Properties;
|
import java.util.Random;
|
import java.util.Set;
|
import java.util.TreeSet;
|
import java.util.logging.Level;
|
import java.util.logging.Logger;
|
|
import javax.naming.ldap.InitialLdapContext;
|
|
import org.opends.quicksetup.Application;
|
import org.opends.quicksetup.ApplicationException;
|
import org.opends.quicksetup.Installation;
|
import org.opends.quicksetup.ReturnCode;
|
import org.opends.quicksetup.util.OutputReader;
|
import org.opends.quicksetup.util.Utils;
|
|
import static org.opends.quicksetup.util.Utils.*;
|
|
import org.opends.server.admin.DefaultBehaviorException;
|
import org.opends.server.admin.ManagedObjectNotFoundException;
|
import org.opends.server.admin.client.ManagementContext;
|
import org.opends.server.admin.client.ldap.LDAPManagementContext;
|
import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
|
import org.opends.server.admin.std.client.*;
|
import org.opends.server.admin.std.meta.*;
|
import org.opends.server.backends.task.TaskState;
|
import org.opends.messages.CoreMessages;
|
import org.opends.messages.JebMessages;
|
import org.opends.messages.ReplicationMessages;
|
import org.opends.messages.Message;
|
import static org.opends.messages.QuickSetupMessages.*;
|
|
import org.opends.server.tools.ConfigureDS;
|
import org.opends.server.tools.ConfigureWindowsService;
|
import org.opends.server.tools.JavaPropertiesTool;
|
import org.opends.server.types.DN;
|
import org.opends.server.types.DirectoryException;
|
import org.opends.server.types.Entry;
|
import org.opends.server.types.ExistingFileBehavior;
|
import org.opends.server.types.LDIFExportConfig;
|
import org.opends.server.util.LDIFException;
|
import org.opends.server.util.LDIFWriter;
|
import org.opends.server.util.SetupUtils;
|
import org.opends.server.util.StaticUtils;
|
|
/**
|
* This is the only class that uses classes in org.opends.server (excluding the
|
* case of DynamicConstants, SetupUtils, OperatingSystem and CertificateManager
|
* which are already included in quicksetup.jar).
|
*
|
* Important note: do not include references to this class until OpenDS.jar has
|
* been loaded. These classes must be loaded during Runtime.
|
* The code is written in a way that when we execute the code that uses these
|
* classes the required jar files are already loaded. However these jar files
|
* are not necessarily loaded when we create this class.
|
*/
|
public class InstallerHelper {
|
private static final Logger LOG = Logger.getLogger(
|
InstallerHelper.class.getName());
|
|
private static final int MAX_ID_VALUE = Short.MAX_VALUE;
|
|
/**
|
* Invokes the method ConfigureDS.configMain with the provided parameters.
|
* @param args the arguments to be passed to ConfigureDS.configMain.
|
* @return the return code of the ConfigureDS.configMain method.
|
* @throws ApplicationException if something goes wrong.
|
* @see org.opends.server.tools.ConfigureDS#configMain(String[]).
|
*/
|
public int invokeConfigureServer(String[] args) throws ApplicationException {
|
return ConfigureDS.configMain(args, System.out, System.err);
|
}
|
|
/**
|
* Invokes the import-ldif command-line with the provided parameters.
|
* @param application the application that is launching this.
|
* @param args the arguments to be passed to import-ldif.
|
* @return the return code of the import-ldif call.
|
* @throws IOException if the process could not be launched.
|
* @throws InterruptedException if the process was interrupted.
|
*/
|
public int invokeImportLDIF(final Application application, String[] args)
|
throws IOException, InterruptedException
|
{
|
File installPath = new File(application.getInstallationPath());
|
ArrayList<String> argList = new ArrayList<String>();
|
File binPath;
|
if (Utils.isWindows())
|
{
|
binPath =
|
new File(installPath, Installation.WINDOWS_BINARIES_PATH_RELATIVE);
|
} else
|
{
|
binPath =
|
new File(installPath, Installation.UNIX_BINARIES_PATH_RELATIVE);
|
}
|
File importPath;
|
if (Utils.isWindows())
|
{
|
importPath = new File(binPath, Installation.WINDOWS_IMPORT_LDIF);
|
} else
|
{
|
importPath = new File(binPath, Installation.UNIX_IMPORT_LDIF);
|
}
|
argList.add(Utils.getScriptPath(importPath.getAbsolutePath()));
|
for (String arg : args)
|
{
|
argList.add(arg);
|
}
|
String[] allArgs = new String[argList.size()];
|
argList.toArray(allArgs);
|
LOG.log(Level.INFO, "import-ldif arg list: "+argList);
|
ProcessBuilder pb = new ProcessBuilder(allArgs);
|
Map<String, String> env = pb.environment();
|
env.remove(SetupUtils.OPENDS_JAVA_HOME);
|
env.remove(SetupUtils.OPENDS_JAVA_ARGS);
|
env.remove("CLASSPATH");
|
pb.directory(installPath);
|
Process process = null;
|
try
|
{
|
process = pb.start();
|
final BufferedReader err =
|
new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
new OutputReader(err)
|
{
|
public void processLine(String line)
|
{
|
LOG.log(Level.WARNING, "import-ldif error log: "+line);
|
application.notifyListeners(Message.raw(line));
|
application.notifyListeners(application.getLineBreak());
|
}
|
};
|
BufferedReader out =
|
new BufferedReader(new InputStreamReader(process.getInputStream()));
|
new OutputReader(out)
|
{
|
public void processLine(String line)
|
{
|
LOG.log(Level.INFO, "import-ldif out log: "+line);
|
application.notifyListeners(Message.raw(line));
|
application.notifyListeners(application.getLineBreak());
|
}
|
};
|
return process.waitFor();
|
}
|
finally
|
{
|
if (process != null)
|
{
|
try
|
{
|
process.getErrorStream().close();
|
}
|
catch (Throwable t)
|
{
|
LOG.log(Level.WARNING, "Error closing error stream: "+t, t);
|
}
|
try
|
{
|
process.getOutputStream().close();
|
}
|
catch (Throwable t)
|
{
|
LOG.log(Level.WARNING, "Error closing output stream: "+t, t);
|
}
|
}
|
}
|
}
|
|
/**
|
* Returns the Message ID that corresponds to a successfully started server.
|
* @return the Message ID that corresponds to a successfully started server.
|
*/
|
public String getStartedId()
|
{
|
return String.valueOf(CoreMessages.NOTE_DIRECTORY_SERVER_STARTED.getId());
|
}
|
|
/**
|
* This methods enables this server as a Windows service.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public void enableWindowsService() throws ApplicationException {
|
int code = ConfigureWindowsService.enableService(System.out, System.err);
|
|
Message errorMessage = INFO_ERROR_ENABLING_WINDOWS_SERVICE.get();
|
|
switch (code) {
|
case
|
ConfigureWindowsService.SERVICE_ENABLE_SUCCESS:
|
break;
|
case
|
ConfigureWindowsService.SERVICE_ALREADY_ENABLED:
|
break;
|
default:
|
throw new ApplicationException(
|
ReturnCode.WINDOWS_SERVICE_ERROR,
|
errorMessage, null);
|
}
|
}
|
|
/**
|
* This method disables this server as a Windows service.
|
* @throws ApplicationException if something goes worong.
|
*/
|
public void disableWindowsService() throws ApplicationException
|
{
|
int code = ConfigureWindowsService.disableService(System.out, System.err);
|
if (code == ConfigureWindowsService.SERVICE_DISABLE_ERROR) {
|
throw new ApplicationException(
|
// TODO: fix this message's format string
|
ReturnCode.WINDOWS_SERVICE_ERROR,
|
INFO_ERROR_DISABLING_WINDOWS_SERVICE.get(""), null);
|
}
|
}
|
|
/**
|
* Creates a template LDIF file with an entry that has as dn the provided
|
* baseDn.
|
* @param baseDn the dn of the entry that will be created in the LDIF file.
|
* @return the File object pointing to the created temporary file.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public File createBaseEntryTempFile(String baseDn)
|
throws ApplicationException {
|
File ldifFile;
|
try
|
{
|
ldifFile = File.createTempFile("opends-base-entry", ".ldif");
|
ldifFile.deleteOnExit();
|
} catch (IOException ioe)
|
{
|
Message failedMsg =
|
getThrowableMsg(INFO_ERROR_CREATING_TEMP_FILE.get(), ioe);
|
throw new ApplicationException(
|
ReturnCode.FILE_SYSTEM_ACCESS_ERROR,
|
failedMsg, ioe);
|
}
|
|
try
|
{
|
LDIFExportConfig exportConfig = new LDIFExportConfig(
|
ldifFile.getAbsolutePath(), ExistingFileBehavior.OVERWRITE);
|
|
LDIFWriter writer = new LDIFWriter(exportConfig);
|
|
DN dn = DN.decode(baseDn);
|
Entry entry = StaticUtils.createEntry(dn);
|
|
writer.writeEntry(entry);
|
writer.close();
|
} catch (DirectoryException de) {
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR,
|
getThrowableMsg(INFO_ERROR_IMPORTING_LDIF.get(), de), de);
|
} catch (LDIFException le) {
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR,
|
getThrowableMsg(INFO_ERROR_IMPORTING_LDIF.get(), le), le);
|
} catch (IOException ioe) {
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR,
|
getThrowableMsg(INFO_ERROR_IMPORTING_LDIF.get(), ioe), ioe);
|
} catch (Throwable t) {
|
throw new ApplicationException(
|
ReturnCode.BUG, getThrowableMsg(
|
INFO_BUG_MSG.get(), t), t);
|
}
|
return ldifFile;
|
}
|
|
/**
|
* Deletes a backend on the server.
|
* @param ctx the connection to the server.
|
* @param backendName the name of the backend to be deleted.
|
* @param serverDisplay the server display.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public void deleteBackend(InitialLdapContext ctx, String backendName,
|
String serverDisplay)
|
throws ApplicationException
|
{
|
try
|
{
|
ManagementContext mCtx = LDAPManagementContext.createFromContext(
|
JNDIDirContextAdaptor.adapt(ctx));
|
RootCfgClient root = mCtx.getRootConfiguration();
|
root.removeBackend(backendName);
|
}
|
catch (Throwable t)
|
{
|
Message errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get(
|
serverDisplay, t.toString());
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR, errorMessage,
|
t);
|
}
|
}
|
|
|
/**
|
* Creates a local database backend on the server.
|
* @param ctx the connection to the server.
|
* @param backendName the name of the backend to be created.
|
* @param baseDNs the list of base DNs to be defined on the server.
|
* @param serverDisplay the server display.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public void createLocalDBBackend(InitialLdapContext ctx,
|
String backendName,
|
Set<String> baseDNs,
|
String serverDisplay)
|
throws ApplicationException
|
{
|
try
|
{
|
ManagementContext mCtx = LDAPManagementContext.createFromContext(
|
JNDIDirContextAdaptor.adapt(ctx));
|
RootCfgClient root = mCtx.getRootConfiguration();
|
LocalDBBackendCfgDefn provider = LocalDBBackendCfgDefn.getInstance();
|
LocalDBBackendCfgClient backend = root.createBackend(provider,
|
backendName, null);
|
backend.setEnabled(true);
|
Set<DN> setBaseDNs = new HashSet<DN>();
|
for (String baseDN : baseDNs)
|
{
|
setBaseDNs.add(DN.decode(baseDN));
|
}
|
backend.setBaseDN(setBaseDNs);
|
backend.setBackendId(backendName);
|
backend.setWritabilityMode(BackendCfgDefn.WritabilityMode.ENABLED);
|
backend.commit();
|
}
|
catch (Throwable t)
|
{
|
Message errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get(
|
serverDisplay, t.toString());
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR, errorMessage,
|
t);
|
}
|
}
|
|
/**
|
* Sets the base DNs on a given backend.
|
* @param ctx the connection to the server.
|
* @param backendName the name of the backend where the base Dns must be
|
* defined.
|
* @param baseDNs the list of base DNs to be defined on the server.
|
* @param serverDisplay the server display.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public void setBaseDns(InitialLdapContext ctx,
|
String backendName,
|
Set<String> baseDNs,
|
String serverDisplay)
|
throws ApplicationException
|
{
|
try
|
{
|
ManagementContext mCtx = LDAPManagementContext.createFromContext(
|
JNDIDirContextAdaptor.adapt(ctx));
|
RootCfgClient root = mCtx.getRootConfiguration();
|
BackendCfgClient backend = root.getBackend(backendName);
|
Set<DN> setBaseDNs = new HashSet<DN>();
|
for (String baseDN : baseDNs)
|
{
|
setBaseDNs.add(DN.decode(baseDN));
|
}
|
backend.setBaseDN(setBaseDNs);
|
backend.commit();
|
}
|
catch (Throwable t)
|
{
|
Message errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get(
|
serverDisplay, t.toString());
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR, errorMessage,
|
t);
|
}
|
}
|
|
/**
|
* Configures the replication on a given server.
|
* @param remoteCtx the conection to the server where we want to configure
|
* the replication.
|
* @param replicationServers a Map where the key value is the base dn and
|
* the value is the list of replication servers for that base dn (or domain).
|
* @param replicationPort the replicationPort of the server that is being
|
* configured (it might not exist and the user specified it in the setup).
|
* @param useSecureReplication whether to encrypt connections with the
|
* replication port or not.
|
* @param serverDisplay the server display.
|
* @param usedReplicationServerIds the list of replication server ids that
|
* are already used.
|
* @param usedServerIds the list of server ids (domain ids) that
|
* are already used.
|
* @throws ApplicationException if something goes wrong.
|
* @return a ConfiguredReplication object describing what has been configured.
|
*/
|
public ConfiguredReplication configureReplication(
|
InitialLdapContext remoteCtx, Map<String,Set<String>> replicationServers,
|
int replicationPort, boolean useSecureReplication, String serverDisplay,
|
Set<Integer> usedReplicationServerIds, Set<Integer> usedServerIds)
|
throws ApplicationException
|
{
|
boolean synchProviderCreated;
|
boolean synchProviderEnabled;
|
boolean replicationServerCreated;
|
boolean secureReplicationEnabled;
|
try
|
{
|
ManagementContext mCtx = LDAPManagementContext.createFromContext(
|
JNDIDirContextAdaptor.adapt(remoteCtx));
|
RootCfgClient root = mCtx.getRootConfiguration();
|
|
/*
|
* Configure Synchronization plugin.
|
*/
|
ReplicationSynchronizationProviderCfgClient sync = null;
|
try
|
{
|
sync = (ReplicationSynchronizationProviderCfgClient)
|
root.getSynchronizationProvider("Multimaster Synchronization");
|
}
|
catch (ManagedObjectNotFoundException monfe)
|
{
|
// It does not exist.
|
}
|
if (sync == null)
|
{
|
ReplicationSynchronizationProviderCfgDefn provider =
|
ReplicationSynchronizationProviderCfgDefn.getInstance();
|
sync = root.createSynchronizationProvider(provider,
|
"Multimaster Synchronization",
|
new ArrayList<DefaultBehaviorException>());
|
sync.setJavaClass(
|
org.opends.server.replication.plugin.MultimasterReplication.class.
|
getName());
|
sync.setEnabled(Boolean.TRUE);
|
synchProviderCreated = true;
|
synchProviderEnabled = false;
|
}
|
else
|
{
|
synchProviderCreated = false;
|
if (!sync.isEnabled())
|
{
|
sync.setEnabled(Boolean.TRUE);
|
synchProviderEnabled = true;
|
}
|
else
|
{
|
synchProviderEnabled = false;
|
}
|
}
|
sync.commit();
|
|
/*
|
* Configure the replication server.
|
*/
|
ReplicationServerCfgClient replicationServer = null;
|
|
if (!sync.hasReplicationServer())
|
{
|
if (useSecureReplication)
|
{
|
CryptoManagerCfgClient crypto = root.getCryptoManager();
|
if (!crypto.isSSLEncryption())
|
{
|
crypto.setSSLEncryption(true);
|
crypto.commit();
|
secureReplicationEnabled = true;
|
}
|
else
|
{
|
// Only mark as true if we actually change the configuration
|
secureReplicationEnabled = false;
|
}
|
}
|
else
|
{
|
secureReplicationEnabled = false;
|
}
|
int id = getReplicationId(usedReplicationServerIds);
|
usedReplicationServerIds.add(id);
|
replicationServer = sync.createReplicationServer(
|
ReplicationServerCfgDefn.getInstance(),
|
new ArrayList<DefaultBehaviorException>());
|
replicationServer.setReplicationServerId(id);
|
replicationServer.setReplicationPort(replicationPort);
|
replicationServerCreated = true;
|
}
|
else
|
{
|
secureReplicationEnabled = false;
|
replicationServer = sync.getReplicationServer();
|
usedReplicationServerIds.add(
|
replicationServer.getReplicationServerId());
|
replicationServerCreated = false;
|
}
|
|
Set<String> servers = replicationServer.getReplicationServer();
|
if (servers == null)
|
{
|
servers = new HashSet<String>();
|
}
|
Set<String> oldServers = new HashSet<String>();
|
oldServers.addAll(servers);
|
for (Set<String> rs : replicationServers.values())
|
{
|
servers.addAll(rs);
|
}
|
|
replicationServer.setReplicationServer(servers);
|
replicationServer.commit();
|
|
Set<String> newReplicationServers = new HashSet<String>();
|
newReplicationServers.addAll(servers);
|
newReplicationServers.removeAll(oldServers);
|
|
/*
|
* Create the domains
|
*/
|
String[] domainNames = sync.listReplicationDomains();
|
if (domainNames == null)
|
{
|
domainNames = new String[]{};
|
}
|
Set<ConfiguredDomain> domainsConf = new HashSet<ConfiguredDomain>();
|
ReplicationDomainCfgClient[] domains =
|
new ReplicationDomainCfgClient[domainNames.length];
|
for (int i=0; i<domains.length; i++)
|
{
|
domains[i] = sync.getReplicationDomain(domainNames[i]);
|
}
|
for (String dn : replicationServers.keySet())
|
{
|
ReplicationDomainCfgClient domain = null;
|
boolean isCreated;
|
String domainName = null;
|
for (int i=0; i<domains.length && (domain == null); i++)
|
{
|
if (areDnsEqual(dn,
|
domains[i].getBaseDN().toString()))
|
{
|
domain = domains[i];
|
domainName = domainNames[i];
|
}
|
}
|
if (domain == null)
|
{
|
int domainId = getReplicationId(usedServerIds);
|
usedServerIds.add(domainId);
|
domainName = getDomainName(domainNames, domainId, dn);
|
domain = sync.createReplicationDomain(
|
ReplicationDomainCfgDefn.getInstance(), domainName,
|
new ArrayList<DefaultBehaviorException>());
|
domain.setServerId(domainId);
|
domain.setBaseDN(DN.decode(dn));
|
isCreated = true;
|
}
|
else
|
{
|
isCreated = false;
|
}
|
oldServers = domain.getReplicationServer();
|
if (oldServers == null)
|
{
|
oldServers = new TreeSet<String>();
|
}
|
servers = replicationServers.get(dn);
|
domain.setReplicationServer(servers);
|
usedServerIds.add(domain.getServerId());
|
|
domain.commit();
|
Set<String> addedServers = new TreeSet<String>();
|
addedServers.addAll(servers);
|
addedServers.removeAll(oldServers);
|
ConfiguredDomain domainConf = new ConfiguredDomain(domainName,
|
isCreated, addedServers);
|
domainsConf.add(domainConf);
|
}
|
return new ConfiguredReplication(synchProviderCreated,
|
synchProviderEnabled, replicationServerCreated,
|
secureReplicationEnabled, newReplicationServers,
|
domainsConf);
|
}
|
catch (Throwable t)
|
{
|
Message errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get(
|
serverDisplay, t.toString());
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR, errorMessage,
|
t);
|
}
|
}
|
|
/**
|
* Configures the replication on a given server.
|
* @param remoteCtx the conection to the server where we want to configure
|
* the replication.
|
* @param replConf the object describing what was configured.
|
* @param serverDisplay the server display.
|
* @throws ApplicationException if something goes wrong.
|
*/
|
public void unconfigureReplication(
|
InitialLdapContext remoteCtx, ConfiguredReplication replConf,
|
String serverDisplay)
|
throws ApplicationException
|
{
|
try
|
{
|
ManagementContext mCtx = LDAPManagementContext.createFromContext(
|
JNDIDirContextAdaptor.adapt(remoteCtx));
|
RootCfgClient root = mCtx.getRootConfiguration();
|
|
/*
|
* Unconfigure Synchronization plugin.
|
*/
|
if (replConf.isSynchProviderCreated())
|
{
|
try
|
{
|
root.removeSynchronizationProvider("Multimaster Synchronization");
|
}
|
catch (ManagedObjectNotFoundException monfe)
|
{
|
// It does not exist.
|
}
|
}
|
else
|
{
|
try
|
{
|
ReplicationSynchronizationProviderCfgClient sync =
|
(ReplicationSynchronizationProviderCfgClient)
|
root.getSynchronizationProvider("Multimaster Synchronization");
|
if (replConf.isSynchProviderEnabled())
|
{
|
sync.setEnabled(Boolean.FALSE);
|
}
|
if (replConf.isReplicationServerCreated())
|
{
|
sync.removeReplicationServer();
|
}
|
else if (sync.hasReplicationServer())
|
{
|
ReplicationServerCfgClient replicationServer =
|
sync.getReplicationServer();
|
Set<String> replServers = replicationServer.getReplicationServer();
|
if (replServers != null)
|
{
|
replServers.removeAll(replConf.getNewReplicationServers());
|
replicationServer.setReplicationServer(replServers);
|
replicationServer.commit();
|
}
|
}
|
for (ConfiguredDomain domain : replConf.getDomainsConf())
|
{
|
if (domain.isCreated())
|
{
|
sync.removeReplicationDomain(domain.getDomainName());
|
}
|
else
|
{
|
try
|
{
|
ReplicationDomainCfgClient d =
|
sync.getReplicationDomain(domain.getDomainName());
|
Set<String> replServers = d.getReplicationServer();
|
if (replServers != null)
|
{
|
replServers.removeAll(domain.getAddedReplicationServers());
|
d.setReplicationServer(replServers);
|
d.commit();
|
}
|
}
|
catch (ManagedObjectNotFoundException monfe)
|
{
|
// It does not exist.
|
}
|
}
|
}
|
sync.commit();
|
}
|
catch (ManagedObjectNotFoundException monfe)
|
{
|
// It does not exist.
|
}
|
}
|
if (replConf.isSecureReplicationEnabled())
|
{
|
CryptoManagerCfgClient crypto = root.getCryptoManager();
|
if (crypto.isSSLEncryption())
|
{
|
crypto.setSSLEncryption(false);
|
crypto.commit();
|
}
|
}
|
}
|
catch (Throwable t)
|
{
|
Message errorMessage = INFO_ERROR_CONFIGURING_REMOTE_GENERIC.get(
|
serverDisplay, t.toString());
|
throw new ApplicationException(
|
ReturnCode.CONFIGURATION_ERROR, errorMessage,
|
t);
|
}
|
}
|
|
/**
|
* For the given state provided by a Task tells if the task is done or not.
|
* @param sState the String representing the task state.
|
* @return <CODE>true</CODE> if the task is done and <CODE>false</CODE>
|
* otherwise.
|
*/
|
public boolean isDone(String sState)
|
{
|
TaskState state = TaskState.fromString(sState);
|
return TaskState.isDone(state);
|
}
|
|
/**
|
* For the given state provided by a Task tells if the task is successful or
|
* not.
|
* @param sState the String representing the task state.
|
* @return <CODE>true</CODE> if the task is successful and <CODE>false</CODE>
|
* otherwise.
|
*/
|
public boolean isSuccessful(String sState)
|
{
|
TaskState state = TaskState.fromString(sState);
|
return TaskState.isSuccessful(state);
|
}
|
|
/**
|
* For the given state provided by a Task tells if the task is complete with
|
* errors or not.
|
* @param sState the String representing the task state.
|
* @return <CODE>true</CODE> if the task is complete with errors and
|
* <CODE>false</CODE> otherwise.
|
*/
|
public boolean isCompletedWithErrors(String sState)
|
{
|
TaskState state = TaskState.fromString(sState);
|
return state == TaskState.COMPLETED_WITH_ERRORS;
|
}
|
|
/**
|
* For the given state provided by a Task tells if the task is stopped by
|
* error or not.
|
* @param sState the String representing the task state.
|
* @return <CODE>true</CODE> if the task is stopped by error and
|
* <CODE>false</CODE> otherwise.
|
*/
|
public boolean isStoppedByError(String sState)
|
{
|
TaskState state = TaskState.fromString(sState);
|
return state == TaskState.STOPPED_BY_ERROR;
|
}
|
|
/**
|
* Tells whether the provided log message corresponds to a peers not found
|
* error during the initialization of a replica or not.
|
* @param logMsg the log message.
|
* @return <CODE>true</CODE> if the log message corresponds to a peers not
|
* found error during initialization and <CODE>false</CODE> otherwise.
|
*/
|
public boolean isPeersNotFoundError(String logMsg)
|
{
|
return logMsg.indexOf(
|
"="+ReplicationMessages.
|
ERR_NO_REACHABLE_PEER_IN_THE_DOMAIN.getId()) != -1;
|
}
|
|
/**
|
* Returns the ID to be used for a new replication server or domain.
|
* @param usedIds the list of already used ids.
|
* @return the ID to be used for a new replication server or domain.
|
*/
|
public static int getReplicationId(Set<Integer> usedIds)
|
{
|
Random r = new Random();
|
int id = 0;
|
while ((id == 0) || usedIds.contains(id))
|
{
|
id = r.nextInt(MAX_ID_VALUE);
|
}
|
return id;
|
}
|
|
/**
|
* Returns the name to be used for a new replication domain.
|
* @param existingDomains the existing domains names.
|
* @param newDomainId the new domain replication id.
|
* @param baseDN the base DN of the domain.
|
* @return the name to be used for a new replication domain.
|
*/
|
public static String getDomainName(String[] existingDomains, int newDomainId,
|
String baseDN)
|
{
|
String domainName = baseDN;
|
boolean nameExists = true;
|
int j = 0;
|
while (nameExists)
|
{
|
boolean found = false;
|
for (int i=0; i<existingDomains.length && !found; i++)
|
{
|
found = existingDomains[i].equalsIgnoreCase(domainName);
|
}
|
if (found)
|
{
|
domainName = baseDN+"-"+j;
|
}
|
else
|
{
|
nameExists = false;
|
}
|
j++;
|
}
|
return domainName;
|
}
|
|
/**
|
* Writes the set-java-home file that is used by the scripts to set the
|
* java home and the java arguments.
|
* @param installPath the install path of the server.
|
* @throws IOException if an error occurred writing the file.
|
*/
|
public void writeSetOpenDSJavaHome(String installPath) throws IOException
|
{
|
final String initialClientHeapArg = "-Xms8m";
|
final String serverHeapArgs = "-Xms128m -Xmx256m";
|
final long serverMaxHeapBytes = 256 * 1024 * 1024;
|
// Scripts to which we will pass -client argument
|
final String[] clientScripts =
|
{
|
"backup.online", "base64", "create-rc-script", "dsconfig",
|
"dsreplication", "dsframework", "export-ldif.online",
|
"import-ldif.online", "ldapcompare", "ldapdelete",
|
"ldapmodify", "ldappasswordmodify", "ldapsearch", "list-backends",
|
"manage-account", "manage-tasks", "restore.online", "stop-ds",
|
"status", "control-panel", "uninstall", "setup"
|
};
|
|
// Scripts to which we will pass -server argument
|
final String[] serverScripts =
|
{
|
"backup.offline", "encode-password", "export-ldif.offline",
|
"import-ldif.offline", "ldif-diff", "ldifmodify", "ldifsearch",
|
"make-ldif", "rebuild-index", "restore.offline", "start-ds",
|
"upgrade", "verify-index", "dbtest"
|
};
|
writeSetOpenDSJavaHome(installPath, initialClientHeapArg,
|
serverHeapArgs, serverMaxHeapBytes, clientScripts, serverScripts);
|
}
|
|
/**
|
* Writes the set-java-home file that is used by the scripts to set the
|
* java home and the java arguments.
|
* @param installPath the install path of the server.
|
* @param initialClientHeapArg the argument to be used to set the initial
|
* heap for the client scripts.
|
* @param serverHeapArgs the argument to be used to set the server scripts
|
* heap sizes.
|
* @param serverMaxHeapBytes the maximum size of the heap for the server
|
* scripts.
|
* @param clientScripts the scripts where the client properties are set.
|
* @param serverScripts the scripts where the server properties are set.
|
* @throws IOException if an error occurred writing the file.
|
*/
|
public void writeSetOpenDSJavaHome(String installPath,
|
String initialClientHeapArg,
|
String serverHeapArgs,
|
long serverMaxHeapBytes,
|
String[] clientScripts,
|
String[] serverScripts) throws IOException
|
{
|
String javaHome = System.getProperty("java.home");
|
if ((javaHome == null) || (javaHome.length() == 0))
|
{
|
javaHome = System.getenv(SetupUtils.OPENDS_JAVA_HOME);
|
}
|
|
String configDir = Utils.getPath(Utils
|
.getInstancePathFromClasspath(installPath),
|
Installation.CONFIG_PATH_RELATIVE);
|
String propertiesFile = Utils.getPath(
|
configDir, Installation.DEFAULT_JAVA_PROPERTIES_FILE);
|
boolean propertiesFileModified = false;
|
FileInputStream fs = null;
|
try
|
{
|
fs = new FileInputStream(propertiesFile);
|
Properties properties = new Properties();
|
properties.load(fs);
|
propertiesFileModified = properties.keySet().size() > 0;
|
}
|
catch (Throwable t)
|
{
|
}
|
finally
|
{
|
if (fs != null)
|
{
|
try
|
{
|
fs.close();
|
}
|
catch (Throwable t)
|
{
|
}
|
}
|
}
|
BufferedWriter writer = new BufferedWriter(new FileWriter(propertiesFile,
|
true));
|
|
if (!propertiesFileModified)
|
{
|
writer.newLine();
|
writer.write("overwrite-env-java-home=false");
|
writer.newLine();
|
writer.write("overwrite-env-java-args=false");
|
writer.newLine();
|
writer.newLine();
|
writer.write("default.java-home="+javaHome);
|
writer.newLine();
|
writer.newLine();
|
boolean supportsClient = supportsClient(javaHome, installPath);
|
boolean supportsServer = supportsServer(javaHome, installPath);
|
|
boolean supportsClientInitialHeap =
|
supportsOption(initialClientHeapArg, javaHome, installPath);
|
boolean supportsServerInitialHeap = false;
|
// If the current max memory is bigger than the max heap we want to set,
|
// assume that the JVM ergonomics are going to be able to allocate enough
|
// memory.
|
if (Runtime.getRuntime().maxMemory() < serverMaxHeapBytes)
|
{
|
supportsServerInitialHeap =
|
supportsOption(serverHeapArgs, javaHome, installPath);
|
}
|
|
if (supportsServer || supportsServerInitialHeap)
|
{
|
for (int i=0; i<serverScripts.length; i++)
|
{
|
writer.newLine();
|
String arg = "";
|
if (supportsServer)
|
{
|
arg = "-server";
|
}
|
if (supportsServerInitialHeap)
|
{
|
if (arg.length() > 0)
|
{
|
arg += " ";
|
}
|
arg += serverHeapArgs;
|
}
|
writer.write(serverScripts[i]+".java-args="+arg);
|
}
|
}
|
else
|
{
|
for (int i=0; i<serverScripts.length; i++)
|
{
|
writer.newLine();
|
writer.write(serverScripts[i]+".java-args=");
|
}
|
}
|
|
if (supportsClient || supportsClientInitialHeap)
|
{
|
for (int i=0; i<clientScripts.length; i++)
|
{
|
writer.newLine();
|
String arg = "";
|
if (supportsClient)
|
{
|
arg = "-client";
|
}
|
if (supportsClientInitialHeap)
|
{
|
if (arg.length() > 0)
|
{
|
arg += " ";
|
}
|
arg += initialClientHeapArg;
|
}
|
writer.write(clientScripts[i]+".java-args="+arg);
|
}
|
}
|
else
|
{
|
for (int i=0; i<clientScripts.length; i++)
|
{
|
writer.newLine();
|
writer.write(clientScripts[i]+".java-args=");
|
}
|
}
|
|
if (supportsClient || supportsServer || supportsClientInitialHeap)
|
{
|
writer.newLine();
|
writer.newLine();
|
}
|
|
writer.close();
|
}
|
String destinationFile;
|
String libDir = Utils.getPath(Utils.
|
getInstancePathFromClasspath(installPath),
|
Installation.LIBRARIES_PATH_RELATIVE);
|
if (Utils.isWindows())
|
{
|
destinationFile = Utils.getPath(libDir,
|
Installation.SET_JAVA_PROPERTIES_FILE_WINDOWS);
|
}
|
else
|
{
|
destinationFile = Utils.getPath(libDir,
|
Installation.SET_JAVA_PROPERTIES_FILE_UNIX);
|
}
|
|
// Launch the script
|
String[] args =
|
{
|
"--propertiesFile", propertiesFile,
|
"--destinationFile", destinationFile,
|
"--quiet"
|
};
|
|
int returnValue = JavaPropertiesTool.mainCLI(args);
|
|
if ((returnValue !=
|
JavaPropertiesTool.ErrorReturnCode.SUCCESSFUL.getReturnCode()) &&
|
returnValue !=
|
JavaPropertiesTool.ErrorReturnCode.SUCCESSFUL_NOP.getReturnCode())
|
{
|
LOG.log(Level.WARNING, "Error creating java home scripts, error code: "+
|
returnValue);
|
throw new IOException(
|
ERR_ERROR_CREATING_JAVA_HOME_SCRIPTS.get(returnValue).toString());
|
}
|
}
|
|
/**
|
* If the log message is of type "[03/Apr/2008:21:25:43 +0200] category=JEB
|
* severity=NOTICE msgID=8847454 Processed 1 entries, imported 0, skipped 1,
|
* rejected 0 and migrated 0 in 1 seconds (average rate 0.0/sec)" returns
|
* the message part. Returns <CODE>null</CODE> otherwise.
|
* @param msg the message to be parsed.
|
* @return the parsed import message.
|
*/
|
public String getImportProgressMessage(String msg)
|
{
|
String parsedMsg = null;
|
if (msg != null)
|
{
|
if ((msg.indexOf(
|
"msgID="+JebMessages.NOTE_JEB_IMPORT_FINAL_STATUS.getId()) != -1) ||
|
(msg.indexOf(
|
"msgID="+JebMessages.NOTE_JEB_IMPORT_PROGRESS_REPORT.getId()) != -1))
|
{
|
int index = msg.indexOf("msg=");
|
if (index != -1)
|
{
|
parsedMsg = msg.substring(index + 4);
|
}
|
}
|
}
|
return parsedMsg;
|
}
|
|
/**
|
* Tells whether the provided java installation supports the server option
|
* or not.
|
* @param javaHome the java installation path.
|
* @param installPath the install path of the server.
|
* @return <CODE>true</CODE> if the provided java installation supports the
|
* server option and <CODE>false</CODE> otherwise.
|
*/
|
private boolean supportsServer(String javaHome, String installPath)
|
{
|
return supportsOption("-server", javaHome, installPath);
|
}
|
|
/**
|
* Tells whether the provided java installation supports the client option
|
* or not.
|
* @param javaHome the java installation path.
|
* @param installPath the install path of the server.
|
* @return <CODE>true</CODE> if the provided java installation supports the
|
* client option and <CODE>false</CODE> otherwise.
|
*/
|
private boolean supportsClient(String javaHome, String installPath)
|
{
|
return supportsOption("-client", javaHome, installPath);
|
}
|
}
|
|
/**
|
* A class describing a replication domain.
|
*
|
*/
|
class DomainEntry
|
{
|
private String name;
|
private int replicationId;
|
private String baseDn;
|
private Set<String> replicationServers;
|
/**
|
* The constructor of the domain entry.
|
* @param name the name of the domain.
|
* @param replicationId the replicationId of the domain.
|
* @param baseDn the base dn of the domain.
|
* @param replicationServers the list of replication servers for the domain.
|
*/
|
public DomainEntry(String name, int replicationId, String baseDn,
|
Set<String> replicationServers)
|
{
|
this.name = name;
|
this.replicationId = replicationId;
|
this.baseDn = baseDn;
|
this.replicationServers = replicationServers;
|
}
|
/**
|
* Returns the base dn of the domain.
|
* @return the base dn of the domain.
|
*/
|
public String getBaseDn()
|
{
|
return baseDn;
|
}
|
/**
|
* Returns the name of the domain.
|
* @return the name of the domain.
|
*/
|
public String getName()
|
{
|
return name;
|
}
|
/**
|
* Returns the replication Id of the domain.
|
* @return the replication Id of the domain.
|
*/
|
public int getReplicationId()
|
{
|
return replicationId;
|
}
|
/**
|
* Returns the list of replication servers of the domain.
|
* @return the list of replication servers of the domain.
|
*/
|
public Set<String> getReplicationServers()
|
{
|
return replicationServers;
|
}
|
}
|