001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.server.ldap.handlers.request;
021
022
023import org.apache.directory.api.ldap.model.message.LdapResult;
024import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
025import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
026import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
027import org.apache.directory.api.ldap.model.name.Dn;
028import org.apache.directory.api.ldap.model.schema.SchemaManager;
029import org.apache.directory.server.core.api.CoreSession;
030import org.apache.directory.server.ldap.LdapSession;
031import org.apache.directory.server.ldap.handlers.LdapRequestHandler;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035
036/**
037 * A single reply MessageReceived handler for {@link org.apache.directory.api.ldap.model.message.ModifyDnRequest}s.
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 */
041public class ModifyDnRequestHandler extends LdapRequestHandler<ModifyDnRequest>
042{
043    private static final Logger LOG = LoggerFactory.getLogger( ModifyDnRequestHandler.class );
044
045
046    /**
047     * Deal with a ModifyDN request received from a client.
048     *
049     * A ModifyDN operation has more than one semantic, depending on its parameters.
050     *
051     * In any case, the first argument is the Dn entry to be changed. We then
052     * have the new relative Dn for this entry.
053     *
054     * Two other arguments can be provided :
055     * - deleteOldRdn : if the old Rdn attributes should be removed from the
056     * new entry or not (for instance, if the old Rdn was cn=acme, and the new
057     * one is sn=acme, then we may have to remove the cn: acme from the attributes
058     * list)
059     * - newSuperior : this is a move operation. The entry is removed from its
060     * current location, and created in the new one.
061     */
062    public void handle( LdapSession session, ModifyDnRequest modifyDnRequest )
063    {
064        ModifyDnResponse modifyDnResponse = ( ModifyDnResponse ) modifyDnRequest.getResultResponse(); 
065        LdapResult result = modifyDnResponse.getLdapResult();
066        LOG.debug( "Handling modify dn request while ignoring referrals: {}", modifyDnRequest );
067
068        if ( modifyDnRequest.getName().isEmpty() )
069        {
070            // it is not allowed to modify the name of the Root DSE
071            String msg = "Modify Dn is not allowed on Root DSE.";
072            result.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
073            result.setDiagnosticMessage( msg );
074            session.getIoSession().write( modifyDnResponse );
075            return;
076        }
077
078        try
079        {
080            SchemaManager schemaManager = session.getCoreSession().getDirectoryService().getSchemaManager();
081            Dn newRdn = new Dn( schemaManager, modifyDnRequest.getNewRdn().getName() );
082
083            Dn oldRdn = new Dn( schemaManager, modifyDnRequest.getName().getRdn().getName() );
084
085            boolean rdnChanged = modifyDnRequest.getNewRdn() != null && !newRdn.equals( oldRdn );
086
087            CoreSession coreSession = session.getCoreSession();
088
089            if ( rdnChanged )
090            {
091                if ( modifyDnRequest.getNewSuperior() != null )
092                {
093                    coreSession.moveAndRename( modifyDnRequest );
094                }
095                else
096                {
097                    coreSession.rename( modifyDnRequest );
098                }
099            }
100            else if ( modifyDnRequest.getNewSuperior() != null )
101            {
102                modifyDnRequest.setNewRdn( null );
103                coreSession.move( modifyDnRequest );
104            }
105            else
106            {
107                result.setDiagnosticMessage( "Attempt to move entry onto itself." );
108                result.setResultCode( ResultCodeEnum.ENTRY_ALREADY_EXISTS );
109                result.setMatchedDn( modifyDnRequest.getName() );
110                session.getIoSession().write( modifyDnResponse );
111                
112                return;
113            }
114
115            result.setResultCode( ResultCodeEnum.SUCCESS );
116            session.getIoSession().write( modifyDnResponse );
117        }
118        catch ( Exception e )
119        {
120            handleException( session, modifyDnRequest, modifyDnResponse, e );
121        }
122    }
123}