harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From telli...@apache.org
Subject svn commit: r598209 - in /harmony/enhanced/classlib/trunk/modules/jndi/src: main/java/org/apache/harmony/jndi/provider/ldap/ main/java/org/apache/harmony/jndi/provider/ldap/event/ test/java/org/apache/harmony/jndi/provider/ldap/
Date Mon, 26 Nov 2007 10:23:40 GMT
Author: tellison
Date: Mon Nov 26 02:23:37 2007
New Revision: 598209

URL: http://svn.apache.org/viewvc?rev=598209&view=rev
Log:
Apply patch HARMONY-5185 ([classlib][jndi][ldap] LdapContextImpl implements EventDirContext
intferface)

Added:
    harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java
  (with props)
Modified:
    harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapClient.java
    harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapContextImpl.java
    harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapSearchResult.java
    harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/LdapContextImplTest.java
    harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/MockLdapClient.java

Modified: harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapClient.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapClient.java?rev=598209&r1=598208&r2=598209&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapClient.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapClient.java
Mon Nov 26 02:23:37 2007
@@ -22,7 +22,9 @@
 import java.io.OutputStream;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 
 import javax.naming.CommunicationException;
 import javax.naming.ConfigurationException;
@@ -34,9 +36,13 @@
 import javax.net.ssl.SSLSocketFactory;
 
 import org.apache.harmony.jndi.internal.nls.Messages;
+import org.apache.harmony.jndi.provider.ldap.LdapContextImpl.UnsolicitedListener;
 import org.apache.harmony.jndi.provider.ldap.asn1.ASN1Decodable;
 import org.apache.harmony.jndi.provider.ldap.asn1.ASN1Encodable;
 import org.apache.harmony.jndi.provider.ldap.asn1.LdapASN1Constant;
+import org.apache.harmony.jndi.provider.ldap.event.ECNotificationControl;
+import org.apache.harmony.jndi.provider.ldap.event.PersistentSearchControl;
+import org.apache.harmony.jndi.provider.ldap.event.PersistentSearchResult;
 import org.apache.harmony.security.asn1.ASN1Integer;
 
 /**
@@ -84,6 +90,11 @@
      */
     private Dispatcher dispatcher;
 
+    /**
+     * registered UnsolicitedListener
+     */
+    private List<UnsolicitedListener> unls = new ArrayList<UnsolicitedListener>();
+
     // constructor for test
     public LdapClient() {
         // do nothing
@@ -163,8 +174,7 @@
 
                             // Unsolicited Notification
                             if (messageId == 0) {
-                                // TODO return instance of
-                                // UnsolicitedNotificationImpl
+                                return new UnsolicitedNotificationImpl();
                             }
 
                             // get response operation according messageId
@@ -211,7 +221,7 @@
         private void processResponse(LdapMessage response, Exception ex) {
             // unsolicited notification
             if (response.getMessageId() == 0) {
-                // TODO notify unsolicited listeners
+                notifyUnls(response);
                 return;
             }
 
@@ -224,7 +234,7 @@
                 // persistent search response
                 if (element.lock == null) {
 
-                    // TODO notify persistent search listeners
+                    notifyPersistenSearchListener(element);
 
                 } else {
                     /*
@@ -260,6 +270,14 @@
         } // end of processResponse
     } // Dispatcher
 
+    private void notifyUnls(LdapMessage response) {
+        UnsolicitedNotificationImpl un = (UnsolicitedNotificationImpl) response
+                .getResponseOp();
+        for (UnsolicitedListener listener : unls) {
+            listener.receiveNotification(un, response.getControls());
+        }
+    }
+
     /**
      * Carry out the ldap operation encapsulated in operation with controls.
      * 
@@ -410,6 +428,34 @@
         out.flush();
     }
 
+    public int addPersistentSearch(SearchOp op) throws IOException {
+        LdapMessage request = new LdapMessage(
+                LdapASN1Constant.OP_SEARCH_REQUEST, op.getRequest(),
+                new Control[] { new PersistentSearchControl() });
+
+        Integer messageID = Integer.valueOf(request.getMessageId());
+
+        // set lock to null, indicate this is persistent search
+        requests.put(messageID, new Element(null, new LdapMessage(op
+                .getResponse())));
+        try {
+            out.write(request.encode());
+            out.flush();
+            return request.getMessageId();
+        } catch (IOException e) {
+            // send request faild, remove request from list
+            requests.remove(messageID);
+            throw e;
+        }
+
+    }
+
+    public void removePersistentSearch(int messageId, Control[] controls)
+            throws IOException {
+        requests.remove(Integer.valueOf(messageId));
+        abandon(messageId, controls);
+    }
+
     /**
      * Close network connection, stop dispather thread, and release all other
      * resources
@@ -639,4 +685,36 @@
         this.dispatcher = new Dispatcher();
         this.dispatcher.start();
     }
+
+    public void addUnsolicitedListener(UnsolicitedListener listener) {
+        if (unls == null) {
+            unls = new ArrayList<UnsolicitedListener>();
+        }
+
+        if (!unls.contains(listener)) {
+            unls.add(listener);
+        }
+    }
+
+    private void notifyPersistenSearchListener(Element element) {
+        PersistentSearchResult psr = (PersistentSearchResult) ((SearchOp) element.response
+                .getResponseOp()).getSearchResult();
+        // test error
+        if (psr.getResult() != null) {
+            psr.receiveNotificationHook(psr.getResult());
+        }
+
+        // notify listener
+        Control[] cs = element.response.getControls();
+        if (cs != null) {
+            for (int i = 0; i < cs.length; i++) {
+                Control control = cs[i];
+                if (ECNotificationControl.OID.equals(control.getID())) {
+                    psr.receiveNotificationHook(new ECNotificationControl(
+                            control.getEncodedValue()));
+                }
+            }
+        }
+    }
+
 }

Modified: harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapContextImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapContextImpl.java?rev=598209&r1=598208&r2=598209&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapContextImpl.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapContextImpl.java
Mon Nov 26 02:23:37 2007
@@ -19,6 +19,8 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -51,6 +53,13 @@
 import javax.naming.directory.ModificationItem;
 import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
+import javax.naming.event.EventContext;
+import javax.naming.event.EventDirContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.NamingListener;
+import javax.naming.event.ObjectChangeListener;
 import javax.naming.ldap.Control;
 import javax.naming.ldap.ControlFactory;
 import javax.naming.ldap.ExtendedRequest;
@@ -59,6 +68,8 @@
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.ManageReferralControl;
 import javax.naming.ldap.Rdn;
+import javax.naming.ldap.UnsolicitedNotificationEvent;
+import javax.naming.ldap.UnsolicitedNotificationListener;
 import javax.naming.spi.DirectoryManager;
 import javax.naming.spi.NamingManager;
 
@@ -66,6 +77,8 @@
 import org.apache.harmony.jndi.internal.parser.AttributeTypeAndValuePair;
 import org.apache.harmony.jndi.internal.parser.LdapNameParser;
 import org.apache.harmony.jndi.provider.ldap.asn1.Utils;
+import org.apache.harmony.jndi.provider.ldap.event.ECNotificationControl;
+import org.apache.harmony.jndi.provider.ldap.event.PersistentSearchResult;
 import org.apache.harmony.jndi.provider.ldap.parser.FilterParser;
 import org.apache.harmony.jndi.provider.ldap.parser.ParseException;
 import org.apache.harmony.jndi.provider.ldap.sasl.SaslBind;
@@ -74,7 +87,7 @@
  * This context implements LdapContext, it's main entry point of all JNDI ldap
  * operations.
  */
-public class LdapContextImpl implements LdapContext {
+public class LdapContextImpl implements LdapContext, EventDirContext {
 
     /**
      * ldap connection
@@ -107,6 +120,10 @@
      */
     private Control[] connCtls;
 
+    private HashMap<NamingListener, List<Integer>> listeners;
+
+    private List<UnsolicitedNotificationListener> unls;
+
     private static final Control NON_CRITICAL_MANAGE_REF_CONTROL = new ManageReferralControl(
             Control.NONCRITICAL);
 
@@ -1626,5 +1643,365 @@
             // jndi.2E=The name is null
             throw new NullPointerException(Messages.getString("jndi.2E")); //$NON-NLS-1$
         }
+    }
+
+    @Override
+    protected void finalize() {
+        try {
+            close();
+        } catch (NamingException e) {
+            // ignore
+        }
+    }
+
+    public void addNamingListener(Name name, String filter,
+            Object[] filterArgs, SearchControls searchControls,
+            NamingListener namingListener) throws NamingException {
+        checkName(name);
+
+        if (namingListener == null) {
+            return;
+        }
+
+        if (!(name instanceof LdapName)) {
+            if (name instanceof CompositeName && name.size() == 1) {
+                name = name.getPrefix(1);
+            } else {
+                // FIXME: read message from file
+                throw new InvalidNameException(
+                        "Target cannot span multiple namespaces: "
+                                + name.toString());
+            }
+        }
+
+        if (namingListener instanceof UnsolicitedNotificationListener) {
+            if (unls == null) {
+                unls = new ArrayList<UnsolicitedNotificationListener>();
+                addUnsolicitedListener();
+            }
+
+            unls.add((UnsolicitedNotificationListener) namingListener);
+
+            if (!(namingListener instanceof NamespaceChangeListener)
+                    && !(namingListener instanceof ObjectChangeListener)) {
+                return;
+            }
+        }
+
+        if (filter == null) {
+            throw new NullPointerException(Messages.getString("ldap.28")); //$NON-NLS-1$
+        }
+
+        if (filterArgs == null) {
+            filterArgs = new Object[0];
+        }
+
+        if (searchControls == null) {
+            searchControls = new SearchControls();
+        }
+
+        FilterParser filterParser = new FilterParser(filter);
+        filterParser.setArgs(filterArgs);
+        Filter f = null;
+        try {
+            f = filterParser.parse();
+        } catch (ParseException e) {
+            InvalidSearchFilterException ex = new InvalidSearchFilterException(
+                    Messages.getString("ldap.29")); //$NON-NLS-1$
+            ex.setRootCause(e);
+            throw ex;
+        }
+
+        String targetDN = getTargetDN(name, contextDn);
+
+        Name tempName = new LdapName(contextDn.toString());
+        tempName.addAll(name);
+        String baseDN = tempName.toString();
+
+        int messageId = doPersistentSearch(targetDN, baseDN, f, searchControls,
+                namingListener);
+
+        if (listeners == null) {
+            listeners = new HashMap<NamingListener, List<Integer>>();
+        }
+
+        List<Integer> idList = listeners.get(namingListener);
+        if (idList == null) {
+            idList = new ArrayList<Integer>();
+        }
+
+        idList.add(Integer.valueOf(messageId));
+    }
+
+    public void addNamingListener(Name name, String filter,
+            SearchControls searchControls, NamingListener namingListener)
+            throws NamingException {
+        addNamingListener(name, filter, new Object[0], searchControls,
+                namingListener);
+    }
+
+    public void addNamingListener(String name, String filter,
+            Object[] filterArgs, SearchControls searchControls,
+            NamingListener namingListener) throws NamingException {
+        addNamingListener(convertFromStringToName(name), filter, filterArgs,
+                searchControls, namingListener);
+    }
+
+    public void addNamingListener(String name, String filter,
+            SearchControls searchControls, NamingListener namingListener)
+            throws NamingException {
+        addNamingListener(convertFromStringToName(name), filter,
+                searchControls, namingListener);
+    }
+
+    public static interface UnsolicitedListener {
+        public void receiveNotification(UnsolicitedNotificationImpl un,
+                Control[] cs);
+    }
+
+    public void addNamingListener(Name name, int scope,
+            NamingListener namingListener) throws NamingException {
+        checkName(name);
+
+        if (namingListener == null) {
+            return;
+        }
+
+        // only ldap name is supportted
+        if (!(name instanceof LdapName)) {
+            if (name instanceof CompositeName && name.size() == 1) {
+                name = name.getPrefix(0);
+            } else {
+                // ldap.32=Target cannot span multiple namespaces: {0}
+                throw new InvalidNameException(Messages.getString("ldap.32", //$NON-NLS-1$
+                        new Object[] { name.toString() }));
+            }
+        }
+
+        if (namingListener instanceof UnsolicitedNotificationListener) {
+            if (unls == null) {
+                unls = new ArrayList<UnsolicitedNotificationListener>();
+                addUnsolicitedListener();
+            }
+
+            unls.add((UnsolicitedNotificationListener) namingListener);
+
+            if (!(namingListener instanceof NamespaceChangeListener)
+                    && !(namingListener instanceof ObjectChangeListener)) {
+                return;
+            }
+        }
+
+        // ri is silent in this case
+        if (scope != EventContext.OBJECT_SCOPE
+                && scope != EventContext.ONELEVEL_SCOPE
+                && scope != EventContext.SUBTREE_SCOPE) {
+            // ldap.33=Scope should be one of 'OBJECT_SCOPE', 'ONELEVEL_SCOPE'
+            // or 'SUBTREE_SCOPE'
+            throw new IllegalArgumentException(Messages.getString("ldap.33")); //$NON-NLS-1$
+        }
+
+        String targetDN = getTargetDN(name, contextDn);
+
+        Filter filter = new Filter(Filter.PRESENT_FILTER);
+        filter.setValue("objectClass");
+
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope(scope);
+
+        Name tempName = new LdapName(contextDn.toString());
+        tempName.addAll(name);
+        String baseDN = tempName.toString();
+
+        int messageId = doPersistentSearch(targetDN, baseDN, filter, controls,
+                namingListener);
+
+        if (listeners == null) {
+            listeners = new HashMap<NamingListener, List<Integer>>();
+        }
+
+        List<Integer> idList = listeners.get(namingListener);
+        if (idList == null) {
+            idList = new ArrayList<Integer>();
+            listeners.put(namingListener, idList);
+        }
+
+        idList.add(Integer.valueOf(messageId));
+
+    }
+
+    private void addUnsolicitedListener() {
+        client.addUnsolicitedListener(new UnsolicitedListener() {
+
+            public void receiveNotification(UnsolicitedNotificationImpl un,
+                    Control[] cs) {
+                EventObject event = null;
+                try {
+                    un.setControls(narrowingControls(cs));
+                    event = new UnsolicitedNotificationEvent(this, un);
+                } catch (NamingException e) {
+                    event = new NamingExceptionEvent(LdapContextImpl.this, e);
+                }
+
+                for (UnsolicitedNotificationListener listener : unls) {
+                    notifyNamingListener(listener, event);
+                }
+
+            }
+
+        });
+    }
+
+    private int doPersistentSearch(String targetDN, final String baseDN,
+            Filter filter, SearchControls controls,
+            NamingListener namingListener) throws CommunicationException {
+
+        SearchOp op = new SearchOp(targetDN, controls, filter);
+
+        final NamingListener listener = namingListener;
+        op.setSearchResult(new PersistentSearchResult() {
+
+            @Override
+            public void receiveNotificationHook(Object obj) {
+                EventObject event = null;
+                // construct event
+                if (obj instanceof ECNotificationControl) {
+                    ECNotificationControl control = (ECNotificationControl) obj;
+                    event = constructNamingEvent(this, control, baseDN);
+                }
+
+                if (obj instanceof LdapResult) {
+                    LdapResult ldapResult = (LdapResult) obj;
+                    NamingException ex = LdapUtils
+                            .getExceptionFromResult(ldapResult);
+                    // may not happen
+                    if (ex == null) {
+                        return;
+                    }
+
+                    event = new NamingExceptionEvent(LdapContextImpl.this, ex);
+                }
+
+                // notify listener
+                notifyNamingListener(listener, event);
+            }
+
+        });
+
+        try {
+            return client.addPersistentSearch(op);
+        } catch (IOException e) {
+            CommunicationException ex = new CommunicationException();
+            ex.setRootCause(e);
+            throw ex;
+        }
+    }
+
+    private void notifyNamingListener(final NamingListener listener,
+            final EventObject event) {
+        /*
+         * start new thread to notify listener, so user code may not affect
+         * dispatcher thread
+         */
+        Thread thread = new Thread(new Runnable() {
+
+            public void run() {
+                if (event instanceof NamingEvent) {
+                    NamingEvent namingEvent = (NamingEvent) event;
+                    namingEvent.dispatch(listener);
+                } else if (event instanceof NamingExceptionEvent) {
+                    NamingExceptionEvent exceptionEvent = (NamingExceptionEvent) event;
+                    listener.namingExceptionThrown(exceptionEvent);
+                } else if (event instanceof UnsolicitedNotificationEvent) {
+                    UnsolicitedNotificationEvent namingEvent = (UnsolicitedNotificationEvent)
event;
+                    namingEvent
+                            .dispatch((UnsolicitedNotificationListener) listener);
+                }
+
+            }
+
+        });
+
+        thread.start();
+    }
+
+    public void addNamingListener(String s, int i, NamingListener namingListener)
+            throws NamingException {
+        addNamingListener(convertFromStringToName(s), i, namingListener);
+    }
+
+    public void removeNamingListener(NamingListener namingListener)
+            throws NamingException {
+        if (listeners == null || !listeners.containsKey(namingListener)) {
+            return;
+        }
+
+        if (namingListener instanceof UnsolicitedNotificationListener) {
+            unls.remove(namingListener);
+        }
+
+        List<Integer> idList = listeners.remove(namingListener);
+        if (idList == null) {
+            return;
+        }
+
+        try {
+            for (Integer id : idList) {
+                client.removePersistentSearch(id.intValue(), requestControls);
+            }
+        } catch (IOException e) {
+            CommunicationException ex = new CommunicationException();
+            ex.setRootCause(e);
+        }
+    }
+
+    public boolean targetMustExist() throws NamingException {
+        // FIXME
+        return false;
+    }
+
+    private NamingEvent constructNamingEvent(PersistentSearchResult result,
+            ECNotificationControl control, String baseDN) {
+        Binding newBinding = null;
+        Binding oldBinding = null;
+
+        switch (control.getChangeType()) {
+        case ECNotificationControl.ADD:
+            String newName = convertToRelativeName(result.getDn(), baseDN);
+            newBinding = new Binding(newName, null);
+            newBinding.setNameInNamespace(result.getDn());
+            break;
+        case ECNotificationControl.DELETE:
+            String deleteName = convertToRelativeName(result.getDn(), baseDN);
+            oldBinding = new Binding(deleteName, null);
+            oldBinding.setNameInNamespace(result.getDn());
+            break;
+        case ECNotificationControl.MODIFY_DN:
+            if (result.getDn() != null) {
+                newBinding = new Binding(convertToRelativeName(result.getDn(),
+                        baseDN), null);
+                newBinding.setNameInNamespace(result.getDn());
+            }
+
+            if (control.getPreviousDN() != null) {
+                oldBinding = new Binding(convertToRelativeName(control
+                        .getPreviousDN(), baseDN), null);
+                oldBinding.setNameInNamespace(control.getPreviousDN());
+            }
+            break;
+        case ECNotificationControl.MODIFY:
+            String relativeName = convertToRelativeName(result.getDn(), baseDN);
+            newBinding = new Binding(relativeName, null);
+            newBinding.setNameInNamespace(result.getDn());
+            // FIXME: how to get old binding?
+            oldBinding = new Binding(relativeName, null);
+            oldBinding.setNameInNamespace(result.getDn());
+        }
+
+        NamingEvent event = new NamingEvent(this, control.getJNDIChangeType(),
+                newBinding, oldBinding, Integer.valueOf(control
+                        .getChangeNumber()));
+
+        return event;
     }
 }

Modified: harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapSearchResult.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapSearchResult.java?rev=598209&r1=598208&r2=598209&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapSearchResult.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/LdapSearchResult.java
Mon Nov 26 02:23:37 2007
@@ -63,19 +63,19 @@
         }
     }
 
-    private void decodeDone(Object value) {
+    protected void decodeDone(Object value) {
         result = new LdapResult();
         result.decodeValues((Object[]) value);
     }
 
-    private void decodeRef(Object value) {
+    protected void decodeRef(Object value) {
         Collection<byte[]> list = (Collection<byte[]>) value;
         for (byte[] bs : list) {
             refURLs.add(Utils.getString(bs));
         }
     }
 
-    private void decodeEntry(Object value) {
+    protected void decodeEntry(Object value) {
         Object[] values = (Object[]) value;
         String name = Utils.getString((byte[]) values[0]);
 

Added: harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java?rev=598209&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java
(added)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java
Mon Nov 26 02:23:37 2007
@@ -0,0 +1,65 @@
+/* 
+ *  Licensed to the Apache Software Foundation (ASF) under one or more 
+ *  contributor license agreements.  See the NOTICE file distributed with 
+ *  this work for additional information regarding copyright ownership. 
+ *  The ASF licenses this file to You under the Apache License, Version 2.0 
+ *  (the "License"); you may not use this file except in compliance with 
+ *  the License.  You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License. 
+ */
+
+package org.apache.harmony.jndi.provider.ldap.event;
+
+import org.apache.harmony.jndi.provider.ldap.LdapSearchResult;
+import org.apache.harmony.jndi.provider.ldap.asn1.Utils;
+
+/**
+ * Search result for persisten search.
+ */
+abstract public class PersistentSearchResult extends LdapSearchResult {
+
+    private String dn;
+
+    @Override
+    protected void decodeRef(Object value) {
+        /*
+         * TODO test ri behavior, how to deal with referrals in persistent
+         * search or maybe referral would be never received
+         */
+    }
+
+    @Override
+    protected void decodeEntry(Object value) {
+        Object[] values = (Object[]) value;
+        dn = Utils.getString((byte[]) values[0]);
+        // TODO is attributes useful for persistent search?
+    }
+
+    /**
+     * This is a callback method which would be invoked when ldap client receive
+     * notifaction from server.
+     * 
+     * @param object
+     *            Received notification from server, one of
+     *            <code>ECNotificationControl</code> or
+     *            <code>LdapResult</code>
+     */
+    abstract public void receiveNotificationHook(Object object);
+
+    /**
+     * Get DN of changed entry
+     * 
+     * @return DN of changed entry
+     */
+    public String getDn() {
+        return dn;
+    }
+
+}

Propchange: harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/ldap/event/PersistentSearchResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/LdapContextImplTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/LdapContextImplTest.java?rev=598209&r1=598208&r2=598209&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/LdapContextImplTest.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/LdapContextImplTest.java
Mon Nov 26 02:23:37 2007
@@ -34,6 +34,11 @@
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InvalidSearchFilterException;
 import javax.naming.directory.SearchControls;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.NamingListener;
 import javax.naming.ldap.BasicControl;
 import javax.naming.ldap.Control;
 import javax.naming.ldap.LdapName;
@@ -41,6 +46,7 @@
 import junit.framework.TestCase;
 
 import org.apache.harmony.jndi.internal.parser.AttributeTypeAndValuePair;
+import org.apache.harmony.jndi.provider.ldap.event.PersistentSearchResult;
 
 public class LdapContextImplTest extends TestCase {
     private LdapContextImpl context;
@@ -543,5 +549,156 @@
         assertEquals("ignore", preValue);
         returnedEnv = (Hashtable<Object, Object>) context.getEnvironment();
         assertFalse(returnedEnv.containsKey(Context.REFERRAL));
+    }
+
+    public void test_addNamingListener() throws Exception {
+        MockLdapClient client = new MockLdapClient();
+        Hashtable<Object, Object> env = new Hashtable<Object, Object>();
+
+        context = new LdapContextImpl(client, env, "cn=test");
+
+        context.addNamingListener("", EventContext.OBJECT_SCOPE,
+                new TestNamingListener());
+
+        SearchOp op = (SearchOp) client.getRequest();
+        assertEquals("cn=test", op.getBaseObject());
+        SearchControls controls = op.getControls();
+        assertEquals(SearchControls.OBJECT_SCOPE, controls.getSearchScope());
+        assertEquals(0, controls.getCountLimit());
+        assertEquals(false, controls.getDerefLinkFlag());
+        assertEquals(false, controls.getReturningObjFlag());
+        assertEquals(null, controls.getReturningAttributes());
+
+        Filter filter = op.getFilter();
+        assertEquals(Filter.PRESENT_FILTER, filter.getType());
+        assertEquals("objectClass", filter.getValue());
+        assertTrue(op.getSearchResult() instanceof PersistentSearchResult);
+
+        try {
+            context.addNamingListener("cn=addlistener/use/bin",
+                    EventContext.OBJECT_SCOPE, new TestNamingListener());
+            fail("Should throw InvalidNameException");
+        } catch (InvalidNameException e) {
+            // expected
+        }
+
+        client = new MockLdapClient();
+        context = new LdapContextImpl(client, env, "cn=test");
+        // listener is null, do nothing
+        context.addNamingListener("", EventContext.OBJECT_SCOPE, null);
+        assertFalse(client.getRequest() instanceof SearchOp);
+
+        try {
+            context.addNamingListener("", 100, new TestNamingListener());
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_addNamingListener_with_filter() throws Exception {
+        MockLdapClient client = new MockLdapClient();
+        Hashtable<Object, Object> env = new Hashtable<Object, Object>();
+
+        context = new LdapContextImpl(client, env, "cn=test");
+
+        SearchControls controls = new SearchControls();
+        controls.setCountLimit(100);
+        controls.setDerefLinkFlag(true);
+        controls.setReturningObjFlag(true);
+        controls.setTimeLimit(5);
+        context.addNamingListener("test=addlistener", "(objectClass=*)",
+                controls, new TestNamingListener());
+
+        SearchOp op = (SearchOp) client.getRequest();
+        assertEquals("test=addlistener,cn=test", op.getBaseObject());
+        Filter filter = op.getFilter();
+        assertEquals(Filter.PRESENT_FILTER, filter.getType());
+        assertEquals("objectClass", filter.getValue());
+        assertEquals(controls.getCountLimit(), op.getControls().getCountLimit());
+        assertEquals(controls.getDerefLinkFlag(), op.getControls()
+                .getDerefLinkFlag());
+        assertEquals(controls.getReturningObjFlag(), op.getControls()
+                .getReturningObjFlag());
+        assertEquals(controls.getSearchScope(), op.getControls()
+                .getSearchScope());
+        assertEquals(controls.getTimeLimit(), op.getControls().getTimeLimit());
+        assertTrue(op.getSearchResult() instanceof PersistentSearchResult);
+
+        try {
+            context.search("test=addlistener", "objectClass=*", controls);
+            fail("Should throw InvalidSearchFilterException");
+        } catch (InvalidSearchFilterException e) {
+            // expected
+        }
+
+        context.addNamingListener("test=addlistener", "(objectClass=*)", null,
+                new TestNamingListener());
+
+        op = (SearchOp) client.getRequest();
+        assertEquals(0, op.getControls().getCountLimit());
+        assertEquals(false, op.getControls().getDerefLinkFlag());
+        assertEquals(false, op.getControls().getReturningObjFlag());
+        assertEquals(SearchControls.ONELEVEL_SCOPE, op.getControls()
+                .getSearchScope());
+        assertEquals(0, op.getControls().getTimeLimit());
+        assertNull(controls.getReturningAttributes());
+        assertTrue(op.getSearchResult() instanceof PersistentSearchResult);
+    }
+
+    public void test_removeNamingListener() throws Exception {
+        MockLdapClient client = new MockLdapClient();
+        Hashtable<Object, Object> env = new Hashtable<Object, Object>();
+
+        context = new LdapContextImpl(client, env, "cn=test");
+        // remove not registered listener, do nothing
+        context.removeNamingListener(new TestNamingListener());
+
+        NamingListener listener = new TestNamingListener();
+
+        context.addNamingListener("test=listener", EventContext.OBJECT_SCOPE,
+                listener);
+        context.removeNamingListener(listener);
+
+        listener = new TestNamingListener();
+        context.addNamingListener("test=listener", EventContext.OBJECT_SCOPE,
+                listener);
+        context.addNamingListener("test=listener", EventContext.ONELEVEL_SCOPE,
+                listener);
+        context.removeNamingListener(listener);
+    }
+
+    public static class TestNamingListener implements NamespaceChangeListener {
+
+        private NamingEvent event;
+
+        private NamingExceptionEvent ex;
+
+        public void objectAdded(NamingEvent namingevent) {
+            this.event = namingevent;
+        }
+
+        public void objectRemoved(NamingEvent namingevent) {
+            this.event = namingevent;
+        }
+
+        public NamingEvent getEvent() {
+            return event;
+        }
+
+        public NamingExceptionEvent getExceptionEvent() {
+            return ex;
+        }
+
+        public void objectRenamed(NamingEvent namingevent) {
+            this.event = namingevent;
+        }
+
+        public void namingExceptionThrown(
+                NamingExceptionEvent namingExceptionEvent) {
+            this.ex = namingExceptionEvent;
+
+        }
+
     }
 }

Modified: harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/MockLdapClient.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/MockLdapClient.java?rev=598209&r1=598208&r2=598209&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/MockLdapClient.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/ldap/MockLdapClient.java
Mon Nov 26 02:23:37 2007
@@ -74,6 +74,13 @@
     }
 
     @Override
+    public int addPersistentSearch(SearchOp op) throws IOException {
+        request = op.getRequest();
+        response = op.getResponse();
+        return new LdapMessage(response).getMessageId();
+    }
+
+    @Override
     public void doOperationWithoutResponse(int opIndex, ASN1Encodable op,
             Control[] controls) throws IOException {
         request = op;



Mime
View raw message