1 /* 2 * Copyright (c) 2011, 2017, 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 import java.io.BufferedInputStream; 24 import java.io.IOException; 25 import java.io.OutputStreamWriter; 26 import java.io.PrintWriter; 27 import java.net.ServerSocket; 28 import java.net.Socket; 29 import java.nio.charset.StandardCharsets; 30 import java.util.ConcurrentModificationException; 31 import java.util.Hashtable; 32 import javax.naming.Context; 33 import javax.naming.InitialContext; 34 import javax.naming.NamingException; 35 import javax.naming.event.EventContext; 36 import javax.naming.event.NamingEvent; 37 import javax.naming.event.NamingExceptionEvent; 38 import javax.naming.event.NamingListener; 39 import javax.naming.event.ObjectChangeListener; 40 41 /** 42 * @test 43 * @bug 8176192 44 * @summary Incorrect usage of Iterator in Java 8 In com.sun.jndi.ldap. 45 * EventSupport.removeNamingListener 46 * @modules java.naming 47 * @run main RemoveNamingListenerTest 48 */ 49 public class RemoveNamingListenerTest { 50 51 private static volatile Exception exception; 52 53 public static void main(String args[]) throws Exception { 54 // start the LDAP server 55 TestLDAPServer server = new TestLDAPServer(); 56 server.start(); 57 58 // Set up environment for creating initial context 59 Hashtable<String, Object> env = new Hashtable<>(3); 60 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 61 env.put(Context.PROVIDER_URL, "ldap://localhost:" + server.getPort() + "/o=example"); 62 env.put("com.sun.jndi.ldap.connect.timeout", "2000"); 63 EventContext ctx = null; 64 65 try { 66 ctx = (EventContext) (new InitialContext(env).lookup("")); 67 String target = "cn=Vyom Tewari"; 68 69 // Create listeners 70 NamingListener oneListener = new SampleListener(); 71 NamingListener objListener = new SampleListener(); 72 NamingListener subListener = new SampleListener(); 73 74 // Register listeners using different scopes 75 ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, oneListener); 76 ctx.addNamingListener(target, EventContext.OBJECT_SCOPE, objListener); 77 ctx.addNamingListener(target, EventContext.SUBTREE_SCOPE, subListener); 78 79 //remove a listener in different thread 80 Thread t = new Thread(new RemoveNamingListener(ctx, subListener)); 81 t.start(); 82 t.join(); 83 84 if (exception != null) { 85 throw exception; 86 } 87 System.out.println("Test run OK!!!"); 88 } finally { 89 if (ctx != null) { 90 ctx.close(); 91 } 92 server.stopServer(); 93 } 94 } 95 96 /** 97 * Helper thread that removes the naming listener. 98 */ 99 static class RemoveNamingListener implements Runnable { 100 101 final EventContext ctx; 102 final NamingListener listener; 103 104 RemoveNamingListener(EventContext ctx, NamingListener listener) { 105 this.ctx = ctx; 106 this.listener = listener; 107 } 108 109 @Override 110 public void run() { 111 try { 112 ctx.removeNamingListener(listener); 113 } catch (NamingException | ConcurrentModificationException ex) { 114 exception = ex; 115 } 116 } 117 } 118 119 static class SampleListener implements ObjectChangeListener { 120 121 @Override 122 public void objectChanged(NamingEvent ne) { 123 //do nothing 124 } 125 126 @Override 127 public void namingExceptionThrown(NamingExceptionEvent nee) { 128 //do nothing 129 } 130 } 131 } 132 133 class TestLDAPServer extends Thread { 134 135 private final int LDAP_PORT; 136 private final ServerSocket serverSocket; 137 private volatile boolean isRunning; 138 139 TestLDAPServer() throws IOException { 140 serverSocket = new ServerSocket(0); 141 isRunning = true; 142 LDAP_PORT = serverSocket.getLocalPort(); 143 setDaemon(true); 144 } 145 146 public int getPort() { 147 return LDAP_PORT; 148 } 149 150 public void stopServer() { 151 isRunning = false; 152 if (serverSocket != null && !serverSocket.isClosed()) { 153 try { 154 // this will cause ServerSocket.accept() to throw SocketException. 155 serverSocket.close(); 156 } catch (IOException ignored) { 157 } 158 } 159 } 160 161 @Override 162 public void run() { 163 try { 164 while (isRunning) { 165 Socket clientSocket = serverSocket.accept(); 166 Thread handler = new Thread(new LDAPServerHandler(clientSocket)); 167 handler.setDaemon(true); 168 handler.start(); 169 } 170 } catch (IOException iOException) { 171 //do not throw exception if server is not running. 172 if (isRunning) { 173 throw new RuntimeException(iOException); 174 } 175 } finally { 176 stopServer(); 177 } 178 } 179 } 180 181 class LDAPServerHandler implements Runnable { 182 183 private final Socket clientSocket; 184 185 public LDAPServerHandler(final Socket clientSocket) { 186 this.clientSocket = clientSocket; 187 } 188 189 @Override 190 public void run() { 191 BufferedInputStream in = null; 192 PrintWriter out = null; 193 byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 194 byte[] searchResponse = {0x30, 0x0C, 0x02, 0x01, 0x02, 0x65, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 195 try { 196 in = new BufferedInputStream(clientSocket.getInputStream()); 197 out = new PrintWriter(new OutputStreamWriter( 198 clientSocket.getOutputStream(), StandardCharsets.UTF_8), true); 199 while (true) { 200 201 // Read the LDAP BindRequest 202 while (in.read() != -1) { 203 in.skip(in.available()); 204 break; 205 } 206 207 // Write an LDAP BindResponse 208 out.write(new String(bindResponse)); 209 out.flush(); 210 211 // Read the LDAP SearchRequest 212 while (in.read() != -1) { 213 in.skip(in.available()); 214 break; 215 } 216 217 // Write an LDAP SearchResponse 218 out.write(new String(searchResponse)); 219 out.flush(); 220 } 221 } catch (IOException iOException) { 222 throw new RuntimeException(iOException); 223 } finally { 224 if (in != null) { 225 try { 226 in.close(); 227 } catch (IOException ignored) { 228 } 229 } 230 if (out != null) { 231 out.close(); 232 } 233 if (clientSocket != null) { 234 try { 235 clientSocket.close(); 236 } catch (IOException ignored) { 237 } 238 } 239 } 240 } 241 } | 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.net.URI; 28 import java.util.ConcurrentModificationException; 29 import java.util.Hashtable; 30 import javax.naming.Context; 31 import javax.naming.InitialContext; 32 import javax.naming.NamingException; 33 import javax.naming.event.EventContext; 34 import javax.naming.event.NamingEvent; 35 import javax.naming.event.NamingExceptionEvent; 36 import javax.naming.event.NamingListener; 37 import javax.naming.event.ObjectChangeListener; 38 import jdk.test.lib.net.URIBuilder; 39 40 /** 41 * @test 42 * @bug 8176192 43 * @summary Incorrect usage of Iterator in Java 8 In com.sun.jndi.ldap. 44 * EventSupport.removeNamingListener 45 * @modules java.naming 46 * @library lib/ /test/lib 47 * @run main RemoveNamingListenerTest 48 */ 49 public class RemoveNamingListenerTest { 50 51 private static volatile Exception exception; 52 53 public static void main(String args[]) throws Exception { 54 // start the LDAP server 55 TestLDAPServer server = new TestLDAPServer(); 56 server.start(); 57 58 URI providerURI = URIBuilder.newBuilder() 59 .scheme("ldap") 60 .loopback() 61 .port(server.getPort()) 62 .path("/o=example") 63 .build(); 64 65 // Set up environment for creating initial context 66 Hashtable<String, Object> env = new Hashtable<>(3); 67 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 68 env.put(Context.PROVIDER_URL, providerURI.toString()); 69 env.put("com.sun.jndi.ldap.connect.timeout", "2000"); 70 EventContext ctx = null; 71 72 try { 73 ctx = (EventContext) (new InitialContext(env).lookup("")); 74 String target = "cn=Vyom Tewari"; 75 76 // Create listeners 77 NamingListener oneListener = new SampleListener(); 78 NamingListener objListener = new SampleListener(); 79 NamingListener subListener = new SampleListener(); 80 81 // Register listeners using different scopes 82 ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, oneListener); 83 ctx.addNamingListener(target, EventContext.OBJECT_SCOPE, objListener); 84 ctx.addNamingListener(target, EventContext.SUBTREE_SCOPE, subListener); 85 86 //remove a listener in different thread 87 Thread t = new Thread(new RemoveNamingListener(ctx, subListener)); 88 t.start(); 89 t.join(); 90 91 if (exception != null) { 92 throw exception; 93 } 94 System.out.println("Test run OK!!!"); 95 } finally { 96 if (ctx != null) { 97 ctx.close(); 98 } 99 server.close(); 100 } 101 } 102 103 /** 104 * Helper thread that removes the naming listener. 105 */ 106 static class RemoveNamingListener implements Runnable { 107 108 final EventContext ctx; 109 final NamingListener listener; 110 111 RemoveNamingListener(EventContext ctx, NamingListener listener) { 112 this.ctx = ctx; 113 this.listener = listener; 114 } 115 116 @Override 117 public void run() { 118 try { 119 ctx.removeNamingListener(listener); 120 } catch (NamingException | ConcurrentModificationException ex) { 121 exception = ex; 122 } 123 } 124 } 125 126 static class SampleListener implements ObjectChangeListener { 127 128 @Override 129 public void objectChanged(NamingEvent ne) { 130 //do nothing 131 } 132 133 @Override 134 public void namingExceptionThrown(NamingExceptionEvent nee) { 135 //do nothing 136 } 137 } 138 } 139 140 class TestLDAPServer extends BaseLdapServer { 141 142 private byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 143 private byte[] searchResponse = {0x30, 0x0C, 0x02, 0x01, 0x02, 0x65, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 144 145 public TestLDAPServer() throws IOException { 146 } 147 148 @Override 149 protected void handleRequest(Socket socket, LdapMessage request, 150 OutputStream out) throws IOException { 151 switch (request.getOperation()) { 152 case BIND_REQUEST: 153 // Write an LDAP BindResponse 154 out.write(bindResponse); 155 break; 156 case SEARCH_REQUEST: 157 // Write an LDAP SearchResponse 158 out.write(searchResponse); 159 break; 160 default: 161 break; 162 } 163 } 164 } |