File: contextprocessor.xml

package info (click to toggle)
libspring-ldap-java 1.3.1.RELEASE-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,872 kB
  • sloc: java: 12,509; xml: 4,106; jsp: 36; makefile: 33; sh: 13
file content (200 lines) | stat: -rw-r--r-- 9,390 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="processor">
  <title>Processing the DirContext</title>

  <sect1 id="processor-overview">
    <title>Custom DirContext Pre/Postprocessing</title>

    <para>In some situations, one would like to perform operations on the
    <literal>DirContext</literal> before and after the search operation. The
    interface that is used for this is called
    <literal>DirContextProcessor</literal>:</para>

    <informalexample>
      <programlisting>public interface DirContextProcessor {
   public void preProcess(DirContext ctx) throws NamingException;
   public void postProcess(DirContext ctx) throws NamingException;
}</programlisting>
    </informalexample>

    <para>The <literal>LdapTemplate</literal> class has a search method that
    takes a <literal>DirContextProcessor</literal>:</para>

    <informalexample>
      <programlisting>public void search(SearchExecutor se, NameClassPairCallbackHandler handler,
   DirContextProcessor processor) throws DataAccessException;</programlisting>
    </informalexample>

    <para>Before the search operation, the <literal>preProcess</literal>
    method is called on the given <literal>DirContextProcessor</literal>
    instance. After the search has been executed and the resulting
    <literal>NamingEnumeration</literal> has been processed, the
    <literal>postProcess</literal> method is called. This enables a user to
    perform operations on the <literal>DirContext</literal> to be used in the
    search, and to check the <literal>DirContext</literal> when the search has
    been performed. This can be very useful for example when handling request
    and response controls.</para>

    <para>There are also a few convenience methods for those that don't need a
    custom <literal>SearchExecutor</literal>:</para>

    <informalexample>
      <programlisting>public void search(Name base, String filter,
   SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor)

public void search(String base, String filter,
   SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor)
   
public void search(Name base, String filter,
   SearchControls controls, AttributesMapper mapper, DirContextProcessor processor)
   
public void search(String base, String filter,
   SearchControls controls, AttributesMapper mapper, DirContextProcessor processor)
   
public void search(Name base, String filter,
   SearchControls controls, ContextMapper mapper, DirContextProcessor processor)

public void search(String base, String filter,
   SearchControls controls, ContextMapper mapper, DirContextProcessor processor)</programlisting>
    </informalexample>
  </sect1>

  <sect1 id="processor-others">
    <title>Implementing a Request Control DirContextProcessor</title>

    <para>The LDAPv3 protocol uses Controls to send and receive additional
    data to affect the behavior of predefined operations. In order to simplify
    the implementation of a request control
    <literal>DirContextProcessor</literal>, Spring LDAP provides the base
    class <literal>AbstractRequestControlDirContextProcessor</literal>. This
    class handles the retrieval of the current request controls from the
    <literal>LdapContext</literal>, calls a template method for creating a
    request control, and adds it to the <literal>LdapContext</literal>. All
    you have to do in the subclass is to implement the template method
    <literal>createRequestControl</literal>, and of course the
    <literal>postProcess</literal> method for performing whatever you need to
    do after the search.</para>

    <informalexample>
      <programlisting>public abstract class AbstractRequestControlDirContextProcessor implements
      DirContextProcessor {

   public void preProcess(DirContext ctx) throws NamingException {
      ...
   }

   public abstract Control createRequestControl();
}</programlisting>

      <para>A typical <literal>DirContextProcessor</literal> will be similar to the following:</para>
    </informalexample>

    <example>
      <title>A request control DirContextProcessor implementation</title>

      <programlisting>package com.example.control;

public class MyCoolRequestControl extends AbstractRequestControlDirContextProcessor {
   private static final boolean CRITICAL_CONTROL = true;
   private MyCoolCookie cookie;
   ...
   public MyCoolCookie getCookie() {
      return cookie;
   }

   public Control createRequestControl() {
      return new SomeCoolControl(cookie.getCookie(), CRITICAL_CONTROL);
   }

   public void postProcess(DirContext ctx) throws NamingException {
      LdapContext ldapContext = (LdapContext) ctx;
      Control[] responseControls = ldapContext.getResponseControls();

      for (int i = 0; i &lt; responseControls.length; i++) {
         if (responseControls[i] instanceof SomeCoolResponseControl) {
            SomeCoolResponseControl control = (SomeCoolResponseControl) responseControls[i];
            this.cookie = new MyCoolCookie(control.getCookie());
         }
      }
   }
}</programlisting>
    </example>

    <note>
      <para>Make sure you use <literal>LdapContextSource</literal> when you
      use Controls. The <literal><ulink
      url="http://download.oracle.com/javase/1.5.0/docs/api/javax/naming/ldap/Control.html">Control</ulink></literal>
      interface is specific for LDAPv3 and requires that
      <literal>LdapContext</literal> is used instead of
      <literal>DirContext</literal>. If an
      <literal>AbstractRequestControlDirContextProcessor</literal> subclass is
      called with an argument that is not an <literal>LdapContext</literal>,
      it will throw an <literal>IllegalArgumentException</literal>.</para>
    </note>
  </sect1>

  <sect1>
    <title>Paged Search Results</title>

    <para>Some searches may return large numbers of results. When there is no
    easy way to filter out a smaller amount, it would be convenient to have
    the server return only a certain number of results each time it is called.
    This is known as <emphasis>paged search results</emphasis>. Each "page" of
    the result could then be displayed at the time, with links to the next and
    previous page. Without this functionality, the client must either manually
    limit the search result into pages, or retrieve the whole result and then
    chop it into pages of suitable size. The former would be rather
    complicated, and the latter would be consuming unnecessary amounts of
    memory.</para>

    <para>Some LDAP servers have support for the
    <literal>PagedResultsControl</literal>, which requests that the results of
    a search operation are returned by the LDAP server in pages of a specified
    size. The user controls the rate at which the pages are returned, simply
    by the rate at which the searches are called. However, the user must keep
    track of a <emphasis>cookie</emphasis> between the calls. The server uses
    this cookie to keep track of where it left off the previous time it was
    called with a paged results request.</para>

    <para>Spring LDAP provides support for paged results by leveraging the
    concept for pre- and postprocessing of an <literal>LdapContext</literal> that was discussed
    in the previous sections. It does so by providing two classes:
    <literal>PagedResultsRequestControl</literal> and
    <literal>PagedResultsCookie</literal>. The
    <literal>PagedResultsRequestControl</literal> class creates a
    <literal>PagedResultsControl</literal> with the requested page size and
    adds it to the <literal>LdapContext</literal>. After the search, it gets
    the <literal>PagedResultsResponseControl</literal> and retrieves two
    pieces of information from it: the estimated total result size and a
    cookie. This cookie is a byte array containing information that the server
    needs the next time it is called with a
    <literal>PagedResultsControl</literal>. In order to make it easy to store
    this cookie between searches, Spring LDAP provides the wrapper class
    <literal>PagedResultsCookie</literal>.</para>

    <para>Below is an example of how the paged search results functionality may
    be used:</para>

    <example>
      <title>Paged results using <literal>PagedResultsRequestControl</literal></title>

      <programlisting>public PagedResult getAllPersons(PagedResultsCookie cookie) {
   PagedResultsRequestControl control = new PagedResultsRequestControl(PAGE_SIZE, cookie);
   SearchControls searchControls = new SearchControls();
   searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
   
   List persons = ldapTemplate.search("", "objectclass=person", searchControls, control);
   
   return new PagedResult(persons, control.getCookie());
 }</programlisting>
    </example>

    <para>In the first call to this method, <literal>null</literal> will be supplied as
    the cookie parameter. On subsequent calls the client will need to supply the cookie from
    the last search (returned wrapped in the <literal>PagedResult</literal>) each time the 
    method is called. When the actual cookie is <literal>null</literal> (i.e. 
    <literal>pagedResult.getCookie().getCookie()</literal> returns <literal>null</literal>),
    the last batch has been returned from the search.</para>
    
  </sect1>
</chapter>