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    import java.util.ArrayList;
031    import java.util.List;
032    
033    import org.opends.server.admin.server.ConfigurationChangeListener;
034    import org.opends.server.admin.std.server.PasswordPolicyCfg;
035    import org.opends.server.config.ConfigException;
036    import org.opends.server.types.ConfigChangeResult;
037    import org.opends.server.types.InitializationException;
038    import org.opends.server.types.ResultCode;
039    
040    import static org.opends.server.loggers.debug.DebugLogger.*;
041    import org.opends.server.loggers.debug.DebugTracer;
042    import org.opends.server.types.DebugLogLevel;
043    import static org.opends.messages.CoreMessages.*;
044    
045    
046    /**
047     This class is the interface between the password policy configurable component
048     and a password policy state object. When a password policy entry is added to
049     the configuration, an instance of this class is created and registered to
050     manage subsequent modification to that configuration entry, including
051     valiadating any proposed modification and applying an accepted modification.
052     */
053    public class PasswordPolicyConfig
054            implements ConfigurationChangeListener<PasswordPolicyCfg>
055    {
056      /**
057       * The tracer object for the debug logger.
058       */
059      private static final DebugTracer TRACER = getTracer();
060    
061    
062      /**
063       * The password policy object corresponding to the configuration entry. The
064       * policy referenced by this field is assumed to be valid, hence any
065       * changes resulting from a modification of the configuration entry must be
066       * applied to a newly allocated instance and validated before updating this
067       * reference to point to the new policy instance.
068       */
069      private PasswordPolicy currentPolicy;
070    
071    
072      /**
073       * Creates a new password policy configurable component to manage the provided
074       * password policy object.
075       *
076       * @param policy The password policy object this object will manage.
077       */
078      public PasswordPolicyConfig(PasswordPolicy policy)
079      {
080        this.currentPolicy = policy;
081      }
082    
083    
084      /**
085       * {@inheritDoc}
086       */
087      public boolean isConfigurationChangeAcceptable(
088          PasswordPolicyCfg configuration, List<Message> unacceptableReasons)
089      {
090        assert configuration.dn().equals(this.currentPolicy.getConfigEntryDN() )
091                : "Internal Error: mismatch between DN of configuration entry and"
092                  + "DN of current password policy." ;
093    
094        try
095        {
096          new PasswordPolicy(configuration);
097        }
098        catch (ConfigException ce)
099        {
100          if (debugEnabled())
101          {
102            TRACER.debugCaught(DebugLogLevel.ERROR, ce);
103          }
104    
105          unacceptableReasons.add(ce.getMessageObject());
106          return false;
107        }
108        catch (InitializationException ie)
109        {
110          if (debugEnabled())
111          {
112            TRACER.debugCaught(DebugLogLevel.ERROR, ie);
113          }
114    
115          unacceptableReasons.add(ie.getMessageObject());
116          return false;
117        }
118    
119        // If we made it here, then the configuration is acceptable.
120        return true;
121      }
122    
123    
124    
125      /**
126       * {@inheritDoc}
127       */
128      public ConfigChangeResult applyConfigurationChange(
129          PasswordPolicyCfg configuration)
130      {
131        assert configuration.dn().equals(this.currentPolicy.getConfigEntryDN() )
132                : "Internal Error: mismatch between DN of configuration entry and"
133                  + "DN of current password policy." ;
134    
135        PasswordPolicy p;
136    
137        try
138        {
139          p = new PasswordPolicy(configuration);
140        }
141        catch (ConfigException ce)
142        {
143          if (debugEnabled())
144          {
145            TRACER.debugCaught(DebugLogLevel.ERROR, ce);
146          }
147          ArrayList<Message> messages = new ArrayList<Message>();
148          messages.add(ce.getMessageObject());
149          return new ConfigChangeResult(
150                  DirectoryServer.getServerErrorResultCode(),
151                  /*adminActionRequired*/ true, messages);
152        }
153        catch (InitializationException ie)
154        {
155          if (debugEnabled())
156          {
157            TRACER.debugCaught(DebugLogLevel.ERROR, ie);
158          }
159          ArrayList<Message> messages = new ArrayList<Message>();
160          messages.add(ie.getMessageObject());
161          return new ConfigChangeResult(
162                  DirectoryServer.getServerErrorResultCode(),
163                  /*adminActionRequired*/ true, messages);
164        }
165    
166        // If we've made it here, then everything is acceptable.  Apply the new
167        // configuration.
168        ArrayList<Message> messages = new ArrayList<Message>();
169        messages.add(INFO_PWPOLICY_UPDATED_POLICY.get(
170                String.valueOf(p.getConfigEntryDN())));
171        this.currentPolicy = p;
172    
173        return new ConfigChangeResult(ResultCode.SUCCESS,
174                                      /*adminActionRequired*/ false, messages);
175      }
176    
177      /**
178       * Retrieves the PasswordPolicy object representing the configuration entry
179       * managed by this object.
180       *
181       * @return The PasswordPolicy object.
182       */
183      public PasswordPolicy getPolicy()
184      {
185        return currentPolicy;
186      }
187    }