001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.core;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    import java.util.HashSet;
034    import java.util.List;
035    import java.util.Properties;
036    import java.util.Set;
037    
038    import org.opends.server.admin.server.ConfigurationChangeListener;
039    import org.opends.server.admin.std.meta.GlobalCfgDefn;
040    import org.opends.server.admin.std.meta.GlobalCfgDefn.WorkflowConfigurationMode;
041    import org.opends.server.admin.std.server.GlobalCfg;
042    import org.opends.server.admin.std.server.RootCfg;
043    import org.opends.server.admin.server.ServerManagementContext;
044    import org.opends.server.config.ConfigException;
045    import org.opends.server.types.*;
046    
047    import static org.opends.messages.ConfigMessages.*;
048    
049    import static org.opends.server.util.ServerConstants.*;
050    
051    
052    
053    /**
054     * This class defines a utility that will be used to manage the set of core
055     * configuration attributes defined in the Directory Server.  These
056     * configuration attributes appear in the "cn=config" configuration entry.
057     */
058    public class CoreConfigManager
059           implements ConfigurationChangeListener<GlobalCfg>
060    {
061      /**
062       * Creates a new instance of this core config manager.
063       */
064      public CoreConfigManager()
065      {
066        // No implementation is required.
067      }
068    
069    
070    
071      /**
072       * Initializes the Directory Server's core configuration.  This should only be
073       * called at server startup.
074       *
075       * @throws  ConfigException  If a configuration problem causes the identity
076       *                           mapper initialization process to fail.
077       *
078       * @throws  InitializationException  If a problem occurs while initializing
079       *                                   the identity mappers that is not related
080       *                                   to the server configuration.
081       */
082      public void initializeCoreConfig()
083             throws ConfigException, InitializationException
084      {
085        // Get the root configuration object.
086        ServerManagementContext managementContext =
087             ServerManagementContext.getInstance();
088        RootCfg rootConfiguration =
089             managementContext.getRootConfiguration();
090    
091    
092        // Get the global configuration and register with it as a change listener.
093        GlobalCfg globalConfig = rootConfiguration.getGlobalConfiguration();
094        globalConfig.addChangeListener(this);
095    
096    
097        // If there are any STMP servers specified, then make sure that if the value
098        // contains a colon that the portion after it is an integer between 1 and
099        // 65535.
100        Set<String> smtpServers = globalConfig.getSMTPServer();
101        if (smtpServers != null)
102        {
103          for (String server : smtpServers)
104          {
105            int colonPos = server.indexOf(':');
106            if ((colonPos == 0) || (colonPos == (server.length()-1)))
107            {
108              Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
109              throw new ConfigException(message);
110            }
111            else if (colonPos > 0)
112            {
113              try
114              {
115                int port = Integer.parseInt(server.substring(colonPos+1));
116                if ((port < 1) || (port > 65535))
117                {
118                  Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
119                  throw new ConfigException(message);
120                }
121              }
122              catch (Exception e)
123              {
124                Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
125                throw new ConfigException(message, e);
126              }
127            }
128          }
129        }
130    
131    
132        // Apply the configuration to the server.
133        applyGlobalConfiguration(globalConfig);
134      }
135    
136    
137    
138      /**
139       * Applies the settings in the provided configuration to the Directory Server.
140       *
141       * @param  globalConfig  The configuration settings to be applied.
142       */
143      private static void applyGlobalConfiguration(GlobalCfg globalConfig)
144      {
145        DirectoryServer.setCheckSchema(globalConfig.isCheckSchema());
146    
147        DirectoryServer.setDefaultPasswordPolicyDN(
148             globalConfig.getDefaultPasswordPolicyDN());
149    
150        DirectoryServer.setAddMissingRDNAttributes(
151             globalConfig.isAddMissingRDNAttributes());
152    
153        DirectoryServer.setAllowAttributeNameExceptions(
154             globalConfig.isAllowAttributeNameExceptions());
155    
156        switch (globalConfig.getInvalidAttributeSyntaxBehavior())
157        {
158          case ACCEPT:
159            DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.ACCEPT);
160            break;
161          case WARN:
162            DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.WARN);
163            break;
164          case REJECT:
165          default:
166            DirectoryServer.setSyntaxEnforcementPolicy(AcceptRejectWarn.REJECT);
167            break;
168        }
169    
170        DirectoryServer.setServerErrorResultCode(
171             ResultCode.valueOf(globalConfig.getServerErrorResultCode()));
172    
173        switch (globalConfig.getSingleStructuralObjectclassBehavior())
174        {
175          case ACCEPT:
176            DirectoryServer.setSingleStructuralObjectClassPolicy(
177                 AcceptRejectWarn.ACCEPT);
178            break;
179          case WARN:
180            DirectoryServer.setSingleStructuralObjectClassPolicy(
181                 AcceptRejectWarn.WARN);
182            break;
183          case REJECT:
184          default:
185            DirectoryServer.setSingleStructuralObjectClassPolicy(
186                 AcceptRejectWarn.REJECT);
187            break;
188        }
189    
190        DirectoryServer.setNotifyAbandonedOperations(
191             globalConfig.isNotifyAbandonedOperations());
192    
193        DirectoryServer.setSizeLimit(globalConfig.getSizeLimit());
194    
195        DirectoryServer.setTimeLimit((int) globalConfig.getTimeLimit());
196    
197        DirectoryServer.setProxiedAuthorizationIdentityMapperDN(
198             globalConfig.getProxiedAuthorizationIdentityMapperDN());
199    
200        switch (globalConfig.getWritabilityMode())
201        {
202          case ENABLED:
203            DirectoryServer.setWritabilityMode(WritabilityMode.ENABLED);
204            break;
205          case INTERNAL_ONLY:
206            DirectoryServer.setWritabilityMode(WritabilityMode.INTERNAL_ONLY);
207            break;
208          case DISABLED:
209          default:
210            DirectoryServer.setWritabilityMode(WritabilityMode.DISABLED);
211            break;
212        }
213    
214        DirectoryServer.setRejectUnauthenticatedRequests(
215             globalConfig.isRejectUnauthenticatedRequests());
216    
217        DirectoryServer.setBindWithDNRequiresPassword(
218             globalConfig.isBindWithDNRequiresPassword());
219    
220        DirectoryServer.setLookthroughLimit(globalConfig.getLookthroughLimit());
221    
222    
223        ArrayList<Properties> mailServerProperties = new ArrayList<Properties>();
224        Set<String> smtpServers = globalConfig.getSMTPServer();
225        if ((smtpServers != null) && (! smtpServers.isEmpty()))
226        {
227          for (String smtpServer : smtpServers)
228          {
229            int colonPos = smtpServer.indexOf(':');
230            if (colonPos > 0)
231            {
232              String smtpHost = smtpServer.substring(0, colonPos);
233              String smtpPort = smtpServer.substring(colonPos+1);
234    
235              Properties properties = new Properties();
236              properties.setProperty(SMTP_PROPERTY_HOST, smtpHost);
237              properties.setProperty(SMTP_PROPERTY_PORT, smtpPort);
238              mailServerProperties.add(properties);
239            }
240            else
241            {
242              Properties properties = new Properties();
243              properties.setProperty(SMTP_PROPERTY_HOST, smtpServer);
244              mailServerProperties.add(properties);
245            }
246          }
247        }
248        DirectoryServer.setMailServerPropertySets(mailServerProperties);
249    
250        DirectoryServer.setAllowedTasks(globalConfig.getAllowedTask());
251    
252    
253        HashSet<Privilege> disabledPrivileges = new HashSet<Privilege>();
254        Set<GlobalCfgDefn.DisabledPrivilege> configuredDisabledPrivs =
255             globalConfig.getDisabledPrivilege();
256        if (configuredDisabledPrivs != null)
257        {
258          for (GlobalCfgDefn.DisabledPrivilege p : configuredDisabledPrivs)
259          {
260            switch (p)
261            {
262              case BACKEND_BACKUP:
263                disabledPrivileges.add(Privilege.BACKEND_BACKUP);
264                break;
265              case BACKEND_RESTORE:
266                disabledPrivileges.add(Privilege.BACKEND_RESTORE);
267                break;
268              case BYPASS_ACL:
269                disabledPrivileges.add(Privilege.BYPASS_ACL);
270                break;
271              case CANCEL_REQUEST:
272                disabledPrivileges.add(Privilege.CANCEL_REQUEST);
273                break;
274              case CONFIG_READ:
275                disabledPrivileges.add(Privilege.CONFIG_READ);
276                break;
277              case CONFIG_WRITE:
278                disabledPrivileges.add(Privilege.CONFIG_WRITE);
279                break;
280              case DATA_SYNC:
281                disabledPrivileges.add(Privilege.DATA_SYNC);
282                break;
283              case DISCONNECT_CLIENT:
284                disabledPrivileges.add(Privilege.DISCONNECT_CLIENT);
285                break;
286              case JMX_NOTIFY:
287                disabledPrivileges.add(Privilege.JMX_NOTIFY);
288                break;
289              case JMX_READ:
290                disabledPrivileges.add(Privilege.JMX_READ);
291                break;
292              case JMX_WRITE:
293                disabledPrivileges.add(Privilege.JMX_WRITE);
294                break;
295              case LDIF_EXPORT:
296                disabledPrivileges.add(Privilege.LDIF_EXPORT);
297                break;
298              case LDIF_IMPORT:
299                disabledPrivileges.add(Privilege.LDIF_IMPORT);
300                break;
301              case MODIFY_ACL:
302                disabledPrivileges.add(Privilege.MODIFY_ACL);
303                break;
304              case PASSWORD_RESET:
305                disabledPrivileges.add(Privilege.PASSWORD_RESET);
306                break;
307              case PRIVILEGE_CHANGE:
308                disabledPrivileges.add(Privilege.PRIVILEGE_CHANGE);
309                break;
310              case PROXIED_AUTH:
311                disabledPrivileges.add(Privilege.PROXIED_AUTH);
312                break;
313              case SERVER_RESTART:
314                disabledPrivileges.add(Privilege.SERVER_RESTART);
315                break;
316              case SERVER_SHUTDOWN:
317                disabledPrivileges.add(Privilege.SERVER_SHUTDOWN);
318                break;
319              case UNINDEXED_SEARCH:
320                disabledPrivileges.add(Privilege.UNINDEXED_SEARCH);
321                break;
322              case UPDATE_SCHEMA:
323                disabledPrivileges.add(Privilege.UPDATE_SCHEMA);
324                break;
325            }
326          }
327        }
328        DirectoryServer.setDisabledPrivileges(disabledPrivileges);
329    
330        DirectoryServer.setReturnBindErrorMessages(
331             globalConfig.isReturnBindErrorMessages());
332    
333        DirectoryServer.setIdleTimeLimit(globalConfig.getIdleTimeLimit());
334    
335        DirectoryServer.setSaveConfigOnSuccessfulStartup(
336             globalConfig.isSaveConfigOnSuccessfulStartup());
337    
338        // If the workflow configuration mode has changed then reconfigure
339        // the workflows-only if the server is running. If the server is not
340        // running (ie. the server is starting up) simply update the workflow
341        // configuration mode as the workflow configuration is processed
342        // elsewhere.
343        WorkflowConfigurationMode oldMode =
344          DirectoryServer.getWorkflowConfigurationMode();
345        WorkflowConfigurationMode newMode =
346          globalConfig.getWorkflowConfigurationMode();
347        if (DirectoryServer.isRunning())
348        {
349          DirectoryServer.reconfigureWorkflows(oldMode, newMode);
350        }
351        else
352        {
353          DirectoryServer.setWorkflowConfigurationMode(newMode);
354        }
355    
356        DirectoryServer.setUseNanoTime(globalConfig.getEtimeResolution() ==
357          GlobalCfgDefn.EtimeResolution.NANOSECONDS);
358      }
359    
360    
361      /**
362       * {@inheritDoc}
363       */
364      public boolean isConfigurationChangeAcceptable(GlobalCfg configuration,
365                          List<Message> unacceptableReasons)
366      {
367        boolean configAcceptable = true;
368    
369        Set<String> smtpServers = configuration.getSMTPServer();
370        if (smtpServers != null)
371        {
372          for (String server : smtpServers)
373          {
374            int colonPos = server.indexOf(':');
375            if ((colonPos == 0) || (colonPos == (server.length()-1)))
376            {
377              Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
378              unacceptableReasons.add(message);
379              configAcceptable = false;
380            }
381            else if (colonPos > 0)
382            {
383              try
384              {
385                int port = Integer.parseInt(server.substring(colonPos+1));
386                if ((port < 1) || (port > 65535))
387                {
388                  Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
389                  unacceptableReasons.add(message);
390                  configAcceptable = false;
391                }
392              }
393              catch (Exception e)
394              {
395                Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
396                unacceptableReasons.add(message);
397                configAcceptable = false;
398              }
399            }
400          }
401        }
402    
403        return configAcceptable;
404      }
405    
406    
407    
408      /**
409       * {@inheritDoc}
410       */
411      public ConfigChangeResult applyConfigurationChange(GlobalCfg configuration)
412      {
413        ResultCode         resultCode          = ResultCode.SUCCESS;
414        boolean            adminActionRequired = false;
415        ArrayList<Message> messages            = new ArrayList<Message>();
416    
417        applyGlobalConfiguration(configuration);
418    
419        return new ConfigChangeResult(resultCode, adminActionRequired, messages);
420      }
421    }
422