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.core.jndi;
021    
022    
023    import javax.naming.Binding;
024    import javax.naming.NamingException;
025    import javax.naming.directory.SearchControls;
026    import javax.naming.event.NamespaceChangeListener;
027    import javax.naming.event.NamingEvent;
028    import javax.naming.event.NamingExceptionEvent;
029    import javax.naming.event.NamingListener;
030    import javax.naming.event.ObjectChangeListener;
031    
032    import org.apache.directory.server.core.entry.ServerEntryUtils;
033    import org.apache.directory.server.core.event.DirectoryListener;
034    import org.apache.directory.server.core.interceptor.context.AddOperationContext;
035    import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
036    import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
037    import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
038    import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
039    import org.apache.directory.server.core.interceptor.context.OperationContext;
040    import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
041    import org.apache.directory.server.i18n.I18n;
042    
043    import org.slf4j.Logger;
044    import org.slf4j.LoggerFactory;
045    
046    
047    /**
048     * A DirectoryListener implementation which adapts call back to methods 
049     * notifying of changes to the DIT into NamingEvents for use with the ApacheDS
050     * DirectoryService JNDI provider.
051     * 
052     * TODO for the time being bindings in NamingEvents generated are not relative 
053     * to the source context which they should be.
054     * 
055     * TODO presume correctly manipulated entry values in opContext.getEntry() 
056     * objects to function properly - at this point this is not handled in the
057     * Interceptors and needs to be added for this adapter to populate the event
058     * bindings.
059     * 
060     * TODO - Should we factor in the attributes to be returned in bindings? 
061     * Perhaps this should be privided as search controls along with the info
062     * we need to handle aliases, and referals?
063     *
064     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
065     * @version $Rev$, $Date$
066     */
067    public class EventListenerAdapter implements DirectoryListener
068    {
069        private static final Logger LOG = LoggerFactory.getLogger( EventListenerAdapter.class );
070        private final NamingListener listener;
071        private final ServerLdapContext source;
072        
073        /** 
074         * TODO not utilized but should be to effect returns in bindings, alias 
075         * and referral handling
076         */
077        private final SearchControls controls;
078    
079        
080        public EventListenerAdapter( ServerLdapContext source, NamingListener listener )
081        {
082            this( source, listener, new SearchControls() );
083        }
084        
085        
086        public EventListenerAdapter( ServerLdapContext source, NamingListener listener, SearchControls controls )
087        {
088            this.source = source;
089            this.controls = controls;
090            this.listener = listener;
091        }
092        
093        
094        private void deliverNamingExceptionEvent( Exception e, OperationContext opContext )
095        {
096            LOG.error( I18n.err( I18n.ERR_118 ), e );
097            NamingExceptionEvent evt = null;
098            
099            if ( e instanceof NamingException )
100            {
101                evt = new NamingExceptionEvent( source, ( NamingException ) e );
102            }
103            else
104            {
105                NamingException ne = new NamingException( I18n.err( I18n.ERR_119 ) );
106                ne.setRootCause( e );
107                evt = new NamingExceptionEvent( source, ne );
108            }
109            
110            listener.namingExceptionThrown( evt );
111        }
112        
113    
114        /* (non-Javadoc)
115         * @see org.apache.directory.server.core.event.DirectoryListener#entryAdded(org.apache.directory.server.core.interceptor.context.AddOperationContext)
116         */
117        public void entryAdded( AddOperationContext opContext )
118        {
119            try
120            {
121                Binding binding = new Binding( opContext.getDn().getName(), 
122                    ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
123                NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_ADDED, 
124                    binding, null, opContext );
125    
126                if ( listener instanceof NamespaceChangeListener )
127                {
128                    ( ( NamespaceChangeListener ) listener ).objectAdded( evt );
129                }
130            }
131            catch ( Exception e )
132            {
133                deliverNamingExceptionEvent( e, opContext );
134            }
135        }
136    
137    
138        /* (non-Javadoc)
139         * @see org.apache.directory.server.core.event.DirectoryListener#entryDeleted(org.apache.directory.server.core.interceptor.context.DeleteOperationContext)
140         */
141        public void entryDeleted( DeleteOperationContext opContext )
142        {
143            try
144            {
145                if ( listener instanceof NamespaceChangeListener )
146                {
147                    Binding binding = new Binding( opContext.getDn().getName(), 
148                        ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
149                    NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_REMOVED, null, 
150                        binding, opContext );
151                    ( ( NamespaceChangeListener ) listener ).objectAdded( evt );
152                }
153            }
154            catch ( Exception e )
155            {
156                deliverNamingExceptionEvent( e, opContext );
157            }
158        }
159    
160    
161        /* (non-Javadoc)
162         * @see org.apache.directory.server.core.event.DirectoryListener#entryModified(org.apache.directory.server.core.interceptor.context.ModifyOperationContext)
163         */
164        public void entryModified( ModifyOperationContext opContext )
165        {
166            try
167            {
168                Binding newBinding = new Binding( opContext.getDn().getName(), 
169                    ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
170                Binding oldBinding = new Binding( opContext.getDn().getName(), 
171                    ServerEntryUtils.toBasicAttributes( opContext.getEntry().getOriginalEntry() ),  false );
172                NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_CHANGED, 
173                    newBinding, oldBinding, opContext );
174    
175                if ( listener instanceof ObjectChangeListener )
176                {
177                    ( ( ObjectChangeListener ) listener ).objectChanged( evt );
178                }
179            }
180            catch ( Exception e )
181            {
182                deliverNamingExceptionEvent( e, opContext );
183            }
184        }
185    
186    
187        /* (non-Javadoc)
188         * @see org.apache.directory.server.core.event.DirectoryListener#entryMoved(org.apache.directory.server.core.interceptor.context.MoveOperationContext)
189         */
190        public void entryMoved( MoveOperationContext opContext )
191        {
192            try
193            {
194                if ( listener instanceof NamespaceChangeListener )
195                {
196                    Binding newBinding = new Binding( opContext.getDn().getName(), 
197                        ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
198                    Binding oldBinding = new Binding( opContext.getDn().getName(), 
199                        ServerEntryUtils.toBasicAttributes( opContext.getEntry().getOriginalEntry() ), false );
200                    NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_RENAMED, 
201                        newBinding, oldBinding, opContext );
202                    ( ( NamespaceChangeListener ) listener ).objectRenamed( evt );
203                }
204            }
205            catch ( Exception e )
206            {
207                deliverNamingExceptionEvent( e, opContext );
208            }
209        }
210    
211    
212        /* (non-Javadoc)
213         * @see org.apache.directory.server.core.event.DirectoryListener#entryMovedAndRenamed(org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext)
214         */
215        public void entryMovedAndRenamed( MoveAndRenameOperationContext opContext )
216        {
217            try
218            {
219                if ( listener instanceof NamespaceChangeListener )
220                {
221                    Binding newBinding = new Binding( opContext.getDn().getName(), 
222                        ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
223                    Binding oldBinding = new Binding( opContext.getDn().getName(), 
224                        ServerEntryUtils.toBasicAttributes( opContext.getEntry().getOriginalEntry() ), false );
225                    NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_RENAMED, 
226                        newBinding, oldBinding, opContext );
227                    ( ( NamespaceChangeListener ) listener ).objectRenamed( evt );
228                }
229            }
230            catch ( Exception e )
231            {
232                deliverNamingExceptionEvent( e, opContext );
233            }
234        }
235    
236    
237        /* (non-Javadoc)
238         * @see org.apache.directory.server.core.event.DirectoryListener#entryRenamed(org.apache.directory.server.core.interceptor.context.RenameOperationContext)
239         */
240        public void entryRenamed( RenameOperationContext opContext )
241        {
242            try
243            {
244                if ( listener instanceof NamespaceChangeListener )
245                {
246                    Binding newBinding = new Binding( opContext.getDn().getName(), 
247                        ServerEntryUtils.toBasicAttributes( opContext.getEntry() ), false );
248                    Binding oldBinding = new Binding( opContext.getDn().getName(), 
249                        ServerEntryUtils.toBasicAttributes( opContext.getEntry().getOriginalEntry() ), false );
250                    NamingEvent evt = new NamingEvent( source, NamingEvent.OBJECT_RENAMED, 
251                        newBinding, oldBinding, null );
252                    ( ( NamespaceChangeListener ) listener ).objectRenamed( evt );
253                }
254            }
255            catch ( Exception e )
256            {
257                deliverNamingExceptionEvent( e, opContext );
258            }
259        }
260    }