1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 package org.apache.jmeter.protocol.ldap.sampler;
20
21 import javax.naming.NamingException;
22 import javax.naming.directory.Attribute;
23 import javax.naming.directory.BasicAttribute;
24 import javax.naming.directory.BasicAttributes;
25 import javax.naming.directory.DirContext;
26 import javax.naming.directory.ModificationItem;
27
28 import org.apache.jmeter.config.Argument;
29 import org.apache.jmeter.config.Arguments;
30 import org.apache.jmeter.config.ConfigTestElement;
31 import org.apache.jmeter.samplers.AbstractSampler;
32 import org.apache.jmeter.samplers.Entry;
33 import org.apache.jmeter.samplers.SampleResult;
34 import org.apache.jmeter.testelement.property.BooleanProperty;
35 import org.apache.jmeter.testelement.property.PropertyIterator;
36 import org.apache.jmeter.testelement.property.StringProperty;
37 import org.apache.jmeter.testelement.property.TestElementProperty;
38 import org.apache.jorphan.logging.LoggingManager;
39 import org.apache.log.Logger;
40
41 /**
42 * Ldap Sampler class is main class for the LDAP test. This will control all the
43 * test available in the LDAP Test.
44 *
45 */
46 public class LDAPSampler extends AbstractSampler {
47 private static final Logger log = LoggingManager.getLoggerForClass();
48
49 public static final String SERVERNAME = "servername"; //$NON-NLS-1$
50
51 public static final String PORT = "port"; //$NON-NLS-1$
52
53 public static final String ROOTDN = "rootdn"; //$NON-NLS-1$
54
55 public static final String TEST = "test"; //$NON-NLS-1$
56
57 public static final String ADD = "add"; //$NON-NLS-1$
58
59 public static final String MODIFY = "modify"; //$NON-NLS-1$
60
61 public static final String DELETE = "delete"; //$NON-NLS-1$
62
63 public static final String SEARCHBASE = "search"; //$NON-NLS-1$
64
65 public static final String SEARCHFILTER = "searchfilter"; //$NON-NLS-1$
66
67 public static final String USER_DEFINED = "user_defined"; //$NON-NLS-1$
68
69 public static final String ARGUMENTS = "arguments"; //$NON-NLS-1$
70
71 public static final String BASE_ENTRY_DN = "base_entry_dn"; //$NON-NLS-1$
72
73 // For In build test case using this counter
74 // create the new entry in the server
75 private static volatile int counter = 0;
76
77 private boolean searchFoundEntries;// TODO turn into parameter?
78
79 public LDAPSampler() {
80 }
81
82 /**
83 * Gets the username attribute of the LDAP object.
84 *
85 * @return the username
86 */
87 public String getUsername() {
88 return getPropertyAsString(ConfigTestElement.USERNAME);
89 }
90
91 /**
92 * Gets the password attribute of the LDAP object.
93 *
94 * @return the password
95 */
96 public String getPassword() {
97 return getPropertyAsString(ConfigTestElement.PASSWORD);
98 }
99
100 /**
101 * Sets the Servername attribute of the ServerConfig object.
102 *
103 * @param servername
104 * the new servername value
105 */
106 public void setServername(String servername) {
107 setProperty(new StringProperty(SERVERNAME, servername));
108 }
109
110 /**
111 * Sets the Port attribute of the ServerConfig object.
112 *
113 * @param port
114 * the new Port value
115 */
116 public void setPort(String port) {
117 setProperty(new StringProperty(PORT, port));
118 }
119
120 /**
121 * Gets the servername attribute of the LDAPSampler object.
122 *
123 * @return the Servername value
124 */
125 public String getServername() {
126 return getPropertyAsString(SERVERNAME);
127 }
128
129 /**
130 * Gets the Port attribute of the LDAPSampler object.
131 *
132 * @return the Port value
133 */
134 public String getPort() {
135 return getPropertyAsString(PORT);
136 }
137
138 /**
139 * Sets the Rootdn attribute of the LDAPSampler object.
140 *
141 * @param newRootdn
142 * the new rootdn value
143 */
144 public void setRootdn(String newRootdn) {
145 this.setProperty(ROOTDN, newRootdn);
146 }
147
148 /**
149 * Gets the Rootdn attribute of the LDAPSampler object.
150 *
151 * @return the Rootdn value
152 */
153 public String getRootdn() {
154 return getPropertyAsString(ROOTDN);
155 }
156
157 /**
158 * Sets the Test attribute of the LdapConfig object.
159 *
160 * @param newTest
161 * the new test value(Add,Modify,Delete and search)
162 */
163 public void setTest(String newTest) {
164 this.setProperty(TEST, newTest);
165 }
166
167 /**
168 * Gets the test attribute of the LDAPSampler object.
169 *
170 * @return the test value (Add, Modify, Delete and search)
171 */
172 public String getTest() {
173 return getPropertyAsString(TEST);
174 }
175
176 /**
177 * Sets the UserDefinedTest attribute of the LDAPSampler object.
178 *
179 * @param value
180 * the new UserDefinedTest value
181 */
182 public void setUserDefinedTest(boolean value) {
183 setProperty(new BooleanProperty(USER_DEFINED, value));
184 }
185
186 /**
187 * Gets the UserDefinedTest attribute of the LDAPSampler object.
188 *
189 * @return the test value true or false. If true it will do the
190 * UserDefinedTest else our own inbuild test case.
191 */
192 public boolean getUserDefinedTest() {
193 return getPropertyAsBoolean(USER_DEFINED);
194 }
195
196 /**
197 * Sets the Base Entry DN attribute of the LDAPSampler object.
198 *
199 * @param newbaseentry
200 * the new Base entry DN value
201 */
202 public void setBaseEntryDN(String newbaseentry) {
203 setProperty(new StringProperty(BASE_ENTRY_DN, newbaseentry));
204 }
205
206 /**
207 * Gets the BaseEntryDN attribute of the LDAPSampler object.
208 *
209 * @return the Base entry DN value
210 */
211 public String getBaseEntryDN() {
212 return getPropertyAsString(BASE_ENTRY_DN);
213 }
214
215 /**
216 * Sets the Arguments attribute of the LdapConfig object. This will collect
217 * values from the table for user defined test case.
218 *
219 * @param value
220 * the arguments
221 */
222 public void setArguments(Arguments value) {
223 setProperty(new TestElementProperty(ARGUMENTS, value));
224 }
225
226 /**
227 * Gets the Arguments attribute of the LdapConfig object.
228 *
229 * @return the arguments. User defined test case.
230 */
231 public Arguments getArguments() {
232 return (Arguments) getProperty(ARGUMENTS).getObjectValue();
233 }
234
235 /**
236 * Collect all the value from the table (Arguments), using this create the
237 * basicAttributes. This will create the Basic Attributes for the User
238 * defined TestCase for Add Test.
239 *
240 * @return the BasicAttributes
241 */
242 private BasicAttributes getUserAttributes() {
243 BasicAttribute basicattribute = new BasicAttribute("objectclass"); //$NON-NLS-1$
244 basicattribute.add("top"); //$NON-NLS-1$
245 basicattribute.add("person"); //$NON-NLS-1$
246 basicattribute.add("organizationalPerson"); //$NON-NLS-1$
247 basicattribute.add("inetOrgPerson"); //$NON-NLS-1$
248 BasicAttributes attrs = new BasicAttributes(true);
249 attrs.put(basicattribute);
250 BasicAttribute attr;
251 PropertyIterator iter = getArguments().iterator();
252
253 while (iter.hasNext()) {
254 Argument item = (Argument) iter.next().getObjectValue();
255 attr = getBasicAttribute(item.getName(), item.getValue());
256 attrs.put(attr);
257 }
258 return attrs;
259 }
260
261 /**
262 * Collect all the value from the table (Arguments), using this create the
263 * basicAttributes. This will create the Basic Attributes for the User
264 * defined TestCase for Modify test.
265 *
266 * @return the BasicAttributes
267 */
268 private ModificationItem[] getUserModAttributes() {
269 ModificationItem[] mods = new ModificationItem[getArguments().getArguments().size()];
270 BasicAttribute attr;
271 PropertyIterator iter = getArguments().iterator();
272 int count = 0;
273 while (iter.hasNext()) {
274 Argument item = (Argument) iter.next().getObjectValue();
275 attr = getBasicAttribute(item.getName(), item.getValue());
276 mods[count] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
277 count = +1;
278 }
279 return mods;
280 }
281
282 /**
283 * This will create the Basic Attributes for the Inbuilt TestCase for Modify
284 * test.
285 *
286 * @return the BasicAttributes
287 */
288 private ModificationItem[] getModificationItem() {
289 ModificationItem[] mods = new ModificationItem[2];
290 // replace (update) attribute
291 Attribute mod0 = new BasicAttribute("userpassword", "secret"); //$NON-NLS-1$ //$NON-NLS-2$
292 // add mobile phone number attribute
293 Attribute mod1 = new BasicAttribute("mobile", "123-456-1234"); //$NON-NLS-1$ //$NON-NLS-2$
294
295 mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
296 mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod1);
297
298 return mods;
299 }
300
301 /**
302 * This will create the Basic Attributes for the In build TestCase for Add
303 * Test.
304 *
305 * @return the BasicAttributes
306 */
307 private BasicAttributes getBasicAttributes() {
308 BasicAttributes basicattributes = new BasicAttributes();
309 BasicAttribute basicattribute = new BasicAttribute("objectclass"); //$NON-NLS-1$
310 basicattribute.add("top"); //$NON-NLS-1$
311 basicattribute.add("person"); //$NON-NLS-1$
312 basicattribute.add("organizationalPerson"); //$NON-NLS-1$
313 basicattribute.add("inetOrgPerson"); //$NON-NLS-1$
314 basicattributes.put(basicattribute);
315 String s1 = "User"; //$NON-NLS-1$
316 String s3 = "Test"; //$NON-NLS-1$
317 String s5 = "user"; //$NON-NLS-1$
318 String s6 = "test"; //$NON-NLS-1$
319 counter += 1;
320 basicattributes.put(new BasicAttribute("givenname", s1)); //$NON-NLS-1$
321 basicattributes.put(new BasicAttribute("sn", s3)); //$NON-NLS-1$
322 basicattributes.put(new BasicAttribute("cn", "TestUser" + counter)); //$NON-NLS-1$ //$NON-NLS-2$
323 basicattributes.put(new BasicAttribute("uid", s5)); //$NON-NLS-1$
324 basicattributes.put(new BasicAttribute("userpassword", s6)); //$NON-NLS-1$
325 setProperty(new StringProperty(ADD, "cn=TestUser" + counter)); //$NON-NLS-1$
326 return basicattributes;
327 }
328
329 /**
330 * This will create the Basic Attribute for the given name value pair.
331 *
332 * @return the BasicAttribute
333 */
334 private BasicAttribute getBasicAttribute(String name, String value) {
335 BasicAttribute attr = new BasicAttribute(name, value);
336 return attr;
337 }
338
339 /**
340 * Returns a formatted string label describing this sampler
341 *
342 * @return a formatted string label describing this sampler
343 */
344 public String getLabel() {
345 return ("ldap://" + this.getServername() + ":" + getPort() + "/" + this.getRootdn());
346 }
347
348 /**
349 * This will do the add test for the User defined TestCase as well as
350 * inbuilt test case.
351 *
352 */
353 private void addTest(LdapClient ldap, SampleResult res) throws NamingException {
354 if (getPropertyAsBoolean(USER_DEFINED)) {
355 res.sampleStart();
356 ldap.createTest(getUserAttributes(), getPropertyAsString(BASE_ENTRY_DN));
357 res.sampleEnd();
358 } else {
359 res.sampleStart();
360 ldap.createTest(getBasicAttributes(), getPropertyAsString(ADD));
361 res.sampleEnd();
362 ldap.deleteTest(getPropertyAsString(ADD));
363 }
364 }
365
366 /**
367 * This will do the delete test for the User defined TestCase as well as
368 * inbuilt test case.
369 *
370 */
371 private void deleteTest(LdapClient ldap, SampleResult res) throws NamingException {
372 if (!getPropertyAsBoolean(USER_DEFINED)) {
373 ldap.createTest(getBasicAttributes(), getPropertyAsString(ADD));
374 setProperty(new StringProperty(DELETE, getPropertyAsString(ADD)));
375 }
376 res.sampleStart();
377 ldap.deleteTest(getPropertyAsString(DELETE));
378 res.sampleEnd();
379 }
380
381 /**
382 * This will do the search test for the User defined TestCase as well as
383 * inbuilt test case.
384 *
385 */
386 private void searchTest(LdapClient ldap, SampleResult res) throws NamingException {
387 if (!getPropertyAsBoolean(USER_DEFINED)) {
388 ldap.createTest(getBasicAttributes(), getPropertyAsString(ADD));
389 setProperty(new StringProperty(SEARCHBASE, getPropertyAsString(ADD)));
390 setProperty(new StringProperty(SEARCHFILTER, getPropertyAsString(ADD)));
391 }
392 res.sampleStart();
393 searchFoundEntries = ldap.searchTest(getPropertyAsString(SEARCHBASE), getPropertyAsString(SEARCHFILTER));
394 res.sampleEnd();
395 if (!getPropertyAsBoolean(USER_DEFINED)) {
396 ldap.deleteTest(getPropertyAsString(ADD));
397 }
398 }
399
400 /**
401 * This will do the search test for the User defined TestCase as well as
402 * inbuilt test case.
403 *
404 */
405 private void modifyTest(LdapClient ldap, SampleResult res) throws NamingException {
406 if (getPropertyAsBoolean(USER_DEFINED)) {
407 res.sampleStart();
408 ldap.modifyTest(getUserModAttributes(), getPropertyAsString(BASE_ENTRY_DN));
409 res.sampleEnd();
410 } else {
411 ldap.createTest(getBasicAttributes(), getPropertyAsString(ADD));
412 setProperty(new StringProperty(MODIFY, getPropertyAsString(ADD)));
413 res.sampleStart();
414 ldap.modifyTest(getModificationItem(), getPropertyAsString(MODIFY));
415 res.sampleEnd();
416 ldap.deleteTest(getPropertyAsString(ADD));
417 }
418 }
419
420 public SampleResult sample(Entry e) {
421 SampleResult res = new SampleResult();
422 boolean isSuccessful = false;
423 res.setSampleLabel(getName());
424 res.setSamplerData(getPropertyAsString(TEST));// TODO improve this
425 LdapClient ldap = new LdapClient();
426
427 try {
428 ldap.connect(getServername(), getPort(), getRootdn(), getUsername(), getPassword());
429
430 if (getPropertyAsString(TEST).equals(ADD)) {
431 addTest(ldap, res);
432 } else if (getPropertyAsString(TEST).equals(DELETE)) {
433 deleteTest(ldap, res);
434 } else if (getPropertyAsString(TEST).equals(MODIFY)) {
435 modifyTest(ldap, res);
436 } else if (getPropertyAsString(TEST).equals(SEARCHBASE)) {
437 searchTest(ldap, res);
438 }
439
440 // TODO - needs more work ...
441 if (getPropertyAsString(TEST).equals(SEARCHBASE) && !searchFoundEntries) {
442 res.setResponseCode("201");// TODO is this a sensible number? //$NON-NLS-1$
443 res.setResponseMessage("OK - no results");
444 res.setResponseData("successful - no results".getBytes());
445 } else {
446 res.setResponseCodeOK();
447 res.setResponseMessage("OK"); //$NON-NLS-1$
448 res.setResponseData("successful".getBytes());
449 }
450 res.setDataType(SampleResult.TEXT);
451 isSuccessful = true;
452 } catch (Exception ex) {
453 log.error("Ldap client - ", ex);
454 // Could time this
455 // res.sampleEnd();
456 // if sampleEnd() is not called, elapsed time will remain zero
457 res.setResponseCode("500");// TODO distinguish errors better //$NON-NLS-1$
458 res.setResponseMessage(ex.toString());
459 isSuccessful = false;
460 } finally {
461 ldap.disconnect();
462 }
463
464 // Set if we were successful or not
465 res.setSuccessful(isSuccessful);
466 return res;
467 }
468 }