View Javadoc
1   /*
2    * Copyright (c) 1999, 2011, 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.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.jndi.ldap;
27  
28  import java.io.IOException;
29  import java.util.concurrent.BlockingQueue;
30  import java.util.concurrent.LinkedBlockingQueue;
31  import javax.naming.CommunicationException;
32  
33  final class LdapRequest {
34  
35      LdapRequest next;   // Set/read in synchronized Connection methods
36      int msgId;          // read-only
37  
38      private int gotten = 0;
39      private BlockingQueue<BerDecoder> replies;
40      private int highWatermark = -1;
41      private boolean cancelled = false;
42      private boolean pauseAfterReceipt = false;
43      private boolean completed = false;
44  
45      LdapRequest(int msgId, boolean pause) {
46          this(msgId, pause, -1);
47      }
48  
49      LdapRequest(int msgId, boolean pause, int replyQueueCapacity) {
50          this.msgId = msgId;
51          this.pauseAfterReceipt = pause;
52          if (replyQueueCapacity == -1) {
53              this.replies = new LinkedBlockingQueue<BerDecoder>();
54          } else {
55              this.replies =
56                  new LinkedBlockingQueue<BerDecoder>(replyQueueCapacity);
57              highWatermark = (replyQueueCapacity * 80) / 100; // 80% capacity
58          }
59      }
60  
61      synchronized void cancel() {
62          cancelled = true;
63  
64          // Unblock reader of pending request
65          // Should only ever have atmost one waiter
66          notify();
67      }
68  
69      synchronized boolean addReplyBer(BerDecoder ber) {
70          if (cancelled) {
71              return false;
72          }
73  
74          // Add a new reply to the queue of unprocessed replies.
75          try {
76              replies.put(ber);
77          } catch (InterruptedException e) {
78              // ignore
79          }
80  
81          // peek at the BER buffer to check if it is a SearchResultDone PDU
82          try {
83              ber.parseSeq(null);
84              ber.parseInt();
85              completed = (ber.peekByte() == LdapClient.LDAP_REP_RESULT);
86          } catch (IOException e) {
87              // ignore
88          }
89          ber.reset();
90  
91          notify(); // notify anyone waiting for reply
92          /*
93           * If a queue capacity has been set then trigger a pause when the
94           * queue has filled to 80% capacity. Later, when the queue has drained
95           * then the reader gets unpaused.
96           */
97          if (highWatermark != -1 && replies.size() >= highWatermark) {
98              return true; // trigger the pause
99          }
100         return pauseAfterReceipt;
101     }
102 
103     synchronized BerDecoder getReplyBer() throws CommunicationException {
104         if (cancelled) {
105             throw new CommunicationException("Request: " + msgId +
106                 " cancelled");
107         }
108 
109         /*
110          * Remove a reply if the queue is not empty.
111          * poll returns null if queue is empty.
112          */
113         BerDecoder reply = replies.poll();
114         return reply;
115     }
116 
117     synchronized boolean hasSearchCompleted() {
118         return completed;
119     }
120 }