1 /* 2 * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.IOException; 25 import java.io.OutputStream; 26 import java.net.Socket; 27 import java.util.ConcurrentModificationException; 28 import java.util.Hashtable; 29 import javax.naming.Context; 30 import javax.naming.InitialContext; 31 import javax.naming.NamingException; 32 import javax.naming.event.EventContext; 33 import javax.naming.event.NamingEvent; 34 import javax.naming.event.NamingExceptionEvent; 35 import javax.naming.event.NamingListener; 36 import javax.naming.event.ObjectChangeListener; 37 38 /** 39 * @test 40 * @bug 8176192 41 * @summary Incorrect usage of Iterator in Java 8 In com.sun.jndi.ldap. 42 * EventSupport.removeNamingListener 43 * @modules java.naming 44 * @library lib/ 45 * @run main RemoveNamingListenerTest 46 */ 47 public class RemoveNamingListenerTest { 48 49 private static volatile Exception exception; 50 51 public static void main(String args[]) throws Exception { 52 // start the LDAP server 53 TestLDAPServer server = new TestLDAPServer(); 54 server.start(); 55 56 // Set up environment for creating initial context 57 Hashtable<String, Object> env = new Hashtable<>(3); 58 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 59 env.put(Context.PROVIDER_URL, "ldap://localhost:" + server.getPort() + "/o=example"); 60 env.put("com.sun.jndi.ldap.connect.timeout", "2000"); 61 EventContext ctx = null; 62 63 try { 64 ctx = (EventContext) (new InitialContext(env).lookup("")); 65 String target = "cn=Vyom Tewari"; 66 67 // Create listeners 68 NamingListener oneListener = new SampleListener(); 69 NamingListener objListener = new SampleListener(); 70 NamingListener subListener = new SampleListener(); 71 72 // Register listeners using different scopes 73 ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, oneListener); 74 ctx.addNamingListener(target, EventContext.OBJECT_SCOPE, objListener); 75 ctx.addNamingListener(target, EventContext.SUBTREE_SCOPE, subListener); 76 77 //remove a listener in different thread 78 Thread t = new Thread(new RemoveNamingListener(ctx, subListener)); 79 t.start(); 80 t.join(); 81 82 if (exception != null) { 83 throw exception; 84 } 85 System.out.println("Test run OK!!!"); 86 } finally { 87 if (ctx != null) { 88 ctx.close(); 89 } 90 server.close(); 91 } 92 } 93 94 /** 95 * Helper thread that removes the naming listener. 96 */ 97 static class RemoveNamingListener implements Runnable { 98 99 final EventContext ctx; 100 final NamingListener listener; 101 102 RemoveNamingListener(EventContext ctx, NamingListener listener) { 103 this.ctx = ctx; 104 this.listener = listener; 105 } 106 107 @Override 108 public void run() { 109 try { 110 ctx.removeNamingListener(listener); 111 } catch (NamingException | ConcurrentModificationException ex) { 112 exception = ex; 113 } 114 } 115 } 116 117 static class SampleListener implements ObjectChangeListener { 118 119 @Override 120 public void objectChanged(NamingEvent ne) { 121 //do nothing 122 } 123 124 @Override 125 public void namingExceptionThrown(NamingExceptionEvent nee) { 126 //do nothing 127 } 128 } 129 } 130 131 class TestLDAPServer extends BaseLdapServer { 132 133 private byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 134 private byte[] searchResponse = {0x30, 0x0C, 0x02, 0x01, 0x02, 0x65, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 135 136 public TestLDAPServer() throws IOException { 137 } 138 139 @Override 140 protected void handleRequest(Socket socket, LdapMessage request, 141 OutputStream out) throws IOException { 142 switch (request.getOperation()) { 143 case BIND_REQUEST: 144 // Write an LDAP BindResponse 145 out.write(bindResponse); 146 break; 147 case SEARCH_REQUEST: 148 // Write an LDAP SearchResponse 149 out.write(searchResponse); 150 break; 151 default: 152 break; 153 } 154 } 155 }