Path: blob/master/src/java.naming/share/classes/com/sun/jndi/ldap/LdapRequest.java
41161 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.jndi.ldap;2627import java.io.IOException;28import java.util.concurrent.BlockingQueue;29import java.util.concurrent.LinkedBlockingQueue;30import javax.naming.CommunicationException;31import javax.naming.NamingException;32import java.util.concurrent.TimeUnit;3334final class LdapRequest {3536private static final BerDecoder EOF = new BerDecoder(new byte[]{}, -1, 0);37private static final String CLOSE_MSG = "LDAP connection has been closed";38private static final String TIMEOUT_MSG_FMT = "LDAP response read timed out, timeout used: %d ms.";3940LdapRequest next; // Set/read in synchronized Connection methods41final int msgId; // read-only4243private final BlockingQueue<BerDecoder> replies;44private volatile boolean cancelled;45private volatile boolean closed;46private volatile boolean completed;47private final boolean pauseAfterReceipt;4849LdapRequest(int msgId, boolean pause, int replyQueueCapacity) {50this.msgId = msgId;51this.pauseAfterReceipt = pause;52if (replyQueueCapacity == -1) {53this.replies = new LinkedBlockingQueue<>();54} else {55this.replies = new LinkedBlockingQueue<>(8 * replyQueueCapacity / 10);56}57}5859void cancel() {60cancelled = true;61replies.offer(EOF);62}6364synchronized void close() {65closed = true;66replies.offer(EOF);67}6869private boolean isClosed() {70return closed && (replies.size() == 0 || replies.peek() == EOF);71}7273synchronized boolean addReplyBer(BerDecoder ber) {74// check the closed boolean value here as we don't want anything75// to be added to the queue after close() has been called.76if (cancelled || closed) {77return false;78}7980// peek at the BER buffer to check if it is a SearchResultDone PDU81try {82ber.parseSeq(null);83ber.parseInt();84completed = (ber.peekByte() == LdapClient.LDAP_REP_RESULT);85} catch (IOException e) {86// ignore87}88ber.reset();8990// Add a new reply to the queue of unprocessed replies.91try {92replies.put(ber);93} catch (InterruptedException e) {94// ignore95}9697return pauseAfterReceipt;98}99100/**101* Read reply BER102* @param millis timeout, infinite if the value is negative103* @return BerDecoder if reply was read successfully104* @throws CommunicationException request has been canceled and request does not need to be abandoned105* @throws NamingException request has been closed or timed out. Request does need to be abandoned106* @throws InterruptedException LDAP operation has been interrupted107*/108BerDecoder getReplyBer(long millis) throws NamingException,109InterruptedException {110if (cancelled) {111throw new CommunicationException("Request: " + msgId +112" cancelled");113}114if (isClosed()) {115throw new NamingException(CLOSE_MSG);116}117118BerDecoder result = millis > 0 ?119replies.poll(millis, TimeUnit.MILLISECONDS) : replies.take();120121if (cancelled) {122throw new CommunicationException("Request: " + msgId +123" cancelled");124}125126// poll from 'replies' blocking queue ended-up with timeout127if (result == null) {128throw new NamingException(String.format(TIMEOUT_MSG_FMT, millis));129}130// Unexpected EOF can be caused by connection closure or cancellation131if (result == EOF) {132throw new NamingException(CLOSE_MSG);133}134return result;135}136137boolean hasSearchCompleted() {138return completed;139}140}141142143