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 */
020 package org.apache.directory.server.ldap.handlers;
021
022
023 import org.apache.directory.server.core.CoreSession;
024 import org.apache.directory.server.ldap.LdapSession;
025 import org.apache.directory.shared.ldap.message.InternalLdapResult;
026 import org.apache.directory.shared.ldap.message.InternalModifyDnRequest;
027 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
028 import org.apache.directory.shared.ldap.name.LdapDN;
029
030 import org.slf4j.Logger;
031 import org.slf4j.LoggerFactory;
032
033
034 /**
035 * A single reply handler for {@link InternalModifyDnRequest}s.
036 *
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 * @version $Rev: 664302 $
039 */
040 public class ModifyDnHandler extends LdapRequestHandler<InternalModifyDnRequest>
041 {
042 private static final Logger LOG = LoggerFactory.getLogger( ModifyDnHandler.class );
043
044
045 /**
046 * Deal with a ModifyDN request received from a client.
047 *
048 * A ModifyDN operation has more than one semantic, depending on its parameters.
049 *
050 * In any case, the first argument is the DN entry to be changed. We then
051 * have the new relative DN for this entry.
052 *
053 * Two other arguments can be provided :
054 * - deleteOldRdn : if the old RDN attributes should be removed from the
055 * new entry or not (for instance, if the old RDN was cn=acme, and the new
056 * one is sn=acme, then we may have to remove the cn: acme from the attributes
057 * list)
058 * - newSuperior : this is a move operation. The entry is removed from its
059 * current location, and created in the new one.
060 */
061 public void handle( LdapSession session, InternalModifyDnRequest req )
062 {
063 InternalLdapResult result = req.getResultResponse().getLdapResult();
064 LOG.debug( "Handling modify dn request while ignoring referrals: {}", req );
065
066 if ( req.getName().isEmpty() )
067 {
068 // it is not allowed to modify the name of the Root DSE
069 String msg = "Modify DN is not allowed on Root DSE.";
070 result.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
071 result.setErrorMessage( msg );
072 session.getIoSession().write( req.getResultResponse() );
073 return;
074 }
075
076 try
077 {
078 LdapDN newRdn = new LdapDN( req.getNewRdn().toString() );
079 newRdn.normalize( session.getCoreSession().getDirectoryService()
080 .getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
081
082 LdapDN oldRdn = new LdapDN( req.getName().getRdn().toString() );
083 oldRdn.normalize( session.getCoreSession().getDirectoryService()
084 .getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
085
086 boolean rdnChanged = req.getNewRdn() != null &&
087 ! newRdn.getNormName().equals( oldRdn.getNormName() );
088
089 CoreSession coreSession = session.getCoreSession();
090
091 if ( rdnChanged )
092 {
093 if ( req.getNewSuperior() != null )
094 {
095 coreSession.moveAndRename( req );
096 }
097 else
098 {
099 coreSession.rename( req );
100 }
101 }
102 else if ( req.getNewSuperior() != null )
103 {
104 req.setNewRdn( null );
105 coreSession.move( req );
106 }
107 else
108 {
109 result.setErrorMessage( "Attempt to move entry onto itself." );
110 result.setResultCode( ResultCodeEnum.ENTRY_ALREADY_EXISTS );
111 result.setMatchedDn( req.getName() );
112 session.getIoSession().write( req.getResultResponse() );
113 return;
114 }
115
116 result.setResultCode( ResultCodeEnum.SUCCESS );
117 session.getIoSession().write( req.getResultResponse() );
118 }
119 catch ( Exception e )
120 {
121 handleException( session, req, e );
122 }
123 }
124 }