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 javax.naming.directory.SearchControls;
29  import javax.naming.event.*;
30  
31  /**
32   * This class holds the information in an event registration/deregistration
33   * request. This includes the name, filter, search controls and
34   * the different interfaces that the listener implements. This last piece
35   * of information determines which event(s) the listener is interested in.
36   *<p>
37   * It overrides equals() and hashCode() to use all these pieces of
38   * information so that it can be used correctly in a hashtable.
39   *
40   * @author Rosanna Lee
41   */
42  final class NotifierArgs {
43      static final int ADDED_MASK = 0x1;
44      static final int REMOVED_MASK = 0x2;
45      static final int CHANGED_MASK = 0x4;
46      static final int RENAMED_MASK = 0x8;
47  
48      // these fields are package private; used by NamingEventNotifier
49      String name;
50      String filter;
51      SearchControls controls;
52      int mask;
53  
54      // package private
55      NotifierArgs(String name, int scope, NamingListener l) {
56          this(name, "(objectclass=*)", null, l);
57  
58          // if scope is not default, create search ctl and set it
59          if (scope != EventContext.ONELEVEL_SCOPE) {
60              controls = new SearchControls();
61              controls.setSearchScope(scope);
62          }
63      }
64  
65      // package private
66      NotifierArgs(String name, String filter, SearchControls ctls,
67          NamingListener l) {
68          this.name = name;
69          this.filter = filter;
70          this.controls = ctls;
71  
72          if (l instanceof NamespaceChangeListener) {
73              mask |= ADDED_MASK|REMOVED_MASK|RENAMED_MASK;
74          }
75          if (l instanceof ObjectChangeListener) {
76              mask |= CHANGED_MASK;
77          }
78      }
79  
80      // checks name, filter, controls
81      public boolean equals(Object obj) {
82          if (obj instanceof NotifierArgs) {
83              NotifierArgs target = (NotifierArgs)obj;
84              return mask == target.mask &&
85                  name.equals(target.name) && filter.equals(target.filter) &&
86                  checkControls(target.controls);
87          }
88          return false;
89      }
90  
91      private boolean checkControls(SearchControls ctls) {
92          if ((controls == null || ctls == null)) {
93              return ctls == controls;
94          }
95          // ctls are nonempty
96  
97          return (controls.getSearchScope() == ctls.getSearchScope()) &&
98              (controls.getTimeLimit() == ctls.getTimeLimit()) &&
99              (controls.getDerefLinkFlag() == ctls.getDerefLinkFlag()) &&
100             (controls.getReturningObjFlag() == ctls.getReturningObjFlag()) &&
101             (controls.getCountLimit() == ctls.getCountLimit()) &&
102             checkStringArrays(controls.getReturningAttributes(),
103                 ctls.getReturningAttributes());
104     }
105 
106     private static boolean checkStringArrays(String[] s1, String[] s2) {
107         if ((s1 == null) || (s2 == null)) {
108             return s1 == s2;
109         }
110 
111         // both are nonnull
112         if (s1.length != s2.length) {
113             return false;
114         }
115 
116         for (int i = 0; i < s1.length; i++) {
117             if (!s1[i].equals(s2[i])) {
118                 return false;
119             }
120         }
121         return true;
122     }
123 
124     // save from having to recalculate each time
125     private int sum = -1;
126     public int hashCode() {
127         if (sum == -1)
128             sum = mask + name.hashCode() + filter.hashCode() + controlsCode();
129         return sum;
130     }
131 
132     // used in calculating hash code
133     private int controlsCode() {
134         if (controls == null) return 0;
135 
136         int total = controls.getTimeLimit() + (int)controls.getCountLimit() +
137             (controls.getDerefLinkFlag() ? 1 : 0) +
138             (controls.getReturningObjFlag() ? 1 : 0);
139 
140         String[] attrs = controls.getReturningAttributes();
141         if (attrs != null) {
142             for (int i = 0; i < attrs.length; i++) {
143                 total += attrs[i].hashCode();
144             }
145         }
146 
147         return total;
148     }
149 }